mrc0mmand / rpms / lvm2

Forked from rpms/lvm2 2 years ago
Clone
Blob Blame History Raw
 WHATS_NEW                        |  2 ++
 daemons/clvmd/lvm-functions.c    |  2 +-
 lib/activate/activate.c          | 20 ++++++++++++--------
 lib/activate/activate.h          |  5 +++--
 lib/activate/dev_manager.c       | 15 +++++++++++----
 lib/format_text/flags.c          |  5 +++--
 lib/locking/file_locking.c       |  4 ++--
 lib/locking/no_locking.c         |  4 ++--
 lib/metadata/lv_manip.c          |  6 ++++++
 lib/metadata/metadata-exported.h |  1 +
 udev/11-dm-lvm.rules.in          | 15 +++++++++++++++
 udev/13-dm-disk.rules.in         |  3 ++-
 udev/69-dm-lvm-metad.rules.in    |  2 ++
 13 files changed, 62 insertions(+), 22 deletions(-)

diff --git a/WHATS_NEW b/WHATS_NEW
index e0cb795..cd55d54 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,7 @@
 Version 2.02.104 - 
 ===================================
+  Recognize new flag to skip udev scanning in udev rules and act appropriately.
+  Add support for flagging an LV to skip udev scanning during activation.
   Improve message when unable to change discards setting on active thin pool.
   Fix lvconvert when converting to a thin pool and thin LV at once.
 
diff --git a/daemons/clvmd/lvm-functions.c b/daemons/clvmd/lvm-functions.c
index da7d335..f544218 100644
--- a/daemons/clvmd/lvm-functions.c
+++ b/daemons/clvmd/lvm-functions.c
@@ -401,7 +401,7 @@ static int do_activate_lv(char *resource, unsigned char command, unsigned char l
 	}
 
 	/* Now activate it */
-	if (!lv_activate(cmd, resource, exclusive, NULL))
+	if (!lv_activate(cmd, resource, exclusive, 0, NULL))
 		goto error;
 
 	return 0;
diff --git a/lib/activate/activate.c b/lib/activate/activate.c
index 28549fc..c077113 100644
--- a/lib/activate/activate.c
+++ b/lib/activate/activate.c
@@ -337,12 +337,13 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
 {
 	return 1;
 }
-int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive, struct logical_volume *lv)
+int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive, int noscan,
+		struct logical_volume *lv)
 {
 	return 1;
 }
 int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive,
-			    struct logical_volume *lv)
+			    int noscan, struct logical_volume *lv)
 {
 	return 1;
 }
@@ -2027,9 +2028,10 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
 	if (filter)
 		laopts->read_only = _passes_readonly_filter(cmd, lv);
 
-	log_debug_activation("Activating %s/%s%s%s.", lv->vg->name, lv->name,
+	log_debug_activation("Activating %s/%s%s%s%s.", lv->vg->name, lv->name,
 			     laopts->exclusive ? " exclusively" : "",
-			     laopts->read_only ? " read-only" : "");
+			     laopts->read_only ? " read-only" : "",
+			     laopts->noscan ? " noscan" : "");
 
 	if (!lv_info(cmd, lv, 0, &info, 0, 0))
 		goto_out;
@@ -2066,9 +2068,10 @@ out:
 }
 
 /* Activate LV */
-int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive, struct logical_volume *lv)
+int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive,
+		int noscan, struct logical_volume *lv)
 {
-	struct lv_activate_opts laopts = { .exclusive = exclusive };
+	struct lv_activate_opts laopts = { .exclusive = exclusive, .noscan = noscan };
 
 	if (!_lv_activate(cmd, lvid_s, &laopts, 0, lv))
 		return_0;
@@ -2077,9 +2080,10 @@ int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive, stru
 }
 
 /* Activate LV only if it passes filter */
-int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive, struct logical_volume *lv)
+int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive,
+			    int noscan, struct logical_volume *lv)
 {
-	struct lv_activate_opts laopts = { .exclusive = exclusive };
+	struct lv_activate_opts laopts = { .exclusive = exclusive, .noscan = noscan  };
 
 	if (!_lv_activate(cmd, lvid_s, &laopts, 1, lv))
 		return_0;
diff --git a/lib/activate/activate.h b/lib/activate/activate.h
index f34d376..4eac320 100644
--- a/lib/activate/activate.h
+++ b/lib/activate/activate.h
@@ -38,6 +38,7 @@ struct lv_activate_opts {
 	int skip_in_use;
 	unsigned revert;
 	unsigned read_only;
+	unsigned noscan;
 };
 
 /* target attribute flags */
@@ -80,9 +81,9 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s, unsigned o
 int lv_resume(struct cmd_context *cmd, const char *lvid_s, unsigned origin_only, struct logical_volume *lv);
 int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s,
 			unsigned origin_only, unsigned exclusive, unsigned revert, struct logical_volume *lv);
-int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive, struct logical_volume *lv);
+int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive, int noscan, struct logical_volume *lv);
 int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s,
-			    int exclusive, struct logical_volume *lv);
+			    int exclusive, int noscan, struct logical_volume *lv);
 int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, struct logical_volume *lv);
 
 int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index b8233bf..0f5a04c 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -30,6 +30,7 @@
 #include <dirent.h>
 
 #define MAX_TARGET_PARAMSIZE 50000
+#define LVM_UDEV_NOSCAN_FLAG DM_SUBSYSTEM_UDEV_FLAG0
 
 typedef enum {
 	PRELOAD,
@@ -1399,7 +1400,7 @@ static int _check_udev_fallback(struct cmd_context *cmd)
 #endif /* UDEV_SYNC_SUPPORT */
 
 static uint16_t _get_udev_flags(struct dev_manager *dm, struct logical_volume *lv,
-				const char *layer)
+				const char *layer, uint16_t flags)
 {
 	uint16_t udev_flags = 0;
 
@@ -1447,6 +1448,11 @@ static uint16_t _get_udev_flags(struct dev_manager *dm, struct logical_volume *l
 		udev_flags |= DM_UDEV_DISABLE_DM_RULES_FLAG |
 			      DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG;
 
+	/*
+	 * Firmly set requested flags.
+	 */
+	udev_flags |= flags;
+
 	return udev_flags;
 }
 
@@ -1493,7 +1499,7 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
 	}
 
 	if (info.exists && !dm_tree_add_dev_with_udev_flags(dtree, info.major, info.minor,
-							_get_udev_flags(dm, lv, layer))) {
+							_get_udev_flags(dm, lv, layer, 0))) {
 		log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree",
 			  info.major, info.minor);
 		return 0;
@@ -2334,7 +2340,7 @@ static int _set_udev_flags_for_children(struct dev_manager *dm,
 		}
 
 		dm_tree_node_set_udev_flags(child,
-					    _get_udev_flags(dm, lvl->lv, NULL));
+					    _get_udev_flags(dm, lvl->lv, NULL, 0));
 	}
 
 	return 1;
@@ -2411,7 +2417,8 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
 					     read_only_lv(lv, laopts),
 					     ((lv->vg->status & PRECOMMITTED) | laopts->revert) ? 1 : 0,
 					     lvlayer,
-					     _get_udev_flags(dm, lv, layer))))
+					     _get_udev_flags(dm, lv, layer,
+						laopts->noscan ? LVM_UDEV_NOSCAN_FLAG : 0))))
 		return_0;
 
 	/* Store existing name so we can do rename later */
diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
index 5077576..a27b791 100644
--- a/lib/format_text/flags.c
+++ b/lib/format_text/flags.c
@@ -61,6 +61,7 @@ static const struct flag _lv_flags[] = {
 	{LV_REBUILD, "REBUILD", STATUS_FLAG},
 	{LV_WRITEMOSTLY, "WRITEMOSTLY", STATUS_FLAG},
 	{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG},
+	{LV_NOSCAN, NULL, 0},
 	{POOL_METADATA_SPARE, NULL, 0},
 	{RAID, NULL, 0},
 	{RAID_META, NULL, 0},
@@ -144,8 +145,8 @@ int print_flags(uint64_t status, int type, char *buffer, size_t size)
 		return 0;
 
 	if (status)
-		log_warn("Metadata inconsistency: Not all flags successfully "
-			 "exported.");
+		log_warn(INTERNAL_ERROR "Metadata inconsistency: "
+			 "Not all flags successfully exported.");
 
 	return 1;
 }
diff --git a/lib/locking/file_locking.c b/lib/locking/file_locking.c
index 5e49bc4..b6b2b10 100644
--- a/lib/locking/file_locking.c
+++ b/lib/locking/file_locking.c
@@ -305,7 +305,7 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
 			break;
 		case LCK_READ:
 			log_very_verbose("Locking LV %s (R)", resource);
-			if (!lv_activate_with_filter(cmd, resource, 0, lv_ondisk(lv)))
+			if (!lv_activate_with_filter(cmd, resource, 0, lv->status & LV_NOSCAN ? 1 : 0, lv_ondisk(lv)))
 				return 0;
 			break;
 		case LCK_PREAD:
@@ -318,7 +318,7 @@ static int _file_lock_resource(struct cmd_context *cmd, const char *resource,
 			break;
 		case LCK_EXCL:
 			log_very_verbose("Locking LV %s (EX)", resource);
-			if (!lv_activate_with_filter(cmd, resource, 1, lv_ondisk(lv)))
+			if (!lv_activate_with_filter(cmd, resource, 1, lv->status & LV_NOSCAN ? 1 : 0, lv_ondisk(lv)))
 				return 0;
 			break;
 		default:
diff --git a/lib/locking/no_locking.c b/lib/locking/no_locking.c
index 5f3f0b6..4772706 100644
--- a/lib/locking/no_locking.c
+++ b/lib/locking/no_locking.c
@@ -48,11 +48,11 @@ static int _no_lock_resource(struct cmd_context *cmd, const char *resource,
 		case LCK_UNLOCK:
 			return lv_resume_if_active(cmd, resource, (flags & LCK_ORIGIN_ONLY) ? 1: 0, 0, (flags & LCK_REVERT) ? 1 : 0, lv_ondisk(lv));
 		case LCK_READ:
-			return lv_activate_with_filter(cmd, resource, 0, lv_ondisk(lv));
+			return lv_activate_with_filter(cmd, resource, 0, lv->status & LV_NOSCAN ? 1 : 0, lv_ondisk(lv));
 		case LCK_WRITE:
 			return lv_suspend_if_active(cmd, resource, (flags & LCK_ORIGIN_ONLY) ? 1 : 0, 0, lv_ondisk(lv), lv);
 		case LCK_EXCL:
-			return lv_activate_with_filter(cmd, resource, 1, lv_ondisk(lv));
+			return lv_activate_with_filter(cmd, resource, 1, lv->status & LV_NOSCAN ? 1 : 0, lv_ondisk(lv));
 		default:
 			break;
 		}
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index f42db1d..22327d7 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -5421,6 +5421,8 @@ int set_lv(struct cmd_context *cmd, struct logical_volume *lv,
 	if (!dev_close_immediate(dev))
 		stack;
 
+	lv->status &= ~LV_NOSCAN;
+
 	return 1;
 }
 
@@ -5977,6 +5979,10 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
 		goto out;
 	}
 
+	/* Do not scan this LV until properly zeroed. */
+	if (lp->zero)
+		lv->status |= LV_NOSCAN;
+
 	if (lv_is_thin_pool(lv)) {
 		if (is_change_activating(lp->activate)) {
 			if (vg_is_clustered(lv->vg)) {
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 308dcfe..1e9543a 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -102,6 +102,7 @@
 #define LV_WRITEMOSTLY		UINT64_C(0x0000020000000000)	/* LV (RAID1) */
 
 #define LV_ACTIVATION_SKIP	UINT64_C(0x0000040000000000)	/* LV */
+#define LV_NOSCAN		UINT64_C(0x0000080000000000)	/* LV */
 
 /* Format features flags */
 #define FMT_SEGMENTS		0x00000001U	/* Arbitrary segment params? */
diff --git a/udev/11-dm-lvm.rules.in b/udev/11-dm-lvm.rules.in
index f21d0aa..5032280 100644
--- a/udev/11-dm-lvm.rules.in
+++ b/udev/11-dm-lvm.rules.in
@@ -20,6 +20,21 @@ ENV{DM_UUID}!="LVM-?*", GOTO="lvm_end"
 # Use DM name and split it up into its VG/LV/layer constituents.
 IMPORT{program}="(DM_EXEC)/dmsetup splitname --nameprefixes --noheadings --rows $env{DM_NAME}"
 
+# DM_SUBSYSTEM_UDEV_FLAG0 is the 'NOSCAN' flag for LVM subsystem.
+# This flag is used to temporarily disable selected rules to prevent any
+# processing or scanning done on the LVM volume before LVM has any chance
+# to zero any stale metadata found within the LV data area. Such stale
+# metadata could cause false claim of the LV device, keeping it open etc.
+#
+# If the NOSCAN flag is present, backup selected existing flags used to
+# disable rules, then set them firmly so those selected rules are surely skipped.
+# Restore these flags once the NOSCAN flag is dropped (which is normally any
+# uevent that follows for this LV, even an artificially generated one).
+ENV{DM_SUBSYSTEM_UDEV_FLAG0}=="1", ENV{DM_NOSCAN}="1", ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}="$env{DM_UDEV_DISABLE_OTHER_RULES_FLAG}", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
+ENV{DM_SUBSYSTEM_UDEV_FLAG0}!="1", IMPORT{db}="DM_NOSCAN", IMPORT{db}="DM_DISABLE_OTHER_RULES_FLAG_OLD"
+ENV{DM_SUBSYSTEM_UDEV_FLAG0}!="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="$env{DM_DISABLE_OTHER_RULES_FLAG_OLD}", \
+				   ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG_OLD}="", ENV{DM_NOSCAN}=""
+
 ENV{DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG}=="1", GOTO="lvm_end"
 
 OPTIONS+="event_timeout=180"
diff --git a/udev/13-dm-disk.rules.in b/udev/13-dm-disk.rules.in
index 1920260..4b64dd6 100644
--- a/udev/13-dm-disk.rules.in
+++ b/udev/13-dm-disk.rules.in
@@ -18,6 +18,7 @@ SYMLINK+="disk/by-id/dm-name-$env{DM_NAME}"
 ENV{DM_UUID}=="?*", SYMLINK+="disk/by-id/dm-uuid-$env{DM_UUID}"
 
 ENV{DM_SUSPENDED}=="1", GOTO="dm_end"
+ENV{DM_NOSCAN}=="1", GOTO="dm_watch"
 
 (BLKID_RULE)
 ENV{DM_UDEV_LOW_PRIORITY_FLAG}=="1", OPTIONS="link_priority=-100"
@@ -32,7 +33,7 @@ ENV{ID_FS_USAGE}=="filesystem|other", ENV{ID_FS_LABEL_ENC}=="?*", SYMLINK+="disk
 # (like creating a filesystem, changing filesystem label etc.).
 #
 # But let's use this until we have something better...
-
+LABEL="dm_watch"
 OPTIONS+="watch"
 
 LABEL="dm_end"
diff --git a/udev/69-dm-lvm-metad.rules.in b/udev/69-dm-lvm-metad.rules.in
index ba43396..3303f4d 100644
--- a/udev/69-dm-lvm-metad.rules.in
+++ b/udev/69-dm-lvm-metad.rules.in
@@ -17,6 +17,8 @@
 SUBSYSTEM!="block", GOTO="lvm_end"
 (LVM_EXEC_RULE)
 
+ENV{DM_NOSCAN}=="1", GOTO="lvm_end"
+
 # If the PV label got lost, inform lvmetad immediately.
 # Detect the lost PV label by comparing previous ID_FS_TYPE value with current one.
 ENV{.ID_FS_TYPE_NEW}="$env{ID_FS_TYPE}"