Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=9b78f7eee9f231d88ed5c…
Commit: 9b78f7eee9f231d88ed5ca05fbf6da8c473ab41e
Parent: 7e14835a46a6c9e66087d6502d23df53c2a9954f
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Sun Feb 12 23:53:18 2023 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Feb 13 13:41:59 2023 +0100
libdm: match reactivation of sibling for snapshot
Apply same code for libdm as in device_mapper dir from
commit c8a5948a71b041ae2cce03e1b3a9843f0fab023f.
---
libdm/libdm-deptree.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 89 insertions(+)
diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c
index 33a80cf4d..bb2e53669 100644
--- a/libdm/libdm-deptree.c
+++ b/libdm/libdm-deptree.c
@@ -254,6 +254,10 @@ struct load_properties {
unsigned send_messages;
/* Skip suspending node's children, used when sending messages to thin-pool */
int skip_suspend;
+
+ /* Suspend and Resume siblings after node activation with udev flags*/
+ unsigned reactivate_siblings;
+ uint16_t reactivate_udev_flags;
};
/* Two of these used to join two nodes with uses and used_by. */
@@ -1877,6 +1881,68 @@ static int _rename_conflict_exists(struct dm_tree_node *parent,
return 0;
}
+/*
+ * Reactivation of sibling nodes
+ *
+ * Function is used when activating origin and its thick snapshots
+ * to ensure udev is processing first the origin LV and all the
+ * snapshot LVs are processed afterwards.
+ */
+static int _reactivate_siblings(struct dm_tree_node *dnode,
+ const char *uuid_prefix,
+ size_t uuid_prefix_len)
+{
+ struct dm_tree_node *child;
+ const char *uuid;
+ void *handle = NULL;
+ int r = 1;
+
+ /* Wait for udev before reactivating siblings */
+ if (!dm_udev_wait(dm_tree_get_cookie(dnode)))
+ stack;
+
+ dm_tree_set_cookie(dnode, 0);
+
+ while ((child = dm_tree_next_child(&handle, dnode, 0))) {
+ if (child->props.reactivate_siblings) {
+ /* Skip 'leading' device in this group, marked with flag */
+ child->props.reactivate_siblings = 0;
+ continue;
+ }
+
+ if (!(uuid = dm_tree_node_get_uuid(child))) {
+ stack;
+ continue;
+ }
+
+ if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
+ continue;
+
+ if (!_suspend_node(child->name, child->info.major, child->info.minor,
+ child->dtree->skip_lockfs,
+ child->dtree->no_flush, &child->info)) {
+ log_error("Unable to suspend %s (" FMTu32
+ ":" FMTu32 ")", child->name,
+ child->info.major, child->info.minor);
+ r = 0;
+ continue;
+ }
+ if (!_resume_node(child->name, child->info.major, child->info.minor,
+ child->props.read_ahead, child->props.read_ahead_flags,
+ &child->info, &child->dtree->cookie,
+ child->props.reactivate_udev_flags, // use these flags
+ child->info.suspended)) {
+ log_error("Failed to suspend %s (" FMTu32
+ ":" FMTu32 ")", child->name,
+ child->info.major, child->info.minor);
+ r = 0;
+ continue;
+ }
+ }
+
+ return r;
+}
+
int dm_tree_activate_children(struct dm_tree_node *dnode,
const char *uuid_prefix,
size_t uuid_prefix_len)
@@ -1965,6 +2031,11 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
if (r && (child->props.send_messages > 1) &&
!(r = _node_send_messages(child, uuid_prefix, uuid_prefix_len, 1)))
stack;
+
+ /* Reactivate only for fresh activated origin */
+ if (r && child->props.reactivate_siblings &&
+ (!(r = _reactivate_siblings(dnode, uuid_prefix, uuid_prefix_len))))
+ stack;
}
if (awaiting_peer_rename)
priority--; /* redo priority level */
@@ -2999,6 +3070,10 @@ int dm_tree_node_add_snapshot_origin_target(struct dm_tree_node *dnode,
/* Resume snapshot origins after new snapshots */
dnode->activation_priority = 1;
+ if (!dnode->info.exists)
+ /* Reactivate siblings for this origin after being resumed */
+ dnode->props.reactivate_siblings = 1;
+
/*
* Don't resume the origin immediately in case it is a non-trivial
* target that must not be active more than once concurrently!
@@ -3061,6 +3136,20 @@ static int _add_snapshot_target(struct dm_tree_node *node,
/* Resume merging snapshot after snapshot-merge */
seg->merge->activation_priority = 2;
}
+ } else if (!origin_node->info.exists) {
+ /* Keep original udev_flags for reactivation. */
+ node->props.reactivate_udev_flags = node->udev_flags;
+
+ /* Reactivation is needed if the origin's -real device is not in DM table.
+ * For this case after the resume of its origin LV we resume its snapshots
+ * with updated udev_flags to completely avoid udev scanning for the first resume.
+ * Reactivation then resumes snapshots with original udev_flags.
+ */
+ node->udev_flags |= DM_SUBSYSTEM_UDEV_FLAG0 |
+ DM_UDEV_DISABLE_DISK_RULES_FLAG |
+ DM_UDEV_DISABLE_OTHER_RULES_FLAG;
+ log_debug_activation("Using udev_flags 0x%x for activation of %s.",
+ node->udev_flags, node->name);
}
return 1;
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=7e14835a46a6c9e66087d…
Commit: 7e14835a46a6c9e66087d6502d23df53c2a9954f
Parent: cf0dc9a13cf365859e7dad3bb1ad02040925ae11
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Sun Feb 12 23:44:43 2023 +0100
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Feb 13 13:41:59 2023 +0100
libdm: improve parallel create of control node
When two parallel commands would have tried to create our
/dev/mapper/control node at the same time, one of them could
actually fail even if the 2nd. command actually mknod()
this control node correctly.
So for EEXIST case add detection if the control node is ok.
This may possibly help with some race case in early boot.
---
device_mapper/ioctl/libdm-iface.c | 9 +++++++--
libdm/ioctl/libdm-iface.c | 9 +++++++--
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/device_mapper/ioctl/libdm-iface.c b/device_mapper/ioctl/libdm-iface.c
index d25b07800..ffcbc8a48 100644
--- a/device_mapper/ioctl/libdm-iface.c
+++ b/device_mapper/ioctl/libdm-iface.c
@@ -312,8 +312,13 @@ static int _create_control(const char *control, uint32_t major, uint32_t minor)
old_umask = umask(DM_CONTROL_NODE_UMASK);
if (mknod(control, S_IFCHR | S_IRUSR | S_IWUSR,
MKDEV(major, minor)) < 0) {
- log_sys_error("mknod", control);
- ret = 0;
+ if (errno != EEXIST) {
+ log_sys_error("mknod", control);
+ ret = 0;
+ } else if (_control_exists(control, major, minor) != 1) {
+ stack; /* Invalid control node created by parallel command ? */
+ ret = 0;
+ }
}
umask(old_umask);
(void) dm_prepare_selinux_context(NULL, 0);
diff --git a/libdm/ioctl/libdm-iface.c b/libdm/ioctl/libdm-iface.c
index dfa91b866..2e2da8b99 100644
--- a/libdm/ioctl/libdm-iface.c
+++ b/libdm/ioctl/libdm-iface.c
@@ -311,8 +311,13 @@ static int _create_control(const char *control, uint32_t major, uint32_t minor)
old_umask = umask(DM_CONTROL_NODE_UMASK);
if (mknod(control, S_IFCHR | S_IRUSR | S_IWUSR,
MKDEV(major, minor)) < 0) {
- log_sys_error("mknod", control);
- ret = 0;
+ if (errno != EEXIST) {
+ log_sys_error("mknod", control);
+ ret = 0;
+ } else if (_control_exists(control, major, minor) != 1) {
+ stack; /* Invalid control node created by parallel command ? */
+ ret = 0;
+ }
}
umask(old_umask);
(void) dm_prepare_selinux_context(NULL, 0);