From 9abf5e70be07b147c902e149521cf33cb76de78a Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Fri, 6 Nov 2009 00:43:08 +0000 Subject: [PATCH] Add support for querying a device's inactive table. Currently this data is invisible to userspace. Requires dm >= 4.16 (likely to be in linux 2.6.33). --- WHATS_NEW_DM | 2 ++ libdm/.exported_symbols | 1 + libdm/ioctl/libdm-iface.c | 16 ++++++++++++- libdm/ioctl/libdm-targets.h | 1 + libdm/libdevmapper.h | 1 + libdm/libdm-common.c | 1 + libdm/misc/dm-ioctl.h | 13 ++++++++--- man/dmsetup.8.in | 9 ++++++-- tools/dmsetup.c | 45 ++++++++++++++++++++++++++++++++++++- 9 files changed, 82 insertions(+), 7 deletions(-) diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM index 71b0223ac..28e86634a 100644 --- a/WHATS_NEW_DM +++ b/WHATS_NEW_DM @@ -1,5 +1,7 @@ Version 1.02.40 - =================================== + Add dmsetup --inactive support. + Add dm_task_query_inactive_table to libdevmapper for kernel driver >= 4.16. Fix hash lookup segfault when keys compared are different lengths. Version 1.02.39 - 26th October 2009 diff --git a/libdm/.exported_symbols b/libdm/.exported_symbols index 71f7b8653..554b90a91 100644 --- a/libdm/.exported_symbols +++ b/libdm/.exported_symbols @@ -40,6 +40,7 @@ dm_task_add_target dm_task_no_flush dm_task_no_open_count dm_task_skip_lockfs +dm_task_query_inactive_table dm_task_update_nodes dm_task_run dm_get_next_target diff --git a/libdm/ioctl/libdm-iface.c b/libdm/ioctl/libdm-iface.c index e49ac7127..6e6446f6e 100644 --- a/libdm/ioctl/libdm-iface.c +++ b/libdm/ioctl/libdm-iface.c @@ -1135,6 +1135,13 @@ int dm_task_skip_lockfs(struct dm_task *dmt) return 1; } +int dm_task_query_inactive_table(struct dm_task *dmt) +{ + dmt->query_inactive_table = 1; + + return 1; +} + int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr) { dmt->event_nr = event_nr; @@ -1382,6 +1389,12 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count) dmi->flags |= DM_READONLY_FLAG; if (dmt->skip_lockfs) dmi->flags |= DM_SKIP_LOCKFS_FLAG; + if (dmt->query_inactive_table) { + if (_dm_version_minor < 16) + log_warn("WARNING: Inactive table query unsupported " + "by kernel. It will use live table."); + dmi->flags |= DM_QUERY_INACTIVE_TABLE_FLAG; + } dmi->target_count = count; dmi->event_nr = dmt->event_nr; @@ -1723,7 +1736,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command, } log_debug("dm %s %s %s%s%s %s%.0d%s%.0d%s" - "%s%c%c%s %.0" PRIu64 " %s [%u]", + "%s%c%c%s%s %.0" PRIu64 " %s [%u]", _cmd_data_v4[dmt->type].name, dmi->name, dmi->uuid, dmt->newname ? " " : "", dmt->newname ? dmt->newname : "", @@ -1736,6 +1749,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command, dmt->no_open_count ? 'N' : 'O', dmt->no_flush ? 'N' : 'F', dmt->skip_lockfs ? "S " : "", + dmt->query_inactive_table ? "I " : "", dmt->sector, dmt->message ? dmt->message : "", dmi->data_size); #ifdef DM_IOCTLS diff --git a/libdm/ioctl/libdm-targets.h b/libdm/ioctl/libdm-targets.h index 5975f9853..ea3d14f77 100644 --- a/libdm/ioctl/libdm-targets.h +++ b/libdm/ioctl/libdm-targets.h @@ -58,6 +58,7 @@ struct dm_task { int no_flush; int no_open_count; int skip_lockfs; + int query_inactive_table; int suppress_identical_reload; uint64_t existing_table_size; int cookie_set; diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h index 721e08a00..ac0a758c5 100644 --- a/libdm/libdevmapper.h +++ b/libdm/libdevmapper.h @@ -172,6 +172,7 @@ int dm_task_set_sector(struct dm_task *dmt, uint64_t sector); int dm_task_no_flush(struct dm_task *dmt); int dm_task_no_open_count(struct dm_task *dmt); 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); /* diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c index ede17b25a..121f02005 100644 --- a/libdm/libdm-common.c +++ b/libdm/libdm-common.c @@ -181,6 +181,7 @@ struct dm_task *dm_task_create(int type) dmt->read_ahead_flags = 0; dmt->event_nr = 0; dmt->cookie_set = 0; + dmt->query_inactive_table = 0; return dmt; } diff --git a/libdm/misc/dm-ioctl.h b/libdm/misc/dm-ioctl.h index 8222a75d1..77979842b 100644 --- a/libdm/misc/dm-ioctl.h +++ b/libdm/misc/dm-ioctl.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2001 - 2003 Sistina Software (UK) Limited. - * Copyright (C) 2004 - 2005 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004 - 2009 Red Hat, Inc. All rights reserved. * * This file is released under the LGPL. */ @@ -268,9 +268,9 @@ enum { #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) #define DM_VERSION_MAJOR 4 -#define DM_VERSION_MINOR 15 +#define DM_VERSION_MINOR 16 #define DM_VERSION_PATCHLEVEL 0 -#define DM_VERSION_EXTRA "-ioctl (2009-04-01)" +#define DM_VERSION_EXTRA "-ioctl (2009-11-05)" /* Status bits */ #define DM_READONLY_FLAG (1 << 0) /* In/Out */ @@ -311,4 +311,11 @@ enum { */ #define DM_NOFLUSH_FLAG (1 << 11) /* In */ +/* + * If set, any table information returned will relate to the inactive + * table instead of the live one. Always check DM_INACTIVE_PRESENT_FLAG + * is set before using the data returned. + */ +#define DM_QUERY_INACTIVE_TABLE_FLAG (1 << 12) /* In */ + #endif /* _LINUX_DM_IOCTL_H */ diff --git a/man/dmsetup.8.in b/man/dmsetup.8.in index ebf422eb2..f3ca785d0 100644 --- a/man/dmsetup.8.in +++ b/man/dmsetup.8.in @@ -107,6 +107,11 @@ Invoking the command as \fBdevmap_name\fP is equivalent to .IP \fB-c|-C|--columns .br Display output in columns rather than as Field: Value lines. +.IP \fB--inactive +.br +When returning any table information from the kernel report on the +inactive table instead of the live table. +Requires kernel driver version 4.16.0 or above. .IP \fB-j|--major\ \fImajor .br Specify the major number. @@ -277,7 +282,7 @@ Sets the device geometry to C/H/S. Splits given device name into subsystem constituents. Default subsystem is LVM. .IP \fBstatus -.I [--target target_type] +.I [--target target_type] [--inactive] .I [device_name] .br Outputs status information for each of the device's targets. @@ -296,7 +301,7 @@ Some targets such as recent (October 2006) versions of multipath may support the --noflush option. This lets outstanding I/O that has not yet reached the device to remain unflushed. .IP \fBtable -.I [--target target_type] +.I [--target target_type] [--inactive] .I [device_name] .br Outputs the current table for the device in a format that can be fed diff --git a/tools/dmsetup.c b/tools/dmsetup.c index a7f1d257f..186f8f0c3 100644 --- a/tools/dmsetup.c +++ b/tools/dmsetup.c @@ -117,6 +117,7 @@ enum { EXEC_ARG, FORCE_ARG, GID_ARG, + INACTIVE_ARG, MAJOR_ARG, MINOR_ARG, MODE_ARG, @@ -296,6 +297,9 @@ static struct dm_task *_get_deps_task(int major, int minor) if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto err; + if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt)) + goto err; + if (!dm_task_run(dmt)) goto err; @@ -530,6 +534,9 @@ static int _load(int argc, char **argv, void *data __attribute((unused))) if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto out; + if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt)) + goto out; + if (!dm_task_run(dmt)) goto out; @@ -587,6 +594,9 @@ static int _create(int argc, char **argv, void *data __attribute((unused))) if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto out; + if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt)) + goto out; + if (_switches[READAHEAD_ARG] && !dm_task_set_read_ahead(dmt, _int_args[READAHEAD_ARG], _read_ahead_flags)) @@ -630,6 +640,9 @@ static int _rename(int argc, char **argv, void *data __attribute((unused))) if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto out; + if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt)) + goto out; + if (!dm_task_set_cookie(dmt, &cookie, 0) || !dm_task_run(dmt)) goto out; @@ -696,6 +709,9 @@ static int _message(int argc, char **argv, void *data __attribute((unused))) if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto out; + if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt)) + goto out; + if (!dm_task_run(dmt)) goto out; @@ -728,6 +744,12 @@ static int _setgeometry(int argc, char **argv, void *data __attribute((unused))) if (!dm_task_set_geometry(dmt, argv[1], argv[2], argv[3], argv[4])) goto out; + if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) + goto out; + + if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt)) + goto out; + /* run the task */ if (!dm_task_run(dmt)) goto out; @@ -1002,6 +1024,9 @@ static int _simple(int task, const char *name, uint32_t event_nr, int display) if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto out; + if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt)) + goto out; + if (_switches[NOLOCKFS_ARG] && !dm_task_skip_lockfs(dmt)) goto out; @@ -1115,6 +1140,9 @@ static uint64_t _get_device_size(const char *name) if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto out; + if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt)) + goto out; + if (!dm_task_run(dmt)) goto out; @@ -1162,6 +1190,9 @@ static int _error_device(int argc __attribute((unused)), char **argv __attribute if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto error; + if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt)) + goto error; + if (!dm_task_run(dmt)) goto error; @@ -1337,6 +1368,9 @@ static int _status(int argc, char **argv, void *data) if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto out; + if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt)) + goto out; + if (!dm_task_run(dmt)) goto out; @@ -1458,6 +1492,9 @@ static int _info(int argc, char **argv, void *data) if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto out; + if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt)) + goto out; + if (!dm_task_run(dmt)) goto out; @@ -1496,6 +1533,9 @@ static int _deps(int argc, char **argv, void *data) if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto out; + if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt)) + goto out; + if (!dm_task_run(dmt)) goto out; @@ -2510,7 +2550,7 @@ static void _usage(FILE *out) fprintf(out, "Usage:\n\n"); fprintf(out, "dmsetup [--version] [-v|--verbose [-v|--verbose ...]]\n" - " [-r|--readonly] [--noopencount] [--nolockfs]\n" + " [-r|--readonly] [--noopencount] [--nolockfs] [--inactive]\n" " [--noudevsync] [-y|--yes] [--readahead [+]|auto|none]\n" " [-c|-C|--columns] [-o ] [-O|--sort ]\n" " [--nameprefixes] [--noheadings] [--separator ]\n\n"); @@ -2866,6 +2906,7 @@ static int _process_switches(int *argc, char ***argv, const char *dev_dir) {"exec", 1, &ind, EXEC_ARG}, {"force", 0, &ind, FORCE_ARG}, {"gid", 1, &ind, GID_ARG}, + {"inactive", 0, &ind, INACTIVE_ARG}, {"major", 1, &ind, MAJOR_ARG}, {"minor", 1, &ind, MINOR_ARG}, {"mode", 1, &ind, MODE_ARG}, @@ -3010,6 +3051,8 @@ static int _process_switches(int *argc, char ***argv, const char *dev_dir) _switches[TARGET_ARG]++; _target = optarg; } + if ((ind == INACTIVE_ARG)) + _switches[INACTIVE_ARG]++; if ((ind == NAMEPREFIXES_ARG)) _switches[NAMEPREFIXES_ARG]++; if ((ind == NOFLUSH_ARG))