diff options
| author | Alasdair G. Kergon <agk@redhat.com> | 2004-11-15 04:09:53 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-11-15 04:09:53 -0800 |
| commit | 30b81706fb10abd310579954438f3bb0cd3dd91b (patch) | |
| tree | 5c971682a6c968f6d6e228f11c94bf734b1cb146 | |
| parent | b93ddaf80b8184c1def38a8518b8fdbdd78e73e1 (diff) | |
[PATCH] device-mapper: Allow referencing by device number
Currently userspace code using the dm ioctls must refer to a mapped device by
either its name or its uuid. But in some circumstances you know neither of
those directly.
This patch lets you reference devices by their major/minor numbers as an
alternative.
Signed-Off-By: Alasdair G Kergon <agk@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | drivers/md/dm-ioctl.c | 29 | ||||
| -rw-r--r-- | drivers/md/dm.c | 41 | ||||
| -rw-r--r-- | drivers/md/dm.h | 2 | ||||
| -rw-r--r-- | include/linux/dm-ioctl.h | 4 |
4 files changed, 56 insertions, 20 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index bcecafe8431c..9f0073f4e0c4 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -18,7 +18,7 @@ #include <asm/uaccess.h> -#define DM_DRIVER_EMAIL "dm@uk.sistina.com" +#define DM_DRIVER_EMAIL "dm-devel@redhat.com" /*----------------------------------------------------------------- * The ioctl interface needs to be able to look up devices by @@ -225,6 +225,7 @@ static int dm_hash_insert(const char *name, const char *uuid, struct mapped_devi } register_with_devfs(cell); dm_get(md); + dm_set_mdptr(md, cell); up_write(&_hash_lock); return 0; @@ -241,6 +242,7 @@ static void __hash_remove(struct hash_cell *hc) list_del(&hc->uuid_list); list_del(&hc->name_list); unregister_with_devfs(hc); + dm_set_mdptr(hc->md, NULL); dm_put(hc->md); if (hc->new_map) dm_table_put(hc->new_map); @@ -580,12 +582,16 @@ static int dev_create(struct dm_ioctl *param, size_t param_size) } /* - * Always use UUID for lookups if it's present, otherwise use name. + * Always use UUID for lookups if it's present, otherwise use name or dev. */ static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) { - return *param->uuid ? - __get_uuid_cell(param->uuid) : __get_name_cell(param->name); + if (*param->uuid) + return __get_uuid_cell(param->uuid); + else if (*param->name) + return __get_name_cell(param->name); + else + return dm_get_mdptr(huge_decode_dev(param->dev)); } static inline struct mapped_device *find_device(struct dm_ioctl *param) @@ -597,6 +603,7 @@ static inline struct mapped_device *find_device(struct dm_ioctl *param) hc = __find_device_hash_cell(param); if (hc) { md = hc->md; + dm_get(md); /* * Sneakily write in both the name and the uuid @@ -612,8 +619,6 @@ static inline struct mapped_device *find_device(struct dm_ioctl *param) param->flags |= DM_INACTIVE_PRESENT_FLAG; else param->flags &= ~DM_INACTIVE_PRESENT_FLAG; - - dm_get(md); } up_read(&_hash_lock); @@ -1266,14 +1271,14 @@ static int validate_params(uint cmd, struct dm_ioctl *param) cmd == DM_LIST_VERSIONS_CMD) return 0; - /* Unless creating, either name or uuid but not both */ - if (cmd != DM_DEV_CREATE_CMD) { - if ((!*param->uuid && !*param->name) || - (*param->uuid && *param->name)) { - DMWARN("one of name or uuid must be supplied, cmd(%u)", - cmd); + if ((cmd == DM_DEV_CREATE_CMD)) { + if (!*param->name) { + DMWARN("name not supplied when creating device"); return -EINVAL; } + } else if ((*param->uuid && *param->name)) { + DMWARN("only supply one of name or uuid, cmd(%u)", cmd); + return -EINVAL; } /* Ensure strings are terminated */ diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 31a68d3b6ef2..bf99fec5d222 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2001, 2002 Sistina Software (UK) Limited. + * Copyright (C) 2004 Red Hat, Inc. All rights reserved. * * This file is released under the GPL. */ @@ -59,6 +60,8 @@ struct mapped_device { request_queue_t *queue; struct gendisk *disk; + void *interface_ptr; + /* * A list of ios that arrived while we were suspended. */ @@ -640,7 +643,7 @@ static void free_minor(unsigned int minor) /* * See if the device with a specific minor # is free. */ -static int specific_minor(unsigned int minor) +static int specific_minor(struct mapped_device *md, unsigned int minor) { int r, m; @@ -660,7 +663,7 @@ static int specific_minor(unsigned int minor) goto out; } - r = idr_get_new_above(&_minor_idr, specific_minor, minor, &m); + r = idr_get_new_above(&_minor_idr, md, minor, &m); if (r) { goto out; } @@ -676,7 +679,7 @@ out: return r; } -static int next_free_minor(unsigned int *minor) +static int next_free_minor(struct mapped_device *md, unsigned int *minor) { int r; unsigned int m; @@ -689,7 +692,7 @@ static int next_free_minor(unsigned int *minor) goto out; } - r = idr_get_new(&_minor_idr, next_free_minor, &m); + r = idr_get_new(&_minor_idr, md, &m); if (r) { goto out; } @@ -723,7 +726,7 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent) } /* get a minor number for the dev */ - r = persistent ? specific_minor(minor) : next_free_minor(&minor); + r = persistent ? specific_minor(md, minor) : next_free_minor(md, &minor); if (r < 0) goto bad1; @@ -880,6 +883,32 @@ int dm_create_with_minor(unsigned int minor, struct mapped_device **result) return create_aux(minor, 1, result); } +void *dm_get_mdptr(dev_t dev) +{ + struct mapped_device *md; + void *mdptr = NULL; + unsigned minor = MINOR(dev); + + if (MAJOR(dev) != _major || minor >= (1 << MINORBITS)) + return NULL; + + down(&_minor_lock); + + md = idr_find(&_minor_idr, minor); + + if (md && (dm_disk(md)->first_minor == minor)) + mdptr = md->interface_ptr; + + up(&_minor_lock); + + return mdptr; +} + +void dm_set_mdptr(struct mapped_device *md, void *ptr) +{ + md->interface_ptr = ptr; +} + void dm_get(struct mapped_device *md) { atomic_inc(&md->holders); @@ -1139,5 +1168,5 @@ module_exit(dm_exit); module_param(major, uint, 0); MODULE_PARM_DESC(major, "The major number of the device mapper"); MODULE_DESCRIPTION(DM_NAME " driver"); -MODULE_AUTHOR("Joe Thornber <thornber@sistina.com>"); +MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>"); MODULE_LICENSE("GPL"); diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 165251cdd8dd..4ff5be590b0c 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -55,6 +55,8 @@ struct mapped_device; *---------------------------------------------------------------*/ int dm_create(struct mapped_device **md); int dm_create_with_minor(unsigned int minor, struct mapped_device **md); +void dm_set_mdptr(struct mapped_device *md, void *ptr); +void *dm_get_mdptr(dev_t dev); /* * Reference counting for md. diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h index a1f659508c30..183e777d7786 100644 --- a/include/linux/dm-ioctl.h +++ b/include/linux/dm-ioctl.h @@ -272,9 +272,9 @@ typedef char ioctl_struct[308]; #define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl) #define DM_VERSION_MAJOR 4 -#define DM_VERSION_MINOR 2 +#define DM_VERSION_MINOR 3 #define DM_VERSION_PATCHLEVEL 0 -#define DM_VERSION_EXTRA "-ioctl (2004-06-08)" +#define DM_VERSION_EXTRA "-ioctl (2004-09-30)" /* Status bits */ #define DM_READONLY_FLAG (1 << 0) /* In/Out */ |
