diff options
author | NeilBrown <neilb@suse.de> | 2013-06-24 13:02:35 +1000 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2013-06-24 13:02:35 +1000 |
commit | a6a78630acd3772b493c042c71fc8c22799fab4d (patch) | |
tree | 402d2c88c7d79b4dfb054be198bb24a2a9436f0c /Grow.c | |
parent | 534f543296e6e28d44bb1176eb37258e8a542dc5 (diff) |
Grow: Try hard to set new_offset.
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>
Diffstat (limited to 'Grow.c')
-rw-r--r-- | Grow.c | 19 |
1 files changed, 15 insertions, 4 deletions
@@ -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); |