diff --git a/daemons/lvmlockd/lvmlockd-client.h b/daemons/lvmlockd/lvmlockd-client.h index 187c07f03..b1bbabd4a 100644 --- a/daemons/lvmlockd/lvmlockd-client.h +++ b/daemons/lvmlockd/lvmlockd-client.h @@ -54,5 +54,8 @@ static inline void lvmlockd_close(daemon_handle h) #define EREMOVED 219 #define EDEVOPEN 220 /* sanlock failed to open lvmlock LV */ #define ELMERR 221 +#define EORPHAN 222 +#define EADOPT_NONE 223 +#define EADOPT_RETRY 224 #endif /* _LVM_LVMLOCKD_CLIENT_H */ diff --git a/daemons/lvmlockd/lvmlockd-core.c b/daemons/lvmlockd/lvmlockd-core.c index 7ede0c14b..e246434a0 100644 --- a/daemons/lvmlockd/lvmlockd-core.c +++ b/daemons/lvmlockd/lvmlockd-core.c @@ -1062,16 +1062,16 @@ static int lm_prepare_lockspace(struct lockspace *ls, struct action *act) return rv; } -static int lm_add_lockspace(struct lockspace *ls, struct action *act, int adopt) +static int lm_add_lockspace(struct lockspace *ls, struct action *act, int adopt_only, int adopt_ok) { int rv; if (ls->lm_type == LD_LM_DLM) - rv = lm_add_lockspace_dlm(ls, adopt); + rv = lm_add_lockspace_dlm(ls, adopt_only, adopt_ok); else if (ls->lm_type == LD_LM_SANLOCK) - rv = lm_add_lockspace_sanlock(ls, adopt); + rv = lm_add_lockspace_sanlock(ls, adopt_only, adopt_ok); else if (ls->lm_type == LD_LM_IDM) - rv = lm_add_lockspace_idm(ls, adopt); + rv = lm_add_lockspace_idm(ls, adopt_only, adopt_ok); else return -1; @@ -1099,17 +1099,17 @@ static int lm_rem_lockspace(struct lockspace *ls, struct action *act, int free_v } static int lm_lock(struct lockspace *ls, struct resource *r, int mode, struct action *act, - struct val_blk *vb_out, int *retry, int adopt) + struct val_blk *vb_out, int *retry, int adopt_only, int adopt_ok) { int rv; if (ls->lm_type == LD_LM_DLM) - rv = lm_lock_dlm(ls, r, mode, vb_out, adopt); + rv = lm_lock_dlm(ls, r, mode, vb_out, adopt_only, adopt_ok); else if (ls->lm_type == LD_LM_SANLOCK) - rv = lm_lock_sanlock(ls, r, mode, vb_out, retry, adopt); + rv = lm_lock_sanlock(ls, r, mode, vb_out, retry, adopt_only, adopt_ok); else if (ls->lm_type == LD_LM_IDM) rv = lm_lock_idm(ls, r, mode, vb_out, act->lv_uuid, - &act->pvs, adopt); + &act->pvs, adopt_only, adopt_ok); else return -1; @@ -1190,10 +1190,13 @@ static int lm_find_free_lock(struct lockspace *ls, uint64_t *free_offset, int *s /* * While adopting locks, actions originate from the adopt_locks() - * function, not from a client. So, these actions (flagged ADOPT), + * function, not from a client. So, these actions (flagged ADOPT_ONLY), * should be passed back to the adopt_locks() function through the * adopt_results list, and not be sent back to a client via the - * client_list/client_thread. + * client_list/client_thread. INTERNAL_CLIENT_ID indicates the + * act was generated internally and not from a client, and + * distinguishes internal adopt request from those received from + * a client. */ static void add_client_result(struct action *act) @@ -1206,7 +1209,7 @@ static void add_client_result(struct action *act) } pthread_mutex_lock(&client_mutex); - if (act->flags & LD_AF_ADOPT) + if ((act->flags & LD_AF_ADOPT_ONLY) && (act->client_id == INTERNAL_CLIENT_ID)) list_add_tail(&act->list, &adopt_results); else list_add_tail(&act->list, &client_results); @@ -1283,7 +1286,9 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act if (r->type == LD_RT_LV && act->lv_args[0]) memcpy(r->lv_args, act->lv_args, MAX_ARGS); - rv = lm_lock(ls, r, act->mode, act, &vb, retry, act->flags & LD_AF_ADOPT); + rv = lm_lock(ls, r, act->mode, act, &vb, retry, + act->flags & LD_AF_ADOPT_ONLY ? 1 : 0, + act->flags & LD_AF_ADOPT ? 1 : 0); if (rv && r->use_vb) log_debug("%s:%s res_lock rv %d read vb %x %x %u", @@ -2486,7 +2491,8 @@ static void *lockspace_thread_main(void *arg_in) int free_vg = 0; int drop_vg = 0; int error = 0; - int adopt_flag = 0; + int adopt_only = 0; + int adopt_ok = 0; int wait_flag = 0; int retry; int rv; @@ -2505,14 +2511,16 @@ static void *lockspace_thread_main(void *arg_in) if (add_act->flags & LD_AF_WAIT) wait_flag = 1; + if (add_act->flags & LD_AF_ADOPT_ONLY) + adopt_only = 1; if (add_act->flags & LD_AF_ADOPT) - adopt_flag = 1; + adopt_ok = 1; } } pthread_mutex_unlock(&ls->mutex); - log_debug("S %s lm_add_lockspace %s wait %d adopt %d", - ls->name, lm_str(ls->lm_type), wait_flag, adopt_flag); + log_debug("S %s lm_add_lockspace %s wait %d adopt_only %d adopt_ok %d", + ls->name, lm_str(ls->lm_type), wait_flag, adopt_only, adopt_ok); /* * The prepare step does not wait for anything and is quick; @@ -2531,7 +2539,7 @@ static void *lockspace_thread_main(void *arg_in) * The actual lockspace join can take a while. */ if (!error) { - error = lm_add_lockspace(ls, add_act, adopt_flag); + error = lm_add_lockspace(ls, add_act, adopt_only, adopt_ok); log_debug("S %s lm_add_lockspace done %d", ls->name, error); @@ -4505,6 +4513,12 @@ static uint32_t str_to_opts(const char *str) flags |= LD_AF_ENABLE; if (strstr(str, "disable")) flags |= LD_AF_DISABLE; + + /* FIXME: parse the flag values properly */ + if (strstr(str, "adopt_only")) + flags |= LD_AF_ADOPT_ONLY; + else if (strstr(str, "adopt")) + flags |= LD_AF_ADOPT; out: return flags; } @@ -5755,7 +5769,7 @@ static void adopt_locks(void) act->op = LD_OP_LOCK; act->rt = LD_RT_LV; act->mode = r->adopt_mode; - act->flags = (LD_AF_ADOPT | LD_AF_PERSISTENT); + act->flags = (LD_AF_ADOPT_ONLY | LD_AF_PERSISTENT); act->client_id = INTERNAL_CLIENT_ID; act->lm_type = ls->lm_type; dm_strncpy(act->vg_name, ls->vg_name, sizeof(act->vg_name)); @@ -5783,7 +5797,7 @@ static void adopt_locks(void) act->op = LD_OP_LOCK; act->rt = LD_RT_VG; act->mode = LD_LK_SH; - act->flags = LD_AF_ADOPT; + act->flags = LD_AF_ADOPT_ONLY; act->client_id = INTERNAL_CLIENT_ID; act->lm_type = ls->lm_type; dm_strncpy(act->vg_name, ls->vg_name, sizeof(act->vg_name)); @@ -5809,7 +5823,7 @@ static void adopt_locks(void) act->op = LD_OP_LOCK; act->rt = LD_RT_GL; act->mode = LD_LK_SH; - act->flags = LD_AF_ADOPT; + act->flags = LD_AF_ADOPT_ONLY; act->client_id = INTERNAL_CLIENT_ID; act->lm_type = (gl_use_sanlock ? LD_LM_SANLOCK : LD_LM_DLM); @@ -5848,7 +5862,7 @@ static void adopt_locks(void) * lock adopt results */ - if (act->result == -EUCLEAN) { + if (act->result == -EADOPT_RETRY) { /* * Adopt failed because the orphan has a different mode * than initially requested. Repeat the lock-adopt operation @@ -5887,7 +5901,7 @@ static void adopt_locks(void) free_action(act); } - } else if (act->result == -ENOENT) { + } else if (act->result == -EADOPT_NONE) { /* * No orphan lock exists. This is common for GL/VG locks * because they may not have been held when lvmlockd exited. diff --git a/daemons/lvmlockd/lvmlockd-dlm.c b/daemons/lvmlockd/lvmlockd-dlm.c index a95dd55db..7ee13cf51 100644 --- a/daemons/lvmlockd/lvmlockd-dlm.c +++ b/daemons/lvmlockd/lvmlockd-dlm.c @@ -305,20 +305,27 @@ fail: return rv; } -int lm_add_lockspace_dlm(struct lockspace *ls, int adopt) +int lm_add_lockspace_dlm(struct lockspace *ls, int adopt_only, int adopt_ok) { struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data; if (daemon_test) return 0; - if (adopt) + if (adopt_only || adopt_ok) { lmd->dh = dlm_open_lockspace(ls->name); - else + if (!lmd->dh && adopt_ok) + lmd->dh = dlm_new_lockspace(ls->name, 0600, DLM_LSFL_NEWEXCL); + if (!lmd->dh) + log_error("add_lockspace_dlm adopt_only %d adopt_ok %d %s error", + adopt_only, adopt_ok, ls->name); + } else { lmd->dh = dlm_new_lockspace(ls->name, 0600, DLM_LSFL_NEWEXCL); + if (!lmd->dh) + log_error("add_lockspace_dlm %s error", ls->name); + } if (!lmd->dh) { - log_error("add_lockspace_dlm %s adopt %d error", ls->name, adopt); free(lmd); ls->lm_data = NULL; return -1; @@ -486,13 +493,13 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode, if (rv == -1 && (errno == EAGAIN)) { log_debug("%s:%s adopt_dlm adopt mode %d try other mode", ls->name, r->name, ld_mode); - rv = -EUCLEAN; + rv = -EADOPT_RETRY; goto fail; } if (rv == -1 && (errno == ENOENT)) { log_debug("%s:%s adopt_dlm adopt mode %d no lock", ls->name, r->name, ld_mode); - rv = -ENOENT; + rv = -EADOPT_NONE; goto fail; } if (rv < 0) { @@ -526,7 +533,7 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode, */ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode, - struct val_blk *vb_out, int adopt) + struct val_blk *vb_out, int adopt_only, int adopt_ok) { struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data; struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data; @@ -536,7 +543,13 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode, int mode; int rv; - if (adopt) { + if (adopt_ok) { + log_debug("%s:%s lock_dlm adopt_ok not supported", ls->name, r->name); + return -1; + } + + if (adopt_only) { + log_debug("%s:%s lock_dlm adopt_only", ls->name, r->name); /* When adopting, we don't follow the normal method of acquiring a NL lock then converting it to the desired mode. */ diff --git a/daemons/lvmlockd/lvmlockd-idm.c b/daemons/lvmlockd/lvmlockd-idm.c index e13fb62ae..1a5818a2a 100644 --- a/daemons/lvmlockd/lvmlockd-idm.c +++ b/daemons/lvmlockd/lvmlockd-idm.c @@ -391,7 +391,7 @@ int lm_prepare_lockspace_idm(struct lockspace *ls) return 0; } -int lm_add_lockspace_idm(struct lockspace *ls, int adopt) +int lm_add_lockspace_idm(struct lockspace *ls, int adopt_only, int adopt_ok) { char killpath[IDM_FAILURE_PATH_LEN]; char killargs[IDM_FAILURE_ARGS_LEN]; @@ -530,7 +530,7 @@ static int to_idm_mode(int ld_mode) int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode, struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs, - int adopt) + int adopt_only, int adopt_ok) { struct lm_idm *lmi = (struct lm_idm *)ls->lm_data; struct rd_idm *rdi = (struct rd_idm *)r->lm_data; diff --git a/daemons/lvmlockd/lvmlockd-internal.h b/daemons/lvmlockd/lvmlockd-internal.h index 3aede3299..6034349b2 100644 --- a/daemons/lvmlockd/lvmlockd-internal.h +++ b/daemons/lvmlockd/lvmlockd-internal.h @@ -107,11 +107,12 @@ struct client { #define LD_AF_SEARCH_LS 0x00000200 #define LD_AF_WAIT_STARTING 0x00001000 #define LD_AF_DUP_GL_LS 0x00002000 -#define LD_AF_ADOPT 0x00010000 +#define LD_AF_ADOPT 0x00010000 /* adopt ok but not required */ #define LD_AF_WARN_GL_REMOVED 0x00020000 #define LD_AF_LV_LOCK 0x00040000 #define LD_AF_LV_UNLOCK 0x00080000 #define LD_AF_SH_EXISTS 0x00100000 +#define LD_AF_ADOPT_ONLY 0x00200000 /* adopt orphan or fail */ /* * Number of times to repeat a lock request after @@ -393,11 +394,11 @@ static inline const char *mode_str(int x) int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args); int lm_prepare_lockspace_dlm(struct lockspace *ls); -int lm_add_lockspace_dlm(struct lockspace *ls, int adopt); +int lm_add_lockspace_dlm(struct lockspace *ls, int adopt_only, int adopt_ok); int lm_purge_locks_dlm(struct lockspace *ls); int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg); int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode, - struct val_blk *vb_out, int adopt); + struct val_blk *vb_out, int adopt_only, int adopt_ok); int lm_convert_dlm(struct lockspace *ls, struct resource *r, int ld_mode, uint32_t r_version); int lm_unlock_dlm(struct lockspace *ls, struct resource *r, @@ -427,7 +428,7 @@ static inline int lm_prepare_lockspace_dlm(struct lockspace *ls) return -1; } -static inline int lm_add_lockspace_dlm(struct lockspace *ls, int adopt) +static inline int lm_add_lockspace_dlm(struct lockspace *ls, int adopt_only, int adopt_ok) { return -1; } @@ -443,7 +444,7 @@ static inline int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg) } static inline int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode, - struct val_blk *vb_out, int adopt) + struct val_blk *vb_out, int adopt_only, int adopt_ok) { return -1; } @@ -509,10 +510,11 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_arg int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r); int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args); int lm_prepare_lockspace_sanlock(struct lockspace *ls); -int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt); +int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok); int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg); int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode, - struct val_blk *vb_out, int *retry, int adopt); + struct val_blk *vb_out, int *retry, + int adopt_only, int adopt_ok); int lm_convert_sanlock(struct lockspace *ls, struct resource *r, int ld_mode, uint32_t r_version); int lm_unlock_sanlock(struct lockspace *ls, struct resource *r, @@ -559,7 +561,7 @@ static inline int lm_prepare_lockspace_sanlock(struct lockspace *ls) return -1; } -static inline int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt) +static inline int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok) { return -1; } @@ -570,7 +572,8 @@ static inline int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg) } static inline int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode, - struct val_blk *vb_out, int *retry, int adopt) + struct val_blk *vb_out, int *retry, + int adopt_only, int adopt_ok) { return -1; } @@ -644,11 +647,11 @@ static inline int lm_support_sanlock(void) int lm_data_size_idm(void); int lm_init_vg_idm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args); int lm_prepare_lockspace_idm(struct lockspace *ls); -int lm_add_lockspace_idm(struct lockspace *ls, int adopt); +int lm_add_lockspace_idm(struct lockspace *ls, int adopt_only, int adopt_ok); int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg); int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode, struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs, - int adopt); + int adopt_only, int adopt_ok); int lm_convert_idm(struct lockspace *ls, struct resource *r, int ld_mode, uint32_t r_version); int lm_unlock_idm(struct lockspace *ls, struct resource *r, @@ -681,7 +684,7 @@ static inline int lm_prepare_lockspace_idm(struct lockspace *ls) return -1; } -static inline int lm_add_lockspace_idm(struct lockspace *ls, int adopt) +static inline int lm_add_lockspace_idm(struct lockspace *ls, int adopt_only, int adopt_ok) { return -1; } @@ -693,7 +696,7 @@ static inline int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg) static inline int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode, struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs, - int adopt) + int adopt_only, int adopt_ok) { return -1; } diff --git a/daemons/lvmlockd/lvmlockd-sanlock.c b/daemons/lvmlockd/lvmlockd-sanlock.c index a8aa15571..35dabc472 100644 --- a/daemons/lvmlockd/lvmlockd-sanlock.c +++ b/daemons/lvmlockd/lvmlockd-sanlock.c @@ -1501,7 +1501,7 @@ fail: return ret; } -int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt) +int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok) { struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data; int rv; @@ -1512,11 +1512,15 @@ int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt) } rv = sanlock_add_lockspace_timeout(&lms->ss, 0, sanlock_io_timeout); - if (rv == -EEXIST && adopt) { + if (rv == -EEXIST && (adopt_ok || adopt_only)) { /* We could alternatively just skip the sanlock call for adopt. */ log_debug("S %s add_lockspace_san adopt found ls", ls->name); goto out; } + if ((rv != -EEXIST) && adopt_only) { + log_error("S %s add_lockspace_san add_lockspace adopt_only not found", ls->name); + goto fail; + } if (rv < 0) { /* retry for some errors? */ log_error("S %s add_lockspace_san add_lockspace error %d", ls->name, rv); @@ -1638,7 +1642,7 @@ int lm_rem_resource_sanlock(struct lockspace *ls, struct resource *r) } int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode, - struct val_blk *vb_out, int *retry, int adopt) + struct val_blk *vb_out, int *retry, int adopt_only, int adopt_ok) { struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data; struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data; @@ -1732,8 +1736,10 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode, if (rds->vb) flags |= SANLK_ACQUIRE_LVB; - if (adopt) + if (adopt_only) flags |= SANLK_ACQUIRE_ORPHAN_ONLY; + if (adopt_ok) + flags |= SANLK_ACQUIRE_ORPHAN; /* * Don't block waiting for a failed lease to expire since it causes @@ -1779,7 +1785,7 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode, return -EMSGSIZE; } - if (adopt && (rv == -EUCLEAN)) { + if ((adopt_only || adopt_ok) && (rv == -EUCLEAN)) { /* * The orphan lock exists but in a different mode than we asked * for, so the caller should try again with the other mode. @@ -1787,17 +1793,17 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode, log_debug("%s:%s lock_san adopt mode %d try other mode", ls->name, r->name, ld_mode); *retry = 0; - return -EUCLEAN; + return -EADOPT_RETRY; } - if (adopt && (rv == -ENOENT)) { + if (adopt_only && (rv == -ENOENT)) { /* * No orphan lock exists. */ - log_debug("%s:%s lock_san adopt mode %d no orphan found", + log_debug("%s:%s lock_san adopt_only mode %d no orphan found", ls->name, r->name, ld_mode); *retry = 0; - return -ENOENT; + return -EADOPT_NONE; } if (rv == SANLK_ACQUIRE_IDLIVE || rv == SANLK_ACQUIRE_OWNED || rv == SANLK_ACQUIRE_OTHER) { @@ -1880,7 +1886,7 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode, /* sanlock gets i/o errors trying to read/write the leases. */ if (rv == -EIO) - rv = -ELOCKIO; + return -ELOCKIO; /* * The sanlock lockspace can disappear if the lease storage fails, @@ -1889,7 +1895,11 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode, * stop and free the lockspace. */ if (rv == -ENOSPC) - rv = -ELOCKIO; + return -ELOCKIO; + + /* The request conflicted with an orphan lock. */ + if (rv == -EUCLEAN) + return -EORPHAN; /* * generic error number for sanlock errors that we are not diff --git a/lib/locking/lvmlockd.c b/lib/locking/lvmlockd.c index 4b5f0278b..75dd9f2ac 100644 --- a/lib/locking/lvmlockd.c +++ b/lib/locking/lvmlockd.c @@ -1315,6 +1315,7 @@ void lockd_free_vg_final(struct cmd_context *cmd, struct volume_group *vg) int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int *exists) { char uuid[64] __attribute__((aligned(8))); + const char *opts = NULL; daemon_reply reply; uint32_t lockd_flags = 0; int host_id = 0; @@ -1336,6 +1337,11 @@ int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int *exists return 0; } + if (cmd->lockopt & LOCKOPT_ADOPTLS) + opts = "adopt_only"; + else if (cmd->lockopt & LOCKOPT_ADOPT) + opts = "adopt"; + log_debug("lockd start VG %s lock_type %s", vg->name, vg->lock_type ? vg->lock_type : "empty"); @@ -1372,7 +1378,7 @@ int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int *exists "vg_uuid = %s", uuid[0] ? uuid : "none", "version = " FMTd64, (int64_t) vg->seqno, "host_id = " FMTd64, (int64_t) host_id, - "opts = %s", "none", + "opts = %s", opts ?: "none", NULL); _lockd_free_pv_list(&lock_pvs); } else { @@ -1385,7 +1391,7 @@ int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int *exists "vg_uuid = %s", uuid[0] ? uuid : "none", "version = " FMTd64, (int64_t) vg->seqno, "host_id = " FMTd64, (int64_t) host_id, - "opts = %s", "none", + "opts = %s", opts ?: "none", NULL); } @@ -1840,6 +1846,11 @@ int lockd_global(struct cmd_context *cmd, const char *def_mode) return 0; } + if (cmd->lockopt & LOCKOPT_ADOPTGL) + opts = "adopt_only"; + else if (cmd->lockopt & LOCKOPT_ADOPT) + opts = "adopt"; + if (!strcmp(mode, "sh") && cmd->lockd_global_ex) return 1; @@ -1912,7 +1923,10 @@ int lockd_global(struct cmd_context *cmd, const char *def_mode) if (result == -ENOLS || result == -ESTARTING || result == -EVGKILLED || - result == -ELOCKIO) { + result == -ELOCKIO || + result == -EORPHAN || + result == -EADOPT_RETRY || + result == -EADOPT_NONE) { /* * If an ex global lock fails, then the command fails. */ @@ -1925,6 +1939,12 @@ int lockd_global(struct cmd_context *cmd, const char *def_mode) log_error("Global lock failed: storage errors for sanlock leases"); else if (result == -EVGKILLED) log_error("Global lock failed: storage failed for sanlock leases"); + else if (result == -EORPHAN) + log_error("Global lock failed: orphan lock needs to be adopted"); + else if (result == -EADOPT_NONE) + log_error("Global lock failed: adopt found no orphan"); + else if (result == -EADOPT_RETRY) + log_error("Global lock failed: adopt found other mode"); else log_error("Global lock failed: error %d", result); @@ -1953,6 +1973,21 @@ int lockd_global(struct cmd_context *cmd, const char *def_mode) goto allow; } + if (result == -EORPHAN) { + log_warn("Skipping global lock: orphan lock needs to be adopted"); + goto allow; + } + + if (result == -EADOPT_NONE) { + log_warn("Skipping global lock: adopt found no orphan"); + goto allow; + } + + if (result == -EADOPT_RETRY) { + log_warn("Skipping global lock: adopt found other mode"); + goto allow; + } + if ((lockd_flags & LD_RF_NO_GL_LS) || (lockd_flags & LD_RF_NO_LOCKSPACES)) { log_debug("Skipping global lock: lockspace not found or started"); goto allow; @@ -2037,6 +2072,7 @@ int lockd_vg(struct cmd_context *cmd, const char *vg_name, const char *def_mode, uint32_t flags, uint32_t *lockd_state) { const char *mode = NULL; + const char *opts = NULL; uint32_t lockd_flags; uint32_t prev_state = *lockd_state; int retries = 0; @@ -2103,6 +2139,11 @@ int lockd_vg(struct cmd_context *cmd, const char *vg_name, const char *def_mode, if (!mode) mode = cmd->lockd_vg_default_sh ? "sh" : "ex"; + if (cmd->lockopt & LOCKOPT_ADOPTVG) + opts = "adopt_only"; + else if (cmd->lockopt & LOCKOPT_ADOPT) + opts = "adopt"; + if (!strcmp(mode, "ex")) *lockd_state |= LDST_EX; @@ -2124,7 +2165,7 @@ int lockd_vg(struct cmd_context *cmd, const char *vg_name, const char *def_mode, log_debug("lockd VG %s mode %s", vg_name, mode); if (!_lockd_request(cmd, "lock_vg", - vg_name, NULL, NULL, NULL, NULL, NULL, mode, NULL, + vg_name, NULL, NULL, NULL, NULL, NULL, mode, opts, NULL, &result, &lockd_flags)) { /* * No result from lvmlockd, it is probably not running. @@ -2237,6 +2278,43 @@ int lockd_vg(struct cmd_context *cmd, const char *vg_name, const char *def_mode, goto out; } } + + if (result == -EORPHAN) { + if (!strcmp(mode, "sh")) { + log_warn("VG %s lock skipped: orphan lock needs to be adopted.", vg_name); + ret = 1; + goto out; + } else { + log_error("VG %s lock failed: orphan lock needs to be adopted.", vg_name); + ret = 0; + goto out; + } + } + + if (result == -EADOPT_NONE) { + if (!strcmp(mode, "sh")) { + log_warn("VG %s lock skipped: adopt found no orphan.", vg_name); + ret = 1; + goto out; + } else { + log_error("VG %s lock failed: adopt found no orphan.", vg_name); + ret = 0; + goto out; + } + } + + if (result == -EADOPT_RETRY) { + if (!strcmp(mode, "sh")) { + log_warn("VG %s lock skipped: adopt found other mode.", vg_name); + ret = 1; + goto out; + } else { + log_error("VG %s lock failed: adopt found other mode.", vg_name); + ret = 0; + goto out; + } + } + /* * No lockspace for the VG was found. It may be a local * VG that lvmlockd doesn't keep track of, or it may be @@ -2420,8 +2498,9 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg, const char *lock_args, const char *def_mode, uint32_t flags) { char lv_uuid[64] __attribute__((aligned(8))); - const char *mode = NULL; + char opt_buf[64] = {}; const char *opts = NULL; + const char *mode = NULL; uint32_t lockd_flags; int refreshed = 0; int result; @@ -2485,8 +2564,15 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg, if (!mode) mode = "ex"; - if (flags & LDLV_PERSISTENT) - opts = "persistent"; + if ((flags & LDLV_PERSISTENT) || + (cmd->lockopt & LOCKOPT_ADOPTLV) || + (cmd->lockopt & LOCKOPT_ADOPT)) { + dm_snprintf(opt_buf, sizeof(opt_buf), "%s%s%s", + (flags & LDLV_PERSISTENT) ? "persistent," : "", + (cmd->lockopt & LOCKOPT_ADOPTLV) ? "adopt_only" : "", + (cmd->lockopt & LOCKOPT_ADOPT) ? "adopt" : ""); + opts = opt_buf; + } retry: log_debug("lockd LV %s/%s mode %s uuid %s", vg->name, lv_name, mode, lv_uuid); @@ -2527,6 +2613,21 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg, return 0; } + if (result == -EORPHAN) { + log_error("LV %s/%s lock failed: orphan lock needs to be adopted.", vg->name, lv_name); + return 0; + } + + if (result == -EADOPT_NONE) { + log_error("LV %s/%s lock failed: adopt found no orphan.", vg->name, lv_name); + return 0; + } + + if (result == -EADOPT_RETRY) { + log_error("LV %s/%s lock failed: adopt found other mode.", vg->name, lv_name); + return 0; + } + if (result == -EEXIST) { /* * This happens if a command like lvchange tries to modify the @@ -3506,6 +3607,16 @@ void lockd_lockopt_get_flags(const char *str, uint32_t *flags) *flags |= LOCKOPT_NOWAIT; else if (!strcmp(argv[i], "autonowait")) *flags |= LOCKOPT_AUTONOWAIT; + else if (!strcmp(argv[i], "adoptls")) + *flags |= LOCKOPT_ADOPTLS; + else if (!strcmp(argv[i], "adoptgl")) + *flags |= LOCKOPT_ADOPTGL; + else if (!strcmp(argv[i], "adoptvg")) + *flags |= LOCKOPT_ADOPTVG; + else if (!strcmp(argv[i], "adoptlv")) + *flags |= LOCKOPT_ADOPTLV; + else if (!strcmp(argv[i], "adopt")) + *flags |= LOCKOPT_ADOPT; else log_warn("Ignoring unknown lockopt value: %s", argv[i]); } diff --git a/lib/locking/lvmlockd.h b/lib/locking/lvmlockd.h index eda6ed015..b2a047cc3 100644 --- a/lib/locking/lvmlockd.h +++ b/lib/locking/lvmlockd.h @@ -49,6 +49,11 @@ #define LOCKOPT_AUTO 0x00000040 #define LOCKOPT_NOWAIT 0x00000080 #define LOCKOPT_AUTONOWAIT 0x00000100 +#define LOCKOPT_ADOPTLS 0x00000200 +#define LOCKOPT_ADOPTGL 0x00000400 +#define LOCKOPT_ADOPTVG 0x00000800 +#define LOCKOPT_ADOPTLV 0x00001000 +#define LOCKOPT_ADOPT 0x00002000 void lockd_lockopt_get_flags(const char *str, uint32_t *flags);