From 89ced23b58cfd4529ade47488ee37a5ffce7cd8e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 23 Mar 2011 11:07:27 +1100 Subject: Assemble: improve efficacy of -Af in assembling degraded dirty arrays. If a degraded dirty array has some superblocks which are clean and others that are dirty, and the dirty ones are newer by precisely '1' in the event count, then the current code to force the array to be clean will not work. We need to make sure to find a superblock with most recent event count and force that one to be 'clean'. Reported-by: A J Wyborny Signed-off-by: NeilBrown --- Assemble.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Assemble.c b/Assemble.c index ea3a648..83bdbfa 100644 --- a/Assemble.c +++ b/Assemble.c @@ -905,6 +905,8 @@ int Assemble(struct supertype *st, char *mddev, continue; if (!devices[j].uptodate) continue; + if (devices[j].i.events < devices[most_recent].i.events) + continue; chosen_drive = j; if ((fd=dev_open(devices[j].devname, O_RDONLY|O_EXCL))< 0) { fprintf(stderr, Name ": Cannot open %s: %s\n", @@ -996,6 +998,9 @@ int Assemble(struct supertype *st, char *mddev, close(mdfd); return 1; } + if (verbose >= 0) + fprintf(stderr, Name ": Marking array %s as 'clean'\n", + mddev); close(fd); } -- cgit v1.2.1 From b306624e2bfd061339641295ed5cb52d40ab7ae3 Mon Sep 17 00:00:00 2001 From: Piergiorgio Sartor Date: Tue, 22 Mar 2011 10:09:38 +1100 Subject: restripe: allow test code to have an offset on each device. If device name ends :number, e.g. /dev/sda0:1234 then assume the RAID data starts that many sectors from start of device. Signed-off-by: NeilBrown --- restripe.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/restripe.c b/restripe.c index 3074693..9ae1b85 100644 --- a/restripe.c +++ b/restripe.c @@ -777,6 +777,14 @@ main(int argc, char *argv[]) exit(3); } for (i=0; i Date: Tue, 22 Mar 2011 10:32:09 +1100 Subject: ddf: fix up detection of failed/missing devices. If a device hasn't been found yet we can still tell if it is expected to be working, and we must to do to make sure 'working_disks' is correct. Signed-off-by: NeilBrown --- super-ddf.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/super-ddf.c b/super-ddf.c index 93de750..7929364 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -3033,23 +3033,33 @@ static struct mdinfo *container_content_ddf(struct supertype *st) struct mdinfo *dev; struct dl *d; int stt; + int pd; if (vc->conf.phys_refnum[i] == 0xFFFFFFFF) continue; - for (d = ddf->dlist; d ; d=d->next) - if (d->disk.refnum == vc->conf.phys_refnum[i]) + for (pd = __be16_to_cpu(ddf->phys->used_pdes); + pd--;) + if (ddf->phys->entries[pd].refnum + == vc->conf.phys_refnum[i]) break; - if (d == NULL) - /* Haven't found that one yet, maybe there are others */ + if (pd < 0) continue; - stt = __be16_to_cpu(ddf->phys->entries[d->pdnum].state); + + stt = __be16_to_cpu(ddf->phys->entries[pd].state); if ((stt & (DDF_Online|DDF_Failed|DDF_Rebuilding)) != DDF_Online) continue; this->array.working_disks++; + for (d = ddf->dlist; d ; d=d->next) + if (d->disk.refnum == vc->conf.phys_refnum[i]) + break; + if (d == NULL) + /* Haven't found that one yet, maybe there are others */ + continue; + dev = malloc(sizeof(*dev)); memset(dev, 0, sizeof(*dev)); dev->next = this->devs; -- cgit v1.2.1 From ce7a187b9a2c58783276c9da65088494f4f85124 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 22 Mar 2011 14:47:55 +1100 Subject: Monitor: handle v.quick removal of devices better. If a device fails and then is removed before Monitor sees the failure, GET_DISK_INFO returns nothing so Monitor relies on mdstat info where '_' is incorrectly interpreted as 'a spare'. We should treat '_' as 'removed' - that is safer. Without this, a v.quick fail+remove gets reported as 'Failed' then 'SpareActive'. Signed-off-by: NeilBrown --- Monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Monitor.c b/Monitor.c index 0f0adb5..7e8fa85 100644 --- a/Monitor.c +++ b/Monitor.c @@ -369,7 +369,7 @@ int Monitor(mddev_dev_t devlist, } else if (mse && mse->pattern && i < (int)strlen(mse->pattern)) { switch(mse->pattern[i]) { case 'U': newstate = 6 /* ACTIVE/SYNC */; break; - case '_': newstate = 0; break; + case '_': newstate = 8 /* REMOVED */; break; } disc.major = disc.minor = 0; } -- cgit v1.2.1 From fb0d4b9ca2fca333d82fabd1a7aa55e138e83910 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 23 Mar 2011 15:42:24 +1100 Subject: --stop: separate 'is busy' test for 'did it stop properly'. Stopping an md array requires that there is no other user of it. However with udev and udisks and such there can be transient other users of md devices which can interfere with stopping the array. If there is a transient users, we really want "mdadm --stop" to wait a little while and retry. However if the array is genuinely in-use (e.g. mounted), then we don't want to wait at all - we want to fail immediately. So before trying to stop, re-open device with O_EXCL. If this fails then the device is probably in use, so give up. If it succeeds, but a subsequent STOP_ARRAY fails, then it is possibly a transient failure, so try again for a few seconds. Signed-off-by: NeilBrown --- Manage.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/Manage.c b/Manage.c index 5932c90..3502175 100644 --- a/Manage.c +++ b/Manage.c @@ -207,10 +207,26 @@ int Manage_runstop(char *devname, int fd, int runstop, int quiet) struct stat stb; struct mdinfo *mdi; int devnum; + int err; + int count; /* If this is an mdmon managed array, just write 'inactive' * to the array state and let mdmon clear up. */ devnum = fd2devnum(fd); + /* Get EXCL access first. If this fails, then attempting + * to stop is probably a bad idea. + */ + close(fd); + fd = open(devname, O_RDONLY|O_EXCL); + if (fd < 0 || fd2devnum(fd) != devnum) { + if (fd >= 0) + close(fd); + fprintf(stderr, + Name ": Cannot get exclusive access to %s:" + " possibly it is still in use.\n", + devname); + return 1; + } mdi = sysfs_read(fd, -1, GET_LEVEL|GET_VERSION); if (mdi && mdi->array.level > 0 && @@ -229,7 +245,14 @@ int Manage_runstop(char *devname, int fd, int runstop, int quiet) /* Give monitor a chance to act */ ping_monitor(mdi->text_version); - fd = open(devname, O_RDONLY); + fd = open_dev_excl(devnum); + if (fd < 0) { + fprintf(stderr, Name + ": failed to completely stop %s" + ": Device is busy\n", + devname); + return 1; + } } else if (mdi && mdi->array.major_version == -1 && mdi->array.minor_version == -2 && @@ -262,7 +285,18 @@ int Manage_runstop(char *devname, int fd, int runstop, int quiet) } } - if (fd >= 0 && ioctl(fd, STOP_ARRAY, NULL)) { + /* As we have an O_EXCL open, any use of the device + * which blocks STOP_ARRAY is probably a transient use, + * so it is reasonable to retry for a while - 5 seconds. + */ + count = 25; err = 0; + while (count && fd >= 0 + && (err = ioctl(fd, STOP_ARRAY, NULL)) < 0 + && errno == EBUSY) { + usleep(200000); + count --; + } + if (fd >= 0 && err) { if (quiet == 0) { fprintf(stderr, Name ": failed to stop array %s: %s\n", -- cgit v1.2.1 From ebdc4d125346c3514600a8c2d7455e1817e10e2c Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 23 Mar 2011 15:42:35 +1100 Subject: Incr: don't exclude 'active' devices from auto inclusion in a container. For containers, it is always appropriate to include a device in the container. Whether it should then be included in an array is a separate question. Signed-off-by: NeilBrown --- Incremental.c | 19 +++++++------------ mdadm.h | 1 - util.c | 7 +------ 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/Incremental.c b/Incremental.c index 4d3d181..46badc9 100644 --- a/Incremental.c +++ b/Incremental.c @@ -375,20 +375,15 @@ int Incremental(char *devname, int verbose, int runstop, * they failed. However if runstop is 1, then the * array was possibly started early and our best be is * to add this anyway. It would probably be good to - * allow explicit policy statement about this. + * allow explicit policy statement about this.. + * This doesn't apply to containers as the 'non-spare' + * flag has a different meaning. The test has to happen + * at the device level there */ - if ((info.disk.state & (1<ss->external + && (info.disk.state & (1<ss->external) { - char *devname = devnum2devname(fd2devnum(mdfd)); - - active = devname && is_container_active(devname); - free(devname); - } else if (ioctl(mdfd, GET_ARRAY_INFO, &ainf) == 0) - active = 1; - if (active) { + if (ioctl(mdfd, GET_ARRAY_INFO, &ainf) == 0) { fprintf(stderr, Name ": not adding %s to active array (without --run) %s\n", devname, chosen_name); diff --git a/mdadm.h b/mdadm.h index f5367bf..bb293f4 100644 --- a/mdadm.h +++ b/mdadm.h @@ -936,7 +936,6 @@ extern int open_mddev(char *dev, int report_errors); extern int open_container(int fd); extern int is_container_member(struct mdstat_ent *ent, char *devname); extern int is_subarray_active(char *subarray, char *devname); -int is_container_active(char *devname); extern int open_subarray(char *dev, struct supertype *st, int quiet); extern struct superswitch *version_to_superswitch(char *vers); diff --git a/util.c b/util.c index cbefaba..b42056d 100644 --- a/util.c +++ b/util.c @@ -1471,7 +1471,7 @@ int is_subarray_active(char *subarray, char *container) if (is_container_member(ent, container)) { char *inst = &ent->metadata_version[10+strlen(container)+1]; - if (!subarray || strcmp(inst, subarray) == 0) + if (strcmp(inst, subarray) == 0) break; } } @@ -1481,11 +1481,6 @@ int is_subarray_active(char *subarray, char *container) return ent != NULL; } -int is_container_active(char *container) -{ - return is_subarray_active(NULL, container); -} - /* open_subarray - opens a subarray in a container * @dev: container device name * @st: supertype with only ->subarray set -- cgit v1.2.1 From 945f0fcd0179210ae5b72006c3621a73cc6e9205 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 23 Mar 2011 15:43:19 +1100 Subject: Release mdadm-3.1.5 Signed-off-by: NeilBrown --- ANNOUNCE-3.1.5 | 42 ++++++++++++++++++++++++++++++++++++++++++ ReadMe.c | 2 +- inventory | 1 + mdadm.8.in | 2 +- mdadm.spec | 2 +- mdassemble.8 | 2 +- mdmon.8 | 2 +- 7 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 ANNOUNCE-3.1.5 diff --git a/ANNOUNCE-3.1.5 b/ANNOUNCE-3.1.5 new file mode 100644 index 0000000..baa1f92 --- /dev/null +++ b/ANNOUNCE-3.1.5 @@ -0,0 +1,42 @@ +Subject: ANNOUNCE: mdadm 3.1.5 - A tool for managing Soft RAID under Linux + +I am pleased to announce the availability of + mdadm version 3.1.5 + +It is available at the usual places: + countrycode=xx. + http://www.${countrycode}kernel.org/pub/linux/utils/raid/mdadm/ +and via git at + git://neil.brown.name/mdadm + http://neil.brown.name/git?p=mdadm + +This is a bugfix/stability release over 3.1.4. It contains all the +important bugfixes found while working on 3.2 and 3.2.1. It will be +the last 3.1.x release - 3.2.1 is expected to be released in a few days. + +Changes include: + - Fixes for v1.x metadata on big-endian machines. + - man page improvements + - Improve '--detail --export' when run on partitions of an md array. + - Fix regression with removing 'failed' or 'detached' devices. + - Fixes for "--assemble --force" in various unusual cases. + - Allow '-Y' to mean --export. This was documented but not implemented. + - Various fixed for handling 'ddf' metadata. This is now more reliable + but could benefit from more interoperability testing. + - Correctly list subarrays of a container in "--detail" output. + - Improve checks on whether the requested number of devices is supported + by the metadata - both for --create and --grow. + - Don't remove partitions from a device that is being included in an + array until we are fully committed to including it. + - Allow "--assemble --update=no-bitmap" so an array with a corrupt + bitmap can still be assembled. + - Don't allow --add to succeed if it looks like a "--re-add" is probably + wanted, but cannot succeed. This avoids inadvertently turning + devices into spares when an array is failed. + +This release is believed to be stable and you should feel free to +upgrade to 3.1.5 + + +NeilBrown 23rd March 2011 + diff --git a/ReadMe.c b/ReadMe.c index e1f8c68..5f3c124 100644 --- a/ReadMe.c +++ b/ReadMe.c @@ -24,7 +24,7 @@ #include "mdadm.h" -char Version[] = Name " - v3.1.4 - 31st August 2010\n"; +char Version[] = Name " - v3.1.5 - 23rd March 2011\n"; /* * File: ReadMe.c diff --git a/inventory b/inventory index af153e9..d05eb3c 100755 --- a/inventory +++ b/inventory @@ -8,6 +8,7 @@ ANNOUNCE-3.1.1 ANNOUNCE-3.1.2 ANNOUNCE-3.1.3 ANNOUNCE-3.1.4 +ANNOUNCE-3.1.5 Assemble.c bitmap.c bitmap.h diff --git a/mdadm.8.in b/mdadm.8.in index 05ae34f..7758fbb 100644 --- a/mdadm.8.in +++ b/mdadm.8.in @@ -5,7 +5,7 @@ .\" the Free Software Foundation; either version 2 of the License, or .\" (at your option) any later version. .\" See file COPYING in distribution for details. -.TH MDADM 8 "" v3.1.4 +.TH MDADM 8 "" v3.1.5 .SH NAME mdadm \- manage MD devices .I aka diff --git a/mdadm.spec b/mdadm.spec index bae85af..4b834d6 100644 --- a/mdadm.spec +++ b/mdadm.spec @@ -1,6 +1,6 @@ Summary: mdadm is used for controlling Linux md devices (aka RAID arrays) Name: mdadm -Version: 3.1.4 +Version: 3.1.5 Release: 1 Source: http://www.kernel.org/pub/linux/utils/raid/mdadm/mdadm-%{version}.tgz URL: http://neil.brown.name/blog/mdadm diff --git a/mdassemble.8 b/mdassemble.8 index 986432c..d5e2c3e 100644 --- a/mdassemble.8 +++ b/mdassemble.8 @@ -1,5 +1,5 @@ .\" -*- nroff -*- -.TH MDASSEMBLE 8 "" v3.1.4 +.TH MDASSEMBLE 8 "" v3.1.5 .SH NAME mdassemble \- assemble MD devices .I aka diff --git a/mdmon.8 b/mdmon.8 index 2ccb279..c2e5fa4 100644 --- a/mdmon.8 +++ b/mdmon.8 @@ -1,5 +1,5 @@ .\" See file COPYING in distribution for details. -.TH MDMON 8 "" v3.1.4 +.TH MDMON 8 "" v3.1.5 .SH NAME mdmon \- monitor MD external metadata arrays -- cgit v1.2.1