1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-22 17:35:59 +03:00

Add --force to dmsetup remove* to load error target. [Untested.]

Update dmsetup man page.
This commit is contained in:
Alasdair Kergon 2006-06-18 11:35:04 +00:00
parent 3426f31184
commit 1e4b82cc94
3 changed files with 160 additions and 22 deletions

View File

@ -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.

View 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

View 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;
@ -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},
@ -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) {