1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

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
This commit is contained in:
David Teigland 2024-06-18 13:26:09 -05:00
parent 943e979079
commit f32fd1fcb9
8 changed files with 222 additions and 63 deletions

View File

@ -54,5 +54,8 @@ static inline void lvmlockd_close(daemon_handle h)
#define EREMOVED 219 #define EREMOVED 219
#define EDEVOPEN 220 /* sanlock failed to open lvmlock LV */ #define EDEVOPEN 220 /* sanlock failed to open lvmlock LV */
#define ELMERR 221 #define ELMERR 221
#define EORPHAN 222
#define EADOPT_NONE 223
#define EADOPT_RETRY 224
#endif /* _LVM_LVMLOCKD_CLIENT_H */ #endif /* _LVM_LVMLOCKD_CLIENT_H */

View File

@ -1062,16 +1062,16 @@ static int lm_prepare_lockspace(struct lockspace *ls, struct action *act)
return rv; 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; int rv;
if (ls->lm_type == LD_LM_DLM) 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) 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) 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 else
return -1; 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, 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; int rv;
if (ls->lm_type == LD_LM_DLM) 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) 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) else if (ls->lm_type == LD_LM_IDM)
rv = lm_lock_idm(ls, r, mode, vb_out, act->lv_uuid, rv = lm_lock_idm(ls, r, mode, vb_out, act->lv_uuid,
&act->pvs, adopt); &act->pvs, adopt_only, adopt_ok);
else else
return -1; 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() * 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 * should be passed back to the adopt_locks() function through the
* adopt_results list, and not be sent back to a client via 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) 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); 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); list_add_tail(&act->list, &adopt_results);
else else
list_add_tail(&act->list, &client_results); 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]) if (r->type == LD_RT_LV && act->lv_args[0])
memcpy(r->lv_args, act->lv_args, MAX_ARGS); 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) if (rv && r->use_vb)
log_debug("%s:%s res_lock rv %d read vb %x %x %u", 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 free_vg = 0;
int drop_vg = 0; int drop_vg = 0;
int error = 0; int error = 0;
int adopt_flag = 0; int adopt_only = 0;
int adopt_ok = 0;
int wait_flag = 0; int wait_flag = 0;
int retry; int retry;
int rv; int rv;
@ -2505,14 +2511,16 @@ static void *lockspace_thread_main(void *arg_in)
if (add_act->flags & LD_AF_WAIT) if (add_act->flags & LD_AF_WAIT)
wait_flag = 1; wait_flag = 1;
if (add_act->flags & LD_AF_ADOPT_ONLY)
adopt_only = 1;
if (add_act->flags & LD_AF_ADOPT) if (add_act->flags & LD_AF_ADOPT)
adopt_flag = 1; adopt_ok = 1;
} }
} }
pthread_mutex_unlock(&ls->mutex); pthread_mutex_unlock(&ls->mutex);
log_debug("S %s lm_add_lockspace %s wait %d adopt %d", 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_flag); ls->name, lm_str(ls->lm_type), wait_flag, adopt_only, adopt_ok);
/* /*
* The prepare step does not wait for anything and is quick; * 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. * The actual lockspace join can take a while.
*/ */
if (!error) { 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); 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; flags |= LD_AF_ENABLE;
if (strstr(str, "disable")) if (strstr(str, "disable"))
flags |= LD_AF_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: out:
return flags; return flags;
} }
@ -5755,7 +5769,7 @@ static void adopt_locks(void)
act->op = LD_OP_LOCK; act->op = LD_OP_LOCK;
act->rt = LD_RT_LV; act->rt = LD_RT_LV;
act->mode = r->adopt_mode; 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->client_id = INTERNAL_CLIENT_ID;
act->lm_type = ls->lm_type; act->lm_type = ls->lm_type;
dm_strncpy(act->vg_name, ls->vg_name, sizeof(act->vg_name)); 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->op = LD_OP_LOCK;
act->rt = LD_RT_VG; act->rt = LD_RT_VG;
act->mode = LD_LK_SH; act->mode = LD_LK_SH;
act->flags = LD_AF_ADOPT; act->flags = LD_AF_ADOPT_ONLY;
act->client_id = INTERNAL_CLIENT_ID; act->client_id = INTERNAL_CLIENT_ID;
act->lm_type = ls->lm_type; act->lm_type = ls->lm_type;
dm_strncpy(act->vg_name, ls->vg_name, sizeof(act->vg_name)); 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->op = LD_OP_LOCK;
act->rt = LD_RT_GL; act->rt = LD_RT_GL;
act->mode = LD_LK_SH; act->mode = LD_LK_SH;
act->flags = LD_AF_ADOPT; act->flags = LD_AF_ADOPT_ONLY;
act->client_id = INTERNAL_CLIENT_ID; act->client_id = INTERNAL_CLIENT_ID;
act->lm_type = (gl_use_sanlock ? LD_LM_SANLOCK : LD_LM_DLM); act->lm_type = (gl_use_sanlock ? LD_LM_SANLOCK : LD_LM_DLM);
@ -5848,7 +5862,7 @@ static void adopt_locks(void)
* lock adopt results * lock adopt results
*/ */
if (act->result == -EUCLEAN) { if (act->result == -EADOPT_RETRY) {
/* /*
* Adopt failed because the orphan has a different mode * Adopt failed because the orphan has a different mode
* than initially requested. Repeat the lock-adopt operation * than initially requested. Repeat the lock-adopt operation
@ -5887,7 +5901,7 @@ static void adopt_locks(void)
free_action(act); 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 * No orphan lock exists. This is common for GL/VG locks
* because they may not have been held when lvmlockd exited. * because they may not have been held when lvmlockd exited.

View File

@ -305,20 +305,27 @@ fail:
return rv; 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; struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
if (daemon_test) if (daemon_test)
return 0; return 0;
if (adopt) if (adopt_only || adopt_ok) {
lmd->dh = dlm_open_lockspace(ls->name); 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); 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) { if (!lmd->dh) {
log_error("add_lockspace_dlm %s adopt %d error", ls->name, adopt);
free(lmd); free(lmd);
ls->lm_data = NULL; ls->lm_data = NULL;
return -1; 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)) { if (rv == -1 && (errno == EAGAIN)) {
log_debug("%s:%s adopt_dlm adopt mode %d try other mode", log_debug("%s:%s adopt_dlm adopt mode %d try other mode",
ls->name, r->name, ld_mode); ls->name, r->name, ld_mode);
rv = -EUCLEAN; rv = -EADOPT_RETRY;
goto fail; goto fail;
} }
if (rv == -1 && (errno == ENOENT)) { if (rv == -1 && (errno == ENOENT)) {
log_debug("%s:%s adopt_dlm adopt mode %d no lock", log_debug("%s:%s adopt_dlm adopt mode %d no lock",
ls->name, r->name, ld_mode); ls->name, r->name, ld_mode);
rv = -ENOENT; rv = -EADOPT_NONE;
goto fail; goto fail;
} }
if (rv < 0) { 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, 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 lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
struct rd_dlm *rdd = (struct rd_dlm *)r->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 mode;
int rv; 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 /* When adopting, we don't follow the normal method
of acquiring a NL lock then converting it to the of acquiring a NL lock then converting it to the
desired mode. */ desired mode. */

View File

@ -391,7 +391,7 @@ int lm_prepare_lockspace_idm(struct lockspace *ls)
return 0; 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 killpath[IDM_FAILURE_PATH_LEN];
char killargs[IDM_FAILURE_ARGS_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, int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs, 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 lm_idm *lmi = (struct lm_idm *)ls->lm_data;
struct rd_idm *rdi = (struct rd_idm *)r->lm_data; struct rd_idm *rdi = (struct rd_idm *)r->lm_data;

View File

@ -107,11 +107,12 @@ struct client {
#define LD_AF_SEARCH_LS 0x00000200 #define LD_AF_SEARCH_LS 0x00000200
#define LD_AF_WAIT_STARTING 0x00001000 #define LD_AF_WAIT_STARTING 0x00001000
#define LD_AF_DUP_GL_LS 0x00002000 #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_WARN_GL_REMOVED 0x00020000
#define LD_AF_LV_LOCK 0x00040000 #define LD_AF_LV_LOCK 0x00040000
#define LD_AF_LV_UNLOCK 0x00080000 #define LD_AF_LV_UNLOCK 0x00080000
#define LD_AF_SH_EXISTS 0x00100000 #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 * 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_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_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_purge_locks_dlm(struct lockspace *ls);
int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg); int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg);
int lm_lock_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);
int lm_convert_dlm(struct lockspace *ls, struct resource *r, int lm_convert_dlm(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version); int ld_mode, uint32_t r_version);
int lm_unlock_dlm(struct lockspace *ls, struct resource *r, 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; 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; 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, 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; 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_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_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_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_rem_lockspace_sanlock(struct lockspace *ls, int free_vg);
int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode, 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 lm_convert_sanlock(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version); int ld_mode, uint32_t r_version);
int lm_unlock_sanlock(struct lockspace *ls, struct resource *r, 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; 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; 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, 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; return -1;
} }
@ -644,11 +647,11 @@ static inline int lm_support_sanlock(void)
int lm_data_size_idm(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_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_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_rem_lockspace_idm(struct lockspace *ls, int free_vg);
int lm_lock_idm(struct lockspace *ls, struct resource *r, 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, 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 lm_convert_idm(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version); int ld_mode, uint32_t r_version);
int lm_unlock_idm(struct lockspace *ls, struct resource *r, 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; 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; 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, 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, struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs,
int adopt) int adopt_only, int adopt_ok)
{ {
return -1; return -1;
} }

View File

@ -1501,7 +1501,7 @@ fail:
return ret; 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; struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
int rv; 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); 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. */ /* We could alternatively just skip the sanlock call for adopt. */
log_debug("S %s add_lockspace_san adopt found ls", ls->name); log_debug("S %s add_lockspace_san adopt found ls", ls->name);
goto out; 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) { if (rv < 0) {
/* retry for some errors? */ /* retry for some errors? */
log_error("S %s add_lockspace_san add_lockspace error %d", ls->name, rv); 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, 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 lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
struct rd_sanlock *rds = (struct rd_sanlock *)r->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) if (rds->vb)
flags |= SANLK_ACQUIRE_LVB; flags |= SANLK_ACQUIRE_LVB;
if (adopt) if (adopt_only)
flags |= SANLK_ACQUIRE_ORPHAN_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 * 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; 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 * The orphan lock exists but in a different mode than we asked
* for, so the caller should try again with the other mode. * 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", log_debug("%s:%s lock_san adopt mode %d try other mode",
ls->name, r->name, ld_mode); ls->name, r->name, ld_mode);
*retry = 0; *retry = 0;
return -EUCLEAN; return -EADOPT_RETRY;
} }
if (adopt && (rv == -ENOENT)) { if (adopt_only && (rv == -ENOENT)) {
/* /*
* No orphan lock exists. * 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); ls->name, r->name, ld_mode);
*retry = 0; *retry = 0;
return -ENOENT; return -EADOPT_NONE;
} }
if (rv == SANLK_ACQUIRE_IDLIVE || rv == SANLK_ACQUIRE_OWNED || rv == SANLK_ACQUIRE_OTHER) { 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. */ /* sanlock gets i/o errors trying to read/write the leases. */
if (rv == -EIO) if (rv == -EIO)
rv = -ELOCKIO; return -ELOCKIO;
/* /*
* The sanlock lockspace can disappear if the lease storage fails, * 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. * stop and free the lockspace.
*/ */
if (rv == -ENOSPC) 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 * generic error number for sanlock errors that we are not

View File

@ -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) int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int *exists)
{ {
char uuid[64] __attribute__((aligned(8))); char uuid[64] __attribute__((aligned(8)));
const char *opts = NULL;
daemon_reply reply; daemon_reply reply;
uint32_t lockd_flags = 0; uint32_t lockd_flags = 0;
int host_id = 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; 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", log_debug("lockd start VG %s lock_type %s",
vg->name, vg->lock_type ? vg->lock_type : "empty"); 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", "vg_uuid = %s", uuid[0] ? uuid : "none",
"version = " FMTd64, (int64_t) vg->seqno, "version = " FMTd64, (int64_t) vg->seqno,
"host_id = " FMTd64, (int64_t) host_id, "host_id = " FMTd64, (int64_t) host_id,
"opts = %s", "none", "opts = %s", opts ?: "none",
NULL); NULL);
_lockd_free_pv_list(&lock_pvs); _lockd_free_pv_list(&lock_pvs);
} else { } 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", "vg_uuid = %s", uuid[0] ? uuid : "none",
"version = " FMTd64, (int64_t) vg->seqno, "version = " FMTd64, (int64_t) vg->seqno,
"host_id = " FMTd64, (int64_t) host_id, "host_id = " FMTd64, (int64_t) host_id,
"opts = %s", "none", "opts = %s", opts ?: "none",
NULL); NULL);
} }
@ -1840,6 +1846,11 @@ int lockd_global(struct cmd_context *cmd, const char *def_mode)
return 0; 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) if (!strcmp(mode, "sh") && cmd->lockd_global_ex)
return 1; return 1;
@ -1912,7 +1923,10 @@ int lockd_global(struct cmd_context *cmd, const char *def_mode)
if (result == -ENOLS || if (result == -ENOLS ||
result == -ESTARTING || result == -ESTARTING ||
result == -EVGKILLED || result == -EVGKILLED ||
result == -ELOCKIO) { result == -ELOCKIO ||
result == -EORPHAN ||
result == -EADOPT_RETRY ||
result == -EADOPT_NONE) {
/* /*
* If an ex global lock fails, then the command fails. * 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"); log_error("Global lock failed: storage errors for sanlock leases");
else if (result == -EVGKILLED) else if (result == -EVGKILLED)
log_error("Global lock failed: storage failed for sanlock leases"); 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 else
log_error("Global lock failed: error %d", result); 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; 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)) { if ((lockd_flags & LD_RF_NO_GL_LS) || (lockd_flags & LD_RF_NO_LOCKSPACES)) {
log_debug("Skipping global lock: lockspace not found or started"); log_debug("Skipping global lock: lockspace not found or started");
goto allow; 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) uint32_t flags, uint32_t *lockd_state)
{ {
const char *mode = NULL; const char *mode = NULL;
const char *opts = NULL;
uint32_t lockd_flags; uint32_t lockd_flags;
uint32_t prev_state = *lockd_state; uint32_t prev_state = *lockd_state;
int retries = 0; int retries = 0;
@ -2103,6 +2139,11 @@ int lockd_vg(struct cmd_context *cmd, const char *vg_name, const char *def_mode,
if (!mode) if (!mode)
mode = cmd->lockd_vg_default_sh ? "sh" : "ex"; 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")) if (!strcmp(mode, "ex"))
*lockd_state |= LDST_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); log_debug("lockd VG %s mode %s", vg_name, mode);
if (!_lockd_request(cmd, "lock_vg", 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)) { NULL, &result, &lockd_flags)) {
/* /*
* No result from lvmlockd, it is probably not running. * 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; 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 * No lockspace for the VG was found. It may be a local
* VG that lvmlockd doesn't keep track of, or it may be * 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) const char *lock_args, const char *def_mode, uint32_t flags)
{ {
char lv_uuid[64] __attribute__((aligned(8))); char lv_uuid[64] __attribute__((aligned(8)));
const char *mode = NULL; char opt_buf[64] = {};
const char *opts = NULL; const char *opts = NULL;
const char *mode = NULL;
uint32_t lockd_flags; uint32_t lockd_flags;
int refreshed = 0; int refreshed = 0;
int result; int result;
@ -2485,8 +2564,15 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg,
if (!mode) if (!mode)
mode = "ex"; mode = "ex";
if (flags & LDLV_PERSISTENT) if ((flags & LDLV_PERSISTENT) ||
opts = "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: retry:
log_debug("lockd LV %s/%s mode %s uuid %s", vg->name, lv_name, mode, lv_uuid); 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; 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) { if (result == -EEXIST) {
/* /*
* This happens if a command like lvchange tries to modify the * 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; *flags |= LOCKOPT_NOWAIT;
else if (!strcmp(argv[i], "autonowait")) else if (!strcmp(argv[i], "autonowait"))
*flags |= LOCKOPT_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 else
log_warn("Ignoring unknown lockopt value: %s", argv[i]); log_warn("Ignoring unknown lockopt value: %s", argv[i]);
} }

View File

@ -49,6 +49,11 @@
#define LOCKOPT_AUTO 0x00000040 #define LOCKOPT_AUTO 0x00000040
#define LOCKOPT_NOWAIT 0x00000080 #define LOCKOPT_NOWAIT 0x00000080
#define LOCKOPT_AUTONOWAIT 0x00000100 #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); void lockd_lockopt_get_flags(const char *str, uint32_t *flags);