From ff0a8d7b6734c745e52652fc5e7dd3a0f2efb518 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Tue, 8 Aug 2023 16:57:22 -0500 Subject: [PATCH 01/24] lvconvert swapmetadata: fix lvmlockd locking The lockd lock needs to be freed for the LV that is becoming the new metadata LV, and a new lockd lock needs to be created for the old metadata LV that is becoming an independent LV. Fixes b3e45219c2f4 --- tools/lvconvert.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/tools/lvconvert.c b/tools/lvconvert.c index 0004422f2..49047abb0 100644 --- a/tools/lvconvert.c +++ b/tools/lvconvert.c @@ -2818,6 +2818,9 @@ static int _lvconvert_swap_pool_metadata(struct cmd_context *cmd, struct lv_type *lvtype; char meta_name[NAME_LEN]; const char *swap_name; + char *lockd_meta_args = NULL; + char *lockd_meta_name = NULL; + struct id lockd_meta_id; uint32_t chunk_size; int is_thinpool; int is_cachepool; @@ -2872,6 +2875,12 @@ static int _lvconvert_swap_pool_metadata(struct cmd_context *cmd, if (!lockd_lv(cmd, lv, "ex", 0)) return 0; + /* If new metadata LV is inactive here, ensure it's not active elsewhere */ + if (!lockd_lv(cmd, metadata_lv, "ex", 0)) { + log_error("New pool metadata LV %s cannot be locked.", display_lvname(metadata_lv)); + return 0; + } + if (!deactivate_lv(cmd, metadata_lv)) { log_error("Aborting. Failed to deactivate %s.", display_lvname(metadata_lv)); @@ -2883,8 +2892,22 @@ static int _lvconvert_swap_pool_metadata(struct cmd_context *cmd, return 0; } - metadata_lv->lock_args = NULL; - + /* + * metadata_lv is currently an independent LV with its own lockd lock allocated. + * A pool metadata LV does not have its own lockd lock (only the pool LV does.) + * So, when metadata_lv is added to the thin pool, it's lock needs to be freed. + * Save info about the metadata_lv here that will be used to free the lock. + * The current pool metadata LV does not currently have its own lockd lock + * allocated, and once it becomes an independent LV it will need its own lock. + * (see setting prev_metadata_lv->lock_args below.) + */ + if (vg_is_shared(vg) && metadata_lv->lock_args) { + lockd_meta_args = dm_pool_strdup(cmd->mem, metadata_lv->lock_args); + lockd_meta_name = dm_pool_strdup(cmd->mem, metadata_lv->name); + memcpy(&lockd_meta_id, &metadata_lv->lvid.id[1], sizeof(struct id)); + /* Without lock_args, a lock will no longer be acquired for this LV. */ + metadata_lv->lock_args = NULL; + } seg = first_seg(lv); @@ -2950,9 +2973,27 @@ static int _lvconvert_swap_pool_metadata(struct cmd_context *cmd, if (!attach_pool_metadata_lv(seg, metadata_lv)) return_0; + /* + * The previous metadata LV will now be an independent LV so it now + * requires a lockd lock. We could call lockd_init_lv_args() directly + * here, but reuse the existing code in vg_write() to be consistent + * with the way lvcreate allocates locks. + */ + if (is_lockd_type(vg->lock_type)) { + if (!strcmp(vg->lock_type, "sanlock")) + prev_metadata_lv->lock_args = "pending"; + else if (!strcmp(vg->lock_type, "dlm")) + prev_metadata_lv->lock_args = "dlm"; + else if (!strcmp(vg->lock_type, "idm")) + prev_metadata_lv->lock_args = "idm"; + } + if (!vg_write(vg) || !vg_commit(vg)) return_0; + if (lockd_meta_name) + lockd_free_lv(cmd, vg, lockd_meta_name, &lockd_meta_id, lockd_meta_args); + return 1; } -- 2.35.3