X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=blobdiff_plain;f=util.c;h=4cecd6d0cfdc1f0a357475624ac72195ed871be8;hp=8ea30699ac5f9aeae568caa44a3832269dea6a1f;hb=d2ca644994d642c31b41242140e1fe819711c8f7;hpb=2f6079dc96180335fdb56d0b89e462e903abbb50 diff --git a/util.c b/util.c index 8ea30699..4cecd6d0 100644 --- a/util.c +++ b/util.c @@ -32,6 +32,7 @@ #include #include #include +#include /* * following taken from linux/blkpg.h because they aren't @@ -714,21 +715,6 @@ void put_md_name(char *name) unlink(name); } -static int dev2major(int d) -{ - if (d >= 0) - return MD_MAJOR; - else - return get_mdp_major(); -} - -static int dev2minor(int d) -{ - if (d >= 0) - return d; - return (-1-d) << MdpMinorShift; -} - int find_free_devnum(int use_partitions) { int devnum; @@ -770,7 +756,8 @@ int dev_open(char *dev, int flags) if (e > dev && *e == ':' && e[1] && (minor = strtoul(e+1, &e, 0)) >= 0 && *e == 0) { - snprintf(devname, sizeof(devname), "/dev/.tmp.md.%d:%d", major, minor); + snprintf(devname, sizeof(devname), "/dev/.tmp.md.%d:%d:%d", + (int)getpid(), major, minor); if (mknod(devname, S_IFBLK|0600, makedev(major, minor))==0) { fd = open(devname, flags); unlink(devname); @@ -780,9 +767,27 @@ int dev_open(char *dev, int flags) return fd; } -struct superswitch *superlist[] = { &super0, &super1, &super_ddf, NULL }; +int open_dev_excl(int devnum) +{ + char buf[20]; + int i; + + sprintf(buf, "%d:%d", dev2major(devnum), dev2minor(devnum)); + for (i=0 ; i<25 ; i++) { + int fd = dev_open(buf, O_RDWR|O_EXCL); + if (fd >= 0) + return fd; + if (errno != EBUSY) + return fd; + usleep(200000); + } + return -1; +} + +struct superswitch *superlist[] = { &super0, &super1, &super_ddf, &super_imsm, NULL }; #if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) + struct supertype *super_by_fd(int fd) { mdu_array_info_t array; @@ -793,6 +798,7 @@ struct supertype *super_by_fd(int fd) char *verstr; char version[20]; int i; + char *subarray = NULL; sra = sysfs_read(fd, 0, GET_VERSION); @@ -812,42 +818,59 @@ struct supertype *super_by_fd(int fd) sprintf(version, "%d.%d", vers, minor); verstr = version; } + if (minor == -2 && verstr[0] == '/') { + char *dev = verstr+1; + subarray = strchr(dev, '/'); + int devnum; + if (subarray) + *subarray++ = '\0'; + if (strncmp(dev, "md_d", 4) == 0) + devnum = -1-atoi(dev+4); + else + devnum = atoi(dev+2); + subarray = strdup(subarray); + if (sra) + sysfs_free(sra); + sra = sysfs_read(-1, devnum, GET_VERSION); + verstr = sra->text_version ? : "-no-metadata-"; + } + for (i = 0; st == NULL && superlist[i] ; i++) st = superlist[i]->match_metadata_desc(verstr); if (sra) sysfs_free(sra); - if (st) + if (st) { st->sb = NULL; + if (subarray) { + strncpy(st->subarray, subarray, 32); + st->subarray[31] = 0; + free(subarray); + } else + st->subarray[0] = 0; + } return st; } #endif /* !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) */ -struct supertype *dup_super(struct supertype *st) +struct supertype *dup_super(struct supertype *orig) { - struct supertype *stnew = NULL; - char *verstr = NULL; - char version[20]; - int i; + struct supertype *st; + if (!orig) + return orig; + st = malloc(sizeof(*st)); if (!st) return st; - - if (st->ss->text_version) - strcpy(version, st->ss->text_version); - else if (st->minor_version == -1) - sprintf(version, "%d", st->ss->major); - else - sprintf(version, "%d.%d", st->ss->major, st->minor_version); - verstr = version; - - for (i = 0; stnew == NULL && superlist[i] ; i++) - stnew = superlist[i]->match_metadata_desc(verstr); - - if (stnew) - stnew->sb = NULL; - return stnew; + memset(st, 0, sizeof(*st)); + st->ss = orig->ss; + st->max_devs = orig->max_devs; + st->minor_version = orig->minor_version; + strcpy(st->subarray, orig->subarray); + st->sb = NULL; + st->info = NULL; + return st; } struct supertype *guess_super(int fd) @@ -862,11 +885,10 @@ struct supertype *guess_super(int fd) int i; st = malloc(sizeof(*st)); - memset(st, 0, sizeof(*st)); for (i=0 ; superlist[i]; i++) { int rv; ss = superlist[i]; - st->ss = NULL; + memset(st, 0, sizeof(*st)); rv = ss->load_super(st, fd, NULL); if (rv == 0) { struct mdinfo info; @@ -881,7 +903,7 @@ struct supertype *guess_super(int fd) } if (bestsuper != -1) { int rv; - st->ss = NULL; + memset(st, 0, sizeof(*st)); rv = superlist[bestsuper]->load_super(st, fd, NULL); if (rv == 0) { superlist[bestsuper]->free_super(st); @@ -975,6 +997,7 @@ int open_container(int fd) return dfd; } } + closedir(dir); return -1; } @@ -1001,6 +1024,48 @@ int fd2devnum(int fd) return -1; } +int mdmon_running(int devnum) +{ + char path[100]; + char pid[10]; + int fd; + int n; + sprintf(path, "/var/run/mdadm/%s.pid", devnum2devname(devnum)); + fd = open(path, O_RDONLY, 0); + + if (fd < 0) + return 0; + n = read(fd, pid, 9); + close(fd); + if (n <= 0) + return 0; + if (kill(atoi(pid), 0) == 0) + return 1; + return 0; +} + +int signal_mdmon(int devnum) +{ + char path[100]; + char pid[10]; + int fd; + int n; + sprintf(path, "/var/run/mdadm/%s.pid", devnum2devname(devnum)); + fd = open(path, O_RDONLY, 0); + + if (fd < 0) + return 0; + n = read(fd, pid, 9); + close(fd); + if (n <= 0) + return 0; + if (kill(atoi(pid), SIGUSR1) == 0) + return 1; + return 0; +} + + + #ifdef __TINYC__ /* tinyc doesn't optimize this check in ioctl.h out ... */ unsigned int __invalid_size_argument_for_IOC = 0;