Merge with Linux 2.5.48.
[linux-2.6/linux-mips.git] / drivers / md / dm-ioctl.c
bloba3bb66d0873f68be2a59b684bc4c1566ec0a8d19
1 /*
2 * Copyright (C) 2001, 2002 Sistina Software (UK) Limited.
4 * This file is released under the GPL.
5 */
7 #include "dm.h"
9 #include <linux/module.h>
10 #include <linux/vmalloc.h>
11 #include <linux/compatmac.h>
12 #include <linux/miscdevice.h>
13 #include <linux/dm-ioctl.h>
14 #include <linux/init.h>
15 #include <linux/wait.h>
16 #include <linux/blk.h>
17 #include <linux/slab.h>
19 #define DM_DRIVER_EMAIL "dm@uk.sistina.com"
21 /*-----------------------------------------------------------------
22 * The ioctl interface needs to be able to look up devices by
23 * name or uuid.
24 *---------------------------------------------------------------*/
25 struct hash_cell {
26 struct list_head name_list;
27 struct list_head uuid_list;
29 char *name;
30 char *uuid;
31 struct mapped_device *md;
33 /* I hate devfs */
34 devfs_handle_t devfs_entry;
37 #define NUM_BUCKETS 64
38 #define MASK_BUCKETS (NUM_BUCKETS - 1)
39 static struct list_head _name_buckets[NUM_BUCKETS];
40 static struct list_head _uuid_buckets[NUM_BUCKETS];
42 static devfs_handle_t _dev_dir;
43 void dm_hash_remove_all(void);
46 * Guards access to all three tables.
48 static DECLARE_RWSEM(_hash_lock);
50 static void init_buckets(struct list_head *buckets)
52 unsigned int i;
54 for (i = 0; i < NUM_BUCKETS; i++)
55 INIT_LIST_HEAD(buckets + i);
58 int dm_hash_init(void)
60 init_buckets(_name_buckets);
61 init_buckets(_uuid_buckets);
62 _dev_dir = devfs_mk_dir(0, DM_DIR, NULL);
63 return 0;
66 void dm_hash_exit(void)
68 dm_hash_remove_all();
69 devfs_unregister(_dev_dir);
72 /*-----------------------------------------------------------------
73 * Hash function:
74 * We're not really concerned with the str hash function being
75 * fast since it's only used by the ioctl interface.
76 *---------------------------------------------------------------*/
77 static unsigned int hash_str(const char *str)
79 const unsigned int hash_mult = 2654435387U;
80 unsigned int h = 0;
82 while (*str)
83 h = (h + (unsigned int) *str++) * hash_mult;
85 return h & MASK_BUCKETS;
88 /*-----------------------------------------------------------------
89 * Code for looking up a device by name
90 *---------------------------------------------------------------*/
91 static struct hash_cell *__get_name_cell(const char *str)
93 struct list_head *tmp;
94 struct hash_cell *hc;
95 unsigned int h = hash_str(str);
97 list_for_each (tmp, _name_buckets + h) {
98 hc = list_entry(tmp, struct hash_cell, name_list);
99 if (!strcmp(hc->name, str))
100 return hc;
103 return NULL;
106 static struct hash_cell *__get_uuid_cell(const char *str)
108 struct list_head *tmp;
109 struct hash_cell *hc;
110 unsigned int h = hash_str(str);
112 list_for_each (tmp, _uuid_buckets + h) {
113 hc = list_entry(tmp, struct hash_cell, uuid_list);
114 if (!strcmp(hc->uuid, str))
115 return hc;
118 return NULL;
121 /*-----------------------------------------------------------------
122 * Inserting, removing and renaming a device.
123 *---------------------------------------------------------------*/
124 static inline char *kstrdup(const char *str)
126 char *r = kmalloc(strlen(str) + 1, GFP_KERNEL);
127 if (r)
128 strcpy(r, str);
129 return r;
132 static struct hash_cell *alloc_cell(const char *name, const char *uuid,
133 struct mapped_device *md)
135 struct hash_cell *hc;
137 hc = kmalloc(sizeof(*hc), GFP_KERNEL);
138 if (!hc)
139 return NULL;
141 hc->name = kstrdup(name);
142 if (!hc->name) {
143 kfree(hc);
144 return NULL;
147 if (!uuid)
148 hc->uuid = NULL;
150 else {
151 hc->uuid = kstrdup(uuid);
152 if (!hc->uuid) {
153 kfree(hc->name);
154 kfree(hc);
155 return NULL;
159 INIT_LIST_HEAD(&hc->name_list);
160 INIT_LIST_HEAD(&hc->uuid_list);
161 hc->md = md;
162 return hc;
165 static void free_cell(struct hash_cell *hc)
167 if (hc) {
168 kfree(hc->name);
169 kfree(hc->uuid);
170 kfree(hc);
175 * devfs stuff.
177 static int register_with_devfs(struct hash_cell *hc)
179 struct gendisk *disk = dm_disk(hc->md);
180 hc->devfs_entry =
181 devfs_register(_dev_dir, hc->name, DEVFS_FL_CURRENT_OWNER,
182 disk->major, disk->first_minor,
183 S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
184 &dm_blk_dops, NULL);
186 return 0;
189 static int unregister_with_devfs(struct hash_cell *hc)
191 devfs_unregister(hc->devfs_entry);
192 return 0;
196 * The kdev_t and uuid of a device can never change once it is
197 * initially inserted.
199 int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md)
201 struct hash_cell *cell;
204 * Allocate the new cells.
206 cell = alloc_cell(name, uuid, md);
207 if (!cell)
208 return -ENOMEM;
211 * Insert the cell into all three hash tables.
213 down_write(&_hash_lock);
214 if (__get_name_cell(name))
215 goto bad;
217 list_add(&cell->name_list, _name_buckets + hash_str(name));
219 if (uuid) {
220 if (__get_uuid_cell(uuid)) {
221 list_del(&cell->name_list);
222 goto bad;
224 list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid));
226 register_with_devfs(cell);
227 dm_get(md);
228 up_write(&_hash_lock);
230 return 0;
232 bad:
233 up_write(&_hash_lock);
234 free_cell(cell);
235 return -EBUSY;
238 void __hash_remove(struct hash_cell *hc)
240 /* remove from the dev hash */
241 list_del(&hc->uuid_list);
242 list_del(&hc->name_list);
243 unregister_with_devfs(hc);
244 dm_put(hc->md);
247 void dm_hash_remove_all(void)
249 int i;
250 struct hash_cell *hc;
251 struct list_head *tmp, *n;
253 down_write(&_hash_lock);
254 for (i = 0; i < NUM_BUCKETS; i++) {
255 list_for_each_safe (tmp, n, _name_buckets + i) {
256 hc = list_entry(tmp, struct hash_cell, name_list);
257 __hash_remove(hc);
260 up_write(&_hash_lock);
263 int dm_hash_rename(const char *old, const char *new)
265 char *new_name, *old_name;
266 struct hash_cell *hc;
269 * duplicate new.
271 new_name = kstrdup(new);
272 if (!new_name)
273 return -ENOMEM;
275 down_write(&_hash_lock);
278 * Is new free ?
280 hc = __get_name_cell(new);
281 if (hc) {
282 DMWARN("asked to rename to an already existing name %s -> %s",
283 old, new);
284 up_write(&_hash_lock);
285 return -EBUSY;
289 * Is there such a device as 'old' ?
291 hc = __get_name_cell(old);
292 if (!hc) {
293 DMWARN("asked to rename a non existent device %s -> %s",
294 old, new);
295 up_write(&_hash_lock);
296 return -ENXIO;
300 * rename and move the name cell.
302 list_del(&hc->name_list);
303 old_name = hc->name;
304 hc->name = new_name;
305 list_add(&hc->name_list, _name_buckets + hash_str(new_name));
307 /* rename the device node in devfs */
308 unregister_with_devfs(hc);
309 register_with_devfs(hc);
311 up_write(&_hash_lock);
312 kfree(old_name);
313 return 0;
317 /*-----------------------------------------------------------------
318 * Implementation of the ioctl commands
319 *---------------------------------------------------------------*/
322 * All the ioctl commands get dispatched to functions with this
323 * prototype.
325 typedef int (*ioctl_fn)(struct dm_ioctl *param, struct dm_ioctl *user);
328 * Check a string doesn't overrun the chunk of
329 * memory we copied from userland.
331 static int valid_str(char *str, void *begin, void *end)
333 while (((void *) str >= begin) && ((void *) str < end))
334 if (!*str++)
335 return 0;
337 return -EINVAL;
340 static int next_target(struct dm_target_spec *last, uint32_t next,
341 void *begin, void *end,
342 struct dm_target_spec **spec, char **params)
344 *spec = (struct dm_target_spec *)
345 ((unsigned char *) last + next);
346 *params = (char *) (*spec + 1);
348 if (*spec < (last + 1) || ((void *) *spec > end))
349 return -EINVAL;
351 return valid_str(*params, begin, end);
354 static int populate_table(struct dm_table *table, struct dm_ioctl *args)
356 int i = 0, r, first = 1;
357 struct dm_target_spec *spec;
358 char *params;
359 void *begin, *end;
361 if (!args->target_count) {
362 DMWARN("populate_table: no targets specified");
363 return -EINVAL;
366 begin = (void *) args;
367 end = begin + args->data_size;
369 for (i = 0; i < args->target_count; i++) {
371 if (first)
372 r = next_target((struct dm_target_spec *) args,
373 args->data_start,
374 begin, end, &spec, &params);
375 else
376 r = next_target(spec, spec->next, begin, end,
377 &spec, &params);
379 if (r) {
380 DMWARN("unable to find target");
381 return -EINVAL;
384 r = dm_table_add_target(table, spec->target_type,
385 spec->sector_start, spec->length,
386 params);
387 if (r) {
388 DMWARN("internal error adding target to table");
389 return -EINVAL;
392 first = 0;
395 return dm_table_complete(table);
399 * Round up the ptr to the next 'align' boundary. Obviously
400 * 'align' must be a power of 2.
402 static inline void *align_ptr(void *ptr, unsigned int align)
404 align--;
405 return (void *) (((unsigned long) (ptr + align)) & ~align);
409 * Copies a dm_ioctl and an optional additional payload to
410 * userland.
412 static int results_to_user(struct dm_ioctl *user, struct dm_ioctl *param,
413 void *data, uint32_t len)
415 int r;
416 void *ptr = NULL;
418 if (data) {
419 ptr = align_ptr(user + 1, sizeof(unsigned long));
420 param->data_start = ptr - (void *) user;
424 * The version number has already been filled in, so we
425 * just copy later fields.
427 r = copy_to_user(&user->data_size, &param->data_size,
428 sizeof(*param) - sizeof(param->version));
429 if (r)
430 return -EFAULT;
432 if (data) {
433 if (param->data_start + len > param->data_size)
434 return -ENOSPC;
436 if (copy_to_user(ptr, data, len))
437 r = -EFAULT;
440 return r;
444 * Fills in a dm_ioctl structure, ready for sending back to
445 * userland.
447 static int __info(struct mapped_device *md, struct dm_ioctl *param)
449 struct dm_table *table;
450 struct block_device *bdev;
451 struct gendisk *disk = dm_disk(md);
453 param->flags = DM_EXISTS_FLAG;
454 if (dm_suspended(md))
455 param->flags |= DM_SUSPEND_FLAG;
457 param->dev = MKDEV(disk->major, disk->first_minor);
458 bdev = bdget(param->dev);
459 if (!bdev)
460 return -ENXIO;
462 if (disk->policy)
463 param->flags |= DM_READONLY_FLAG;
465 param->open_count = bdev->bd_openers;
466 bdput(bdev);
468 table = dm_get_table(md);
469 param->target_count = dm_table_get_num_targets(table);
470 dm_table_put(table);
472 return 0;
476 * Always use UUID for lookups if it's present, otherwise use name.
478 static inline struct mapped_device *find_device(struct dm_ioctl *param)
480 struct hash_cell *hc;
481 struct mapped_device *md = NULL;
483 down_read(&_hash_lock);
484 hc = *param->uuid ? __get_uuid_cell(param->uuid) :
485 __get_name_cell(param->name);
486 if (hc) {
487 md = hc->md;
490 * Sneakily write in both the name and the uuid
491 * while we have the cell.
493 strncpy(param->name, hc->name, sizeof(param->name));
494 if (hc->uuid)
495 strncpy(param->uuid, hc->uuid, sizeof(param->uuid) - 1);
496 else
497 param->uuid[0] = '\0';
499 dm_get(md);
501 up_read(&_hash_lock);
503 return md;
506 #define ALIGNMENT sizeof(int)
507 static void *_align(void *ptr, unsigned int a)
509 register unsigned long align = --a;
511 return (void *) (((unsigned long) ptr + align) & ~align);
515 * Copies device info back to user space, used by
516 * the create and info ioctls.
518 static int info(struct dm_ioctl *param, struct dm_ioctl *user)
520 struct mapped_device *md;
522 param->flags = 0;
524 md = find_device(param);
525 if (!md)
527 * Device not found - returns cleared exists flag.
529 goto out;
531 __info(md, param);
532 dm_put(md);
534 out:
535 return results_to_user(user, param, NULL, 0);
538 static inline int get_mode(struct dm_ioctl *param)
540 int mode = FMODE_READ | FMODE_WRITE;
542 if (param->flags & DM_READONLY_FLAG)
543 mode = FMODE_READ;
545 return mode;
548 static int check_name(const char *name)
550 if (strchr(name, '/')) {
551 DMWARN("invalid device name");
552 return -EINVAL;
555 return 0;
558 static int create(struct dm_ioctl *param, struct dm_ioctl *user)
560 int r;
561 struct dm_table *t;
562 struct mapped_device *md;
563 int minor;
565 r = check_name(param->name);
566 if (r)
567 return r;
569 r = dm_table_create(&t, get_mode(param));
570 if (r)
571 return r;
573 r = populate_table(t, param);
574 if (r) {
575 dm_table_put(t);
576 return r;
579 minor = (param->flags & DM_PERSISTENT_DEV_FLAG) ?
580 minor(to_kdev_t(param->dev)) : -1;
582 r = dm_create(minor, t, &md);
583 if (r) {
584 dm_table_put(t);
585 return r;
587 dm_table_put(t); /* md will have grabbed its own reference */
589 set_disk_ro(dm_disk(md), (param->flags & DM_READONLY_FLAG));
590 r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md);
591 dm_put(md);
593 return r ? r : info(param, user);
597 * Build up the status struct for each target
599 static int __status(struct mapped_device *md, struct dm_ioctl *param,
600 char *outbuf, int *len)
602 int i, num_targets;
603 struct dm_target_spec *spec;
604 char *outptr;
605 status_type_t type;
606 struct dm_table *table = dm_get_table(md);
608 if (param->flags & DM_STATUS_TABLE_FLAG)
609 type = STATUSTYPE_TABLE;
610 else
611 type = STATUSTYPE_INFO;
613 outptr = outbuf;
615 /* Get all the target info */
616 num_targets = dm_table_get_num_targets(table);
617 for (i = 0; i < num_targets; i++) {
618 struct dm_target *ti = dm_table_get_target(table, i);
620 if (outptr - outbuf +
621 sizeof(struct dm_target_spec) > param->data_size) {
622 dm_table_put(table);
623 return -ENOMEM;
626 spec = (struct dm_target_spec *) outptr;
628 spec->status = 0;
629 spec->sector_start = ti->begin;
630 spec->length = ti->len;
631 strncpy(spec->target_type, ti->type->name,
632 sizeof(spec->target_type));
634 outptr += sizeof(struct dm_target_spec);
636 /* Get the status/table string from the target driver */
637 if (ti->type->status)
638 ti->type->status(ti, type, outptr,
639 outbuf + param->data_size - outptr);
640 else
641 outptr[0] = '\0';
643 outptr += strlen(outptr) + 1;
644 _align(outptr, ALIGNMENT);
645 spec->next = outptr - outbuf;
648 param->target_count = num_targets;
649 *len = outptr - outbuf;
650 dm_table_put(table);
652 return 0;
656 * Return the status of a device as a text string for each
657 * target.
659 static int get_status(struct dm_ioctl *param, struct dm_ioctl *user)
661 struct mapped_device *md;
662 int len = 0;
663 int ret;
664 char *outbuf = NULL;
666 md = find_device(param);
667 if (!md)
669 * Device not found - returns cleared exists flag.
671 goto out;
673 /* We haven't a clue how long the resultant data will be so
674 just allocate as much as userland has allowed us and make sure
675 we don't overun it */
676 outbuf = kmalloc(param->data_size, GFP_KERNEL);
677 if (!outbuf)
678 goto out;
680 * Get the status of all targets
682 __status(md, param, outbuf, &len);
685 * Setup the basic dm_ioctl structure.
687 __info(md, param);
689 out:
690 if (md)
691 dm_put(md);
693 ret = results_to_user(user, param, outbuf, len);
695 if (outbuf)
696 kfree(outbuf);
698 return ret;
702 * Wait for a device to report an event
704 static int wait_device_event(struct dm_ioctl *param, struct dm_ioctl *user)
706 struct mapped_device *md;
707 struct dm_table *table;
708 DECLARE_WAITQUEUE(wq, current);
710 md = find_device(param);
711 if (!md)
713 * Device not found - returns cleared exists flag.
715 goto out;
718 * Setup the basic dm_ioctl structure.
720 __info(md, param);
723 * Wait for a notification event
725 set_current_state(TASK_INTERRUPTIBLE);
726 table = dm_get_table(md);
727 dm_table_add_wait_queue(table, &wq);
728 dm_table_put(table);
729 dm_put(md);
731 yield();
732 set_current_state(TASK_RUNNING);
734 out:
735 return results_to_user(user, param, NULL, 0);
739 * Retrieves a list of devices used by a particular dm device.
741 static int dep(struct dm_ioctl *param, struct dm_ioctl *user)
743 int count, r;
744 struct mapped_device *md;
745 struct list_head *tmp;
746 size_t len = 0;
747 struct dm_target_deps *deps = NULL;
748 struct dm_table *table;
750 md = find_device(param);
751 if (!md)
752 goto out;
753 table = dm_get_table(md);
756 * Setup the basic dm_ioctl structure.
758 __info(md, param);
761 * Count the devices.
763 count = 0;
764 list_for_each(tmp, dm_table_get_devices(table))
765 count++;
768 * Allocate a kernel space version of the dm_target_status
769 * struct.
771 if (array_too_big(sizeof(*deps), sizeof(*deps->dev), count)) {
772 dm_table_put(table);
773 dm_put(md);
774 return -ENOMEM;
777 len = sizeof(*deps) + (sizeof(*deps->dev) * count);
778 deps = kmalloc(len, GFP_KERNEL);
779 if (!deps) {
780 dm_table_put(table);
781 dm_put(md);
782 return -ENOMEM;
786 * Fill in the devices.
788 deps->count = count;
789 count = 0;
790 list_for_each(tmp, dm_table_get_devices(table)) {
791 struct dm_dev *dd = list_entry(tmp, struct dm_dev, list);
792 deps->dev[count++] = dd->bdev->bd_dev;
794 dm_table_put(table);
795 dm_put(md);
797 out:
798 r = results_to_user(user, param, deps, len);
800 kfree(deps);
801 return r;
804 static int remove(struct dm_ioctl *param, struct dm_ioctl *user)
806 struct hash_cell *hc;
808 down_write(&_hash_lock);
809 hc = *param->uuid ? __get_uuid_cell(param->uuid) :
810 __get_name_cell(param->name);
811 if (!hc) {
812 DMWARN("device doesn't appear to be in the dev hash table.");
813 up_write(&_hash_lock);
814 return -EINVAL;
817 __hash_remove(hc);
818 up_write(&_hash_lock);
819 return 0;
822 static int remove_all(struct dm_ioctl *param, struct dm_ioctl *user)
824 dm_hash_remove_all();
825 return 0;
828 static int suspend(struct dm_ioctl *param, struct dm_ioctl *user)
830 int r;
831 struct mapped_device *md;
833 md = find_device(param);
834 if (!md)
835 return -ENXIO;
837 if (param->flags & DM_SUSPEND_FLAG)
838 r = dm_suspend(md);
839 else
840 r = dm_resume(md);
842 dm_put(md);
843 return r;
846 static int reload(struct dm_ioctl *param, struct dm_ioctl *user)
848 int r;
849 struct mapped_device *md;
850 struct dm_table *t;
852 r = dm_table_create(&t, get_mode(param));
853 if (r)
854 return r;
856 r = populate_table(t, param);
857 if (r) {
858 dm_table_put(t);
859 return r;
862 md = find_device(param);
863 if (!md) {
864 dm_table_put(t);
865 return -ENXIO;
868 r = dm_swap_table(md, t);
869 if (r) {
870 dm_put(md);
871 dm_table_put(t);
872 return r;
875 set_disk_ro(dm_disk(md), (param->flags & DM_READONLY_FLAG));
876 dm_put(md);
878 r = info(param, user);
879 return r;
882 static int rename(struct dm_ioctl *param, struct dm_ioctl *user)
884 int r;
885 char *new_name = (char *) param + param->data_start;
887 if (valid_str(new_name, (void *) param,
888 (void *) param + param->data_size)) {
889 DMWARN("Invalid new logical volume name supplied.");
890 return -EINVAL;
893 r = check_name(new_name);
894 if (r)
895 return r;
897 return dm_hash_rename(param->name, new_name);
901 /*-----------------------------------------------------------------
902 * Implementation of open/close/ioctl on the special char
903 * device.
904 *---------------------------------------------------------------*/
905 static ioctl_fn lookup_ioctl(unsigned int cmd)
907 static struct {
908 int cmd;
909 ioctl_fn fn;
910 } _ioctls[] = {
911 {DM_VERSION_CMD, NULL}, /* version is dealt with elsewhere */
912 {DM_REMOVE_ALL_CMD, remove_all},
913 {DM_DEV_CREATE_CMD, create},
914 {DM_DEV_REMOVE_CMD, remove},
915 {DM_DEV_RELOAD_CMD, reload},
916 {DM_DEV_RENAME_CMD, rename},
917 {DM_DEV_SUSPEND_CMD, suspend},
918 {DM_DEV_DEPS_CMD, dep},
919 {DM_DEV_STATUS_CMD, info},
920 {DM_TARGET_STATUS_CMD, get_status},
921 {DM_TARGET_WAIT_CMD, wait_device_event},
924 return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn;
928 * As well as checking the version compatibility this always
929 * copies the kernel interface version out.
931 static int check_version(int cmd, struct dm_ioctl *user)
933 uint32_t version[3];
934 int r = 0;
936 if (copy_from_user(version, user->version, sizeof(version)))
937 return -EFAULT;
939 if ((DM_VERSION_MAJOR != version[0]) ||
940 (DM_VERSION_MINOR < version[1])) {
941 DMWARN("ioctl interface mismatch: "
942 "kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)",
943 DM_VERSION_MAJOR, DM_VERSION_MINOR,
944 DM_VERSION_PATCHLEVEL,
945 version[0], version[1], version[2], cmd);
946 r = -EINVAL;
950 * Fill in the kernel version.
952 version[0] = DM_VERSION_MAJOR;
953 version[1] = DM_VERSION_MINOR;
954 version[2] = DM_VERSION_PATCHLEVEL;
955 if (copy_to_user(user->version, version, sizeof(version)))
956 return -EFAULT;
958 return r;
961 static void free_params(struct dm_ioctl *param)
963 vfree(param);
966 static int copy_params(struct dm_ioctl *user, struct dm_ioctl **param)
968 struct dm_ioctl tmp, *dmi;
970 if (copy_from_user(&tmp, user, sizeof(tmp)))
971 return -EFAULT;
973 if (tmp.data_size < sizeof(tmp))
974 return -EINVAL;
976 dmi = (struct dm_ioctl *) vmalloc(tmp.data_size);
977 if (!dmi)
978 return -ENOMEM;
980 if (copy_from_user(dmi, user, tmp.data_size)) {
981 vfree(dmi);
982 return -EFAULT;
985 *param = dmi;
986 return 0;
989 static int validate_params(uint cmd, struct dm_ioctl *param)
991 /* Unless creating, either name of uuid but not both */
992 if (cmd != DM_DEV_CREATE_CMD) {
993 if ((!*param->uuid && !*param->name) ||
994 (*param->uuid && *param->name)) {
995 DMWARN("one of name or uuid must be supplied");
996 return -EINVAL;
1000 /* Ensure strings are terminated */
1001 param->name[DM_NAME_LEN - 1] = '\0';
1002 param->uuid[DM_UUID_LEN - 1] = '\0';
1004 return 0;
1007 static int ctl_ioctl(struct inode *inode, struct file *file,
1008 uint command, ulong u)
1010 int r = 0, cmd;
1011 struct dm_ioctl *param;
1012 struct dm_ioctl *user = (struct dm_ioctl *) u;
1013 ioctl_fn fn = NULL;
1015 /* only root can play with this */
1016 if (!capable(CAP_SYS_ADMIN))
1017 return -EACCES;
1019 if (_IOC_TYPE(command) != DM_IOCTL)
1020 return -ENOTTY;
1022 cmd = _IOC_NR(command);
1025 * Check the interface version passed in. This also
1026 * writes out the kernels interface version.
1028 r = check_version(cmd, user);
1029 if (r)
1030 return r;
1033 * Nothing more to do for the version command.
1035 if (cmd == DM_VERSION_CMD)
1036 return 0;
1038 fn = lookup_ioctl(cmd);
1039 if (!fn) {
1040 DMWARN("dm_ctl_ioctl: unknown command 0x%x", command);
1041 return -ENOTTY;
1045 * Copy the parameters into kernel space.
1047 r = copy_params(user, &param);
1048 if (r)
1049 return r;
1051 r = validate_params(cmd, param);
1052 if (r) {
1053 free_params(param);
1054 return r;
1057 r = fn(param, user);
1058 free_params(param);
1059 return r;
1062 static struct file_operations _ctl_fops = {
1063 .ioctl = ctl_ioctl,
1064 .owner = THIS_MODULE,
1067 static devfs_handle_t _ctl_handle;
1069 static struct miscdevice _dm_misc = {
1070 .minor = MISC_DYNAMIC_MINOR,
1071 .name = DM_NAME,
1072 .fops = &_ctl_fops
1076 * Create misc character device and link to DM_DIR/control.
1078 int __init dm_interface_init(void)
1080 int r;
1082 r = dm_hash_init();
1083 if (r)
1084 return r;
1086 r = misc_register(&_dm_misc);
1087 if (r) {
1088 DMERR("misc_register failed for control device");
1089 dm_hash_exit();
1090 return r;
1093 r = devfs_mk_symlink(NULL, DM_DIR "/control", DEVFS_FL_DEFAULT,
1094 "../misc/" DM_NAME, &_ctl_handle, NULL);
1095 if (r) {
1096 DMERR("devfs_mk_symlink failed for control device");
1097 goto failed;
1099 DMINFO("%d.%d.%d%s initialised: %s", DM_VERSION_MAJOR,
1100 DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, DM_VERSION_EXTRA,
1101 DM_DRIVER_EMAIL);
1102 return 0;
1104 failed:
1105 dm_hash_exit();
1106 misc_deregister(&_dm_misc);
1107 return r;
1110 void dm_interface_exit(void)
1112 dm_hash_exit();
1114 devfs_remove(DM_DIR "/control");
1116 if (misc_deregister(&_dm_misc) < 0)
1117 DMERR("misc_deregister failed for control device");