X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=blobdiff_plain;f=util.c;h=fde58ebbeffa6271c93e01abae14c5880221e0f6;hp=f3c37e1003b26e157cf7573d7389709c82a473c8;hb=62a48395f60965d04da1a9cbb937bda79dd071c8;hpb=69b2fcc5bb7ee6608790513042110a15d36a21bc diff --git a/util.c b/util.c index f3c37e10..fde58ebb 100644 --- a/util.c +++ b/util.c @@ -160,6 +160,31 @@ int get_linux_version() return (a*1000000)+(b*1000)+c; } +int mdadm_version(char *version) +{ + int a, b, c; + char *cp; + + if (!version) + version = Version; + + cp = strchr(version, '-'); + if (!cp || *(cp+1) != ' ' || *(cp+2) != 'v') + return -1; + cp += 3; + a = strtoul(cp, &cp, 10); + if (*cp != '.') + return -1; + b = strtoul(cp+1, &cp, 10); + if (*cp == '.') + c = strtoul(cp+1, &cp, 10); + else + c = 0; + if (*cp != ' ' && *cp != '-') + return -1; + return (a*1000000)+(b*1000)+c; +} + #ifndef MDASSEMBLE long long parse_size(char *size) { @@ -1043,6 +1068,7 @@ struct supertype *super_by_fd(int fd, char **subarrayp) char version[20]; int i; char *subarray = NULL; + int container = NoMdDev; sra = sysfs_read(fd, 0, GET_VERSION); @@ -1064,15 +1090,15 @@ struct supertype *super_by_fd(int fd, char **subarrayp) } if (minor == -2 && is_subarray(verstr)) { char *dev = verstr+1; + subarray = strchr(dev, '/'); - int devnum; if (subarray) *subarray++ = '\0'; - devnum = devname2devnum(dev); subarray = strdup(subarray); + container = devname2devnum(dev); if (sra) sysfs_free(sra); - sra = sysfs_read(-1, devnum, GET_VERSION); + sra = sysfs_read(-1, container, GET_VERSION); if (sra && sra->text_version[0]) verstr = sra->text_version; else @@ -1086,13 +1112,33 @@ struct supertype *super_by_fd(int fd, char **subarrayp) sysfs_free(sra); if (st) { st->sb = NULL; - *subarrayp = subarray; + if (subarrayp) + *subarrayp = subarray; + st->container_dev = container; + st->devnum = fd2devnum(fd); } else free(subarray); + return st; } #endif /* !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) */ +int dev_size_from_id(dev_t id, unsigned long long *size) +{ + char buf[20]; + int fd; + + sprintf(buf, "%d:%d", major(id), minor(id)); + fd = dev_open(buf, O_RDONLY); + if (fd < 0) + return 0; + if (get_dev_size(fd, NULL, size)) { + close(fd); + return 1; + } + close(fd); + return 0; +} struct supertype *dup_super(struct supertype *orig) { @@ -1188,6 +1234,20 @@ int get_dev_size(int fd, char *dname, unsigned long long *sizep) return 1; } +/* Return true if this can only be a container, not a member device. + * i.e. is and md device and size is zero + */ +int must_be_container(int fd) +{ + unsigned long long size; + if (md_get_version(fd) < 0) + return 0; + if (get_dev_size(fd, NULL, &size) == 0) + return 1; + if (size == 0) + return 1; + return 0; +} /* Sets endofpart parameter to the last block used by the last GPT partition on the device. * Returns: 1 if successful @@ -1418,14 +1478,11 @@ int is_subarray_active(char *subarray, char *container) struct mdstat_ent *mdstat = mdstat_read(0, 0); struct mdstat_ent *ent; - for (ent = mdstat; ent; ent = ent->next) { - if (is_container_member(ent, container)) { - char *inst = &ent->metadata_version[10+strlen(container)+1]; - - if (!subarray || strcmp(inst, subarray) == 0) + for (ent = mdstat; ent; ent = ent->next) + if (is_container_member(ent, container)) + if (!subarray || + strcmp(to_subarray(ent, container), subarray) == 0) break; - } - } free_mdstat(mdstat); @@ -1497,17 +1554,17 @@ int open_subarray(char *dev, char *subarray, struct supertype *st, int quiet) goto free_sysfs; } - if (st->ss->load_super(st, fd, NULL)) { + if (!st->ss->load_container) { if (!quiet) - fprintf(stderr, Name ": Failed to load metadata for %s\n", - dev); + fprintf(stderr, Name ": %s is not a container\n", dev); goto free_name; } - if (!st->loaded_container) { + if (st->ss->load_container(st, fd, NULL)) { if (!quiet) - fprintf(stderr, Name ": %s is not a container\n", dev); - goto free_super; + fprintf(stderr, Name ": Failed to load metadata for %s\n", + dev); + goto free_name; } info = st->ss->container_content(st, subarray); @@ -1569,6 +1626,21 @@ int add_disk(int mdfd, struct supertype *st, return rv; } +int remove_disk(int mdfd, struct supertype *st, + struct mdinfo *sra, struct mdinfo *info) +{ + int rv; + /* Remove the disk given by 'info' from the array */ +#ifndef MDASSEMBLE + if (st->ss->external) + rv = sysfs_set_str(sra, info, "slot", "none"); + else +#endif + rv = ioctl(mdfd, HOT_REMOVE_DISK, makedev(info->disk.major, + info->disk.minor)); + return rv; +} + int set_array_info(int mdfd, struct supertype *st, struct mdinfo *info) { /* Initialise kernel's knowledge of array.