lvm2/0001-lvconvert-swapmetadata-fix-lvmlockd-locking.patch

97 lines
3.4 KiB
Diff

From ff0a8d7b6734c745e52652fc5e7dd3a0f2efb518 Mon Sep 17 00:00:00 2001
From: David Teigland <teigland@redhat.com>
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