diff --git a/block/genhd.c b/block/genhd.c
index 298ee78c1bda..e7c75c5aa831 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -162,6 +162,7 @@ static struct blk_major_name {
 	int major;
 	char name[16];
 	void (*probe)(dev_t devt);
+	struct module *owner;
 } *major_names[BLKDEV_MAJOR_HASH_SIZE];
 static DEFINE_MUTEX(major_names_lock);
 
@@ -190,7 +191,8 @@ void blkdev_show(struct seq_file *seqf, off_t offset)
  * @major: the requested major device number [1..BLKDEV_MAJOR_MAX-1]. If
  *         @major = 0, try to allocate any unused major number.
  * @name: the name of the new block device as a zero terminated string
- * @probe: allback that is called on access to any minor number of @major
+ * @probe: callback that is called on access to any minor number of @major
+ * @owner: THIS_MODULE if @probe is not NULL, ignored if @probe is NULL.
  *
  * The @name must be unique within the system.
  *
@@ -208,7 +210,7 @@ void blkdev_show(struct seq_file *seqf, off_t offset)
  * Use register_blkdev instead for any new code.
  */
 int __register_blkdev(unsigned int major, const char *name,
-		void (*probe)(dev_t devt))
+		      void (*probe)(dev_t devt), struct module *owner)
 {
 	struct blk_major_name **n, *p;
 	int index, ret = 0;
@@ -248,6 +250,7 @@ int __register_blkdev(unsigned int major, const char *name,
 
 	p->major = major;
 	p->probe = probe;
+	p->owner = owner;
 	strlcpy(p->name, name, sizeof(p->name));
 	p->next = NULL;
 	index = major_to_index(major);
@@ -653,14 +656,29 @@ void blk_request_module(dev_t devt)
 {
 	unsigned int major = MAJOR(devt);
 	struct blk_major_name **n;
+	void (*probe_fn)(dev_t devt);
 
 	mutex_lock(&major_names_lock);
 	for (n = &major_names[major_to_index(major)]; *n; n = &(*n)->next) {
-		if ((*n)->major == major && (*n)->probe) {
-			(*n)->probe(devt);
-			mutex_unlock(&major_names_lock);
-			return;
-		}
+		if ((*n)->major != major || !(*n)->probe)
+			continue;
+		if (!try_module_get((*n)->owner))
+			break;
+		/*
+		 * Calling probe function with major_names_lock held causes
+		 * circular locking dependency problem. Thus, call it after
+		 * releasing major_names_lock.
+		 */
+		probe_fn = (*n)->probe;
+		mutex_unlock(&major_names_lock);
+		/*
+		 * Assuming that unregister_blkdev() is called from module's
+		 * __exit function, a module refcount taken above allows us
+		 * to safely call probe function without major_names_lock held.
+		 */
+		probe_fn(devt);
+		module_put((*n)->owner);
+		return;
 	}
 	mutex_unlock(&major_names_lock);
 
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index a093644ac39f..1b7fe10d49e7 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -2016,7 +2016,7 @@ static int __init atari_floppy_init (void)
 		return -ENODEV;
 
 	mutex_lock(&ataflop_probe_lock);
-	ret = __register_blkdev(FLOPPY_MAJOR, "fd", ataflop_probe);
+	ret = __register_blkdev(FLOPPY_MAJOR, "fd", ataflop_probe, THIS_MODULE);
 	if (ret)
 		goto out_unlock;
 
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 95694113e38e..d0bdfd56dfc8 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -487,7 +487,7 @@ static int __init brd_init(void)
 	 *	dynamically.
 	 */
 
-	if (__register_blkdev(RAMDISK_MAJOR, "ramdisk", brd_probe))
+	if (__register_blkdev(RAMDISK_MAJOR, "ramdisk", brd_probe, THIS_MODULE))
 		return -EIO;
 
 	brd_check_and_reset_par();
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 87460e0e5c72..ee33ba03e6bd 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4570,7 +4570,7 @@ static int __init do_floppy_init(void)
 		timer_setup(&motor_off_timer[drive], motor_off_callback, 0);
 	}
 
-	err = __register_blkdev(FLOPPY_MAJOR, "fd", floppy_probe);
+	err = __register_blkdev(FLOPPY_MAJOR, "fd", floppy_probe, THIS_MODULE);
 	if (err)
 		goto out_put_disk;
 
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index f0cdff0c5fbf..d6606c3b7d74 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -2564,7 +2564,7 @@ static int __init loop_init(void)
 		goto err_out;
 
 
-	if (__register_blkdev(LOOP_MAJOR, "loop", loop_probe)) {
+	if (__register_blkdev(LOOP_MAJOR, "loop", loop_probe, THIS_MODULE)) {
 		err = -EIO;
 		goto misc_out;
 	}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index ae8fe54ea358..c13f45c0f502 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -9584,11 +9584,11 @@ static int __init md_init(void)
 	if (!md_rdev_misc_wq)
 		goto err_rdev_misc_wq;
 
-	ret = __register_blkdev(MD_MAJOR, "md", md_probe);
+	ret = __register_blkdev(MD_MAJOR, "md", md_probe, THIS_MODULE);
 	if (ret < 0)
 		goto err_md;
 
-	ret = __register_blkdev(0, "mdp", md_probe);
+	ret = __register_blkdev(0, "mdp", md_probe, THIS_MODULE);
 	if (ret < 0)
 		goto err_mdp;
 	mdp_major = ret;
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index b8d55af763f9..ddd67a1045e7 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -3729,7 +3729,7 @@ static int __init init_sd(void)
 	SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n"));
 
 	for (i = 0; i < SD_MAJORS; i++) {
-		if (__register_blkdev(sd_major(i), "sd", sd_default_probe))
+		if (__register_blkdev(sd_major(i), "sd", sd_default_probe, THIS_MODULE))
 			continue;
 		majors++;
 	}
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 13b34177cc85..b0948003071d 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -303,9 +303,9 @@ struct gendisk *__blk_alloc_disk(int node);
 void blk_cleanup_disk(struct gendisk *disk);
 
 int __register_blkdev(unsigned int major, const char *name,
-		void (*probe)(dev_t devt));
+		      void (*probe)(dev_t devt), struct module *owner);
 #define register_blkdev(major, name) \
-	__register_blkdev(major, name, NULL)
+	__register_blkdev(major, name, NULL, NULL)
 void unregister_blkdev(unsigned int major, const char *name);
 
 bool bdev_check_media_change(struct block_device *bdev);
