[lvm-devel] LVM2 ./WHATS_NEW_DM libdm/libdevmapper.h libdm ...

prajnoha at sourceware.org prajnoha at sourceware.org
Thu Sep 22 17:09:50 UTC 2011


CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	prajnoha at sourceware.org	2011-09-22 17:09:49

Modified files:
	.              : WHATS_NEW_DM 
	libdm          : libdevmapper.h 
	libdm/ioctl    : libdm-iface.c libdm-targets.h 

Log message:
	Add dm_task_retry_remove fn to use retry logic for device removal.
	
	This call ensures that the dm device removal is retried several
	times before failing.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/WHATS_NEW_DM.diff?cvsroot=lvm2&r1=1.499&r2=1.500
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/libdevmapper.h.diff?cvsroot=lvm2&r1=1.149&r2=1.150
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/ioctl/libdm-iface.c.diff?cvsroot=lvm2&r1=1.120&r2=1.121
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/libdm/ioctl/libdm-targets.h.diff?cvsroot=lvm2&r1=1.31&r2=1.32

--- LVM2/WHATS_NEW_DM	2011/09/13 15:13:41	1.499
+++ LVM2/WHATS_NEW_DM	2011/09/22 17:09:48	1.500
@@ -1,6 +1,6 @@
 Version 1.02.68 -
 ==================================
-  Retry DM_DEVICE_REMOVE ioctl if device is busy.
+  Add dm_task_retry_remove fn to use retry logic for device removal.
   Remove unused passed parameters for _mirror_emit_segment_line().
   Add dm_config and string character escaping functions to libdevmapper.
   Mark unreleased memory pools as internal error.
--- LVM2/libdm/libdevmapper.h	2011/09/02 01:32:09	1.149
+++ LVM2/libdm/libdevmapper.h	2011/09/22 17:09:48	1.150
@@ -191,6 +191,7 @@
 int dm_task_query_inactive_table(struct dm_task *dmt);
 int dm_task_suppress_identical_reload(struct dm_task *dmt);
 int dm_task_secure_data(struct dm_task *dmt);
+int dm_task_retry_remove(struct dm_task *dmt);
 
 /*
  * Enable checks for common mistakes such as issuing ioctls in an unsafe order.
--- LVM2/libdm/ioctl/libdm-iface.c	2011/09/13 15:13:41	1.120
+++ LVM2/libdm/ioctl/libdm-iface.c	2011/09/22 17:09:48	1.121
@@ -828,6 +828,13 @@
 	return 1;
 }
 
+int dm_task_retry_remove(struct dm_task *dmt)
+{
+	dmt->retry_remove = 1;
+
+	return 1;
+}
+
 int dm_task_query_inactive_table(struct dm_task *dmt)
 {
 	dmt->query_inactive_table = 1;
@@ -1539,16 +1546,15 @@
 	return sanitised_message;
 }
 
-#define DM_REMOVE_IOCTL_RETRIES 25
-
 static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
-				     unsigned repeat_count)
+				     unsigned buffer_repeat_count,
+				     unsigned retry_repeat_count,
+				     int *retryable)
 {
 	struct dm_ioctl *dmi;
 	int ioctl_with_uevent;
-	int retries = DM_REMOVE_IOCTL_RETRIES;
 
-	dmi = _flatten(dmt, repeat_count);
+	dmi = _flatten(dmt, buffer_repeat_count);
 	if (!dmi) {
 		log_error("Couldn't create ioctl argument.");
 		return NULL;
@@ -1609,7 +1615,7 @@
 	}
 
 	log_debug("dm %s %s%s %s%s%s %s%.0d%s%.0d%s"
-		  "%s%c%c%s%s%s%s%s %.0" PRIu64 " %s [%u]",
+		  "%s%c%c%s%s%s%s%s%s %.0" PRIu64 " %s [%u] (*%u)",
 		  _cmd_data_v4[dmt->type].name,
 		  dmt->new_uuid ? "UUID " : "",
 		  dmi->name, dmi->uuid, dmt->newname ? " " : "",
@@ -1624,29 +1630,18 @@
 		  dmt->no_flush ? 'N' : 'F',
 		  dmt->read_only ? "R" : "",
 		  dmt->skip_lockfs ? "S " : "",
+		  dmt->retry_remove ? "T " : "",
 		  dmt->secure_data ? "W " : "",
 		  dmt->query_inactive_table ? "I " : "",
 		  dmt->enable_checks ? "C" : "",
 		  dmt->sector, _sanitise_message(dmt->message),
-		  dmi->data_size);
+		  dmi->data_size, retry_repeat_count);
 #ifdef DM_IOCTLS
-repeat_dm_ioctl:
 	if (ioctl(_control_fd, command, dmi) < 0) {
 		if (errno == ENXIO && ((dmt->type == DM_DEVICE_INFO) ||
 				       (dmt->type == DM_DEVICE_MKNODES) ||
 				       (dmt->type == DM_DEVICE_STATUS)))
 			dmi->flags &= ~DM_EXISTS_FLAG;	/* FIXME */
-		/*
-		 * FIXME: This is a workaround for asynchronous events generated
-		 *        as a result of using the WATCH udev rule with which we
-		 *        have no way of synchronizing. Processing such events in
-		 *        parallel causes devices to be open.
-		 */
-		else if (errno == EBUSY && (dmt->type == DM_DEVICE_REMOVE) && retries--) {
-			log_debug("device-mapper: device is busy, retrying removal");
-			usleep(200000);
-			goto repeat_dm_ioctl;
-		}
 		else {
 			if (_log_suppress)
 				log_verbose("device-mapper: %s ioctl "
@@ -1658,6 +1653,9 @@
 					  "failed: %s",
 					  _cmd_data_v4[dmt->type].name,
 					  strerror(errno));
+
+			*retryable = errno == EBUSY;
+
 			_dm_zfree_dmi(dmi);
 			return NULL;
 		}
@@ -1680,6 +1678,9 @@
 	update_devs();
 }
 
+#define DM_IOCTL_RETRIES 25
+#define DM_RETRY_USLEEP_DELAY 200000
+
 int dm_task_run(struct dm_task *dmt)
 {
 	struct dm_ioctl *dmi;
@@ -1687,6 +1688,8 @@
 	int check_udev;
 	int rely_on_udev;
 	int suspended_counter;
+	unsigned ioctl_retry = 1;
+	int retryable;
 
 	if ((unsigned) dmt->type >=
 	    (sizeof(_cmd_data_v4) / sizeof(*_cmd_data_v4))) {
@@ -1734,7 +1737,14 @@
 
 	/* FIXME Detect and warn if cookie set but should not be. */
 repeat_ioctl:
-	if (!(dmi = _do_dm_ioctl(dmt, command, _ioctl_buffer_double_factor))) {
+	if (!(dmi = _do_dm_ioctl(dmt, command, _ioctl_buffer_double_factor,
+				 ioctl_retry, &retryable))) {
+		if (retryable && dmt->type == DM_DEVICE_REMOVE &&
+		    dmt->retry_remove && ++ioctl_retry <= DM_IOCTL_RETRIES) {
+			usleep(DM_RETRY_USLEEP_DELAY);
+			goto repeat_ioctl;
+		}
+
 		_udev_complete(dmt);
 		return 0;
 	}
--- LVM2/libdm/ioctl/libdm-targets.h	2011/08/09 17:56:48	1.31
+++ LVM2/libdm/ioctl/libdm-targets.h	2011/09/22 17:09:49	1.32
@@ -63,6 +63,7 @@
 	int cookie_set;
 	int new_uuid;
 	int secure_data;
+	int retry_remove;
 	int enable_checks;
 
 	char *uuid;




More information about the lvm-devel mailing list