From 64026d20be20529b8b90c4c636db8c0ba3f4360a Mon Sep 17 00:00:00 2001 From: David Teigland Date: Nov 29 2016 15:39:27 +0000 Subject: sanlock: write lease with clear flag Add the flag SANLK_WRITE_CLEAR to sanlock_write_resource() which causes the resource lease on disk to be written without the standard magic number. This causes a subsequent sanlock_read_resource() to return the error -223/SANLK_LEADER_MAGIC indicating that no valid lease exists at that location. This can be used by an application to indicate that the lease area on disk is available to be reused for a new resource lease. (An application can continue to use a special resource name of its own choosing to implement the same effect.) --- diff --git a/src/cmd.c b/src/cmd.c index abf0af4..453a1b6 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -139,7 +139,6 @@ static const char *acquire_error_str(int error) return "lease io error"; case SANLK_LEADER_DIFF: - case SANLK_LEADER_MAGIC: case SANLK_LEADER_VERSION: case SANLK_LEADER_SECTORSIZE: case SANLK_LEADER_LOCKSPACE: @@ -148,6 +147,9 @@ static const char *acquire_error_str(int error) case SANLK_LEADER_CHECKSUM: return "lease data invalid"; + case SANLK_LEADER_MAGIC: + return "lease not found"; + default: return ""; }; @@ -1805,6 +1807,7 @@ static void cmd_write_resource(struct task *task, struct cmd_args *ca) struct sanlk_resource res; int token_len, disks_len; int num_hosts, max_hosts; + int write_clear = 0; int j, fd, rv, result; fd = client[ca->ci_in].fd; @@ -1868,6 +1871,9 @@ static void cmd_write_resource(struct task *task, struct cmd_args *ca) num_hosts = ca->header.data; max_hosts = ca->header.data2; + if (ca->header.cmd_flags & SANLK_WRITE_CLEAR) + write_clear = 1; + rv = open_disks(token->disks, token->r.num_disks); if (rv < 0) { result = rv; @@ -1876,7 +1882,7 @@ static void cmd_write_resource(struct task *task, struct cmd_args *ca) token->io_timeout = DEFAULT_IO_TIMEOUT; - result = paxos_lease_init(task, token, num_hosts, max_hosts); + result = paxos_lease_init(task, token, num_hosts, max_hosts, write_clear); close_disks(token->disks, token->r.num_disks); reply: diff --git a/src/direct.c b/src/direct.c index 09ba417..d8bad50 100644 --- a/src/direct.c +++ b/src/direct.c @@ -73,13 +73,10 @@ * delta_lease_renew() */ -static int do_paxos_action(int action, struct task *task, int io_timeout, - struct sanlk_resource *res, - int max_hosts, int num_hosts, - uint64_t local_host_id, - uint64_t local_host_generation, - struct leader_record *leader_in, - struct leader_record *leader_ret) +static int do_paxos_action(int action, struct task *task, int io_timeout, struct sanlk_resource *res, + int max_hosts, int num_hosts, int write_clear, + uint64_t local_host_id, uint64_t local_host_generation, + struct leader_record *leader_in, struct leader_record *leader_ret) { struct token *token; struct leader_record leader; @@ -119,7 +116,7 @@ static int do_paxos_action(int action, struct task *task, int io_timeout, switch (action) { case ACT_DIRECT_INIT: - rv = paxos_lease_init(task, token, num_hosts, max_hosts); + rv = paxos_lease_init(task, token, num_hosts, max_hosts, write_clear); break; case ACT_ACQUIRE: @@ -170,10 +167,9 @@ int direct_acquire(struct task *task, int io_timeout, struct leader_record *leader_ret) { return do_paxos_action(ACT_ACQUIRE, task, io_timeout, res, - -1, num_hosts, + -1, num_hosts, 0, local_host_id, local_host_generation, - NULL, - leader_ret); + NULL, leader_ret); } int direct_release(struct task *task, int io_timeout, @@ -181,10 +177,9 @@ int direct_release(struct task *task, int io_timeout, struct leader_record *leader_ret) { return do_paxos_action(ACT_RELEASE, task, io_timeout, res, - -1, -1, + -1, -1, 0, 0, 0, - NULL, - leader_ret); + NULL, leader_ret); } static int do_delta_action(int action, @@ -340,7 +335,7 @@ int direct_write_lockspace(struct task *task, struct sanlk_lockspace *ls, } int direct_write_resource(struct task *task, struct sanlk_resource *res, - int max_hosts, int num_hosts) + int max_hosts, int num_hosts, int write_clear) { if (!res) return -1; @@ -352,7 +347,9 @@ int direct_write_resource(struct task *task, struct sanlk_resource *res, return -ENODEV; return do_paxos_action(ACT_DIRECT_INIT, task, 0, res, - max_hosts, num_hosts, 0, 0, NULL, NULL); + max_hosts, num_hosts, write_clear, + 0, 0, + NULL, NULL); } int direct_read_leader(struct task *task, @@ -368,7 +365,9 @@ int direct_read_leader(struct task *task, else if (res) rv = do_paxos_action(ACT_READ_LEADER, task, io_timeout, res, - -1, -1, 0, 0, NULL, leader_ret); + -1, -1, 0, + 0, 0, + NULL, leader_ret); return rv; } @@ -385,7 +384,9 @@ int direct_write_leader(struct task *task, } else if (res) { rv = do_paxos_action(ACT_WRITE_LEADER, task, io_timeout, res, - -1, -1, 0, 0, leader, NULL); + -1, -1, 0, + 0, 0, + leader, NULL); } return rv; diff --git a/src/direct.h b/src/direct.h index af2c4d1..29d61a1 100644 --- a/src/direct.h +++ b/src/direct.h @@ -38,7 +38,7 @@ int direct_write_lockspace(struct task *task, struct sanlk_lockspace *ls, int max_hosts, uint32_t io_timeout); int direct_write_resource(struct task *task, struct sanlk_resource *res, - int max_hosts, int num_hosts); + int max_hosts, int num_hosts, int write_clear); int direct_read_leader(struct task *task, int io_timeout, struct sanlk_lockspace *ls, diff --git a/src/direct_lib.c b/src/direct_lib.c index dc1cb7e..a7f1967 100644 --- a/src/direct_lib.c +++ b/src/direct_lib.c @@ -17,6 +17,7 @@ #define EXTERN #include "sanlock_internal.h" #include "sanlock_direct.h" +#include "sanlock_admin.h" #include "diskio.h" #include "direct.h" #include "task.h" @@ -101,14 +102,15 @@ int sanlock_direct_write_lockspace(struct sanlk_lockspace *ls, int max_hosts, int sanlock_direct_write_resource(struct sanlk_resource *res, int max_hosts, int num_hosts, - uint32_t flags GNUC_UNUSED) + uint32_t flags) { struct task task; int rv; setup_task_lib(&task, 1); - rv = direct_write_resource(&task, res, max_hosts, num_hosts); + rv = direct_write_resource(&task, res, max_hosts, num_hosts, + (flags & SANLK_WRITE_CLEAR) ? 1 : 0); close_task_aio(&task); @@ -127,7 +129,7 @@ int sanlock_direct_init(struct sanlk_lockspace *ls, if (ls) rv = direct_write_lockspace(&task, ls, max_hosts, 0); else - rv = direct_write_resource(&task, res, max_hosts, num_hosts); + rv = direct_write_resource(&task, res, max_hosts, num_hosts, 0); close_task_aio(&task); diff --git a/src/leader.h b/src/leader.h index 16a52f3..b95866a 100644 --- a/src/leader.h +++ b/src/leader.h @@ -16,8 +16,9 @@ #define NAME_ID_SIZE 48 #define PAXOS_DISK_MAGIC 0x06152010 +#define PAXOS_DISK_CLEAR 0x11282016 #define PAXOS_DISK_VERSION_MAJOR 0x00060000 -#define PAXOS_DISK_VERSION_MINOR 0x00000001 +#define PAXOS_DISK_VERSION_MINOR 0x00000002 #define DELTA_DISK_MAGIC 0x12212010 #define DELTA_DISK_VERSION_MAJOR 0x00030000 diff --git a/src/main.c b/src/main.c index b68720f..7e905a9 100644 --- a/src/main.c +++ b/src/main.c @@ -1835,7 +1835,7 @@ static void print_usage(void) printf("sanlock client set_config -s LOCKSPACE [-u 0|1] [-O 0|1]\n"); printf("sanlock client log_dump\n"); printf("sanlock client shutdown [-f 0|1] [-w 0|1]\n"); - printf("sanlock client init -s LOCKSPACE | -r RESOURCE\n"); + printf("sanlock client init -s LOCKSPACE | -r RESOURCE [-z 0|1]\n"); printf("sanlock client read -s LOCKSPACE | -r RESOURCE\n"); printf("sanlock client align -s LOCKSPACE\n"); printf("sanlock client add_lockspace -s LOCKSPACE\n"); @@ -2161,6 +2161,9 @@ static int read_command_line(int argc, char *argv[]) com.used_set = 1; com.used = atoi(optionarg); break; + case 'z': + com.clear_arg = 1; + break; case 'c': begin_command = 1; @@ -2761,7 +2764,8 @@ static int do_client(void) else rv = sanlock_write_resource(com.res_args[0], com.max_hosts, - com.num_hosts, 0); + com.num_hosts, + com.clear_arg ? SANLK_WRITE_CLEAR : 0); log_tool("init done %d", rv); break; @@ -3047,7 +3051,7 @@ static int do_direct_init(void) } rv = direct_write_resource(&main_task, com.res_args[0], - com.max_hosts, com.num_hosts); + com.max_hosts, com.num_hosts, com.clear_arg); } log_tool("init done %d", rv); diff --git a/src/paxos_lease.c b/src/paxos_lease.c index ecd4597..3666e21 100644 --- a/src/paxos_lease.c +++ b/src/paxos_lease.c @@ -817,6 +817,9 @@ static int verify_leader(struct token *token, struct leader_record leader_rr; int result, rv; + if (lr->magic == PAXOS_DISK_CLEAR) + return SANLK_LEADER_MAGIC; + if (lr->magic != PAXOS_DISK_MAGIC) { log_errot(token, "verify_leader wrong magic %x %s", lr->magic, disk->path); @@ -2023,7 +2026,7 @@ int paxos_lease_release(struct task *task, int paxos_lease_init(struct task *task, struct token *token, - int num_hosts, int max_hosts) + int num_hosts, int max_hosts, int write_clear) { char *iobuf, **p_iobuf; struct leader_record leader; @@ -2071,12 +2074,19 @@ int paxos_lease_init(struct task *task, memset(iobuf, 0, iobuf_len); memset(&leader, 0, sizeof(leader)); - leader.magic = PAXOS_DISK_MAGIC; + + if (write_clear) { + leader.magic = PAXOS_DISK_CLEAR; + leader.write_timestamp = monotime(); + } else { + leader.magic = PAXOS_DISK_MAGIC; + } + + leader.timestamp = LEASE_FREE; leader.version = PAXOS_DISK_VERSION_MAJOR | PAXOS_DISK_VERSION_MINOR; leader.sector_size = sector_size; leader.num_hosts = num_hosts; leader.max_hosts = max_hosts; - leader.timestamp = LEASE_FREE; strncpy(leader.space_name, token->r.lockspace_name, NAME_ID_SIZE); strncpy(leader.resource_name, token->r.name, NAME_ID_SIZE); leader.checksum = 0; /* set after leader_record_out */ diff --git a/src/paxos_lease.h b/src/paxos_lease.h index d66a210..ec015dd 100644 --- a/src/paxos_lease.h +++ b/src/paxos_lease.h @@ -36,7 +36,7 @@ int paxos_lease_release(struct task *task, int paxos_lease_init(struct task *task, struct token *token, - int num_hosts, int max_hosts); + int num_hosts, int max_hosts, int write_clear); int paxos_lease_request_read(struct task *task, struct token *token, struct request_record *rr); diff --git a/src/sanlock.8 b/src/sanlock.8 index dad85a8..c62edaa 100644 --- a/src/sanlock.8 +++ b/src/sanlock.8 @@ -724,7 +724,8 @@ options require 1MB of space. The host_id in the LOCKSPACE string is not relevant to initialization, so the value is ignored. (The default of 2000 host_ids can be changed for special cases using the -n num_hosts and -m max_hosts options.) With -s, the -o option specifies the io timeout to be -written in the host_id leases. +written in the host_id leases. With -r, the -z 1 option invalidates the +resource lease on disk so it cannot be used until reinitialized normally. .BR "sanlock direct read_leader -s" " LOCKSPACE" .br diff --git a/src/sanlock_admin.h b/src/sanlock_admin.h index eb83390..d017fed 100644 --- a/src/sanlock_admin.h +++ b/src/sanlock_admin.h @@ -20,6 +20,9 @@ /* inq flags */ #define SANLK_INQ_WAIT 0x00000001 +/* write flags */ +#define SANLK_WRITE_CLEAR 0x00000001 /* subsequent read will return error */ + /* sanlk_lockspace.flags returned by get */ #define SANLK_LSF_ADD 0x00000001 #define SANLK_LSF_REM 0x00000002 @@ -219,6 +222,9 @@ int sanlock_read_lockspace(struct sanlk_lockspace *ls, * * use max_hosts = 0 for default value * use num_hosts = 0 for default value + * + * Set flag SANLK_WRITE_CLEAR to cause a subsequent read_resource + * to return an error. */ int sanlock_write_resource(struct sanlk_resource *res, diff --git a/src/sanlock_internal.h b/src/sanlock_internal.h index 1e4e7e1..472380f 100644 --- a/src/sanlock_internal.h +++ b/src/sanlock_internal.h @@ -318,6 +318,7 @@ struct command_line { int used_set; int used; int all; + int clear_arg; char *uname; /* -U */ int uid; /* -U */ char *gname; /* -G */