summaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-ioctl.c
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2017-05-05 14:12:52 -0400
committerMike Snitzer <snitzer@redhat.com>2017-06-19 11:03:49 -0400
commitfc1841e1c15d72b0897ecfc1627ecdc284f0ec95 (patch)
tree33ef078dc10f73ad9eff20777fdcbad88742a6c1 /drivers/md/dm-ioctl.c
parent93e6442c76a0d26ad028c5df9b4a1e3096d9c36b (diff)
dm ioctl: add a new DM_DEV_ARM_POLL ioctl
This ioctl will record the current global event number in the structure dm_file, so that next select or poll call will wait until new events arrived since this ioctl. The DM_DEV_ARM_POLL ioctl has the same effect as closing and reopening the handle. Using the DM_DEV_ARM_POLL ioctl is optional - if the userspace is OK with closing and reopening the /dev/mapper/control handle after select or poll, there is no need to re-arm via ioctl. Usage: 1. open the /dev/mapper/control device 2. send the DM_DEV_ARM_POLL ioctl 3. scan the event numbers of all devices we are interested in and process them 4. call select, poll or epoll on the handle (it waits until some new event happens since the DM_DEV_ARM_POLL ioctl) 5. go to step 2 Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Andy Grover <agrover@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md/dm-ioctl.c')
-rw-r--r--drivers/md/dm-ioctl.c56
1 files changed, 35 insertions, 21 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 6b65a538d91d..a69658b18dc9 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -28,7 +28,7 @@ struct dm_file {
28 * poll will wait until the global event number is greater than 28 * poll will wait until the global event number is greater than
29 * this value. 29 * this value.
30 */ 30 */
31 unsigned global_event_nr; 31 volatile unsigned global_event_nr;
32}; 32};
33 33
34/*----------------------------------------------------------------- 34/*-----------------------------------------------------------------
@@ -464,9 +464,9 @@ void dm_deferred_remove(void)
464 * All the ioctl commands get dispatched to functions with this 464 * All the ioctl commands get dispatched to functions with this
465 * prototype. 465 * prototype.
466 */ 466 */
467typedef int (*ioctl_fn)(struct dm_ioctl *param, size_t param_size); 467typedef int (*ioctl_fn)(struct file *filp, struct dm_ioctl *param, size_t param_size);
468 468
469static int remove_all(struct dm_ioctl *param, size_t param_size) 469static int remove_all(struct file *filp, struct dm_ioctl *param, size_t param_size)
470{ 470{
471 dm_hash_remove_all(true, !!(param->flags & DM_DEFERRED_REMOVE), false); 471 dm_hash_remove_all(true, !!(param->flags & DM_DEFERRED_REMOVE), false);
472 param->data_size = 0; 472 param->data_size = 0;
@@ -499,7 +499,7 @@ static void *get_result_buffer(struct dm_ioctl *param, size_t param_size,
499 return ((void *) param) + param->data_start; 499 return ((void *) param) + param->data_start;
500} 500}
501 501
502static int list_devices(struct dm_ioctl *param, size_t param_size) 502static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_size)
503{ 503{
504 unsigned int i; 504 unsigned int i;
505 struct hash_cell *hc; 505 struct hash_cell *hc;
@@ -590,7 +590,7 @@ static void list_version_get_info(struct target_type *tt, void *param)
590 info->vers = align_ptr(((void *) ++info->vers) + strlen(tt->name) + 1); 590 info->vers = align_ptr(((void *) ++info->vers) + strlen(tt->name) + 1);
591} 591}
592 592
593static int list_versions(struct dm_ioctl *param, size_t param_size) 593static int list_versions(struct file *filp, struct dm_ioctl *param, size_t param_size)
594{ 594{
595 size_t len, needed = 0; 595 size_t len, needed = 0;
596 struct dm_target_versions *vers; 596 struct dm_target_versions *vers;
@@ -732,7 +732,7 @@ static void __dev_status(struct mapped_device *md, struct dm_ioctl *param)
732 } 732 }
733} 733}
734 734
735static int dev_create(struct dm_ioctl *param, size_t param_size) 735static int dev_create(struct file *filp, struct dm_ioctl *param, size_t param_size)
736{ 736{
737 int r, m = DM_ANY_MINOR; 737 int r, m = DM_ANY_MINOR;
738 struct mapped_device *md; 738 struct mapped_device *md;
@@ -824,7 +824,7 @@ static struct mapped_device *find_device(struct dm_ioctl *param)
824 return md; 824 return md;
825} 825}
826 826
827static int dev_remove(struct dm_ioctl *param, size_t param_size) 827static int dev_remove(struct file *filp, struct dm_ioctl *param, size_t param_size)
828{ 828{
829 struct hash_cell *hc; 829 struct hash_cell *hc;
830 struct mapped_device *md; 830 struct mapped_device *md;
@@ -889,7 +889,7 @@ static int invalid_str(char *str, void *end)
889 return -EINVAL; 889 return -EINVAL;
890} 890}
891 891
892static int dev_rename(struct dm_ioctl *param, size_t param_size) 892static int dev_rename(struct file *filp, struct dm_ioctl *param, size_t param_size)
893{ 893{
894 int r; 894 int r;
895 char *new_data = (char *) param + param->data_start; 895 char *new_data = (char *) param + param->data_start;
@@ -919,7 +919,7 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size)
919 return 0; 919 return 0;
920} 920}
921 921
922static int dev_set_geometry(struct dm_ioctl *param, size_t param_size) 922static int dev_set_geometry(struct file *filp, struct dm_ioctl *param, size_t param_size)
923{ 923{
924 int r = -EINVAL, x; 924 int r = -EINVAL, x;
925 struct mapped_device *md; 925 struct mapped_device *md;
@@ -1068,7 +1068,7 @@ static int do_resume(struct dm_ioctl *param)
1068 * Set or unset the suspension state of a device. 1068 * Set or unset the suspension state of a device.
1069 * If the device already is in the requested state we just return its status. 1069 * If the device already is in the requested state we just return its status.
1070 */ 1070 */
1071static int dev_suspend(struct dm_ioctl *param, size_t param_size) 1071static int dev_suspend(struct file *filp, struct dm_ioctl *param, size_t param_size)
1072{ 1072{
1073 if (param->flags & DM_SUSPEND_FLAG) 1073 if (param->flags & DM_SUSPEND_FLAG)
1074 return do_suspend(param); 1074 return do_suspend(param);
@@ -1080,7 +1080,7 @@ static int dev_suspend(struct dm_ioctl *param, size_t param_size)
1080 * Copies device info back to user space, used by 1080 * Copies device info back to user space, used by
1081 * the create and info ioctls. 1081 * the create and info ioctls.
1082 */ 1082 */
1083static int dev_status(struct dm_ioctl *param, size_t param_size) 1083static int dev_status(struct file *filp, struct dm_ioctl *param, size_t param_size)
1084{ 1084{
1085 struct mapped_device *md; 1085 struct mapped_device *md;
1086 1086
@@ -1171,7 +1171,7 @@ static void retrieve_status(struct dm_table *table,
1171/* 1171/*
1172 * Wait for a device to report an event 1172 * Wait for a device to report an event
1173 */ 1173 */
1174static int dev_wait(struct dm_ioctl *param, size_t param_size) 1174static int dev_wait(struct file *filp, struct dm_ioctl *param, size_t param_size)
1175{ 1175{
1176 int r = 0; 1176 int r = 0;
1177 struct mapped_device *md; 1177 struct mapped_device *md;
@@ -1208,6 +1208,19 @@ out:
1208 return r; 1208 return r;
1209} 1209}
1210 1210
1211/*
1212 * Remember the global event number and make it possible to poll
1213 * for further events.
1214 */
1215static int dev_arm_poll(struct file *filp, struct dm_ioctl *param, size_t param_size)
1216{
1217 struct dm_file *priv = filp->private_data;
1218
1219 priv->global_event_nr = atomic_read(&dm_global_event_nr);
1220
1221 return 0;
1222}
1223
1211static inline fmode_t get_mode(struct dm_ioctl *param) 1224static inline fmode_t get_mode(struct dm_ioctl *param)
1212{ 1225{
1213 fmode_t mode = FMODE_READ | FMODE_WRITE; 1226 fmode_t mode = FMODE_READ | FMODE_WRITE;
@@ -1277,7 +1290,7 @@ static bool is_valid_type(enum dm_queue_mode cur, enum dm_queue_mode new)
1277 return false; 1290 return false;
1278} 1291}
1279 1292
1280static int table_load(struct dm_ioctl *param, size_t param_size) 1293static int table_load(struct file *filp, struct dm_ioctl *param, size_t param_size)
1281{ 1294{
1282 int r; 1295 int r;
1283 struct hash_cell *hc; 1296 struct hash_cell *hc;
@@ -1364,7 +1377,7 @@ err:
1364 return r; 1377 return r;
1365} 1378}
1366 1379
1367static int table_clear(struct dm_ioctl *param, size_t param_size) 1380static int table_clear(struct file *filp, struct dm_ioctl *param, size_t param_size)
1368{ 1381{
1369 struct hash_cell *hc; 1382 struct hash_cell *hc;
1370 struct mapped_device *md; 1383 struct mapped_device *md;
@@ -1438,7 +1451,7 @@ static void retrieve_deps(struct dm_table *table,
1438 param->data_size = param->data_start + needed; 1451 param->data_size = param->data_start + needed;
1439} 1452}
1440 1453
1441static int table_deps(struct dm_ioctl *param, size_t param_size) 1454static int table_deps(struct file *filp, struct dm_ioctl *param, size_t param_size)
1442{ 1455{
1443 struct mapped_device *md; 1456 struct mapped_device *md;
1444 struct dm_table *table; 1457 struct dm_table *table;
@@ -1464,7 +1477,7 @@ static int table_deps(struct dm_ioctl *param, size_t param_size)
1464 * Return the status of a device as a text string for each 1477 * Return the status of a device as a text string for each
1465 * target. 1478 * target.
1466 */ 1479 */
1467static int table_status(struct dm_ioctl *param, size_t param_size) 1480static int table_status(struct file *filp, struct dm_ioctl *param, size_t param_size)
1468{ 1481{
1469 struct mapped_device *md; 1482 struct mapped_device *md;
1470 struct dm_table *table; 1483 struct dm_table *table;
@@ -1519,7 +1532,7 @@ static int message_for_md(struct mapped_device *md, unsigned argc, char **argv,
1519/* 1532/*
1520 * Pass a message to the target that's at the supplied device offset. 1533 * Pass a message to the target that's at the supplied device offset.
1521 */ 1534 */
1522static int target_message(struct dm_ioctl *param, size_t param_size) 1535static int target_message(struct file *filp, struct dm_ioctl *param, size_t param_size)
1523{ 1536{
1524 int r, argc; 1537 int r, argc;
1525 char **argv; 1538 char **argv;
@@ -1636,7 +1649,8 @@ static ioctl_fn lookup_ioctl(unsigned int cmd, int *ioctl_flags)
1636 {DM_LIST_VERSIONS_CMD, 0, list_versions}, 1649 {DM_LIST_VERSIONS_CMD, 0, list_versions},
1637 1650
1638 {DM_TARGET_MSG_CMD, 0, target_message}, 1651 {DM_TARGET_MSG_CMD, 0, target_message},
1639 {DM_DEV_SET_GEOMETRY_CMD, 0, dev_set_geometry} 1652 {DM_DEV_SET_GEOMETRY_CMD, 0, dev_set_geometry},
1653 {DM_DEV_ARM_POLL, IOCTL_FLAGS_NO_PARAMS, dev_arm_poll},
1640 }; 1654 };
1641 1655
1642 if (unlikely(cmd >= ARRAY_SIZE(_ioctls))) 1656 if (unlikely(cmd >= ARRAY_SIZE(_ioctls)))
@@ -1791,7 +1805,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param)
1791 return 0; 1805 return 0;
1792} 1806}
1793 1807
1794static int ctl_ioctl(uint command, struct dm_ioctl __user *user) 1808static int ctl_ioctl(struct file *file, uint command, struct dm_ioctl __user *user)
1795{ 1809{
1796 int r = 0; 1810 int r = 0;
1797 int ioctl_flags; 1811 int ioctl_flags;
@@ -1845,7 +1859,7 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
1845 goto out; 1859 goto out;
1846 1860
1847 param->data_size = offsetof(struct dm_ioctl, data); 1861 param->data_size = offsetof(struct dm_ioctl, data);
1848 r = fn(param, input_param_size); 1862 r = fn(file, param, input_param_size);
1849 1863
1850 if (unlikely(param->flags & DM_BUFFER_FULL_FLAG) && 1864 if (unlikely(param->flags & DM_BUFFER_FULL_FLAG) &&
1851 unlikely(ioctl_flags & IOCTL_FLAGS_NO_PARAMS)) 1865 unlikely(ioctl_flags & IOCTL_FLAGS_NO_PARAMS))
@@ -1864,7 +1878,7 @@ out:
1864 1878
1865static long dm_ctl_ioctl(struct file *file, uint command, ulong u) 1879static long dm_ctl_ioctl(struct file *file, uint command, ulong u)
1866{ 1880{
1867 return (long)ctl_ioctl(command, (struct dm_ioctl __user *)u); 1881 return (long)ctl_ioctl(file, command, (struct dm_ioctl __user *)u);
1868} 1882}
1869 1883
1870#ifdef CONFIG_COMPAT 1884#ifdef CONFIG_COMPAT