From f32fd1fcb9e1f1ca1bef11ceafbf5471e59bc4ac Mon Sep 17 00:00:00 2001 From: David Teigland Date: Tue, 18 Jun 2024 13:26:09 -0500 Subject: [PATCH] lvmlockd: adopt options Lock adoption is not part of standard command behavior, but can be used for manual recovery or cleanup from unexpected failure cases. Like other lockopt values, they are hidden options for --lockopt. Different lock managers will behave differently. Adopting locks with lvmlockd -A1 is more accurate and automatic. --lockopt adoptls . for vgchange --lockstart . adopt existing ls, or fail if no existing lockspace is found --lockopt adoptgl | adoptvg | adoptlv . for commands using lvmlockd locks . adopt orphan gl/vg/lv lock, or fail the lock request if no orphan lock is found . will fail if orphan lock exists with a different lock mode . command may still continue with a failed shared lock request --lockopt adopt . for lockstart or any command using lvmlockd locks . adopt existing lockspace, or start lockspace if none exists . adopt orphan gl/vg/lv lock, or acquire new lock if no orphan found . will fail if orphan lock exists with a different lock mode . command may still continue with a failed shared lock request . with dlm this option only works for ls --- daemons/lvmlockd/lvmlockd-client.h | 3 + daemons/lvmlockd/lvmlockd-core.c | 58 ++++++++----- daemons/lvmlockd/lvmlockd-dlm.c | 29 +++++-- daemons/lvmlockd/lvmlockd-idm.c | 4 +- daemons/lvmlockd/lvmlockd-internal.h | 29 ++++--- daemons/lvmlockd/lvmlockd-sanlock.c | 32 ++++--- lib/locking/lvmlockd.c | 125 +++++++++++++++++++++++++-- lib/locking/lvmlockd.h | 5 ++ 8 files changed, 222 insertions(+), 63 deletions(-) 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);