[lvm-devel][PATCH 4/5] Udev integration: add cookie support for dm trees

Peter Rajnoha prajnoha at redhat.com
Thu Apr 23 13:07:28 UTC 2009


...resending updated and cleaned up patches for udev integration.


diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 1083fcd..f697e6a 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -1123,7 +1123,7 @@ static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root)
 		if (!*layer)
 			continue;
 
-		if (!dm_tree_deactivate_children(root, uuid, strlen(uuid)))
+		if (!dm_tree_deactivate_children(root, uuid, strlen(uuid), 0))
 			return_0;
 	}
 
@@ -1157,7 +1157,7 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, actio
 		break;
 	case DEACTIVATE:
  		/* Deactivate LV and all devices it references that nothing else has open. */
-		if (!dm_tree_deactivate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
+		if (!dm_tree_deactivate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1, 0))
 			goto_out;
 		if (!_remove_lv_symlinks(dm, root))
 			log_error("Failed to remove all device symlinks associated with %s.", lv->name);
@@ -1177,11 +1177,11 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, actio
 			goto_out;
 
 		/* Preload any devices required before any suspensions */
-		if (!dm_tree_preload_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
+		if (!dm_tree_preload_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1, 0))
 			goto_out;
 
 		if ((action == ACTIVATE) &&
-		    !dm_tree_activate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
+		    !dm_tree_activate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1, 0))
 			goto_out;
 
 		if (!_create_lv_symlinks(dm, root)) {
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index ea75a64..de61de9 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -308,23 +308,23 @@ int dm_tree_node_num_children(struct dm_tree_node *node, uint32_t inverted);
  * Ignores devices that don't have a uuid starting with uuid_prefix.
  */
 int dm_tree_deactivate_children(struct dm_tree_node *dnode,
-				   const char *uuid_prefix,
-				   size_t uuid_prefix_len);
+				   const char *uuid_prefix, size_t uuid_prefix_len,
+					 uint32_t cookie);
 /*
  * Preload/create a device plus all dependencies.
  * Ignores devices that don't have a uuid starting with uuid_prefix.
  */
 int dm_tree_preload_children(struct dm_tree_node *dnode,
-			     const char *uuid_prefix,
-			     size_t uuid_prefix_len);
+			     const char *uuid_prefix, size_t uuid_prefix_len,
+					 uint32_t cookie);
 
 /*
  * Resume a device plus all dependencies.
  * Ignores devices that don't have a uuid starting with uuid_prefix.
  */
 int dm_tree_activate_children(struct dm_tree_node *dnode,
-			      const char *uuid_prefix,
-			      size_t uuid_prefix_len);
+			      const char *uuid_prefix, size_t uuid_prefix_len,
+						uint32_t cookie);
 
 /*
  * Suspend a device plus all dependencies.
diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c
index 11428ca..bd344ec 100644
--- a/libdm/libdm-deptree.c
+++ b/libdm/libdm-deptree.c
@@ -806,10 +806,10 @@ static int _info_by_dev(uint32_t major, uint32_t minor, int with_open_count,
 	return r;
 }
 
-static int _deactivate_node(const char *name, uint32_t major, uint32_t minor)
+static int _deactivate_node(const char *name, uint32_t major, uint32_t minor, uint32_t cookie)
 {
 	struct dm_task *dmt;
-	int r;
+	int r = 0;
 
 	log_verbose("Removing %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor);
 
@@ -820,26 +820,34 @@ static int _deactivate_node(const char *name, uint32_t major, uint32_t minor)
 
 	if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
 		log_error("Failed to set device number for %s deactivation", name);
-		dm_task_destroy(dmt);
-		return 0;
+		goto out;
 	}
 
 	if (!dm_task_no_open_count(dmt))
 		log_error("Failed to disable open_count");
 
+	if (!dm_task_set_cookie(dmt, cookie) ||
+			!dm_notification_sem_inc(cookie))
+		goto out;
+
 	r = dm_task_run(dmt);
 
+	if (!r)
+		dm_notification_sem_dec(cookie);
+
 	/* FIXME Until kernel returns actual name so dm-ioctl.c can handle it */
 	rm_dev_node(name);
 
 	/* FIXME Remove node from tree or mark invalid? */
 
+out:
 	dm_task_destroy(dmt);
 
 	return r;
 }
 
-static int _rename_node(const char *old_name, const char *new_name, uint32_t major, uint32_t minor)
+static int _rename_node(const char *old_name, const char *new_name, uint32_t major,
+							uint32_t minor, uint32_t cookie)
 {
 	struct dm_task *dmt;
 	int r = 0;
@@ -857,13 +865,20 @@ static int _rename_node(const char *old_name, const char *new_name, uint32_t maj
 	}
 
 	if (!dm_task_set_newname(dmt, new_name))
-                goto_out;
+		goto_out;
 
 	if (!dm_task_no_open_count(dmt))
 		log_error("Failed to disable open_count");
 
+	if (!dm_task_set_cookie(dmt, cookie) ||
+		 (!dm_notification_sem_inc(cookie)))
+		goto out;
+
 	r = dm_task_run(dmt);
 
+	if (!r)
+		dm_notification_sem_dec(cookie);
+
 out:
 	dm_task_destroy(dmt);
 
@@ -873,10 +888,10 @@ out:
 /* FIXME Merge with _suspend_node? */
 static int _resume_node(const char *name, uint32_t major, uint32_t minor,
 			uint32_t read_ahead, uint32_t read_ahead_flags,
-			struct dm_info *newinfo)
+			struct dm_info *newinfo, uint32_t cookie)
 {
 	struct dm_task *dmt;
-	int r;
+	int r = 0;
 
 	log_verbose("Resuming %s (%" PRIu32 ":%" PRIu32 ")", name, major, minor);
 
@@ -888,14 +903,12 @@ static int _resume_node(const char *name, uint32_t major, uint32_t minor,
 	/* FIXME Kernel should fill in name on return instead */
 	if (!dm_task_set_name(dmt, name)) {
 		log_error("Failed to set readahead device name for %s", name);
-		dm_task_destroy(dmt);
-		return 0;
+		goto out;
 	}
 
 	if (!dm_task_set_major(dmt, major) || !dm_task_set_minor(dmt, minor)) {
 		log_error("Failed to set device number for %s resumption.", name);
-		dm_task_destroy(dmt);
-		return 0;
+		goto out;
 	}
 
 	if (!dm_task_no_open_count(dmt))
@@ -904,9 +917,16 @@ static int _resume_node(const char *name, uint32_t major, uint32_t minor,
 	if (!dm_task_set_read_ahead(dmt, read_ahead, read_ahead_flags))
 		log_error("Failed to set read ahead");
 
+	if (!dm_task_set_cookie(dmt, cookie) ||
+			!dm_notification_sem_inc(cookie))
+		goto out;
+
 	if ((r = dm_task_run(dmt)))
 		r = dm_task_get_info(dmt, newinfo);
+	else
+		dm_notification_sem_dec(cookie);
 
+out:
 	dm_task_destroy(dmt);
 
 	return r;
@@ -952,8 +972,8 @@ static int _suspend_node(const char *name, uint32_t major, uint32_t minor,
 }
 
 int dm_tree_deactivate_children(struct dm_tree_node *dnode,
-				   const char *uuid_prefix,
-				   size_t uuid_prefix_len)
+			     const char *uuid_prefix, size_t uuid_prefix_len,
+			     uint32_t cookie)
 {
 	void *handle = NULL;
 	struct dm_tree_node *child = dnode;
@@ -961,6 +981,16 @@ int dm_tree_deactivate_children(struct dm_tree_node *dnode,
 	const struct dm_info *dinfo;
 	const char *name;
 	const char *uuid;
+	uint32_t local_cookie;
+
+	/* Set notification semaphore at the root level only and
+	 * use its value for every child to group them together.
+	 * We are at the root level if cookie == 0. */
+	if (!cookie) {
+		if (!dm_notification_sem_open(&local_cookie))
+			return 0;
+	}	else
+		local_cookie = cookie;
 
 	while ((child = dm_tree_next_child(&handle, dnode, 0))) {
 		if (!(dinfo = dm_tree_node_get_info(child))) {
@@ -987,7 +1017,7 @@ int dm_tree_deactivate_children(struct dm_tree_node *dnode,
 		    !info.exists || info.open_count)
 			continue;
 
-		if (!_deactivate_node(name, info.major, info.minor)) {
+		if (!_deactivate_node(name, info.major, info.minor, local_cookie)) {
 			log_error("Unable to deactivate %s (%" PRIu32
 				  ":%" PRIu32 ")", name, info.major,
 				  info.minor);
@@ -995,7 +1025,12 @@ int dm_tree_deactivate_children(struct dm_tree_node *dnode,
 		}
 
 		if (dm_tree_node_num_children(child, 0))
-			dm_tree_deactivate_children(child, uuid_prefix, uuid_prefix_len);
+			dm_tree_deactivate_children(child, uuid_prefix, uuid_prefix_len, local_cookie);
+	}
+
+	if (!cookie) {
+		dm_notification_sem_wait_zero(local_cookie);
+		dm_notification_sem_close(local_cookie);
 	}
 
 	return 1;
@@ -1085,8 +1120,8 @@ int dm_tree_suspend_children(struct dm_tree_node *dnode,
 }
 
 int dm_tree_activate_children(struct dm_tree_node *dnode,
-				 const char *uuid_prefix,
-				 size_t uuid_prefix_len)
+			     const char *uuid_prefix, size_t uuid_prefix_len,
+			     uint32_t cookie)
 {
 	void *handle = NULL;
 	struct dm_tree_node *child = dnode;
@@ -1094,6 +1129,17 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
 	const char *name;
 	const char *uuid;
 	int priority;
+	uint32_t local_cookie;
+
+	/* Set notification semaphore at the root level only and
+	 * use its value for every child to group them together.
+	 * We are at the root level if cookie == 0. */
+	if (!cookie) {
+		if (!dm_notification_sem_open(&local_cookie))
+			return 0;
+	}
+	else
+		local_cookie = cookie;
 
 	/* Activate children first */
 	while ((child = dm_tree_next_child(&handle, dnode, 0))) {
@@ -1106,7 +1152,7 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
 			continue;
 
 		if (dm_tree_node_num_children(child, 0))
-			dm_tree_activate_children(child, uuid_prefix, uuid_prefix_len);
+			dm_tree_activate_children(child, uuid_prefix, uuid_prefix_len, local_cookie);
 	}
 
 	handle = NULL;
@@ -1131,10 +1177,13 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
 
 			/* Rename? */
 			if (child->props.new_name) {
-				if (!_rename_node(name, child->props.new_name, child->info.major, child->info.minor)) {
+				if (!_rename_node(name, child->props.new_name, child->info.major,
+							child->info.minor, local_cookie)) {
 					log_error("Failed to rename %s (%" PRIu32
 						  ":%" PRIu32 ") to %s", name, child->info.major,
 						  child->info.minor, child->props.new_name);
+					if (!cookie)
+						dm_notification_sem_close(local_cookie);
 					return 0;
 				}
 				child->name = child->props.new_name;
@@ -1145,8 +1194,8 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
 				continue;
 
 			if (!_resume_node(child->name, child->info.major, child->info.minor,
-					  child->props.read_ahead,
-					  child->props.read_ahead_flags, &newinfo)) {
+					  child->props.read_ahead, child->props.read_ahead_flags,
+						&newinfo, local_cookie)) {
 				log_error("Unable to resume %s (%" PRIu32
 					  ":%" PRIu32 ")", child->name, child->info.major,
 					  child->info.minor);
@@ -1160,6 +1209,11 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
 
 	handle = NULL;
 
+	if (!cookie) {
+		dm_notification_sem_wait_zero(local_cookie);
+		dm_notification_sem_close(local_cookie);
+	}
+
 	return 1;
 }
 
@@ -1445,12 +1499,22 @@ out:
 }
 
 int dm_tree_preload_children(struct dm_tree_node *dnode,
-			     const char *uuid_prefix,
-			     size_t uuid_prefix_len)
+			     const char *uuid_prefix, size_t uuid_prefix_len,
+			     uint32_t cookie)
 {
 	void *handle = NULL;
 	struct dm_tree_node *child;
 	struct dm_info newinfo;
+	uint32_t local_cookie;
+
+	/* Set notification semaphore at the root level only and
+	 * use its value for every child to group them together.
+	 * We are at the root level if cookie == 0. */
+	if (!cookie) {
+		if (!dm_notification_sem_open(&local_cookie))
+			return 0;
+	} else
+		local_cookie = cookie;
 
 	/* Preload children first */
 	while ((child = dm_tree_next_child(&handle, dnode, 0))) {
@@ -1464,20 +1528,20 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
 			continue;
 
 		if (dm_tree_node_num_children(child, 0))
-			dm_tree_preload_children(child, uuid_prefix, uuid_prefix_len);
+			dm_tree_preload_children(child, uuid_prefix, uuid_prefix_len, local_cookie);
 
 		/* FIXME Cope if name exists with no uuid? */
 		if (!child->info.exists) {
 			if (!_create_node(child)) {
 				stack;
-				return 0;
+				goto out;
 			}
 		}
 
 		if (!child->info.inactive_table && child->props.segment_count) {
 			if (!_load_node(child)) {
 				stack;
-				return 0;
+				goto out;
 			}
 		}
 
@@ -1489,8 +1553,8 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
 			continue;
 
 		if (!_resume_node(child->name, child->info.major, child->info.minor,
-				  child->props.read_ahead,
-				  child->props.read_ahead_flags, &newinfo)) {
+				  child->props.read_ahead, child->props.read_ahead_flags,
+					&newinfo, local_cookie)) {
 			log_error("Unable to resume %s (%" PRIu32
 				  ":%" PRIu32 ")", child->name, child->info.major,
 				  child->info.minor);
@@ -1503,7 +1567,17 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
 
 	handle = NULL;
 
+	if (!cookie) {
+		dm_notification_sem_wait_zero(local_cookie);
+		dm_notification_sem_close(local_cookie);
+	}
+
 	return 1;
+
+out:
+	if (!cookie)
+		dm_notification_sem_close(local_cookie);
+	return 0;
 }
 
 /*




More information about the lvm-devel mailing list