]> sourceware.org Git - dm.git/commitdiff
Add --force to dmsetup remove* to load error target. [Untested.]
authorAlasdair Kergon <agk@redhat.com>
Sun, 18 Jun 2006 11:35:04 +0000 (11:35 +0000)
committerAlasdair Kergon <agk@redhat.com>
Sun, 18 Jun 2006 11:35:04 +0000 (11:35 +0000)
Update dmsetup man page.

WHATS_NEW
dmsetup/dmsetup.c
man/dmsetup.8

index 158b0c80d377fbc9f812add0ac9cdffe0407dd2b..0aba42a684355a0e491ac6b37f2d110bfe73ec24 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,7 @@
 Version 1.02.08 - 
 =============================
+  Update dmsetup man page.
+  Add --force to dmsetup remove* to load error target.
   dmsetup remove_all also performs mknodes.
   Don't suppress identical table reloads if permission changes.
   Fix corelog segment line.
index 3a42a250f9a76379929a4db43b75497885b34ee3..d2d7cb2f694cd181ae75e9f645bfaf59e0603ec3 100644 (file)
@@ -88,6 +88,7 @@ enum {
        READ_ONLY = 0,
        COLS_ARG,
        EXEC_ARG,
+       FORCE_ARG,
        GID_ARG,
        MAJOR_ARG,
        MINOR_ARG,
@@ -108,6 +109,7 @@ enum {
 
 static int _switches[NUM_SWITCHES];
 static int _values[NUM_SWITCHES];
+static int _num_devices;
 static char *_uuid;
 static char *_fields;
 static char *_target;
@@ -386,7 +388,7 @@ static int _create(int argc, char **argv, void *data __attribute((unused)))
 
        if (argc == 3)
                file = argv[2];
+
        if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
                return 0;
 
@@ -602,16 +604,6 @@ static int _simple(int task, const char *name, uint32_t event_nr, int display)
        return r;
 }
 
-static int _remove_all(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused)))
-{
-       return _simple(DM_DEVICE_REMOVE_ALL, "", 0, 0) | dm_mknodes(NULL);
-}
-
-static int _remove(int argc, char **argv, void *data __attribute((unused)))
-{
-       return _simple(DM_DEVICE_REMOVE, argc > 1 ? argv[1] : NULL, 0, 0);
-}
-
 static int _suspend(int argc, char **argv, void *data __attribute((unused)))
 {
        return _simple(DM_DEVICE_SUSPEND, argc > 1 ? argv[1] : NULL, 0, 1);
@@ -683,6 +675,127 @@ static int _process_all(int argc, char **argv,
        return r;
 }
 
+static uint64_t _get_device_size(const char *name)
+{
+       uint64_t start, length, size = UINT64_C(0);
+       struct dm_info info;
+       char *target_type, *params;
+       struct dm_task *dmt;
+       void *next;
+
+       if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
+               return 0;
+
+       if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
+               goto out;
+
+       if (!dm_task_run(dmt))
+               goto out;
+
+       if (!dm_task_get_info(dmt, &info) || !info.exists)
+               goto out;
+
+       do {
+               next = dm_get_next_target(dmt, next, &start, &length,
+                                         &target_type, &params);
+               size += length;
+       } while (next);
+
+      out:
+       dm_task_destroy(dmt);
+       return size;
+}
+
+static int _error_device(int argc __attribute((unused)), char **argv __attribute((unused)), void *data)
+{
+       struct dm_names *names = (struct dm_names *) data;
+       struct dm_task *dmt;
+       const char *name;
+       uint64_t size;
+
+       if (data)
+               name = names->name;
+       else
+               name = argv[1];
+
+       size = _get_device_size(name);
+
+        if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
+                return 0;
+
+        if (!dm_task_add_target(dmt, 0, size, "error", ""))
+               goto err_task;
+
+        if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
+                goto err_task;
+
+        if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
+                goto err_task;
+
+        if (!dm_task_run(dmt))
+                goto err_task;
+
+       if (!_simple(DM_DEVICE_RESUME, name, 0, 0))
+               goto err_clear;
+
+       return 1;
+
+err_task:
+       dm_task_destroy(dmt);
+       return 0;
+
+err_clear:
+       _simple(DM_DEVICE_CLEAR, name, 0, 0);
+       return 0;
+}
+
+static int _remove(int argc, char **argv, void *data __attribute((unused)))
+{
+       int r;
+
+       if (_switches[FORCE_ARG] && argc > 1)
+               r = _error_device(argc, argv, NULL);
+
+       return _simple(DM_DEVICE_REMOVE, argc > 1 ? argv[1] : NULL, 0, 0);
+}
+
+static int _count_devices(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused)))
+{
+       _num_devices++;
+
+       return 1;
+}
+
+static int _remove_all(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused)))
+{
+       int r;
+
+       /* Remove all closed devices */
+       r =  _simple(DM_DEVICE_REMOVE_ALL, "", 0, 0) | dm_mknodes(NULL);
+
+       if (!_switches[FORCE_ARG])
+               return r;
+
+       _num_devices = 0;
+       r |= _process_all(argc, argv, _count_devices);
+
+       /* No devices left? */
+       if (!_num_devices)
+               return r;
+
+       r |= _process_all(argc, argv, _error_device);
+       r |= _simple(DM_DEVICE_REMOVE_ALL, "", 0, 0) | dm_mknodes(NULL);
+
+       _num_devices = 0;
+       r |= _process_all(argc, argv, _count_devices);
+       if (!_num_devices)
+               return r;
+
+       fprintf(stderr, "Unable to remove %d devices.", _num_devices);
+
+       return r;
+}
+
 static void _display_dev(struct dm_task *dmt, const char *name)
 {
        struct dm_info info;
@@ -1355,8 +1468,8 @@ static struct command _commands[] = {
          "\t                  [-U|--uid <uid>] [-G|--gid <gid>] [-M|--mode <octal_mode>]\n"
          "\t                  [-u|uuid <uuid>] [--notable] [<table_file>]",
         1, 2, _create},
-       {"remove", "<device>", 0, 1, _remove},
-       {"remove_all", "", 0, 0, _remove_all},
+       {"remove", "[-f|--force] <device>", 0, 1, _remove},
+       {"remove_all", "[-f|--force]", 0, 0, _remove_all},
        {"suspend", "<device>", 0, 1, _suspend},
        {"resume", "<device>", 0, 1, _resume},
        {"load", "<device> [<table_file>]", 0, 2, _load},
@@ -1482,6 +1595,7 @@ static int _process_switches(int *argc, char ***argv)
                {"readonly", 0, &ind, READ_ONLY},
                {"columns", 0, &ind, COLS_ARG},
                {"exec", 1, &ind, EXEC_ARG},
+               {"force", 0, &ind, FORCE_ARG},
                {"gid", 1, &ind, GID_ARG},
                {"major", 1, &ind, MAJOR_ARG},
                {"minor", 1, &ind, MINOR_ARG},
@@ -1526,7 +1640,7 @@ static int _process_switches(int *argc, char ***argv)
                        _values[MINOR_ARG] = atoi((*argv)[2]);
                        *argc -= 2;
                        *argv += 2;
-               } else if ((*argc == 2) && 
+               } else if ((*argc == 2) &&
                           (2 == sscanf((*argv)[1], "%i:%i",
                                        &_values[MAJOR_ARG],
                                        &_values[MINOR_ARG]))) {
@@ -1545,10 +1659,12 @@ static int _process_switches(int *argc, char ***argv)
 
        optarg = 0;
        optind = OPTIND_INIT;
-       while ((ind = -1, c = GETOPTLONG_FN(*argc, *argv, "cCGj:m:Mno:ru:Uv",
+       while ((ind = -1, c = GETOPTLONG_FN(*argc, *argv, "cCfGj:m:Mno:ru:Uv",
                                            long_options, NULL)) != -1) {
                if (c == 'c' || c == 'C' || ind == COLS_ARG)
                        _switches[COLS_ARG]++;
+               if (c == 'f' || ind == FORCE_ARG)
+                       _switches[FORCE_ARG]++;
                if (c == 'r' || ind == READ_ONLY)
                        _switches[READ_ONLY]++;
                if (c == 'j' || ind == MAJOR_ARG) {
index a58dd1582ed0d54d7585d92d9b6ac126739a57ee..42d452a92e9ab99c0e713b3a1c4ca0c9d02d3ad1 100644 (file)
@@ -7,9 +7,10 @@ dmsetup \- low level logical volume management
 .I device_name [-u uuid] [--notable] [table_file]
 .br
 .B dmsetup remove
-.I device_name
+.I [-f|--force] device_name
 .br
 .B dmsetup remove_all
+.I [-f|--force]
 .br
 .B dmsetup suspend
 .I [--nolockfs] device_name
@@ -103,7 +104,7 @@ Set the table being loaded read-only.
 .IP \fB-u|--uuid
 .br
 Specify the uuid.
-.IP \fB-v|--verbose [-v|--verbose]
+.IP \fB-v|--verbose\ [-v|--verbose]
 .br
 Produce additional output.
 .IP \fB--version
@@ -163,15 +164,34 @@ ascii, utf, vt100; compact, inverted, notrunc.
 .br
 Loads table_file into the inactive table slot for device_name.
 If table_file is not supplied, reads a table from standard input.
-.IP \fBremove
-.I device_name
+.IP \fBmknodes
+.I [device_name]
 .br
-Removes a device.  It will no longer be visible to dmsetup and
-will be deleted when its open_count is zero.
+Ensure that the node in /dev/mapper for device_name is correct.
+If no device_name is supplied, ensure that all nodes in /dev/mapper 
+correspond to mapped devices currently loaded by the device-mapper kernel
+driver, adding, changing or removing nodes as necessary.
+.IP \fBremove
+.I [-f|--force] device_name
+.br
+Removes a device.  It will no longer be visible to dmsetup.
+Open devices cannot be removed except with older kernels
+that contain a version of device-mapper prior to 4.8.0.
+In this case the device will be deleted when its open_count 
+drops to zero.  From version 4.8.0 onwards, if a device can't
+be removed because an uninterruptible process is waiting for
+I/O to return from it, adding --force will replace the table 
+with one that fails all I/O, which might allow the 
+process to be killed.
 .IP \fBremove_all
+.I [-f|--force]
 .br
 Attempts to remove all device definitions i.e. reset the driver.
-Use with care!
+Use with care!  From version 4.8.0 onwards, if devices can't
+be removed because uninterruptible processess are waiting for
+I/O to return from them, adding --force will replace the table 
+with one that fails all I/O, which might allow the 
+process to be killed.  This also runs \fBmknodes\fP afterwards.
 .IP \fBrename
 .I device_name new_name
 .br
This page took 0.037865 seconds and 5 git commands to generate.