]> sourceware.org Git - lvm2.git/commitdiff
Add dm_task_retry_remove fn to use retry logic for device removal.
authorPeter Rajnoha <prajnoha@redhat.com>
Thu, 22 Sep 2011 17:09:48 +0000 (17:09 +0000)
committerPeter Rajnoha <prajnoha@redhat.com>
Thu, 22 Sep 2011 17:09:48 +0000 (17:09 +0000)
This call ensures that the dm device removal is retried several
times before failing.

WHATS_NEW_DM
libdm/ioctl/libdm-iface.c
libdm/ioctl/libdm-targets.h
libdm/libdevmapper.h

index eec750e07c10969a140992c07358663dffa60b75..0ed1a14a0140944e17bbab9109bffe8e2dfa509d 100644 (file)
@@ -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.
index a6097d35dbb8d0c49435727f0303cca210c1612b..3bd5a7c1e50218f917481c0b5d4a300e9e4eb1bb 100644 (file)
@@ -828,6 +828,13 @@ int dm_task_secure_data(struct dm_task *dmt)
        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 @@ static const char *_sanitise_message(char *message)
        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 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
        }
 
        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 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
                  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 @@ repeat_dm_ioctl:
                                          "failed: %s",
                                          _cmd_data_v4[dmt->type].name,
                                          strerror(errno));
+
+                       *retryable = errno == EBUSY;
+
                        _dm_zfree_dmi(dmi);
                        return NULL;
                }
@@ -1680,6 +1678,9 @@ void dm_task_update_nodes(void)
        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 dm_task_run(struct dm_task *dmt)
        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 @@ int dm_task_run(struct dm_task *dmt)
 
        /* 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;
        }
index 82792e00d9e95ce9c1a791dfd768e7d58aebf131..ca08fe835ad34af9b28b4b76039047f792feabac 100644 (file)
@@ -63,6 +63,7 @@ struct dm_task {
        int cookie_set;
        int new_uuid;
        int secure_data;
+       int retry_remove;
        int enable_checks;
 
        char *uuid;
index c0b9fff19e76f69708260626a8bdee84e9739c35..628d7dac2e9f7b1bfc75614f5acbdb7d3c27697f 100644 (file)
@@ -191,6 +191,7 @@ int dm_task_skip_lockfs(struct dm_task *dmt);
 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.
This page took 0.046554 seconds and 5 git commands to generate.