mirror of
https://github.com/torvalds/linux.git
synced 2024-12-04 10:01:41 +00:00
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
This commit is contained in:
commit
ff91763835
@ -734,7 +734,34 @@ void mddev_init(struct mddev *mddev)
|
||||
}
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
@ -745,13 +772,13 @@ static struct mddev *mddev_find(dev_t unit)
|
||||
spin_lock(&all_mddevs_lock);
|
||||
|
||||
if (unit) {
|
||||
list_for_each_entry(mddev, &all_mddevs, all_mddevs)
|
||||
if (mddev->unit == unit) {
|
||||
mddev_get(mddev);
|
||||
spin_unlock(&all_mddevs_lock);
|
||||
kfree(new);
|
||||
return mddev;
|
||||
}
|
||||
mddev = mddev_find_locked(unit);
|
||||
if (mddev) {
|
||||
mddev_get(mddev);
|
||||
spin_unlock(&all_mddevs_lock);
|
||||
kfree(new);
|
||||
return mddev;
|
||||
}
|
||||
|
||||
if (new) {
|
||||
list_add(&new->all_mddevs, &all_mddevs);
|
||||
@ -777,12 +804,7 @@ static struct mddev *mddev_find(dev_t unit)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
is_free = 1;
|
||||
list_for_each_entry(mddev, &all_mddevs, all_mddevs)
|
||||
if (mddev->unit == dev) {
|
||||
is_free = 0;
|
||||
break;
|
||||
}
|
||||
is_free = !mddev_find_locked(dev);
|
||||
}
|
||||
new->unit = dev;
|
||||
new->md_minor = MINOR(dev);
|
||||
@ -5644,7 +5666,7 @@ static int md_alloc(dev_t dev, char *name)
|
||||
* writing to /sys/module/md_mod/parameters/new_array.
|
||||
*/
|
||||
static DEFINE_MUTEX(disks_mutex);
|
||||
struct mddev *mddev = mddev_find(dev);
|
||||
struct mddev *mddev = mddev_find_or_alloc(dev);
|
||||
struct gendisk *disk;
|
||||
int partitioned;
|
||||
int shift;
|
||||
@ -6524,11 +6546,9 @@ static void autorun_devices(int part)
|
||||
|
||||
md_probe(dev);
|
||||
mddev = mddev_find(dev);
|
||||
if (!mddev || !mddev->gendisk) {
|
||||
if (mddev)
|
||||
mddev_put(mddev);
|
||||
if (!mddev)
|
||||
break;
|
||||
}
|
||||
|
||||
if (mddev_lock(mddev))
|
||||
pr_warn("md: %s locked, cannot run\n", mdname(mddev));
|
||||
else if (mddev->raid_disks || mddev->major_version
|
||||
@ -7821,8 +7841,7 @@ static int md_open(struct block_device *bdev, fmode_t mode)
|
||||
/* Wait until bdev->bd_disk is definitely gone */
|
||||
if (work_pending(&mddev->del_work))
|
||||
flush_workqueue(md_misc_wq);
|
||||
/* Then retry the open from the top */
|
||||
return -ERESTARTSYS;
|
||||
return -EBUSY;
|
||||
}
|
||||
BUG_ON(mddev != bdev->bd_disk->private_data);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user