X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=Manage.c;h=7afd89b7ce7b56c81aa6871ed8c149961cf02382;hb=fdb482f99b9ad2ef8cd1724902fdfeedaa8796a1;hp=6b9825b41b0689065eb19f04afdd5cbb3cfd184d;hpb=6c766cf10178b9bae4ddcfd6b8de2d70f9d84568;p=thirdparty%2Fmdadm.git diff --git a/Manage.c b/Manage.c index 6b9825b4..7afd89b7 100644 --- a/Manage.c +++ b/Manage.c @@ -30,6 +30,7 @@ #include "mdadm.h" #include "md_u.h" #include "md_p.h" +#include #define REGISTER_DEV _IO (MD_MAJOR, 1) #define START_MD _IO (MD_MAJOR, 2) @@ -120,6 +121,54 @@ int Manage_ro(char *devname, int fd, int readonly) #ifndef MDASSEMBLE +static void remove_devices(int devnum, char *path) +{ + /* Remove all 'standard' devices for 'devnum', including + * partitions. Also remove names at 'path' - possibly with + * partition suffixes - which link to those names. + */ + char base[40]; + char *path2; + char link[1024]; + int n; + int part; + char *be; + char *pe; + + if (devnum >= 0) + sprintf(base, "/dev/md%d", devnum); + else + sprintf(base, "/dev/md_d%d", -1-devnum); + be = base + strlen(base); + if (path) { + path2 = malloc(strlen(path)+20); + strcpy(path2, path); + pe = path2 + strlen(path2); + } else + path = NULL; + + for (part = 0; part < 16; part++) { + if (part) { + sprintf(be, "p%d", part); + if (path) { + if (isdigit(pe[-1])) + sprintf(pe, "p%d", part); + else + sprintf(pe, "%d", part); + } + } + /* FIXME test if really is md device ?? */ + unlink(base); + if (path) { + n = readlink(path2, link, sizeof(link)); + if (n && strlen(base) == n && + strncmp(link, base, n) == 0) + unlink(path2); + } + } +} + + int Manage_runstop(char *devname, int fd, int runstop, int quiet) { /* Run or stop the array. array must already be configured @@ -163,9 +212,11 @@ int Manage_runstop(char *devname, int fd, int runstop, int quiet) struct map_ent *map = NULL; struct stat stb; struct mdinfo *mdi; + int devnum; /* If this is an mdmon managed array, just write 'inactive' * to the array state and let mdmon clear up. */ + devnum = fd2devnum(fd); mdi = sysfs_read(fd, -1, GET_LEVEL|GET_VERSION); if (mdi && mdi->array.level > 0 && @@ -195,8 +246,6 @@ int Manage_runstop(char *devname, int fd, int runstop, int quiet) */ ping_monitor(mdi->sys_name); } - if (mdi) - sysfs_free(mdi); if (fd >= 0 && ioctl(fd, STOP_ARRAY, NULL)) { if (quiet == 0) { @@ -208,17 +257,31 @@ int Manage_runstop(char *devname, int fd, int runstop, int quiet) "process, mounted filesystem " "or active volume group?\n"); } + if (mdi) + sysfs_free(mdi); return 1; } + /* 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 (devnum != NoMdDev && + (stat("/dev/.udev", &stb) != 0 || + check_env("MDADM_NO_UDEV"))) { + struct map_ent *mp = map_by_devnum(&map, devnum); + remove_devices(devnum, mp ? mp->path : NULL); + } + if (quiet <= 0) fprintf(stderr, Name ": stopped %s\n", devname); - if (fd >= 0 && fstat(fd, &stb) == 0) { - int devnum; - if (major(stb.st_rdev) == MD_MAJOR) - devnum = minor(stb.st_rdev); - else - devnum = -1-(minor(stb.st_rdev)>>6); + if (devnum != NoMdDev) { map_delete(&map, devnum); map_write(map); map_free(map); @@ -561,8 +624,11 @@ int Manage_subdevs(char *devname, int fd, if (dv->writemostly == 1) disc.state |= 1 << MD_DISK_WRITEMOSTLY; dfd = open(dv->devname, O_RDWR | O_EXCL|O_DIRECT); - tst->ss->add_to_super(tst, &disc, dfd, - dv->devname); + if (tst->ss->add_to_super(tst, &disc, dfd, + dv->devname)) { + close(dfd); + return 1; + } /* write_init_super will close 'dfd' */ if (tst->ss->external) /* mdmon will write the metadata */ @@ -680,7 +746,14 @@ int Manage_subdevs(char *devname, int fd, " to container - odd\n"); return 1; } - if (!sysfs_unique_holder(dnum, stb.st_rdev)) { + /* in the detached case it is not possible to + * check if we are the unique holder, so just + * rely on the 'detached' checks + */ + if (strcmp(dv->devname, "detached") == 0 || + sysfs_unique_holder(dnum, stb.st_rdev)) + /* pass */; + else { fprintf(stderr, Name ": %s is %s, cannot remove.\n", dnprintable,