aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilan Broz <mbroz@redhat.com>2009-06-22 05:12:30 -0400
committerAlasdair G Kergon <agk@redhat.com>2009-06-22 05:12:30 -0400
commit60935eb21d3c5bac79618000f38f92c249d153c4 (patch)
tree0fcd78d7d69e23cd062e5214ddf2959d5c74e605
parent486d220fe4909b5745c4faa67faddd30a707abe2 (diff)
dm ioctl: support cookies for udev
Add support for passing a 32 bit "cookie" into the kernel with the DM_SUSPEND, DM_DEV_RENAME and DM_DEV_REMOVE ioctls. The (unsigned) value of this cookie is returned to userspace alongside the uevents issued by these ioctls in the variable DM_COOKIE. This means the userspace process issuing these ioctls can be notified by udev after udev has completed any actions triggered. To minimise the interface extension, we pass the cookie into the kernel in the event_nr field which is otherwise unused when calling these ioctls. Incrementing the version number allows userspace to determine in advance whether or not the kernel supports the cookie. If the kernel does support this but userspace does not, there should be no impact as the new variable will just get ignored. Signed-off-by: Milan Broz <mbroz@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-rw-r--r--drivers/md/dm-ioctl.c14
-rw-r--r--drivers/md/dm.c25
-rw-r--r--drivers/md/dm.h3
-rw-r--r--include/linux/dm-ioctl.h14
4 files changed, 43 insertions, 13 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 1128d3fba797..1c871736f48c 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -276,7 +276,7 @@ retry:
276 up_write(&_hash_lock); 276 up_write(&_hash_lock);
277} 277}
278 278
279static int dm_hash_rename(const char *old, const char *new) 279static int dm_hash_rename(uint32_t cookie, const char *old, const char *new)
280{ 280{
281 char *new_name, *old_name; 281 char *new_name, *old_name;
282 struct hash_cell *hc; 282 struct hash_cell *hc;
@@ -333,7 +333,7 @@ static int dm_hash_rename(const char *old, const char *new)
333 dm_table_put(table); 333 dm_table_put(table);
334 } 334 }
335 335
336 dm_kobject_uevent(hc->md); 336 dm_kobject_uevent(hc->md, KOBJ_CHANGE, cookie);
337 337
338 dm_put(hc->md); 338 dm_put(hc->md);
339 up_write(&_hash_lock); 339 up_write(&_hash_lock);
@@ -680,6 +680,9 @@ static int dev_remove(struct dm_ioctl *param, size_t param_size)
680 680
681 __hash_remove(hc); 681 __hash_remove(hc);
682 up_write(&_hash_lock); 682 up_write(&_hash_lock);
683
684 dm_kobject_uevent(md, KOBJ_REMOVE, param->event_nr);
685
683 dm_put(md); 686 dm_put(md);
684 param->data_size = 0; 687 param->data_size = 0;
685 return 0; 688 return 0;
@@ -715,7 +718,7 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size)
715 return r; 718 return r;
716 719
717 param->data_size = 0; 720 param->data_size = 0;
718 return dm_hash_rename(param->name, new_name); 721 return dm_hash_rename(param->event_nr, param->name, new_name);
719} 722}
720 723
721static int dev_set_geometry(struct dm_ioctl *param, size_t param_size) 724static int dev_set_geometry(struct dm_ioctl *param, size_t param_size)
@@ -842,8 +845,11 @@ static int do_resume(struct dm_ioctl *param)
842 if (dm_suspended(md)) 845 if (dm_suspended(md))
843 r = dm_resume(md); 846 r = dm_resume(md);
844 847
845 if (!r) 848
849 if (!r) {
850 dm_kobject_uevent(md, KOBJ_CHANGE, param->event_nr);
846 r = __dev_status(md, param); 851 r = __dev_status(md, param);
852 }
847 853
848 dm_put(md); 854 dm_put(md);
849 return r; 855 return r;
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 36142e947ffc..a9210bb594e7 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -24,6 +24,13 @@
24 24
25#define DM_MSG_PREFIX "core" 25#define DM_MSG_PREFIX "core"
26 26
27/*
28 * Cookies are numeric values sent with CHANGE and REMOVE
29 * uevents while resuming, removing or renaming the device.
30 */
31#define DM_COOKIE_ENV_VAR_NAME "DM_COOKIE"
32#define DM_COOKIE_LENGTH 24
33
27static const char *_name = DM_NAME; 34static const char *_name = DM_NAME;
28 35
29static unsigned int major = 0; 36static unsigned int major = 0;
@@ -1731,11 +1738,7 @@ int dm_resume(struct mapped_device *md)
1731 clear_bit(DMF_SUSPENDED, &md->flags); 1738 clear_bit(DMF_SUSPENDED, &md->flags);
1732 1739
1733 dm_table_unplug_all(map); 1740 dm_table_unplug_all(map);
1734
1735 dm_kobject_uevent(md);
1736
1737 r = 0; 1741 r = 0;
1738
1739out: 1742out:
1740 dm_table_put(map); 1743 dm_table_put(map);
1741 mutex_unlock(&md->suspend_lock); 1744 mutex_unlock(&md->suspend_lock);
@@ -1746,9 +1749,19 @@ out:
1746/*----------------------------------------------------------------- 1749/*-----------------------------------------------------------------
1747 * Event notification. 1750 * Event notification.
1748 *---------------------------------------------------------------*/ 1751 *---------------------------------------------------------------*/
1749void dm_kobject_uevent(struct mapped_device *md) 1752void dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
1753 unsigned cookie)
1750{ 1754{
1751 kobject_uevent(&disk_to_dev(md->disk)->kobj, KOBJ_CHANGE); 1755 char udev_cookie[DM_COOKIE_LENGTH];
1756 char *envp[] = { udev_cookie, NULL };
1757
1758 if (!cookie)
1759 kobject_uevent(&disk_to_dev(md->disk)->kobj, action);
1760 else {
1761 snprintf(udev_cookie, DM_COOKIE_LENGTH, "%s=%u",
1762 DM_COOKIE_ENV_VAR_NAME, cookie);
1763 kobject_uevent_env(&disk_to_dev(md->disk)->kobj, action, envp);
1764 }
1752} 1765}
1753 1766
1754uint32_t dm_next_uevent_seq(struct mapped_device *md) 1767uint32_t dm_next_uevent_seq(struct mapped_device *md)
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index a31506d93e91..b5935c610c44 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -92,7 +92,8 @@ void dm_stripe_exit(void);
92int dm_open_count(struct mapped_device *md); 92int dm_open_count(struct mapped_device *md);
93int dm_lock_for_deletion(struct mapped_device *md); 93int dm_lock_for_deletion(struct mapped_device *md);
94 94
95void dm_kobject_uevent(struct mapped_device *md); 95void dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
96 unsigned cookie);
96 97
97int dm_kcopyd_init(void); 98int dm_kcopyd_init(void);
98void dm_kcopyd_exit(void); 99void dm_kcopyd_exit(void);
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h
index 48e44ee2b466..2ab84c83c31a 100644
--- a/include/linux/dm-ioctl.h
+++ b/include/linux/dm-ioctl.h
@@ -123,6 +123,16 @@ struct dm_ioctl {
123 __u32 target_count; /* in/out */ 123 __u32 target_count; /* in/out */
124 __s32 open_count; /* out */ 124 __s32 open_count; /* out */
125 __u32 flags; /* in/out */ 125 __u32 flags; /* in/out */
126
127 /*
128 * event_nr holds either the event number (input and output) or the
129 * udev cookie value (input only).
130 * The DM_DEV_WAIT ioctl takes an event number as input.
131 * The DM_SUSPEND, DM_DEV_REMOVE and DM_DEV_RENAME ioctls
132 * use the field as a cookie to return in the DM_COOKIE
133 * variable with the uevents they issue.
134 * For output, the ioctls return the event number, not the cookie.
135 */
126 __u32 event_nr; /* in/out */ 136 __u32 event_nr; /* in/out */
127 __u32 padding; 137 __u32 padding;
128 138
@@ -256,9 +266,9 @@ enum {
256#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) 266#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
257 267
258#define DM_VERSION_MAJOR 4 268#define DM_VERSION_MAJOR 4
259#define DM_VERSION_MINOR 14 269#define DM_VERSION_MINOR 15
260#define DM_VERSION_PATCHLEVEL 0 270#define DM_VERSION_PATCHLEVEL 0
261#define DM_VERSION_EXTRA "-ioctl (2008-04-23)" 271#define DM_VERSION_EXTRA "-ioctl (2009-04-01)"
262 272
263/* Status bits */ 273/* Status bits */
264#define DM_READONLY_FLAG (1 << 0) /* In/Out */ 274#define DM_READONLY_FLAG (1 << 0) /* In/Out */