From d85ceff9c5d2ebac2343f75eaa37bbc80c182ed6 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Wed, 26 Jun 2024 12:06:02 -0500 Subject: [PATCH] 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. --- daemons/lvmlockd/lvmlockd-core.c | 43 ++++++++++++++++++++++++++--- daemons/lvmlockd/lvmlockd-sanlock.c | 4 ++- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/daemons/lvmlockd/lvmlockd-core.c b/daemons/lvmlockd/lvmlockd-core.c index e246434a0..ee1dbadab 100644 --- a/daemons/lvmlockd/lvmlockd-core.c +++ b/daemons/lvmlockd/lvmlockd-core.c @@ -2488,6 +2488,7 @@ static void *lockspace_thread_main(void *arg_in) struct list_head tmp_act; struct list_head act_close; char tmp_name[MAX_NAME+5]; + int fail_stop_busy; int free_vg = 0; int drop_vg = 0; int error = 0; @@ -2498,6 +2499,7 @@ static void *lockspace_thread_main(void *arg_in) int rv; INIT_LIST_HEAD(&act_close); + INIT_LIST_HEAD(&tmp_act); /* first action may be client add */ pthread_mutex_lock(&ls->mutex); @@ -2566,6 +2568,8 @@ static void *lockspace_thread_main(void *arg_in) if (error) goto out_act; + restart: + while (1) { pthread_mutex_lock(&ls->mutex); while (!ls->thread_work) { @@ -2818,17 +2822,48 @@ out_rem: * 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: /* * Move remaining actions to results; this will usually (always?) * be only the stop action. */ - INIT_LIST_HEAD(&tmp_act); - pthread_mutex_lock(&ls->mutex); list_for_each_entry_safe(act, safe, &ls->actions, list) { if (act->op == LD_OP_FREE) { diff --git a/daemons/lvmlockd/lvmlockd-sanlock.c b/daemons/lvmlockd/lvmlockd-sanlock.c index 35dabc472..cd33e7de2 100644 --- a/daemons/lvmlockd/lvmlockd-sanlock.c +++ b/daemons/lvmlockd/lvmlockd-sanlock.c @@ -1563,8 +1563,10 @@ int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg) goto out; 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); + return rv; + } if (free_vg) { /*