Commit ff917638 authored by Jens Axboe's avatar Jens Axboe

Merge branch 'md-next' of...

Merge branch 'md-next' of https://git.kernel.org/pub/scm/linux/kernel/git/song/md into for-5.13/drivers

Pull MD updates from Song:

"These patches fix a race condition with md_release() and md_open()."

* 'md-next' of https://git.kernel.org/pub/scm/linux/kernel/git/song/md:
  md: split mddev_find
  md: factor out a mddev_find_locked helper from mddev_find
  md: md_open returns -EBUSY when entering racing area
parents 9c282c29 65aa97c4
...@@ -734,7 +734,34 @@ void mddev_init(struct mddev *mddev) ...@@ -734,7 +734,34 @@ void mddev_init(struct mddev *mddev)
} }
EXPORT_SYMBOL_GPL(mddev_init); EXPORT_SYMBOL_GPL(mddev_init);
static struct mddev *mddev_find_locked(dev_t unit)
{
struct mddev *mddev;
list_for_each_entry(mddev, &all_mddevs, all_mddevs)
if (mddev->unit == unit)
return mddev;
return NULL;
}
static struct mddev *mddev_find(dev_t unit) static struct mddev *mddev_find(dev_t unit)
{
struct mddev *mddev;
if (MAJOR(unit) != MD_MAJOR)
unit &= ~((1 << MdpMinorShift) - 1);
spin_lock(&all_mddevs_lock);
mddev = mddev_find_locked(unit);
if (mddev)
mddev_get(mddev);
spin_unlock(&all_mddevs_lock);
return mddev;
}
static struct mddev *mddev_find_or_alloc(dev_t unit)
{ {
struct mddev *mddev, *new = NULL; struct mddev *mddev, *new = NULL;
...@@ -745,13 +772,13 @@ static struct mddev *mddev_find(dev_t unit) ...@@ -745,13 +772,13 @@ static struct mddev *mddev_find(dev_t unit)
spin_lock(&all_mddevs_lock); spin_lock(&all_mddevs_lock);
if (unit) { if (unit) {
list_for_each_entry(mddev, &all_mddevs, all_mddevs) mddev = mddev_find_locked(unit);
if (mddev->unit == unit) { if (mddev) {
mddev_get(mddev); mddev_get(mddev);
spin_unlock(&all_mddevs_lock); spin_unlock(&all_mddevs_lock);
kfree(new); kfree(new);
return mddev; return mddev;
} }
if (new) { if (new) {
list_add(&new->all_mddevs, &all_mddevs); list_add(&new->all_mddevs, &all_mddevs);
...@@ -777,12 +804,7 @@ static struct mddev *mddev_find(dev_t unit) ...@@ -777,12 +804,7 @@ static struct mddev *mddev_find(dev_t unit)
return NULL; return NULL;
} }
is_free = 1; is_free = !mddev_find_locked(dev);
list_for_each_entry(mddev, &all_mddevs, all_mddevs)
if (mddev->unit == dev) {
is_free = 0;
break;
}
} }
new->unit = dev; new->unit = dev;
new->md_minor = MINOR(dev); new->md_minor = MINOR(dev);
...@@ -5644,7 +5666,7 @@ static int md_alloc(dev_t dev, char *name) ...@@ -5644,7 +5666,7 @@ static int md_alloc(dev_t dev, char *name)
* writing to /sys/module/md_mod/parameters/new_array. * writing to /sys/module/md_mod/parameters/new_array.
*/ */
static DEFINE_MUTEX(disks_mutex); static DEFINE_MUTEX(disks_mutex);
struct mddev *mddev = mddev_find(dev); struct mddev *mddev = mddev_find_or_alloc(dev);
struct gendisk *disk; struct gendisk *disk;
int partitioned; int partitioned;
int shift; int shift;
...@@ -6524,11 +6546,9 @@ static void autorun_devices(int part) ...@@ -6524,11 +6546,9 @@ static void autorun_devices(int part)
md_probe(dev); md_probe(dev);
mddev = mddev_find(dev); mddev = mddev_find(dev);
if (!mddev || !mddev->gendisk) { if (!mddev)
if (mddev)
mddev_put(mddev);
break; break;
}
if (mddev_lock(mddev)) if (mddev_lock(mddev))
pr_warn("md: %s locked, cannot run\n", mdname(mddev)); pr_warn("md: %s locked, cannot run\n", mdname(mddev));
else if (mddev->raid_disks || mddev->major_version else if (mddev->raid_disks || mddev->major_version
...@@ -7821,8 +7841,7 @@ static int md_open(struct block_device *bdev, fmode_t mode) ...@@ -7821,8 +7841,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
/* Wait until bdev->bd_disk is definitely gone */ /* Wait until bdev->bd_disk is definitely gone */
if (work_pending(&mddev->del_work)) if (work_pending(&mddev->del_work))
flush_workqueue(md_misc_wq); flush_workqueue(md_misc_wq);
/* Then retry the open from the top */ return -EBUSY;
return -ERESTARTSYS;
} }
BUG_ON(mddev != bdev->bd_disk->private_data); BUG_ON(mddev != bdev->bd_disk->private_data);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment