diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index d7500e1..b670922 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -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, &param->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,
+					&param->flags);
 	}
 
 	if (old_map)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index d21e128..7b364d7 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -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));
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index bad1724..1e9d7fc 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -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.
  */
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index e8865c1..916173b 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -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);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 56b5051..ade71ff 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -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))
