X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=Manage.c;h=1b7b0c111c837a01e084114840d4969d54601121;hb=7eef9be219d6ca1bf4329b6369b7cbf5d7922fc5;hp=7e1b94bed6b4a9ffe8f4f00edc05310589db46cd;hpb=38c2e05b6a2851dd288009e85f2987bd05ce5835;p=thirdparty%2Fmdadm.git diff --git a/Manage.c b/Manage.c index 7e1b94be..1b7b0c11 100644 --- a/Manage.c +++ b/Manage.c @@ -119,8 +119,7 @@ int Manage_ro(char *devname, int fd, int readonly) } out: #ifndef MDASSEMBLE - if (mdi) - sysfs_free(mdi); + sysfs_free(mdi); #endif return rv; } @@ -493,14 +492,17 @@ done: rv = 1; goto out; } - /* prior to 2.6.28, KOBJ_CHANGE was not sent when an md array - * was stopped, so We'll do it here just to be sure. Drop any - * partitions as well... - */ - if (fd >= 0) - ioctl(fd, BLKRRPART, 0); - if (mdi) - sysfs_uevent(mdi, "change"); + + if (get_linux_version() < 2006028) { + /* prior to 2.6.28, KOBJ_CHANGE was not sent when an md array + * was stopped, so We'll do it here just to be sure. Drop any + * partitions as well... + */ + if (fd >= 0) + ioctl(fd, BLKRRPART, 0); + if (mdi) + sysfs_uevent(mdi, "change"); + } if (devnm[0] && use_udev()) { struct map_ent *mp = map_by_devnm(&map, devnm); @@ -513,8 +515,7 @@ done: map_remove(&map, devnm); map_unlock(&map); out: - if (mdi) - sysfs_free(mdi); + sysfs_free(mdi); return rv; } @@ -737,7 +738,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, int raid_slot) { unsigned long long ldsize; - struct supertype *dev_st = NULL; + struct supertype *dev_st; int j; mdu_disk_info_t disc; @@ -842,20 +843,19 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, * simply re-add it. */ - if (array->not_persistent==0) { + if (array->not_persistent == 0) { dev_st = dup_super(tst); dev_st->ss->load_super(dev_st, tfd, NULL); - } - if (dev_st && dev_st->sb && dv->disposition != 'S') { - int rv = attempt_re_add(fd, tfd, dv, - dev_st, tst, - rdev, - update, devname, - verbose, - array); - dev_st->ss->free_super(dev_st); - if (rv) - return rv; + if (dev_st->sb && dv->disposition != 'S') { + int rv; + + rv = attempt_re_add(fd, tfd, dv, dev_st, tst, + rdev, update, devname, + verbose, array); + dev_st->ss->free_super(dev_st); + if (rv) + return rv; + } } if (dv->disposition == 'M') { if (verbose > 0) @@ -879,10 +879,10 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, continue; if (disc.major == 0 && disc.minor == 0) continue; - found++; if (!(disc.state & (1<level, array->raid_disks, array->layout, 1, avail); @@ -937,12 +937,19 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, struct mdinfo *mdp; mdp = sysfs_read(fd, NULL, GET_ARRAY_STATE); + if (!mdp) { + pr_err("%s unable to read array state.\n", devname); + return -1; + } if (strncmp(mdp->sysfs_array_state, "readonly", 8) != 0) { + sysfs_free(mdp); pr_err("%s is not readonly, cannot add journal.\n", devname); return -1; } + sysfs_free(mdp); + tst->ss->getinfo_super(tst, &mdi, NULL); if (mdi.journal_device_required == 0) { pr_err("%s does not support journal device.\n", devname); @@ -1118,19 +1125,34 @@ int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv, */ if (rdev == 0) ret = -1; - else - ret = sysfs_unique_holder(devnm, rdev); - if (ret == 0) { - pr_err("%s is not a member, cannot remove.\n", - dv->devname); - close(lfd); - return -1; - } - if (ret >= 2) { - pr_err("%s is still in use, cannot remove.\n", - dv->devname); - close(lfd); - return -1; + else { + /* + * The drive has already been set to 'faulty', however + * monitor might not have had time to process it and the + * drive might still have an entry in the 'holders' + * directory. Try a few times to avoid a false error + */ + int count = 20; + + do { + ret = sysfs_unique_holder(devnm, rdev); + if (ret < 2) + break; + usleep(100 * 1000); /* 100ms */ + } while (--count > 0); + + if (ret == 0) { + pr_err("%s is not a member, cannot remove.\n", + dv->devname); + close(lfd); + return -1; + } + if (ret >= 2) { + pr_err("%s is still in use, cannot remove.\n", + dv->devname); + close(lfd); + return -1; + } } } /* FIXME check that it is a current member */ @@ -1161,8 +1183,7 @@ int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv, "state", "remove"); else err = -1; - if (sra) - sysfs_free(sra); + sysfs_free(sra); } } if (err) { @@ -1410,7 +1431,7 @@ int Manage_subdevs(char *devname, int fd, } if (strcmp(dv->devname, "missing") == 0) { - struct mddev_dev *add_devlist = NULL; + struct mddev_dev *add_devlist; struct mddev_dev **dp; if (dv->disposition == 'c') { rv = ioctl(fd, CLUSTERED_DISK_NACK, NULL); @@ -1504,9 +1525,10 @@ int Manage_subdevs(char *devname, int fd, } else { struct stat stb; tfd = dev_open(dv->devname, O_RDONLY); - if (tfd >= 0) + if (tfd >= 0) { fstat(tfd, &stb); - else { + close(tfd); + } else { int open_err = errno; if (stat(dv->devname, &stb) != 0) { pr_err("Cannot find %s: %s\n",