X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=blobdiff_plain;f=util.c;h=21a63c9a638ca9e6bbb6d5a1b2ea4b5e6d3efaa5;hp=818f8392177e4ff584067d8e9ffec2c30e98cb31;hb=99148c19bd9149bb938309ffb6b4dcde20b67934;hpb=41b06495ba3c6da9bddef7ae89c2c633c4c21c5c diff --git a/util.c b/util.c index 818f8392..21a63c9a 100644 --- a/util.c +++ b/util.c @@ -89,7 +89,6 @@ int dlm_funs_ready(void) return is_dlm_hooks_ready ? 1 : 0; } -#ifndef MDASSEMBLE static struct dlm_hooks *dlm_hooks = NULL; struct dlm_lock_resource *dlm_lock_res = NULL; static int ast_called = 0; @@ -200,16 +199,58 @@ int cluster_release_dlmlock(int lockid) out: return ret; } -#else -int cluster_get_dlmlock(int *lockid) + +int md_array_active(int fd) { - return -1; + struct mdinfo *sra; + struct mdu_array_info_s array; + int ret; + + sra = sysfs_read(fd, NULL, GET_ARRAY_STATE); + if (sra) { + if (sra->array_state != ARRAY_CLEAR && + sra->array_state != ARRAY_INACTIVE && + sra->array_state != ARRAY_UNKNOWN_STATE) + ret = 0; + else + ret = -ENODEV; + + free(sra); + } else { + /* + * GET_ARRAY_INFO doesn't provide access to the proper state + * information, so fallback to a basic check for raid_disks != 0 + */ + ret = ioctl(fd, GET_ARRAY_INFO, &array); + } + + return !ret; } -int cluster_release_dlmlock(int lockid) + +/* + * Get array info from the kernel. Longer term we want to deprecate the + * ioctl and get it from sysfs. + */ +int md_get_array_info(int fd, struct mdu_array_info_s *array) { - return -1; + return ioctl(fd, GET_ARRAY_INFO, array); +} + +/* + * Set array info + */ +int md_set_array_info(int fd, struct mdu_array_info_s *array) +{ + return ioctl(fd, SET_ARRAY_INFO, array); +} + +/* + * Get disk info from the kernel. + */ +int md_get_disk_info(int fd, struct mdu_disk_info_s *disk) +{ + return ioctl(fd, GET_DISK_INFO, disk); } -#endif /* * Parse a 128 bit uuid in 4 integers @@ -248,35 +289,6 @@ int parse_uuid(char *str, int uuid[4]) return 0; } -/* - * Get the md version number. - * We use the RAID_VERSION ioctl if it is supported - * If not, but we have a block device with major '9', we assume - * 0.36.0 - * - * Return version number as 24 but number - assume version parts - * always < 255 - */ - -int md_get_version(int fd) -{ - struct stat stb; - mdu_version_t vers; - - if (fstat(fd, &stb)<0) - return -1; - if ((S_IFMT&stb.st_mode) != S_IFBLK) - return -1; - - if (ioctl(fd, RAID_VERSION, &vers) == 0) - return (vers.major*10000) + (vers.minor*100) + vers.patchlevel; - if (errno == EACCES) - return -1; - if (major(stb.st_rdev) == MD_MAJOR) - return (3600); - return -1; -} - int get_linux_version() { struct utsname name; @@ -295,7 +307,6 @@ int get_linux_version() return (a*1000000)+(b*1000)+c; } -#ifndef MDASSEMBLE int mdadm_version(char *version) { int a, b, c; @@ -401,7 +412,6 @@ long parse_num(char *num) else return rv; } -#endif int parse_cluster_confirm_arg(char *input, char **devname, int *slot) { @@ -532,38 +542,6 @@ int enough(int level, int raid_disks, int layout, int clean, char *avail) } } -int enough_fd(int fd) -{ - struct mdu_array_info_s array; - struct mdu_disk_info_s disk; - int i, rv; - char *avail; - - if (ioctl(fd, GET_ARRAY_INFO, &array) != 0 || - array.raid_disks <= 0) - return 0; - avail = xcalloc(array.raid_disks, 1); - for (i = 0; i < MAX_DISKS && array.nr_disks > 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) - continue; - avail[disk.raid_disk] = 1; - } - /* This is used on an active array, so assume it is clean */ - rv = enough(array.level, array.raid_disks, array.layout, - 1, avail); - free(avail); - return rv; -} - const int uuid_zero[4] = { 0, 0, 0, 0 }; int same_uuid(int a[4], int b[4], int swapuuid) @@ -644,7 +622,6 @@ char *fname_from_uuid(struct supertype *st, struct mdinfo *info, char *buf, char return __fname_from_uuid(info->uuid, (st->ss == &super1) ? 1 : st->ss->swapuuid, buf, sep); } -#ifndef MDASSEMBLE int check_ext2(int fd, char *name) { /* @@ -748,7 +725,6 @@ int ask(char *mesg) pr_err("assuming 'no'\n"); return 0; } -#endif /* MDASSEMBLE */ int is_standard(char *dev, int *nump) { @@ -808,10 +784,9 @@ unsigned long calc_csum(void *super, int bytes) return csum; } -#ifndef MDASSEMBLE char *human_size(long long bytes) { - static char buf[30]; + static char buf[47]; /* We convert bytes to either centi-M{ega,ibi}bytes or * centi-G{igi,ibi}bytes, with appropriate rounding, @@ -828,14 +803,12 @@ char *human_size(long long bytes) long cMiB = (bytes * 200LL / (1LL<<20) + 1) / 2; long cMB = (bytes / ( 1000000LL / 200LL ) +1) /2; snprintf(buf, sizeof(buf), " (%ld.%02ld MiB %ld.%02ld MB)", - cMiB/100 , cMiB % 100, - cMB/100, cMB % 100); + cMiB/100, cMiB % 100, cMB/100, cMB % 100); } else { long cGiB = (bytes * 200LL / (1LL<<30) +1) / 2; long cGB = (bytes / (1000000000LL/200LL ) +1) /2; snprintf(buf, sizeof(buf), " (%ld.%02ld GiB %ld.%02ld GB)", - cGiB/100 , cGiB % 100, - cGB/100, cGB % 100); + cGiB/100, cGiB % 100, cGB/100, cGB % 100); } return buf; } @@ -862,22 +835,22 @@ char *human_size_brief(long long bytes, int prefix) if (bytes < 2*1024LL*1024LL*1024LL) { long cMiB = (bytes * 200LL / (1LL<<20) +1) /2; snprintf(buf, sizeof(buf), "%ld.%02ldMiB", - cMiB/100 , cMiB % 100); + cMiB/100, cMiB % 100); } else { long cGiB = (bytes * 200LL / (1LL<<30) +1) /2; snprintf(buf, sizeof(buf), "%ld.%02ldGiB", - cGiB/100 , cGiB % 100); + cGiB/100, cGiB % 100); } } else if (prefix == JEDEC) { if (bytes < 2*1024LL*1024LL*1024LL) { long cMB = (bytes / ( 1000000LL / 200LL ) +1) /2; snprintf(buf, sizeof(buf), "%ld.%02ldMB", - cMB/100, cMB % 100); + cMB/100, cMB % 100); } else { long cGB = (bytes / (1000000000LL/200LL ) +1) /2; snprintf(buf, sizeof(buf), "%ld.%02ldGB", - cGB/100 , cGB % 100); + cGB/100, cGB % 100); } } else @@ -902,7 +875,6 @@ void print_r10_layout(int layout) if (near*far == 1) printf("NO REDUNDANCY"); } -#endif unsigned long long calc_array_size(int level, int raid_disks, int layout, int chunksize, unsigned long long devsize) @@ -969,7 +941,6 @@ dev_t devnm2devid(char *devnm) return 0; } -#if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) char *get_md_name(char *devnm) { /* find /dev/md%d or /dev/md/%d or make a device /dev/.tmp.md%d */ @@ -1023,7 +994,6 @@ void put_md_name(char *name) if (strncmp(name, "/dev/.tmp.md", 12) == 0) unlink(name); } -#endif /* !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) */ int get_maj_min(char *dev, int *major, int *minor) { @@ -1093,7 +1063,7 @@ int open_dev_excl(char *devnm) long delay = 1000; sprintf(buf, "%d:%d", major(devid), minor(devid)); - for (i = 0 ; i < 25 ; i++) { + for (i = 0; i < 25; i++) { int fd = dev_open(buf, flags|O_EXCL); if (fd >= 0) return fd; @@ -1134,7 +1104,7 @@ void wait_for(char *dev, int fd) (stb_want.st_mode & S_IFMT) != S_IFBLK) return; - for (i = 0 ; i < 25 ; i++) { + for (i = 0; i < 25; i++) { struct stat stb; if (stat(dev, &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFBLK && @@ -1153,9 +1123,8 @@ struct superswitch *superlist[] = &super0, &super1, &super_ddf, &super_imsm, &mbr, &gpt, - NULL }; - -#if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) + NULL +}; struct supertype *super_by_fd(int fd, char **subarrayp) { @@ -1177,7 +1146,7 @@ struct supertype *super_by_fd(int fd, char **subarrayp) minor = sra->array.minor_version; verstr = sra->text_version; } else { - if (ioctl(fd, GET_ARRAY_INFO, &array)) + if (md_get_array_info(fd, &array)) array.major_version = array.minor_version = 0; vers = array.major_version; minor = array.minor_version; @@ -1205,7 +1174,7 @@ struct supertype *super_by_fd(int fd, char **subarrayp) verstr = "-no-metadata-"; } - for (i = 0; st == NULL && superlist[i] ; i++) + for (i = 0; st == NULL && superlist[i]; i++) st = superlist[i]->match_metadata_desc(verstr); sysfs_free(sra); @@ -1220,7 +1189,6 @@ struct supertype *super_by_fd(int fd, char **subarrayp) return st; } -#endif /* !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) */ int dev_size_from_id(dev_t id, unsigned long long *size) { @@ -1270,7 +1238,7 @@ struct supertype *guess_super_type(int fd, enum guess_types guess_type) st = xcalloc(1, sizeof(*st)); st->container_devnm[0] = 0; - for (i = 0 ; superlist[i]; i++) { + for (i = 0; superlist[i]; i++) { int rv; ss = superlist[i]; if (guess_type == guess_array && ss->add_to_super == NULL) @@ -1354,9 +1322,14 @@ int get_dev_sector_size(int fd, char *dname, unsigned int *sectsizep) */ int must_be_container(int fd) { + struct mdinfo *mdi; unsigned long long size; - if (md_get_version(fd) < 0) + + mdi = sysfs_read(fd, NULL, GET_VERSION); + if (!mdi) return 0; + sysfs_free(mdi); + if (get_dev_size(fd, NULL, &size) == 0) return 1; if (size == 0) @@ -1435,6 +1408,7 @@ static int get_last_partition_end(int fd, unsigned long long *endofpart) struct MBR boot_sect; unsigned long long curr_part_end; unsigned part_nr; + unsigned int sector_size; int retval = 0; *endofpart = 0; @@ -1474,6 +1448,9 @@ static int get_last_partition_end(int fd, unsigned long long *endofpart) /* Unknown partition table */ retval = -1; } + /* calculate number of 512-byte blocks */ + if (get_dev_sector_size(fd, NULL, §or_size)) + *endofpart *= (sector_size / 512); abort: return retval; } @@ -1485,9 +1462,8 @@ int check_partitions(int fd, char *dname, unsigned long long freesize, * Check where the last partition ends */ unsigned long long endofpart; - int ret; - if ((ret = get_last_partition_end(fd, &endofpart)) > 0) { + if (get_last_partition_end(fd, &endofpart) > 0) { /* There appears to be a partition table here */ if (freesize == 0) { /* partitions will not be visible in new device */ @@ -1752,7 +1728,7 @@ int add_disk(int mdfd, struct supertype *st, { /* Add a device to an array, in one of 2 ways. */ int rv; -#ifndef MDASSEMBLE + if (st->ss->external) { if (info->disk.state & (1<recovery_start = MaxSector; @@ -1772,7 +1748,6 @@ int add_disk(int mdfd, struct supertype *st, } } } else -#endif rv = ioctl(mdfd, ADD_NEW_DISK, &info->disk); return rv; } @@ -1781,39 +1756,63 @@ 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 hot_remove_disk(int mdfd, unsigned long dev, int force) +{ + int cnt = force ? 500 : 5; + int ret; + + /* HOT_REMOVE_DISK can fail with EBUSY if there are + * outstanding IO requests to the device. + * In this case, it can be helpful to wait a little while, + * up to 5 seconds if 'force' is set, or 50 msec if not. + */ + while ((ret = ioctl(mdfd, HOT_REMOVE_DISK, dev)) == -1 && + errno == EBUSY && + cnt-- > 0) + usleep(10000); + + return ret; +} + +int sys_hot_remove_disk(int statefd, int force) +{ + int cnt = force ? 500 : 5; + int ret; + + while ((ret = write(statefd, "remove", 6)) == -1 && + errno == EBUSY && + cnt-- > 0) + usleep(10000); + return ret == 6 ? 0 : -1; +} + int set_array_info(int mdfd, struct supertype *st, struct mdinfo *info) { /* Initialise kernel's knowledge of array. * This varies between externally managed arrays * and older kernels */ - int vers = md_get_version(mdfd); + mdu_array_info_t inf; int rv; -#ifndef MDASSEMBLE if (st->ss->external) - rv = sysfs_set_array(info, vers); - else -#endif - if ((vers % 100) >= 1) { /* can use different versions */ - mdu_array_info_t inf; - memset(&inf, 0, sizeof(inf)); - inf.major_version = info->array.major_version; - inf.minor_version = info->array.minor_version; - rv = ioctl(mdfd, SET_ARRAY_INFO, &inf); - } else - rv = ioctl(mdfd, SET_ARRAY_INFO, NULL); + return sysfs_set_array(info, 9003); + + memset(&inf, 0, sizeof(inf)); + inf.major_version = info->array.major_version; + inf.minor_version = info->array.minor_version; + rv = md_set_array_info(mdfd, &inf); + return rv; } @@ -1987,7 +1986,6 @@ use_random: memcpy(buf, r, 16); } -#ifndef MDASSEMBLE int flush_metadata_updates(struct supertype *st) { int sfd; @@ -2029,7 +2027,6 @@ void append_metadata_update(struct supertype *st, void *buf, int len) *st->update_tail = mu; st->update_tail = &mu->next; } -#endif /* MDASSEMBLE */ #ifdef __TINYC__ /* tinyc doesn't optimize this check in ioctl.h out ... */ @@ -2169,7 +2166,6 @@ void reopen_mddev(int mdfd) dup2(fd, mdfd); } -#ifndef MDASSEMBLE static struct cmap_hooks *cmap_hooks = NULL; static int is_cmap_hooks_ready = 0; @@ -2244,4 +2240,3 @@ void set_hooks(void) set_dlm_hooks(); set_cmap_hooks(); } -#endif