1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-02 01:18:26 +03:00

lvmlockd: let vgchange lockstop fail with EBUSY for orphans

vgchange --lockstop will fail with EBUSY if orphan locks in the
lock manager prevent stopping the lockspace.  The orphan locks
can then be adopted and released, and the lockspace then stopped
cleanly.
This commit is contained in:
David Teigland 2024-06-26 12:06:02 -05:00
parent f32fd1fcb9
commit d85ceff9c5
2 changed files with 42 additions and 5 deletions

View File

@ -2488,6 +2488,7 @@ static void *lockspace_thread_main(void *arg_in)
struct list_head tmp_act; struct list_head tmp_act;
struct list_head act_close; struct list_head act_close;
char tmp_name[MAX_NAME+5]; char tmp_name[MAX_NAME+5];
int fail_stop_busy;
int free_vg = 0; int free_vg = 0;
int drop_vg = 0; int drop_vg = 0;
int error = 0; int error = 0;
@ -2498,6 +2499,7 @@ static void *lockspace_thread_main(void *arg_in)
int rv; int rv;
INIT_LIST_HEAD(&act_close); INIT_LIST_HEAD(&act_close);
INIT_LIST_HEAD(&tmp_act);
/* first action may be client add */ /* first action may be client add */
pthread_mutex_lock(&ls->mutex); pthread_mutex_lock(&ls->mutex);
@ -2566,6 +2568,8 @@ static void *lockspace_thread_main(void *arg_in)
if (error) if (error)
goto out_act; goto out_act;
restart:
while (1) { while (1) {
pthread_mutex_lock(&ls->mutex); pthread_mutex_lock(&ls->mutex);
while (!ls->thread_work) { while (!ls->thread_work) {
@ -2818,17 +2822,48 @@ out_rem:
* Leave the lockspace. * Leave the lockspace.
*/ */
rv = lm_rem_lockspace(ls, NULL, free_vg); fail_stop_busy = 0;
log_debug("S %s rem_lockspace done %d", ls->name, rv); rv = lm_rem_lockspace(ls, NULL, free_vg);
if (rv < 0) {
pthread_mutex_lock(&ls->mutex);
list_for_each_entry_safe(act, safe, &ls->actions, list) {
/*
* If there's a stop action then there's a path to return an error,
* and in the case of EBUSY presumably there's a chance to redo it.
*/
if ((act->op == LD_OP_STOP) && (rv == -EBUSY)) {
log_debug("S %s rem_lockspace for stop error %d", ls->name, rv);
act->result = -EBUSY;
list_del(&act->list);
list_add_tail(&act->list, &tmp_act);
ls->thread_stop = 0;
fail_stop_busy = 1;
break;
}
}
pthread_mutex_unlock(&ls->mutex);
if (fail_stop_busy) {
pthread_mutex_lock(&client_mutex);
list_del(&act->list);
list_add_tail(&act->list, &client_results);
pthread_cond_signal(&client_cond);
pthread_mutex_unlock(&client_mutex);
goto restart;
}
}
if (rv < 0)
log_debug("S %s rem_lockspace error %d", ls->name, rv);
else
log_debug("S %s rem_lockspace done", ls->name);
out_act: out_act:
/* /*
* Move remaining actions to results; this will usually (always?) * Move remaining actions to results; this will usually (always?)
* be only the stop action. * be only the stop action.
*/ */
INIT_LIST_HEAD(&tmp_act);
pthread_mutex_lock(&ls->mutex); pthread_mutex_lock(&ls->mutex);
list_for_each_entry_safe(act, safe, &ls->actions, list) { list_for_each_entry_safe(act, safe, &ls->actions, list) {
if (act->op == LD_OP_FREE) { if (act->op == LD_OP_FREE) {

View File

@ -1563,8 +1563,10 @@ int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg)
goto out; goto out;
rv = sanlock_rem_lockspace(&lms->ss, 0); rv = sanlock_rem_lockspace(&lms->ss, 0);
if (rv < 0) if (rv < 0) {
log_error("S %s rem_lockspace_san error %d", ls->name, rv); log_error("S %s rem_lockspace_san error %d", ls->name, rv);
return rv;
}
if (free_vg) { if (free_vg) {
/* /*