X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fmdadm.git;a=blobdiff_plain;f=util.c;h=4adbbff0295e30c984f59b5c5a5c4bfe024e1d60;hp=d89438c812ef809e18710e052bee584f8525def9;hb=1b7eb962db2cf9179d097e06cce74b84ac80e49d;hpb=d7be7d87366a7f9b190bc4e41ea06f7c9984028e diff --git a/util.c b/util.c index d89438c8..4adbbff0 100644 --- a/util.c +++ b/util.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -127,11 +128,17 @@ static void dlm_ast(void *arg) static char *cluster_name = NULL; /* Create the lockspace, take bitmapXXX locks on all the bitmaps. */ -int cluster_get_dlmlock(int *lockid) +int cluster_get_dlmlock(void) { int ret = -1; char str[64]; int flags = LKF_NOQUEUE; + int retry_count = 0; + + if (!dlm_funs_ready()) { + pr_err("Something wrong with dlm library\n"); + return -1; + } ret = get_cluster_name(&cluster_name); if (ret) { @@ -140,38 +147,57 @@ int cluster_get_dlmlock(int *lockid) } dlm_lock_res = xmalloc(sizeof(struct dlm_lock_resource)); - dlm_lock_res->ls = dlm_hooks->create_lockspace(cluster_name, O_RDWR); + dlm_lock_res->ls = dlm_hooks->open_lockspace(cluster_name); if (!dlm_lock_res->ls) { - pr_err("%s failed to create lockspace\n", cluster_name); - return -ENOMEM; + 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; + } + } else { + pr_err("open existed %s lockspace\n", cluster_name); } 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); +retry: + 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); + /* let's try several times if EAGAIN happened */ + if (dlm_lock_res->lksb.sb_status == EAGAIN && retry_count < 10) { + sleep(10); + retry_count++; + goto retry; + } 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; + if (dlm_lock_res->lksb.sb_status) { + pr_err("failed to lock cluster\n"); + return -1; + } + return 1; } -int cluster_release_dlmlock(int lockid) +int cluster_release_dlmlock(void) { int ret = -1; if (!cluster_name) - return -1; + goto out; - ret = dlm_hooks->ls_unlock(dlm_lock_res->ls, lockid, 0, - &dlm_lock_res->lksb, dlm_lock_res); + if (!dlm_lock_res->lksb.sb_lkid) + goto out; + + ret = dlm_hooks->ls_unlock_wait(dlm_lock_res->ls, + dlm_lock_res->lksb.sb_lkid, 0, + &dlm_lock_res->lksb); if (ret) { pr_err("error %d happened when unlock\n", errno); /* XXX make sure the lock is unlocked eventually */ @@ -183,7 +209,8 @@ int cluster_release_dlmlock(int lockid) errno = dlm_lock_res->lksb.sb_status; if (errno != EUNLOCK) { - pr_err("error %d happened in ast when unlock lockspace\n", errno); + pr_err("error %d happened in ast when unlock lockspace\n", + errno); /* XXX make sure the lockspace is unlocked eventually */ goto out; } @@ -228,15 +255,11 @@ int md_array_active(int fd) { struct mdinfo *sra; struct mdu_array_info_s array; - int ret; + int ret = 0; 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 + if (!md_array_is_active(sra)) ret = -ENODEV; free(sra); @@ -251,6 +274,13 @@ int md_array_active(int fd) return !ret; } +int md_array_is_active(struct mdinfo *info) +{ + return (info->array_state != ARRAY_CLEAR && + info->array_state != ARRAY_INACTIVE && + info->array_state != ARRAY_UNKNOWN_STATE); +} + /* * Get array info from the kernel. Longer term we want to deprecate the * ioctl and get it from sysfs. @@ -392,6 +422,17 @@ unsigned long long parse_size(char *size) return s; } +int is_near_layout_10(int layout) +{ + int fc, fo; + + fc = (layout >> 8) & 255; + fo = layout & (1 << 16); + if (fc > 1 || fo > 0) + return 0; + return 1; +} + int parse_layout_10(char *layout) { int copies, rv; @@ -636,14 +677,16 @@ char *__fname_from_uuid(int id[4], int swap, char *buf, char sep) } -char *fname_from_uuid(struct supertype *st, struct mdinfo *info, char *buf, char sep) +char *fname_from_uuid(struct supertype *st, struct mdinfo *info, + char *buf, char sep) { // dirty hack to work around an issue with super1 superblocks... // super1 superblocks need swapuuid set in order for assembly to // work, but can't have it set if we want this printout to match // all the other uuid printouts in super1.c, so we force swapuuid // to 1 to make our printout match the rest of super1 - return __fname_from_uuid(info->uuid, (st->ss == &super1) ? 1 : st->ss->swapuuid, buf, sep); + return __fname_from_uuid(info->uuid, (st->ss == &super1) ? 1 : + st->ss->swapuuid, buf, sep); } int check_ext2(int fd, char *name) @@ -1081,9 +1124,11 @@ int dev_open(char *dev, int flags) } if (fd < 0) { /* Try /tmp as /dev appear to be read-only */ - snprintf(devname, sizeof(devname), "/tmp/.tmp.md.%d:%d:%d", + snprintf(devname, sizeof(devname), + "/tmp/.tmp.md.%d:%d:%d", (int)getpid(), major, minor); - if (mknod(devname, S_IFBLK|0600, makedev(major, minor)) == 0) { + if (mknod(devname, S_IFBLK|0600, + makedev(major, minor)) == 0) { fd = open(devname, flags); unlink(devname); } @@ -1169,7 +1214,7 @@ void wait_for(char *dev, int fd) delay *= 2; } if (i == 25) - dprintf("timeout waiting for %s\n", dev); + pr_err("timeout waiting for %s\n", dev); } struct superswitch *superlist[] = @@ -2258,8 +2303,10 @@ void set_cmap_hooks(void) if (!cmap_hooks->cmap_handle) return; - cmap_hooks->initialize = dlsym(cmap_hooks->cmap_handle, "cmap_initialize"); - cmap_hooks->get_string = dlsym(cmap_hooks->cmap_handle, "cmap_get_string"); + 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"); if (!cmap_hooks->initialize || !cmap_hooks->get_string || @@ -2302,16 +2349,22 @@ void set_dlm_hooks(void) 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->open_lockspace = + dlsym(dlm_hooks->dlm_handle, "dlm_open_lockspace"); + 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_unlock_wait = + dlsym(dlm_hooks->dlm_handle, "dlm_ls_unlock_wait"); 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) + if (!dlm_hooks->open_lockspace || !dlm_hooks->create_lockspace || + !dlm_hooks->ls_lock || !dlm_hooks->ls_unlock_wait || + !dlm_hooks->release_lockspace || !dlm_hooks->ls_get_fd || + !dlm_hooks->dispatch) dlclose(dlm_hooks->dlm_handle); else is_dlm_hooks_ready = 1; @@ -2322,3 +2375,51 @@ void set_hooks(void) set_dlm_hooks(); set_cmap_hooks(); } + +int zero_disk_range(int fd, unsigned long long sector, size_t count) +{ + int ret = 0; + int fd_zero; + void *addr = NULL; + size_t written = 0; + size_t len = count * 512; + ssize_t n; + + fd_zero = open("/dev/zero", O_RDONLY); + if (fd_zero < 0) { + pr_err("Cannot open /dev/zero\n"); + return -1; + } + + if (lseek64(fd, sector * 512, SEEK_SET) < 0) { + ret = -errno; + pr_err("Failed to seek offset for zeroing\n"); + goto out; + } + + addr = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd_zero, 0); + + if (addr == MAP_FAILED) { + ret = -errno; + pr_err("Mapping /dev/zero failed\n"); + goto out; + } + + do { + n = write(fd, addr + written, len - written); + if (n < 0) { + if (errno == EINTR) + continue; + ret = -errno; + pr_err("Zeroing disk range failed\n"); + break; + } + written += n; + } while (written != len); + + munmap(addr, len); + +out: + close(fd_zero); + return ret; +}