Commit ff917638 authored by Jens Axboe's avatar Jens Axboe
Browse files

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
Loading
Loading
Loading
Loading
+39 −20
Original line number Diff line number Diff line
@@ -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,8 +772,8 @@ 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 = mddev_find_locked(unit);
		if (mddev) {
			mddev_get(mddev);
			spin_unlock(&all_mddevs_lock);
			kfree(new);
@@ -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);