X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=util.c;h=4032fa9b1778aff6895b95e43b21c7449915c7c7;hb=7d55dca2cce88de443864b1e843dd0faf9142bd7;hp=afb2bb110f24cf65c4cdd23bed3f23dc2db0c884;hpb=76d0f1886fdef89891d617df7e7f3fde89a38e1a;p=thirdparty%2Fmdadm.git diff --git a/util.c b/util.c index afb2bb11..4032fa9b 100644 --- a/util.c +++ b/util.c @@ -34,6 +34,15 @@ #include #include #include +#include +#include +#ifdef NO_COROSYNC + typedef uint64_t cmap_handle_t; + #define CS_OK 1 +#else + #include +#endif + /* * following taken from linux/blkpg.h because they aren't @@ -271,6 +280,16 @@ long parse_num(char *num) } #endif +int parse_cluster_confirm_arg(char *input, char **devname, int *slot) +{ + char *dev; + *slot = strtoul(input, &dev, 10); + if (dev == input || dev[0] != ':') + return -1; + *devname = dev+1; + return 0; +} + void remove_partitions(int fd) { /* remove partitions from this block devices. @@ -368,6 +387,13 @@ int enough(int level, int raid_disks, int layout, int clean, char *avail) case 1: return avail_disks >= 1; case 4: + if (avail_disks == raid_disks - 1 && + !avail[raid_disks - 1]) + /* If just the parity device is missing, then we + * have enough, even if not clean + */ + return 1; + /* FALL THROUGH */ case 5: if (clean) return avail_disks >= raid_disks-1; @@ -671,13 +697,13 @@ char *human_size(long long bytes) if (bytes < 5000*1024) buf[0] = 0; else if (bytes < 2*1024LL*1024LL*1024LL) { - long cMiB = (bytes / ( (1LL<<20) / 200LL ) +1) /2; + 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); } else { - long cGiB = (bytes / ( (1LL<<30) / 200LL ) +1) /2; + 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, @@ -706,11 +732,11 @@ char *human_size_brief(long long bytes, int prefix) buf[0] = 0; else if (prefix == IEC) { if (bytes < 2*1024LL*1024LL*1024LL) { - long cMiB = (bytes / ( (1LL<<20) / 200LL ) +1) /2; + long cMiB = (bytes * 200LL / (1LL<<20) +1) /2; snprintf(buf, sizeof(buf), "%ld.%02ldMiB", cMiB/100 , cMiB % 100); } else { - long cGiB = (bytes / ( (1LL<<30) / 200LL ) +1) /2; + long cGiB = (bytes * 200LL / (1LL<<30) +1) /2; snprintf(buf, sizeof(buf), "%ld.%02ldGiB", cGiB/100 , cGiB % 100); } @@ -871,12 +897,20 @@ void put_md_name(char *name) } #endif /* !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) */ +int get_maj_min(char *dev, int *major, int *minor) +{ + char *e; + *major = strtoul(dev, &e, 0); + return (e > dev && *e == ':' && e[1] && + (*minor = strtoul(e+1, &e, 0)) >= 0 && + *e == 0); +} + int dev_open(char *dev, int flags) { /* like 'open', but if 'dev' matches %d:%d, create a temp * block device and open that */ - char *e; int fd = -1; char devname[32]; int major; @@ -885,10 +919,7 @@ int dev_open(char *dev, int flags) if (!dev) return -1; flags |= O_DIRECT; - major = strtoul(dev, &e, 0); - if (e > dev && *e == ':' && e[1] && - (minor = strtoul(e+1, &e, 0)) >= 0 && - *e == 0) { + if (get_maj_min(dev, &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) { @@ -985,7 +1016,7 @@ void wait_for(char *dev, int fd) delay *= 2; } if (i == 25) - dprintf("%s: timeout waiting for %s\n", __func__, dev); + dprintf("timeout waiting for %s\n", dev); } struct superswitch *superlist[] = @@ -1688,7 +1719,7 @@ int start_mdmon(char *devnm) char pathbuf[1024]; char *paths[4] = { pathbuf, - "/sbin/mdmon", + BINDIR "/mdmon", "./mdmon", NULL }; @@ -1735,8 +1766,7 @@ int start_mdmon(char *devnm) status = execl("/bin/systemctl", "systemctl", "start", pathbuf, NULL); exit(1); - case -1: pr_err("cannot run mdmon. " - "Array remains readonly\n"); + case -1: pr_err("cannot run mdmon. Array remains readonly\n"); return -1; default: /* parent - good */ pid = wait(&status); @@ -1761,14 +1791,12 @@ int start_mdmon(char *devnm) devnm, NULL); } exit(1); - case -1: pr_err("cannot run mdmon. " - "Array remains readonly\n"); + case -1: pr_err("cannot run mdmon. Array remains readonly\n"); return -1; default: /* parent - good */ pid = wait(&status); if (pid < 0 || status != 0) { - pr_err("failed to launch mdmon. " - "Array remains readonly\n"); + pr_err("failed to launch mdmon. Array remains readonly\n"); return -1; } } @@ -1840,8 +1868,7 @@ int experimental(void) if (check_env("MDADM_EXPERIMENTAL")) return 1; else { - pr_err("To use this feature MDADM_EXPERIMENTAL" - " environment variable has to be defined.\n"); + pr_err("To use this feature MDADM_EXPERIMENTAL environment variable has to be defined.\n"); return 0; } } @@ -1968,3 +1995,52 @@ void reopen_mddev(int mdfd) if (fd >= 0 && fd != mdfd) dup2(fd, mdfd); } +#ifndef MDASSEMBLE +int get_cluster_name(char **cluster_name) +{ + void *lib_handle = NULL; + int rv = -1; + + cmap_handle_t handle; + static int (*initialize)(cmap_handle_t *handle); + static int (*get_string)(cmap_handle_t handle, + const char *string, + char **name); + static int (*finalize)(cmap_handle_t handle); + + + lib_handle = dlopen("libcmap.so.4", RTLD_NOW | RTLD_LOCAL); + if (!lib_handle) + return rv; + + initialize = dlsym(lib_handle, "cmap_initialize"); + if (!initialize) + goto out; + + get_string = dlsym(lib_handle, "cmap_get_string"); + if (!get_string) + goto out; + + finalize = dlsym(lib_handle, "cmap_finalize"); + if (!finalize) + goto out; + + rv = initialize(&handle); + if (rv != CS_OK) + goto out; + + rv = get_string(handle, "totem.cluster_name", cluster_name); + if (rv != CS_OK) { + free(*cluster_name); + rv = -1; + goto name_err; + } + + rv = 0; +name_err: + finalize(handle); +out: + dlclose(lib_handle); + return rv; +} +#endif