Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Mikulas Patocka and committed by
Mike Snitzer
fc1841e1 93e6442c

+38 -22
+35 -21
drivers/md/dm-ioctl.c
··· 28 28 * poll will wait until the global event number is greater than 29 29 * this value. 30 30 */ 31 - unsigned global_event_nr; 31 + volatile unsigned global_event_nr; 32 32 }; 33 33 34 34 /*----------------------------------------------------------------- ··· 464 464 * All the ioctl commands get dispatched to functions with this 465 465 * prototype. 466 466 */ 467 - typedef int (*ioctl_fn)(struct dm_ioctl *param, size_t param_size); 467 + typedef int (*ioctl_fn)(struct file *filp, struct dm_ioctl *param, size_t param_size); 468 468 469 - static int remove_all(struct dm_ioctl *param, size_t param_size) 469 + static int remove_all(struct file *filp, struct dm_ioctl *param, size_t param_size) 470 470 { 471 471 dm_hash_remove_all(true, !!(param->flags & DM_DEFERRED_REMOVE), false); 472 472 param->data_size = 0; ··· 499 499 return ((void *) param) + param->data_start; 500 500 } 501 501 502 - static int list_devices(struct dm_ioctl *param, size_t param_size) 502 + static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_size) 503 503 { 504 504 unsigned int i; 505 505 struct hash_cell *hc; ··· 590 590 info->vers = align_ptr(((void *) ++info->vers) + strlen(tt->name) + 1); 591 591 } 592 592 593 - static int list_versions(struct dm_ioctl *param, size_t param_size) 593 + static int list_versions(struct file *filp, struct dm_ioctl *param, size_t param_size) 594 594 { 595 595 size_t len, needed = 0; 596 596 struct dm_target_versions *vers; ··· 732 732 } 733 733 } 734 734 735 - static int dev_create(struct dm_ioctl *param, size_t param_size) 735 + static int dev_create(struct file *filp, struct dm_ioctl *param, size_t param_size) 736 736 { 737 737 int r, m = DM_ANY_MINOR; 738 738 struct mapped_device *md; ··· 824 824 return md; 825 825 } 826 826 827 - static int dev_remove(struct dm_ioctl *param, size_t param_size) 827 + static int dev_remove(struct file *filp, struct dm_ioctl *param, size_t param_size) 828 828 { 829 829 struct hash_cell *hc; 830 830 struct mapped_device *md; ··· 889 889 return -EINVAL; 890 890 } 891 891 892 - static int dev_rename(struct dm_ioctl *param, size_t param_size) 892 + static int dev_rename(struct file *filp, struct dm_ioctl *param, size_t param_size) 893 893 { 894 894 int r; 895 895 char *new_data = (char *) param + param->data_start; ··· 919 919 return 0; 920 920 } 921 921 922 - static int dev_set_geometry(struct dm_ioctl *param, size_t param_size) 922 + static int dev_set_geometry(struct file *filp, struct dm_ioctl *param, size_t param_size) 923 923 { 924 924 int r = -EINVAL, x; 925 925 struct mapped_device *md; ··· 1068 1068 * Set or unset the suspension state of a device. 1069 1069 * If the device already is in the requested state we just return its status. 1070 1070 */ 1071 - static int dev_suspend(struct dm_ioctl *param, size_t param_size) 1071 + static int dev_suspend(struct file *filp, struct dm_ioctl *param, size_t param_size) 1072 1072 { 1073 1073 if (param->flags & DM_SUSPEND_FLAG) 1074 1074 return do_suspend(param); ··· 1080 1080 * Copies device info back to user space, used by 1081 1081 * the create and info ioctls. 1082 1082 */ 1083 - static int dev_status(struct dm_ioctl *param, size_t param_size) 1083 + static int dev_status(struct file *filp, struct dm_ioctl *param, size_t param_size) 1084 1084 { 1085 1085 struct mapped_device *md; 1086 1086 ··· 1171 1171 /* 1172 1172 * Wait for a device to report an event 1173 1173 */ 1174 - static int dev_wait(struct dm_ioctl *param, size_t param_size) 1174 + static int dev_wait(struct file *filp, struct dm_ioctl *param, size_t param_size) 1175 1175 { 1176 1176 int r = 0; 1177 1177 struct mapped_device *md; ··· 1206 1206 dm_put(md); 1207 1207 1208 1208 return r; 1209 + } 1210 + 1211 + /* 1212 + * Remember the global event number and make it possible to poll 1213 + * for further events. 1214 + */ 1215 + static 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; 1209 1222 } 1210 1223 1211 1224 static inline fmode_t get_mode(struct dm_ioctl *param) ··· 1290 1277 return false; 1291 1278 } 1292 1279 1293 - static int table_load(struct dm_ioctl *param, size_t param_size) 1280 + static int table_load(struct file *filp, struct dm_ioctl *param, size_t param_size) 1294 1281 { 1295 1282 int r; 1296 1283 struct hash_cell *hc; ··· 1377 1364 return r; 1378 1365 } 1379 1366 1380 - static int table_clear(struct dm_ioctl *param, size_t param_size) 1367 + static int table_clear(struct file *filp, struct dm_ioctl *param, size_t param_size) 1381 1368 { 1382 1369 struct hash_cell *hc; 1383 1370 struct mapped_device *md; ··· 1451 1438 param->data_size = param->data_start + needed; 1452 1439 } 1453 1440 1454 - static int table_deps(struct dm_ioctl *param, size_t param_size) 1441 + static int table_deps(struct file *filp, struct dm_ioctl *param, size_t param_size) 1455 1442 { 1456 1443 struct mapped_device *md; 1457 1444 struct dm_table *table; ··· 1477 1464 * Return the status of a device as a text string for each 1478 1465 * target. 1479 1466 */ 1480 - static int table_status(struct dm_ioctl *param, size_t param_size) 1467 + static int table_status(struct file *filp, struct dm_ioctl *param, size_t param_size) 1481 1468 { 1482 1469 struct mapped_device *md; 1483 1470 struct dm_table *table; ··· 1532 1519 /* 1533 1520 * Pass a message to the target that's at the supplied device offset. 1534 1521 */ 1535 - static int target_message(struct dm_ioctl *param, size_t param_size) 1522 + static int target_message(struct file *filp, struct dm_ioctl *param, size_t param_size) 1536 1523 { 1537 1524 int r, argc; 1538 1525 char **argv; ··· 1649 1636 {DM_LIST_VERSIONS_CMD, 0, list_versions}, 1650 1637 1651 1638 {DM_TARGET_MSG_CMD, 0, target_message}, 1652 - {DM_DEV_SET_GEOMETRY_CMD, 0, dev_set_geometry} 1639 + {DM_DEV_SET_GEOMETRY_CMD, 0, dev_set_geometry}, 1640 + {DM_DEV_ARM_POLL, IOCTL_FLAGS_NO_PARAMS, dev_arm_poll}, 1653 1641 }; 1654 1642 1655 1643 if (unlikely(cmd >= ARRAY_SIZE(_ioctls))) ··· 1805 1791 return 0; 1806 1792 } 1807 1793 1808 - static int ctl_ioctl(uint command, struct dm_ioctl __user *user) 1794 + static int ctl_ioctl(struct file *file, uint command, struct dm_ioctl __user *user) 1809 1795 { 1810 1796 int r = 0; 1811 1797 int ioctl_flags; ··· 1859 1845 goto out; 1860 1846 1861 1847 param->data_size = offsetof(struct dm_ioctl, data); 1862 - r = fn(param, input_param_size); 1848 + r = fn(file, param, input_param_size); 1863 1849 1864 1850 if (unlikely(param->flags & DM_BUFFER_FULL_FLAG) && 1865 1851 unlikely(ioctl_flags & IOCTL_FLAGS_NO_PARAMS)) ··· 1878 1864 1879 1865 static long dm_ctl_ioctl(struct file *file, uint command, ulong u) 1880 1866 { 1881 - return (long)ctl_ioctl(command, (struct dm_ioctl __user *)u); 1867 + return (long)ctl_ioctl(file, command, (struct dm_ioctl __user *)u); 1882 1868 } 1883 1869 1884 1870 #ifdef CONFIG_COMPAT
+3 -1
include/uapi/linux/dm-ioctl.h
··· 240 240 /* Added later */ 241 241 DM_LIST_VERSIONS_CMD, 242 242 DM_TARGET_MSG_CMD, 243 - DM_DEV_SET_GEOMETRY_CMD 243 + DM_DEV_SET_GEOMETRY_CMD, 244 + DM_DEV_ARM_POLL_CMD, 244 245 }; 245 246 246 247 #define DM_IOCTL 0xfd ··· 256 255 #define DM_DEV_SUSPEND _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl) 257 256 #define DM_DEV_STATUS _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl) 258 257 #define DM_DEV_WAIT _IOWR(DM_IOCTL, DM_DEV_WAIT_CMD, struct dm_ioctl) 258 + #define DM_DEV_ARM_POLL _IOWR(DM_IOCTL, DM_DEV_ARM_POLL_CMD, struct dm_ioctl) 259 259 260 260 #define DM_TABLE_LOAD _IOWR(DM_IOCTL, DM_TABLE_LOAD_CMD, struct dm_ioctl) 261 261 #define DM_TABLE_CLEAR _IOWR(DM_IOCTL, DM_TABLE_CLEAR_CMD, struct dm_ioctl)