X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=blobdiff_plain;f=util.c;h=a238a2107b968443ad530506340cfed7e21f8ef3;hp=ea6e6889869d293eee8986b8324c649ac7fe147c;hb=fa219dd26aa498f3e446798b7b341e8e4a29d378;hpb=4de90913020923b69515630b8f19094d2e0d1d5a diff --git a/util.c b/util.c index ea6e6889..a238a210 100644 --- a/util.c +++ b/util.c @@ -31,17 +31,11 @@ #include #include #include +#include #include #include #include #include -#include -#ifdef NO_COROSYNC - typedef uint64_t cmap_handle_t; - #define CS_OK 1 -#else - #include -#endif /* @@ -88,6 +82,135 @@ struct blkpg_partition { aren't permitted). */ #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) +static int is_dlm_hooks_ready = 0; + +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; + +struct dlm_lock_resource { + dlm_lshandle_t *ls; + struct dlm_lksb lksb; +}; + +/* Using poll(2) to wait for and dispatch ASTs */ +static int poll_for_ast(dlm_lshandle_t ls) +{ + struct pollfd pfd; + + pfd.fd = dlm_hooks->ls_get_fd(ls); + pfd.events = POLLIN; + + while (!ast_called) + { + if (poll(&pfd, 1, 0) < 0) + { + perror("poll"); + return -1; + } + dlm_hooks->dispatch(dlm_hooks->ls_get_fd(ls)); + } + ast_called = 0; + + return 0; +} + +static void dlm_ast(void *arg) +{ + ast_called = 1; +} + +static char *cluster_name = NULL; +/* Create the lockspace, take bitmapXXX locks on all the bitmaps. */ +int cluster_get_dlmlock(int *lockid) +{ + int ret = -1; + char str[64]; + int flags = LKF_NOQUEUE; + + ret = get_cluster_name(&cluster_name); + if (ret) { + pr_err("The md can't get cluster name\n"); + return -1; + } + + dlm_lock_res = xmalloc(sizeof(struct dlm_lock_resource)); + dlm_lock_res->ls = dlm_hooks->create_lockspace(cluster_name, O_RDWR); + if (!dlm_lock_res->ls) { + pr_err("%s failed to create lockspace\n", cluster_name); + return -ENOMEM; + } + + snprintf(str, 64, "bitmap%s", cluster_name); + ret = dlm_hooks->ls_lock(dlm_lock_res->ls, LKM_PWMODE, &dlm_lock_res->lksb, + flags, str, strlen(str), 0, dlm_ast, + dlm_lock_res, NULL, NULL); + if (ret) { + pr_err("error %d when get PW mode on lock %s\n", errno, str); + dlm_hooks->release_lockspace(cluster_name, dlm_lock_res->ls, 1); + return ret; + } + + /* Wait for it to complete */ + poll_for_ast(dlm_lock_res->ls); + *lockid = dlm_lock_res->lksb.sb_lkid; + + return dlm_lock_res->lksb.sb_status; +} + +int cluster_release_dlmlock(int lockid) +{ + int ret = -1; + + if (!cluster_name) + return -1; + + ret = dlm_hooks->ls_unlock(dlm_lock_res->ls, lockid, 0, + &dlm_lock_res->lksb, dlm_lock_res); + if (ret) { + pr_err("error %d happened when unlock\n", errno); + /* XXX make sure the lock is unlocked eventually */ + goto out; + } + + /* Wait for it to complete */ + poll_for_ast(dlm_lock_res->ls); + + errno = dlm_lock_res->lksb.sb_status; + if (errno != EUNLOCK) { + pr_err("error %d happened in ast when unlock lockspace\n", errno); + /* XXX make sure the lockspace is unlocked eventually */ + goto out; + } + + ret = dlm_hooks->release_lockspace(cluster_name, dlm_lock_res->ls, 1); + if (ret) { + pr_err("error %d happened when release lockspace\n", errno); + /* XXX make sure the lockspace is released eventually */ + goto out; + } + free(dlm_lock_res); + +out: + return ret; +} +#else +int cluster_get_dlmlock(int *lockid) +{ + return -1; +} +int cluster_release_dlmlock(int lockid) +{ + return -1; +} +#endif + /* * Parse a 128 bit uuid in 4 integers * format is 32 hexx nibbles with options :. separator @@ -587,17 +710,22 @@ int check_raid(int fd, char *name) if (!st) return 0; - st->ss->load_super(st, fd, name); - /* Looks like a raid array .. */ - pr_err("%s appears to be part of a raid array:\n", - name); - st->ss->getinfo_super(st, &info, NULL); - st->ss->free_super(st); - crtime = info.array.ctime; - level = map_num(pers, info.array.level); - if (!level) level = "-unknown-"; - cont_err("level=%s devices=%d ctime=%s", - level, info.array.raid_disks, ctime(&crtime)); + if (st->ss->add_to_super != NULL) { + st->ss->load_super(st, fd, name); + /* Looks like a raid array .. */ + pr_err("%s appears to be part of a raid array:\n", name); + st->ss->getinfo_super(st, &info, NULL); + st->ss->free_super(st); + crtime = info.array.ctime; + level = map_num(pers, info.array.level); + if (!level) + level = "-unknown-"; + cont_err("level=%s devices=%d ctime=%s", + level, info.array.raid_disks, ctime(&crtime)); + } else { + /* Looks like GPT or MBR */ + pr_err("partition table exists on %s\n", name); + } return 1; } @@ -805,7 +933,7 @@ int get_data_disks(int level, int layout, int raid_disks) return data_disks; } -int devnm2devid(char *devnm) +dev_t devnm2devid(char *devnm) { /* First look in /sys/block/$DEVNM/dev for %d:%d * If that fails, try parsing out a number @@ -916,7 +1044,8 @@ int dev_open(char *dev, int flags) int major; int minor; - if (!dev) return -1; + if (!dev) + return -1; flags |= O_DIRECT; if (get_maj_min(dev, &major, &minor)) { @@ -942,7 +1071,7 @@ int dev_open(char *dev, int flags) int open_dev_flags(char *devnm, int flags) { - int devid; + dev_t devid; char buf[20]; devid = devnm2devid(devnm); @@ -960,7 +1089,7 @@ int open_dev_excl(char *devnm) char buf[20]; int i; int flags = O_RDWR; - int devid = devnm2devid(devnm); + dev_t devid = devnm2devid(devnm); long delay = 1000; sprintf(buf, "%d:%d", major(devid), minor(devid)); @@ -1068,8 +1197,7 @@ struct supertype *super_by_fd(int fd, char **subarrayp) subarray = xstrdup(subarray); } strcpy(container, dev); - if (sra) - sysfs_free(sra); + sysfs_free(sra); sra = sysfs_read(-1, container, GET_VERSION); if (sra && sra->text_version[0]) verstr = sra->text_version; @@ -1080,8 +1208,7 @@ struct supertype *super_by_fd(int fd, char **subarrayp) for (i = 0; st == NULL && superlist[i] ; i++) st = superlist[i]->match_metadata_desc(verstr); - if (sra) - sysfs_free(sra); + sysfs_free(sra); if (st) { st->sb = NULL; if (subarrayp) @@ -1136,7 +1263,7 @@ struct supertype *guess_super_type(int fd, enum guess_types guess_type) */ struct superswitch *ss; struct supertype *st; - time_t besttime = 0; + unsigned int besttime = 0; int bestsuper = -1; int i; @@ -1814,6 +1941,27 @@ __u32 random32(void) return rv; } +void random_uuid(__u8 *buf) +{ + int fd, i, len; + __u32 r[4]; + + fd = open("/dev/urandom", O_RDONLY); + if (fd < 0) + goto use_random; + len = read(fd, buf, 16); + close(fd); + if (len != 16) + goto use_random; + + return; + +use_random: + for (i = 0; i < 4; i++) + r[i] = random(); + memcpy(buf, r, 16); +} + #ifndef MDASSEMBLE int flush_metadata_updates(struct supertype *st) { @@ -1996,40 +2144,41 @@ void reopen_mddev(int mdfd) dup2(fd, mdfd); } -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); +#ifndef MDASSEMBLE +static struct cmap_hooks *cmap_hooks = NULL; +static int is_cmap_hooks_ready = 0; +void set_cmap_hooks(void) +{ + cmap_hooks = xmalloc(sizeof(struct cmap_hooks)); + cmap_hooks->cmap_handle = dlopen("libcmap.so.4", RTLD_NOW | RTLD_LOCAL); + if (!cmap_hooks->cmap_handle) + return; - lib_handle = dlopen("libcmap.so.4", RTLD_NOW | RTLD_LOCAL); - if (!lib_handle) - return rv; + cmap_hooks->initialize = dlsym(cmap_hooks->cmap_handle, "cmap_initialize"); + cmap_hooks->get_string = dlsym(cmap_hooks->cmap_handle, "cmap_get_string"); + cmap_hooks->finalize = dlsym(cmap_hooks->cmap_handle, "cmap_finalize"); - initialize = dlsym(lib_handle, "cmap_initialize"); - if (!initialize) - goto out; + if (!cmap_hooks->initialize || !cmap_hooks->get_string || + !cmap_hooks->finalize) + dlclose(cmap_hooks->cmap_handle); + else + is_cmap_hooks_ready = 1; +} - get_string = dlsym(lib_handle, "cmap_get_string"); - if (!get_string) - goto out; +int get_cluster_name(char **cluster_name) +{ + int rv = -1; + cmap_handle_t handle; - finalize = dlsym(lib_handle, "cmap_finalize"); - if (!finalize) - goto out; + if (!is_cmap_hooks_ready) + return rv; - rv = initialize(&handle); + rv = cmap_hooks->initialize(&handle); if (rv != CS_OK) goto out; - rv = get_string(handle, "totem.cluster_name", cluster_name); + rv = cmap_hooks->get_string(handle, "totem.cluster_name", cluster_name); if (rv != CS_OK) { free(*cluster_name); rv = -1; @@ -2038,8 +2187,36 @@ int get_cluster_name(char **cluster_name) rv = 0; name_err: - finalize(handle); + cmap_hooks->finalize(handle); out: - dlclose(lib_handle); return rv; } + +void set_dlm_hooks(void) +{ + dlm_hooks = xmalloc(sizeof(struct dlm_hooks)); + dlm_hooks->dlm_handle = dlopen("libdlm_lt.so.3", RTLD_NOW | RTLD_LOCAL); + if (!dlm_hooks->dlm_handle) + return; + + dlm_hooks->create_lockspace = dlsym(dlm_hooks->dlm_handle, "dlm_create_lockspace"); + dlm_hooks->release_lockspace = dlsym(dlm_hooks->dlm_handle, "dlm_release_lockspace"); + dlm_hooks->ls_lock = dlsym(dlm_hooks->dlm_handle, "dlm_ls_lock"); + dlm_hooks->ls_unlock = dlsym(dlm_hooks->dlm_handle, "dlm_ls_unlock"); + dlm_hooks->ls_get_fd = dlsym(dlm_hooks->dlm_handle, "dlm_ls_get_fd"); + dlm_hooks->dispatch = dlsym(dlm_hooks->dlm_handle, "dlm_dispatch"); + + if (!dlm_hooks->create_lockspace || !dlm_hooks->ls_lock || + !dlm_hooks->ls_unlock || !dlm_hooks->release_lockspace || + !dlm_hooks->ls_get_fd || !dlm_hooks->dispatch) + dlclose(dlm_hooks->dlm_handle); + else + is_dlm_hooks_ready = 1; +} + +void set_hooks(void) +{ + set_dlm_hooks(); + set_cmap_hooks(); +} +#endif