10 #include <linux/module.h>
14 #include <linux/wait.h>
15 #include <linux/slab.h>
20 #include <asm/uaccess.h>
22 #define DM_MSG_PREFIX "ioctl"
47 #define NUM_BUCKETS 64
48 #define MASK_BUCKETS (NUM_BUCKETS - 1)
52 static void dm_hash_remove_all(
int keep_open_devices);
64 static void init_buckets(
struct list_head *buckets)
69 INIT_LIST_HEAD(buckets + i);
72 static int dm_hash_init(
void)
74 init_buckets(_name_buckets);
75 init_buckets(_uuid_buckets);
79 static void dm_hash_exit(
void)
81 dm_hash_remove_all(0);
89 static unsigned int hash_str(
const char *
str)
91 const unsigned int hash_mult = 2654435387
U;
95 h = (h + (
unsigned int) *str++) * hash_mult;
103 static struct hash_cell *__get_name_cell(
const char *str)
106 unsigned int h = hash_str(str);
117 static struct hash_cell *__get_uuid_cell(
const char *str)
120 unsigned int h = hash_str(str);
186 static void free_cell(
struct hash_cell *hc)
199 static int dm_hash_insert(
const char *name,
const char *uuid,
struct mapped_device *md)
206 cell = alloc_cell(name, uuid, md);
214 hc = __get_name_cell(name);
220 list_add(&cell->
name_list, _name_buckets + hash_str(name));
223 hc = __get_uuid_cell(uuid);
229 list_add(&cell->
uuid_list, _uuid_buckets + hash_str(uuid));
245 static void __hash_remove(
struct hash_cell *hc)
268 static void dm_hash_remove_all(
int keep_open_devices)
295 if (
likely(keep_open_devices))
313 DMWARN(
"remove_all left %d open device(s)", dev_skipped);
319 static void __set_cell_uuid(
struct hash_cell *hc,
char *new_uuid)
325 list_add(&hc->
uuid_list, _uuid_buckets + hash_str(new_uuid));
332 static char *__change_cell_name(
struct hash_cell *hc,
char *new_name)
346 list_add(&hc->
name_list, _name_buckets + hash_str(new_name));
354 char *new_data, *old_name =
NULL;
373 hc = __get_uuid_cell(
new);
375 hc = __get_name_cell(
new);
378 DMWARN(
"Unable to change %s on mapped device %s to one that "
379 "already exists: %s",
380 change_uuid ?
"uuid" :
"name",
385 return ERR_PTR(-
EBUSY);
391 hc = __get_name_cell(param->
name);
393 DMWARN(
"Unable to rename non-existent device, %s to %s%s",
394 param->
name, change_uuid ?
"uuid " :
"",
new);
397 return ERR_PTR(-
ENXIO);
403 if (change_uuid && hc->
uuid) {
404 DMWARN(
"Unable to change uuid of mapped device %s to %s "
405 "because uuid is already set to %s",
414 __set_cell_uuid(hc, new_data);
416 old_name = __change_cell_name(hc, new_data);
448 dm_hash_remove_all(1);
457 static inline void *align_ptr(
void *
ptr)
469 param->
data_start = align_ptr(param + 1) - (
void *) param;
479 static int list_devices(
struct dm_ioctl *param,
size_t param_size)
483 size_t len, needed = 0;
484 struct gendisk *disk;
504 nl = get_result_buffer(param, param_size, &len);
522 nl->
dev = huge_encode_dev(disk_devt(disk));
527 nl = align_ptr(((
void *) ++nl) +
strlen(hc->
name) + 1);
536 static void list_version_get_needed(
struct target_type *
tt,
void *needed_param)
538 size_t *needed = needed_param;
545 static void list_version_get_info(
struct target_type *
tt,
void *param)
563 info->
vers->next = 0;
570 static int list_versions(
struct dm_ioctl *param,
size_t param_size)
572 size_t len, needed = 0;
585 vers = get_result_buffer(param, param_size, &len);
593 iter_info.old_vers =
NULL;
594 iter_info.vers =
vers;
596 iter_info.end = (
char *)vers+len;
602 param->
flags |= iter_info.flags;
608 static int check_name(
const char *name)
611 DMWARN(
"invalid device name");
630 if (!hc || hc->
md != md) {
631 DMWARN(
"device has been removed from the dev hash table.");
658 struct gendisk *disk =
dm_disk(md);
667 param->
dev = huge_encode_dev(disk_devt(disk));
682 if (get_disk_ro(disk))
692 table = dm_get_inactive_table(md);
702 static int dev_create(
struct dm_ioctl *param,
size_t param_size)
707 r = check_name(param->
name);
712 m =
MINOR(huge_decode_dev(param->
dev));
727 __dev_status(md, param);
742 if (*param->
name || param->
dev)
745 hc = __get_uuid_cell(param->
uuid);
748 }
else if (*param->
name) {
752 hc = __get_name_cell(param->
name);
755 }
else if (param->
dev) {
756 hc = __get_dev_cell(param->
dev);
770 param->
uuid[0] =
'\0';
786 hc = __find_device_hash_cell(param);
794 static int dev_remove(
struct dm_ioctl *param,
size_t param_size)
801 hc = __find_device_hash_cell(param);
804 DMDEBUG_LIMIT(
"device doesn't appear to be in the dev hash table.");
837 static int invalid_str(
char *str,
void *
end)
839 while ((
void *) str < end)
846 static int dev_rename(
struct dm_ioctl *param,
size_t param_size)
849 char *new_data = (
char *) param + param->
data_start;
853 if (new_data < param->
data ||
854 invalid_str(new_data, (
void *) param + param_size) ||
856 DMWARN(
"Invalid new mapped device name or uuid string supplied.");
861 r = check_name(new_data);
866 md = dm_hash_rename(param, new_data);
870 __dev_status(md, param);
876 static int dev_set_geometry(
struct dm_ioctl *param,
size_t param_size)
881 unsigned long indata[4];
882 char *geostr = (
char *) param + param->
data_start;
885 md = find_device(param);
889 if (geostr < param->
data ||
890 invalid_str(geostr, (
void *) param + param_size)) {
891 DMWARN(
"Invalid geometry supplied.");
895 x =
sscanf(geostr,
"%lu %lu %lu %lu%c", indata,
896 indata + 1, indata + 2, indata + 3, &
dummy);
899 DMWARN(
"Unable to interpret geometry settings.");
903 if (indata[0] > 65535 || indata[1] > 255 ||
904 indata[2] > 255 || indata[3] >
ULONG_MAX) {
905 DMWARN(
"Geometry exceeds range limits.");
923 static int do_suspend(
struct dm_ioctl *param)
929 md = find_device(param);
944 __dev_status(md, param);
952 static int do_resume(
struct dm_ioctl *param)
962 hc = __find_device_hash_cell(param);
964 DMDEBUG_LIMIT(
"device doesn't appear to be in the dev hash table.");
988 if (IS_ERR(old_map)) {
991 return PTR_ERR(old_map);
1010 __dev_status(md, param);
1020 static int dev_suspend(
struct dm_ioctl *param,
size_t param_size)
1023 return do_suspend(param);
1025 return do_resume(param);
1036 md = find_device(param);
1040 __dev_status(md, param);
1049 static void retrieve_status(
struct dm_table *table,
1050 struct dm_ioctl *param,
size_t param_size)
1052 unsigned int i, num_targets;
1054 char *outbuf, *outptr;
1056 size_t remaining, len,
used = 0;
1057 unsigned status_flags = 0;
1059 outptr = outbuf = get_result_buffer(param, param_size, &len);
1068 for (i = 0; i < num_targets; i++) {
1071 remaining = len - (outptr - outbuf);
1086 remaining = len - (outptr - outbuf);
1087 if (remaining <= 0) {
1093 if (ti->
type->status) {
1096 if (ti->
type->status(ti, type, status_flags, outptr, remaining)) {
1103 outptr +=
strlen(outptr) + 1;
1104 used = param->
data_start + (outptr - outbuf);
1106 outptr = align_ptr(outptr);
1107 spec->
next = outptr - outbuf;
1119 static int dev_wait(
struct dm_ioctl *param,
size_t param_size)
1125 md = find_device(param);
1142 __dev_status(md, param);
1144 table = dm_get_live_or_inactive_table(md, param);
1146 retrieve_status(table, param, param_size);
1170 *target_params = (
char *) (*spec + 1);
1172 if (*spec < (last + 1))
1175 return invalid_str(*target_params, end);
1178 static int populate_table(
struct dm_table *table,
1179 struct dm_ioctl *param,
size_t param_size)
1185 void *end = (
void *) param + param_size;
1186 char *target_params;
1189 DMWARN(
"populate_table: no targets specified");
1195 r = next_target(spec, next, end, &spec, &target_params);
1197 DMWARN(
"unable to find target");
1206 DMWARN(
"error adding target to table");
1216 static int table_load(
struct dm_ioctl *param,
size_t param_size)
1224 md = find_device(param);
1232 r = populate_table(t, param, param_size);
1239 if (immutable_target_type &&
1241 DMWARN(
"can't replace immutable target type %s",
1242 immutable_target_type->
name);
1254 DMWARN(
"can't change device type after initial table load.");
1264 DMWARN(
"unable to set up device queue for new table.");
1274 if (!hc || hc->
md != md) {
1275 DMWARN(
"device has been removed from the dev hash table.");
1288 __dev_status(md, param);
1296 static int table_clear(
struct dm_ioctl *param,
size_t param_size)
1303 hc = __find_device_hash_cell(param);
1305 DMDEBUG_LIMIT(
"device doesn't appear to be in the dev hash table.");
1317 __dev_status(hc->
md, param);
1328 static void retrieve_deps(
struct dm_table *table,
1329 struct dm_ioctl *param,
size_t param_size)
1331 unsigned int count = 0;
1337 deps = get_result_buffer(param, param_size, &len);
1360 deps->dev[count++] = huge_encode_dev(dd->
dm_dev.bdev->bd_dev);
1362 param->
data_size = param->data_start + needed;
1370 md = find_device(param);
1374 __dev_status(md, param);
1376 table = dm_get_live_or_inactive_table(md, param);
1378 retrieve_deps(table, param, param_size);
1391 static int table_status(
struct dm_ioctl *param,
size_t param_size)
1396 md = find_device(param);
1400 __dev_status(md, param);
1402 table = dm_get_live_or_inactive_table(md, param);
1404 retrieve_status(table, param, param_size);
1416 static int target_message(
struct dm_ioctl *param,
size_t param_size)
1425 md = find_device(param);
1430 invalid_str(tmsg->
message, (
void *) param + param_size)) {
1431 DMWARN(
"Invalid target message parameters.");
1438 DMWARN(
"Failed to split target message parameters");
1443 DMWARN(
"Empty message received.");
1458 DMWARN(
"Target message sector outside device.");
1460 }
else if (ti->
type->message)
1461 r = ti->
type->message(ti, argc, argv);
1463 DMWARN(
"Target type does not support messages");
1516 static int check_version(
unsigned int cmd,
struct dm_ioctl __user *
user)
1526 DMWARN(
"ioctl interface mismatch: "
1527 "kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)",
1530 version[0], version[1], version[2], cmd);
1540 if (
copy_to_user(user->version, version,
sizeof(version)))
1546 static int copy_params(
struct dm_ioctl __user *user,
struct dm_ioctl **param)
1554 if (tmp.data_size < (
sizeof(tmp) -
sizeof(tmp.data)))
1561 if (secure_data &&
clear_user(user, tmp.data_size))
1570 if (secure_data &&
clear_user(user, tmp.data_size))
1578 memset(dmi, 0, tmp.data_size);
1583 static int validate_params(
uint cmd,
struct dm_ioctl *param)
1597 if (!*param->
name) {
1598 DMWARN(
"name not supplied when creating device");
1601 }
else if ((*param->
uuid && *param->
name)) {
1602 DMWARN(
"only supply one of name or uuid, cmd(%u)", cmd);
1620 size_t input_param_size;
1635 r = check_version(cmd, user);
1645 fn = lookup_ioctl(cmd);
1647 DMWARN(
"dm_ctl_ioctl: unknown command 0x%x", command);
1660 r = copy_params(user, ¶m);
1670 r = validate_params(cmd, param);
1675 r =
fn(param, input_param_size);
1685 memset(param, 0, input_param_size);
1693 return (
long)ctl_ioctl(command, (
struct dm_ioctl __user *)u);
1696 #ifdef CONFIG_COMPAT
1699 return (
long)dm_ctl_ioctl(file, command, (
ulong) compat_ptr(u));
1702 #define dm_compat_ctl_ioctl NULL
1707 .unlocked_ioctl = dm_ctl_ioctl,
1736 DMERR(
"misc_register failed for control device");
1750 DMERR(
"misc_deregister failed for control device");
1771 if (!hc || hc->
md != md) {