[patch 09/56] md: Ensure an md array never has too many devices.

From: Greg KH
Date: Tue Feb 10 2009 - 19:31:25 EST


2.6.27-stable review patch. If anyone has any objections, please let us know.
------------------

From: NeilBrown <neilb@xxxxxxx>

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@xxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>

---
drivers/md/md.c | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)

--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1454,6 +1454,11 @@ static int bind_rdev_to_array(mdk_rdev_t
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,
* 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,
md_new_event(mddev);
return 0;

-abort_unbind_export:
- unbind_rdev_from_array(rdev);
-
abort_export:
export_rdev(rdev);
return err;

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/