Commit 455abda6 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:

"1. mddev_find_or_alloc() clean up, from Christoph.
 2. Fix NULL pointer deref with external bitmap, from Sudhakar."

* 'md-next' of https://git.kernel.org/pub/scm/linux/kernel/git/song/md:
  md/bitmap: wait for external bitmap writes to complete during tear down
  md: do not return existing mddevs from mddev_find_or_alloc
  md: refactor mddev_find_or_alloc
  md: factor out a mddev_alloc_unit helper from mddev_find
parents e63c8eb1 404a8ef5
...@@ -1722,6 +1722,8 @@ void md_bitmap_flush(struct mddev *mddev) ...@@ -1722,6 +1722,8 @@ void md_bitmap_flush(struct mddev *mddev)
md_bitmap_daemon_work(mddev); md_bitmap_daemon_work(mddev);
bitmap->daemon_lastrun -= sleep; bitmap->daemon_lastrun -= sleep;
md_bitmap_daemon_work(mddev); md_bitmap_daemon_work(mddev);
if (mddev->bitmap_info.external)
md_super_wait(mddev);
md_bitmap_update_sb(bitmap); md_bitmap_update_sb(bitmap);
} }
......
...@@ -745,6 +745,27 @@ static struct mddev *mddev_find_locked(dev_t unit) ...@@ -745,6 +745,27 @@ static struct mddev *mddev_find_locked(dev_t unit)
return NULL; return NULL;
} }
/* find an unused unit number */
static dev_t mddev_alloc_unit(void)
{
static int next_minor = 512;
int start = next_minor;
bool is_free = 0;
dev_t dev = 0;
while (!is_free) {
dev = MKDEV(MD_MAJOR, next_minor);
next_minor++;
if (next_minor > MINORMASK)
next_minor = 0;
if (next_minor == start)
return 0; /* Oh dear, all in use. */
is_free = !mddev_find_locked(dev);
}
return dev;
}
static struct mddev *mddev_find(dev_t unit) static struct mddev *mddev_find(dev_t unit)
{ {
struct mddev *mddev; struct mddev *mddev;
...@@ -761,73 +782,46 @@ static struct mddev *mddev_find(dev_t unit) ...@@ -761,73 +782,46 @@ static struct mddev *mddev_find(dev_t unit)
return mddev; return mddev;
} }
static struct mddev *mddev_find_or_alloc(dev_t unit) static struct mddev *mddev_alloc(dev_t unit)
{ {
struct mddev *mddev, *new = NULL; struct mddev *new;
int error;
if (unit && MAJOR(unit) != MD_MAJOR) if (unit && MAJOR(unit) != MD_MAJOR)
unit &= ~((1<<MdpMinorShift)-1); unit &= ~((1 << MdpMinorShift) - 1);
retry: new = kzalloc(sizeof(*new), GFP_KERNEL);
spin_lock(&all_mddevs_lock); if (!new)
return ERR_PTR(-ENOMEM);
mddev_init(new);
spin_lock(&all_mddevs_lock);
if (unit) { if (unit) {
mddev = mddev_find_locked(unit); error = -EEXIST;
if (mddev) { if (mddev_find_locked(unit))
mddev_get(mddev); goto out_free_new;
spin_unlock(&all_mddevs_lock); new->unit = unit;
kfree(new); if (MAJOR(unit) == MD_MAJOR)
return mddev; new->md_minor = MINOR(unit);
} else
new->md_minor = MINOR(unit) >> MdpMinorShift;
if (new) { new->hold_active = UNTIL_IOCTL;
list_add(&new->all_mddevs, &all_mddevs); } else {
spin_unlock(&all_mddevs_lock); error = -ENODEV;
new->hold_active = UNTIL_IOCTL; new->unit = mddev_alloc_unit();
return new; if (!new->unit)
} goto out_free_new;
} else if (new) { new->md_minor = MINOR(new->unit);
/* find an unused unit number */
static int next_minor = 512;
int start = next_minor;
int is_free = 0;
int dev = 0;
while (!is_free) {
dev = MKDEV(MD_MAJOR, next_minor);
next_minor++;
if (next_minor > MINORMASK)
next_minor = 0;
if (next_minor == start) {
/* Oh dear, all in use. */
spin_unlock(&all_mddevs_lock);
kfree(new);
return NULL;
}
is_free = !mddev_find_locked(dev);
}
new->unit = dev;
new->md_minor = MINOR(dev);
new->hold_active = UNTIL_STOP; new->hold_active = UNTIL_STOP;
list_add(&new->all_mddevs, &all_mddevs);
spin_unlock(&all_mddevs_lock);
return new;
} }
spin_unlock(&all_mddevs_lock);
new = kzalloc(sizeof(*new), GFP_KERNEL); list_add(&new->all_mddevs, &all_mddevs);
if (!new) spin_unlock(&all_mddevs_lock);
return NULL; return new;
out_free_new:
new->unit = unit; spin_unlock(&all_mddevs_lock);
if (MAJOR(unit) == MD_MAJOR) kfree(new);
new->md_minor = MINOR(unit); return ERR_PTR(error);
else
new->md_minor = MINOR(unit) >> MdpMinorShift;
mddev_init(new);
goto retry;
} }
static struct attribute_group md_redundancy_group; static struct attribute_group md_redundancy_group;
...@@ -5666,29 +5660,29 @@ static int md_alloc(dev_t dev, char *name) ...@@ -5666,29 +5660,29 @@ 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_or_alloc(dev); struct mddev *mddev;
struct gendisk *disk; struct gendisk *disk;
int partitioned; int partitioned;
int shift; int shift;
int unit; int unit;
int error; int error ;
if (!mddev) /*
return -ENODEV; * Wait for any previous instance of this device to be completely
* removed (mddev_delayed_delete).
partitioned = (MAJOR(mddev->unit) != MD_MAJOR);
shift = partitioned ? MdpMinorShift : 0;
unit = MINOR(mddev->unit) >> shift;
/* wait for any previous instance of this device to be
* completely removed (mddev_delayed_delete).
*/ */
flush_workqueue(md_misc_wq); flush_workqueue(md_misc_wq);
mutex_lock(&disks_mutex); mutex_lock(&disks_mutex);
error = -EEXIST; mddev = mddev_alloc(dev);
if (mddev->gendisk) if (IS_ERR(mddev)) {
goto abort; mutex_unlock(&disks_mutex);
return PTR_ERR(mddev);
}
partitioned = (MAJOR(mddev->unit) != MD_MAJOR);
shift = partitioned ? MdpMinorShift : 0;
unit = MINOR(mddev->unit) >> shift;
if (name && !dev) { if (name && !dev) {
/* Need to ensure that 'name' is not a duplicate. /* Need to ensure that 'name' is not a duplicate.
...@@ -5700,6 +5694,7 @@ static int md_alloc(dev_t dev, char *name) ...@@ -5700,6 +5694,7 @@ static int md_alloc(dev_t dev, char *name)
if (mddev2->gendisk && if (mddev2->gendisk &&
strcmp(mddev2->gendisk->disk_name, name) == 0) { strcmp(mddev2->gendisk->disk_name, name) == 0) {
spin_unlock(&all_mddevs_lock); spin_unlock(&all_mddevs_lock);
error = -EEXIST;
goto abort; goto abort;
} }
spin_unlock(&all_mddevs_lock); spin_unlock(&all_mddevs_lock);
......
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