]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Grow: Try hard to set new_offset.
authorNeilBrown <neilb@suse.de>
Mon, 24 Jun 2013 03:02:35 +0000 (13:02 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 24 Jun 2013 03:02:35 +0000 (13:02 +1000)
Setting new_offset can fail if the v1.x "data_size" is too small.
So if that happens, try increasing it first by writing "0".
That can fail on spare devices due to a kernel bug, so if it doesn't
try writing the correct number of sectors.

Signed-off-by: NeilBrown <neilb@suse.de>
Grow.c

diff --git a/Grow.c b/Grow.c
index 122ca0ec16d10c6a08b47962c109e4fb7c6a4493..556bdafea5a1a575c40caa29d8799877e4726f8f 100644 (file)
--- a/Grow.c
+++ b/Grow.c
@@ -2353,10 +2353,21 @@ static int set_new_data_offset(struct mdinfo *sra, struct supertype *st,
                                                                        sd->data_offset - min);
                        }
                }
-               if (sysfs_set_num(sra, sd, "new_offset",
-                                 new_data_offset) < 0) {
-                       err = errno;
-                       err = -1;
+               err = sysfs_set_num(sra, sd, "new_offset", new_data_offset);
+               if (err < 0 && errno == E2BIG) {
+                       /* try again after increasing data size to max */
+                       err = sysfs_set_num(sra, sd, "size", 0);
+                       if (err < 0 && errno == EINVAL &&
+                           !(sd->disk.state & (1<<MD_DISK_SYNC))) {
+                               /* some kernels have a bug where you cannot
+                                * use '0' on spare devices. */
+                               sysfs_set_num(sra, sd, "size",
+                                             (sra->component_size + after)/2);
+                       }
+                       err = sysfs_set_num(sra, sd, "new_offset",
+                                           new_data_offset);
+               }
+               if (err < 0) {
                        if (errno == E2BIG && data_offset != INVALID_SECTORS) {
                                pr_err("data-offset is too big for %s\n",
                                       dn);