X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=util.c;h=f1b0b952ab535c25f77236c8e9d020d0802c8091;hb=50d72ed4298618c679efd43647dd055527e59b10;hp=4032fa9b1778aff6895b95e43b21c7449915c7c7;hpb=7d55dca2cce88de443864b1e843dd0faf9142bd7;p=thirdparty%2Fmdadm.git diff --git a/util.c b/util.c index 4032fa9b..f1b0b952 100644 --- a/util.c +++ b/util.c @@ -24,6 +24,7 @@ #include "mdadm.h" #include "md_p.h" +#include #include #include #include @@ -35,13 +36,6 @@ #include #include #include -#include -#ifdef NO_COROSYNC - typedef uint64_t cmap_handle_t; - #define CS_OK 1 -#else - #include -#endif /* @@ -88,6 +82,137 @@ struct blkpg_partition { aren't permitted). */ #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) +static struct dlm_hooks *dlm_hooks = NULL; +static int is_dlm_hooks_ready = 0; +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; +}; + +int dlm_funs_ready(void) +{ + return is_dlm_hooks_ready ? 1 : 0; +} + +/* 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); + goto out; + } + + /* Conversions need the lockid in the LKSB */ + if (flags & LKF_CONVERT) + dlm_lock_res->lksb.sb_lkid = *lockid; + + snprintf(str, 64, "bitmap%s", cluster_name); + /* if flags with LKF_CONVERT causes below return ENOENT which means + * "No such file or directory" */ + 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); + goto out; + } + + /* Wait for it to complete */ + poll_for_ast(dlm_lock_res->ls); + *lockid = dlm_lock_res->lksb.sb_lkid; + + errno = dlm_lock_res->lksb.sb_status; + if (errno) { + pr_err("error %d happened in ast with lock %s\n", errno, str); + goto out; + } + +out: + return ret; +} + +int cluster_release_dlmlock(int lockid) +{ + int ret = -1; + + if (!cluster_name) + return -1; + + /* if flags with LKF_CONVERT causes below return EINVAL which means + * "Invalid argument" */ + 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; +} + /* * Parse a 128 bit uuid in 4 integers * format is 32 hexx nibbles with options :. separator @@ -1995,41 +2120,42 @@ 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); +static struct cmap_hooks *cmap_hooks = NULL; +static int is_cmap_hooks_ready = 0; +#ifndef MDASSEMBLE +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,9 +2164,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