@@ -61,6 +61,24 @@ static DECLARE_RWSEM(_hash_lock);
*/
static DEFINE_MUTEX(dm_hash_cells_mutex);
+static void dm_ioctl_uevent(struct mapped_device *md,
+ enum kobject_action action,
+ unsigned cookie,
+ uint32_t *dm_flags)
+{
+ /*
+ * The first change event is translated to add event.
+ */
+ if (!dm_initialised_md(md)) {
+ if (action == KOBJ_CHANGE)
+ action = KOBJ_ADD;
+ WARN_ON(action != KOBJ_ADD);
+ }
+
+ if (!dm_kobject_uevent(md, action, cookie))
+ *dm_flags |= DM_UEVENT_GENERATED_FLAG;
+}
+
static void init_buckets(struct list_head *buckets)
{
unsigned int i;
@@ -345,8 +363,7 @@ static int dm_hash_rename(uint32_t cookie, uint32_t *flags, const char *old,
dm_table_put(table);
}
- if (!dm_kobject_uevent(hc->md, KOBJ_CHANGE, cookie))
- *flags |= DM_UEVENT_GENERATED_FLAG;
+ dm_ioctl_uevent(hc->md, KOBJ_CHANGE, cookie, flags);
dm_put(hc->md);
up_write(&_hash_lock);
@@ -738,8 +755,7 @@ static int dev_remove(struct dm_ioctl *param, size_t param_size)
__hash_remove(hc);
up_write(&_hash_lock);
- if (!dm_kobject_uevent(md, KOBJ_REMOVE, param->event_nr))
- param->flags |= DM_UEVENT_GENERATED_FLAG;
+ dm_ioctl_uevent(md, KOBJ_REMOVE, param->event_nr, ¶m->flags);
dm_put(md);
return 0;
@@ -903,8 +919,9 @@ static int do_resume(struct dm_ioctl *param)
if (dm_suspended_md(md)) {
r = dm_resume(md);
- if (!r && !dm_kobject_uevent(md, KOBJ_CHANGE, param->event_nr))
- param->flags |= DM_UEVENT_GENERATED_FLAG;
+ if (!r)
+ dm_ioctl_uevent(md, KOBJ_CHANGE, param->event_nr,
+ ¶m->flags);
}
if (old_map)
@@ -109,6 +109,7 @@ EXPORT_SYMBOL_GPL(dm_get_rq_mapinfo);
#define DMF_DELETING 4
#define DMF_NOFLUSH_SUSPENDING 5
#define DMF_QUEUE_IO_TO_THREAD 6
+#define DMF_INITIALISED 7
/*
* Work processed by per-device workqueue.
@@ -1932,6 +1933,7 @@ static struct mapped_device *alloc_dev(int minor)
md->disk->queue = md->queue;
md->disk->private_data = md;
sprintf(md->disk->disk_name, "dm-%d", minor);
+ md->disk->flags |= GENHD_FL_SUPPRESS_ADD_EVENT;
add_disk(md->disk);
format_dev_t(md->name, MKDEV(_major, minor));
@@ -2619,19 +2621,30 @@ out:
* Event notification.
*---------------------------------------------------------------*/
int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
- unsigned cookie)
+ unsigned cookie)
{
char udev_cookie[DM_COOKIE_LENGTH];
char *envp[] = { udev_cookie, NULL };
+ int r = 0;
+
+ if (action == KOBJ_ADD) {
+ set_bit(DMF_INITIALISED, &md->flags);
+ dev_set_uevent_suppress(disk_to_dev(md->disk), 0);
+ }
if (!cookie)
- return kobject_uevent(&disk_to_dev(md->disk)->kobj, action);
+ r = kobject_uevent(&disk_to_dev(md->disk)->kobj, action);
else {
snprintf(udev_cookie, DM_COOKIE_LENGTH, "%s=%u",
DM_COOKIE_ENV_VAR_NAME, cookie);
- return kobject_uevent_env(&disk_to_dev(md->disk)->kobj,
+ r = kobject_uevent_env(&disk_to_dev(md->disk)->kobj,
action, envp);
}
+
+ if (!r && dev_get_uevent_suppress(disk_to_dev(md->disk)))
+ r = -EINVAL;
+
+ return r;
}
uint32_t dm_next_uevent_seq(struct mapped_device *md)
@@ -2698,6 +2711,11 @@ int dm_suspended_md(struct mapped_device *md)
return test_bit(DMF_SUSPENDED, &md->flags);
}
+int dm_initialised_md(struct mapped_device *md)
+{
+ return test_bit(DMF_INITIALISED, &md->flags);
+}
+
int dm_suspended(struct dm_target *ti)
{
return dm_suspended_md(dm_table_get_md(ti->table));
@@ -99,6 +99,11 @@ int dm_deleting_md(struct mapped_device *md);
int dm_suspended_md(struct mapped_device *md);
/*
+ * Is the device initialised? (Add event was sent.)
+ */
+int dm_initialised_md(struct mapped_device *md);
+
+/*
* The device-mapper can be driven through one of two interfaces;
* ioctl or filesystem, depending which patch you have applied.
*/
@@ -526,6 +526,10 @@ void register_disk(struct gendisk *disk)
blkdev_put(bdev, FMODE_READ);
exit:
+ /* caller will send ADD event later */
+ if (disk->flags & GENHD_FL_SUPPRESS_ADD_EVENT)
+ return;
+
/* announce disk after possible partitions are created */
dev_set_uevent_suppress(ddev, 0);
kobject_uevent(&ddev->kobj, KOBJ_ADD);
@@ -116,6 +116,7 @@ struct hd_struct {
#define GENHD_FL_SUPPRESS_PARTITION_INFO 32
#define GENHD_FL_EXT_DEVT 64 /* allow extended devt */
#define GENHD_FL_NATIVE_CAPACITY 128
+#define GENHD_FL_SUPPRESS_ADD_EVENT 256
#define BLK_SCSI_MAX_CMDS (256)
#define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8))