diff options
author | NeilBrown <neilb@suse.de> | 2009-02-06 18:02:46 +1100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-02-12 09:31:01 -0800 |
commit | d7a95c07acbca8128e8a3a776bc1ab43ad744f9f (patch) | |
tree | 581ea5d1b8e385647e9cbc0c0c225cb9301bce82 /drivers/md/md.c | |
parent | 106d6a4bdb51dc18233e43a4baee041167db3973 (diff) | |
download | linux-stable-d7a95c07acbca8128e8a3a776bc1ab43ad744f9f.tar.gz linux-stable-d7a95c07acbca8128e8a3a776bc1ab43ad744f9f.tar.bz2 linux-stable-d7a95c07acbca8128e8a3a776bc1ab43ad744f9f.zip |
md: Ensure an md array never has too many devices.
commit de01dfadf25bf83cfe3d85c163005c4320532658 upstream.
Each different metadata format supported by md supports a
different maximum number of devices.
We really should be enforcing this maximum in the kernel, but
we aren't quite doing that properly.
We currently only enforce it at the 'hot_add' point, which is an
older interface which is not used by current userspace.
We need to also enforce it at 'add_new_disk' time for active arrays
and at 'do_md_run' time when starting a new array.
So move the test from 'hot_add' into 'bind_rdev_to_array' which is
called from both 'hot_add' and 'add_new_disk, and add a new
test in 'analyse_sbs' which is called from 'do_md_run'.
This bug (or missing feature) has been around "forever" and so
the patch is suitable for any -stable that is currently maintained.
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index fe6eccd6ceea..4d7cfc2dd861 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1454,6 +1454,11 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) if (find_rdev_nr(mddev, rdev->desc_nr)) return -EBUSY; } + if (mddev->max_disks && rdev->desc_nr >= mddev->max_disks) { + printk(KERN_WARNING "md: %s: array is limited to %d devices\n", + mdname(mddev), mddev->max_disks); + return -EBUSY; + } bdevname(rdev->bdev,b); while ( (s=strchr(b, '/')) != NULL) *s = '!'; @@ -2362,6 +2367,15 @@ static void analyze_sbs(mddev_t * mddev) i = 0; rdev_for_each(rdev, tmp, mddev) { + if (rdev->desc_nr >= mddev->max_disks || + i > mddev->max_disks) { + printk(KERN_WARNING + "md: %s: %s: only %d devices permitted\n", + mdname(mddev), bdevname(rdev->bdev, b), + mddev->max_disks); + kick_rdev_from_array(rdev); + continue; + } if (rdev != freshest) if (super_types[mddev->major_version]. validate_super(mddev, rdev)) { @@ -4450,13 +4464,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) * noticed in interrupt contexts ... */ - if (rdev->desc_nr == mddev->max_disks) { - printk(KERN_WARNING "%s: can not hot-add to full array!\n", - mdname(mddev)); - err = -EBUSY; - goto abort_unbind_export; - } - rdev->raid_disk = -1; md_update_sb(mddev, 1); @@ -4470,9 +4477,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) md_new_event(mddev); return 0; -abort_unbind_export: - unbind_rdev_from_array(rdev); - abort_export: export_rdev(rdev); return err; |