From cf37d5c7abf4f85dfdda520920fce48bba9ba52a Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Fri, 23 Jan 2004 14:37:47 +0000 Subject: [PATCH] Userspace support for LIST_VERSIONS ioctl. --- libdm/.export.sym | 1 + libdm/ioctl/libdevmapper.c | 11 +++++++++++ libdm/ioctl/libdm-compat.h | 33 +++++++++++++++++---------------- libdm/libdevmapper.h | 12 +++++++++++- tools/dmsetup.c | 37 ++++++++++++++++++++++++++++++++++++- 5 files changed, 76 insertions(+), 18 deletions(-) diff --git a/libdm/.export.sym b/libdm/.export.sym index 0399e6e2e..1c5b956e3 100644 --- a/libdm/.export.sym +++ b/libdm/.export.sym @@ -12,6 +12,7 @@ Base { dm_task_get_deps; dm_task_get_name; dm_task_get_names; + dm_task_get_versions; dm_task_get_uuid; dm_task_set_ro; dm_task_set_newname; diff --git a/libdm/ioctl/libdevmapper.c b/libdm/ioctl/libdevmapper.c index ac7ba0c86..10bcba60a 100644 --- a/libdm/ioctl/libdevmapper.c +++ b/libdm/ioctl/libdevmapper.c @@ -80,6 +80,7 @@ static struct cmd_data _cmd_data_v4[] = { {"names", DM_LIST_DEVICES, {4, 0, 0}}, {"clear", DM_TABLE_CLEAR, {4, 0, 0}}, {"mknodes", DM_DEV_STATUS, {4, 0, 0}}, + {"versions", DM_LIST_VERSIONS, {4, 1, 0}}, }; /* *INDENT-ON* */ @@ -384,6 +385,10 @@ static int _dm_names_v1(struct dm_ioctl_v1 *dmi) struct stat buf; char path[PATH_MAX]; + log_print("Warning: Device list may be incomplete with interface " + "version 1."); + log_print("Please upgrade your kernel device-mapper driver."); + if (!(d = opendir(dev_dir))) { log_error("%s: opendir failed: %s", dev_dir, strerror(errno)); return 0; @@ -736,6 +741,12 @@ struct dm_names *dm_task_get_names(struct dm_task *dmt) dmt->dmi.v4->data_start); } +struct dm_versions *dm_task_get_versions(struct dm_task *dmt) +{ + return (struct dm_versions *) (((void *) dmt->dmi.v4) + + dmt->dmi.v4->data_start); +} + int dm_task_set_ro(struct dm_task *dmt) { dmt->read_only = 1; diff --git a/libdm/ioctl/libdm-compat.h b/libdm/ioctl/libdm-compat.h index af7a9f1f7..bf16bb816 100644 --- a/libdm/ioctl/libdm-compat.h +++ b/libdm/ioctl/libdm-compat.h @@ -89,22 +89,23 @@ enum { /* *INDENT-OFF* */ static struct cmd_data _cmd_data_v1[] = { - { "create", DM_DEV_CREATE_V1, {1, 0, 0} }, - { "reload", DM_DEV_RELOAD_V1, {1, 0, 0} }, - { "remove", DM_DEV_REMOVE_V1, {1, 0, 0} }, - { "remove_all", DM_REMOVE_ALL_V1, {1, 0, 0} }, - { "suspend", DM_DEV_SUSPEND_V1, {1, 0, 0} }, - { "resume", DM_DEV_SUSPEND_V1, {1, 0, 0} }, - { "info", DM_DEV_STATUS_V1, {1, 0, 0} }, - { "deps", DM_DEV_DEPS_V1, {1, 0, 0} }, - { "rename", DM_DEV_RENAME_V1, {1, 0, 0} }, - { "version", DM_VERSION_V1, {1, 0, 0} }, - { "status", DM_TARGET_STATUS_V1, {1, 0, 0} }, - { "table", DM_TARGET_STATUS_V1, {1, 0, 0} }, - { "waitevent", DM_TARGET_WAIT_V1, {1, 0, 0} }, - { "names", 0, {4, 0, 0} }, - { "clear", 0, {4, 0, 0} }, - { "mknodes", 0, {4, 0, 0} }, + { "create", DM_DEV_CREATE_V1, {1, 0, 0} }, + { "reload", DM_DEV_RELOAD_V1, {1, 0, 0} }, + { "remove", DM_DEV_REMOVE_V1, {1, 0, 0} }, + { "remove_all", DM_REMOVE_ALL_V1, {1, 0, 0} }, + { "suspend", DM_DEV_SUSPEND_V1, {1, 0, 0} }, + { "resume", DM_DEV_SUSPEND_V1, {1, 0, 0} }, + { "info", DM_DEV_STATUS_V1, {1, 0, 0} }, + { "deps", DM_DEV_DEPS_V1, {1, 0, 0} }, + { "rename", DM_DEV_RENAME_V1, {1, 0, 0} }, + { "version", DM_VERSION_V1, {1, 0, 0} }, + { "status", DM_TARGET_STATUS_V1, {1, 0, 0} }, + { "table", DM_TARGET_STATUS_V1, {1, 0, 0} }, + { "waitevent", DM_TARGET_WAIT_V1, {1, 0, 0} }, + { "names", 0, {4, 0, 0} }, + { "clear", 0, {4, 0, 0} }, + { "mknodes", 0, {4, 0, 0} }, + { "versions", 0, {4, 1, 0} }, }; /* *INDENT-ON* */ diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h index 42ef16a5c..87038c35a 100644 --- a/libdm/libdevmapper.h +++ b/libdm/libdevmapper.h @@ -57,7 +57,9 @@ enum { DM_DEVICE_CLEAR, - DM_DEVICE_MKNODES + DM_DEVICE_MKNODES, + + DM_DEVICE_LIST_VERSIONS }; struct dm_task; @@ -97,6 +99,13 @@ struct dm_names { char name[0]; }; +struct dm_versions { + uint32_t next; /* Offset to next struct from start of this struct */ + uint32_t version[3]; + + char name[0]; +}; + int dm_get_library_version(char *version, size_t size); int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size); int dm_task_get_info(struct dm_task *dmt, struct dm_info *dmi); @@ -105,6 +114,7 @@ const char *dm_task_get_uuid(struct dm_task *dmt); struct dm_deps *dm_task_get_deps(struct dm_task *dmt); struct dm_names *dm_task_get_names(struct dm_task *dmt); +struct dm_versions *dm_task_get_versions(struct dm_task *dmt); int dm_task_set_ro(struct dm_task *dmt); int dm_task_set_newname(struct dm_task *dmt, const char *newname); diff --git a/tools/dmsetup.c b/tools/dmsetup.c index b8ed05d39..a51dac319 100644 --- a/tools/dmsetup.c +++ b/tools/dmsetup.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001 Sistina Software (UK) Limited. + * Copyright (C) 2001-2003 Sistina Software (UK) Limited. * * This file is released under the GPL. */ @@ -462,6 +462,40 @@ static int _status(int argc, char **argv, void *data) } +/* Show target names and their version numbers */ +static int _targets(int argc, char **argv, void *data) +{ + int r = 0; + struct dm_task *dmt; + struct dm_versions *target; + struct dm_versions *last_target; + + if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS))) + return 0; + + if (!dm_task_run(dmt)) + goto out; + + target = dm_task_get_versions(dmt); + + /* Fetch targets and print 'em */ + do { + last_target = target; + + printf("%-16s v%d.%d.%d\n", target->name, target->version[0], + target->version[1], target->version[2]); + + target = (void *) target + target->next; + } while (last_target != target); + + r = 1; + + out: + dm_task_destroy(dmt); + return r; + +} + static int _info(int argc, char **argv, void *data) { int r = 0; @@ -611,6 +645,7 @@ static struct command _commands[] = { {"status", "[]", 0, 1, _status}, {"table", "[]", 0, 1, _status}, {"wait", " []", 1, 2, _wait}, + {"targets", "", 0, 0, _targets}, {"version", "", 0, 0, _version}, {NULL, NULL, 0, 0, NULL} };