From 9e6d9291275267d3fd4b6d85d7232081f89cd8e2 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 23 May 2011 17:21:35 +1000 Subject: [PATCH 1/1] Check all member devices in enough_fd The loop over all member devices in enough_fd could easily stop before it had found all devices. This would cause --re-add to fail incorrectly. So change the loop to be based on the reported number of devices in the device - with a safe-guard limit of 1024. Change some other loops to be more careful too. Reported-by: "Schmidt, Annemarie" Signed-off-by: NeilBrown --- Manage.c | 8 ++++++-- Monitor.c | 10 ++++++++-- util.c | 13 ++++++++++--- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/Manage.c b/Manage.c index 0e54bc77..66d69780 100644 --- a/Manage.c +++ b/Manage.c @@ -438,19 +438,21 @@ int Manage_subdevs(char *devname, int fd, if (strcmp(dv->devname, "failed")==0 || strcmp(dv->devname, "faulty")==0) { + int remaining_disks = array.nr_disks; if (dv->disposition != 'r') { fprintf(stderr, Name ": %s only meaningful " "with -r, not -%c\n", dv->devname, dv->disposition); return 1; } - for (; j < array.raid_disks + array.nr_disks ; j++) { + for (; j < 1024 && remaining_disks > 0; j++) { unsigned dev; disc.number = j; if (ioctl(fd, GET_DISK_INFO, &disc)) continue; if (disc.major == 0 && disc.minor == 0) continue; + remaining_disks --; if ((disc.state & 1) == 0) /* faulty */ continue; dev = makedev(disc.major, disc.minor); @@ -469,13 +471,14 @@ int Manage_subdevs(char *devname, int fd, if (next != dv) continue; } else if (strcmp(dv->devname, "detached") == 0) { + int remaining_disks = array.nr_disks; if (dv->disposition != 'r' && dv->disposition != 'f') { fprintf(stderr, Name ": %s only meaningful " "with -r of -f, not -%c\n", dv->devname, dv->disposition); return 1; } - for (; j < array.raid_disks + array.nr_disks; j++) { + for (; j < 1024 && remaining_disks > 0; j++) { int sfd; unsigned dev; disc.number = j; @@ -483,6 +486,7 @@ int Manage_subdevs(char *devname, int fd, continue; if (disc.major == 0 && disc.minor == 0) continue; + remaining_disks --; sprintf(dvname,"%d:%d", disc.major, disc.minor); sfd = dev_open(dvname, O_RDONLY); if (sfd >= 0) { diff --git a/Monitor.c b/Monitor.c index 55aebeba..101bca4c 100644 --- a/Monitor.c +++ b/Monitor.c @@ -449,6 +449,8 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat, char *dev = st->devname; int fd; int i; + int remaining_disks; + int last_disk; if (test) alert("TestMessage", dev, NULL, ainfo); @@ -565,7 +567,8 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat, } st->percent = mse->percent; - for (i=0; i 0; i++) { mdu_disk_info_t disc; disc.number = i; @@ -573,9 +576,12 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat, info[i].state = disc.state; info[i].major = disc.major; info[i].minor = disc.minor; + if (disc.major || disc.minor) + remaining_disks --; } else info[i].major = info[i].minor = 0; } + last_disk = i; if (mse->metadata_version && strncmp(mse->metadata_version, "external:", 9) == 0 && @@ -596,7 +602,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat, int change; char *dv = NULL; disc.number = i; - if (i > array.raid_disks + array.nr_disks) { + if (i >= last_disk) { newstate = 0; disc.major = disc.minor = 0; } else if (info[i].major || info[i].minor) { diff --git a/util.c b/util.c index 1056ae4a..e92be4fe 100644 --- a/util.c +++ b/util.c @@ -370,10 +370,14 @@ int enough_fd(int fd) array.raid_disks <= 0) return 0; avail = calloc(array.raid_disks, 1); - for (i=0; i 0; i++) { disk.number = i; if (ioctl(fd, GET_DISK_INFO, &disk) != 0) continue; + if (disk.major == 0 && disk.minor == 0) + continue; + array.nr_disks--; + if (! (disk.state & (1<= array.raid_disks) @@ -1256,10 +1260,13 @@ int check_partitions(int fd, char *dname, unsigned long long freesize, void get_one_disk(int mdfd, mdu_array_info_t *ainf, mdu_disk_info_t *disk) { int d; + ioctl(mdfd, GET_ARRAY_INFO, ainf); - for (d = 0 ; d < ainf->raid_disks + ainf->nr_disks ; d++) - if (ioctl(mdfd, GET_DISK_INFO, disk) == 0) + for (d = 0 ; d < 1024 ; d++) { + if (ioctl(mdfd, GET_DISK_INFO, disk) == 0 && + (disk->major || disk->minor)) return; + } } int open_container(int fd) -- 2.39.2