Print this page
8115 parallel zfs mount

*** 58,67 **** --- 58,68 ---- #include <sys/mount.h> #include <sys/stat.h> #include <sys/fs/zfs.h> #include <sys/types.h> #include <time.h> + #include <synch.h> #include <libzfs.h> #include <libzfs_core.h> #include <zfs_prop.h> #include <zfs_deleg.h>
*** 5747,5769 **** return (0 != errors); } #define CHECK_SPINNER 30 #define SPINNER_TIME 3 /* seconds */ ! #define MOUNT_TIME 5 /* seconds */ static int get_one_dataset(zfs_handle_t *zhp, void *data) { static char *spin[] = { "-", "\\", "|", "/" }; static int spinval = 0; static int spincheck = 0; static time_t last_spin_time = (time_t)0; ! get_all_cb_t *cbp = data; zfs_type_t type = zfs_get_type(zhp); ! if (cbp->cb_verbose) { if (--spincheck < 0) { time_t now = time(NULL); if (last_spin_time + SPINNER_TIME < now) { update_progress(spin[spinval++ % 4]); last_spin_time = now; --- 5748,5775 ---- return (0 != errors); } #define CHECK_SPINNER 30 #define SPINNER_TIME 3 /* seconds */ ! #define MOUNT_TIME 1 /* seconds */ + typedef struct get_all_state { + boolean_t ga_verbose; + get_all_cb_t *ga_cbp; + } get_all_state_t; + static int get_one_dataset(zfs_handle_t *zhp, void *data) { static char *spin[] = { "-", "\\", "|", "/" }; static int spinval = 0; static int spincheck = 0; static time_t last_spin_time = (time_t)0; ! get_all_state_t *state = data; zfs_type_t type = zfs_get_type(zhp); ! if (state->ga_verbose) { if (--spincheck < 0) { time_t now = time(NULL); if (last_spin_time + SPINNER_TIME < now) { update_progress(spin[spinval++ % 4]); last_spin_time = now;
*** 5785,5826 **** */ if ((type & ZFS_TYPE_FILESYSTEM) == 0) { zfs_close(zhp); return (0); } ! libzfs_add_handle(cbp, zhp); ! assert(cbp->cb_used <= cbp->cb_alloc); return (0); } static void ! get_all_datasets(zfs_handle_t ***dslist, size_t *count, boolean_t verbose) { ! get_all_cb_t cb = { 0 }; ! cb.cb_verbose = verbose; ! cb.cb_getone = get_one_dataset; if (verbose) set_progress_header(gettext("Reading ZFS config")); ! (void) zfs_iter_root(g_zfs, get_one_dataset, &cb); - *dslist = cb.cb_handles; - *count = cb.cb_used; - if (verbose) finish_progress(gettext("done.")); } /* * Generic callback for sharing or mounting filesystems. Because the code is so * similar, we have a common function with an extra parameter to determine which * mode we are using. */ ! #define OP_SHARE 0x1 ! #define OP_MOUNT 0x2 /* * Share or mount a dataset. */ static int share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol, --- 5791,5841 ---- */ if ((type & ZFS_TYPE_FILESYSTEM) == 0) { zfs_close(zhp); return (0); } ! libzfs_add_handle(state->ga_cbp, zhp); ! assert(state->ga_cbp->cb_used <= state->ga_cbp->cb_alloc); return (0); } static void ! get_all_datasets(get_all_cb_t *cbp, boolean_t verbose) { ! get_all_state_t state = { ! .ga_verbose = verbose, ! .ga_cbp = cbp ! }; if (verbose) set_progress_header(gettext("Reading ZFS config")); ! (void) zfs_iter_root(g_zfs, get_one_dataset, &state); if (verbose) finish_progress(gettext("done.")); } /* * Generic callback for sharing or mounting filesystems. Because the code is so * similar, we have a common function with an extra parameter to determine which * mode we are using. */ ! typedef enum { OP_SHARE, OP_MOUNT } share_mount_op_t; + typedef struct share_mount_state { + share_mount_op_t sm_op; + boolean_t sm_verbose; + int sm_flags; + char *sm_options; + char *sm_proto; /* only valid for OP_SHARE */ + mutex_t sm_lock; /* protects the remaining fields */ + uint_t sm_total; /* number of filesystems to process */ + uint_t sm_done; /* number of filesystems processed */ + int sm_status; /* -1 if any of the share/mount operations failed */ + } share_mount_state_t; + /* * Share or mount a dataset. */ static int share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol,
*** 6057,6066 **** --- 6072,6104 ---- finish_progress(info); else update_progress(info); } + /* + * zfs_foreach_mountpoint() callback that mounts or shares one filesystem and + * updates the progress meter. + */ + static int + share_mount_one_cb(zfs_handle_t *zhp, void *arg) + { + share_mount_state_t *sms = arg; + int ret; + + ret = share_mount_one(zhp, sms->sm_op, sms->sm_flags, sms->sm_proto, + B_FALSE, sms->sm_options); + + (void) mutex_lock(&sms->sm_lock); + if (ret != 0) + sms->sm_status = ret; + sms->sm_done++; + if (sms->sm_verbose) + report_mount_progress(sms->sm_done, sms->sm_total); + (void) mutex_unlock(&sms->sm_lock); + return (ret); + } + static void append_options(char *mntopts, char *newopts) { int len = strlen(mntopts);
*** 6129,6140 **** argc -= optind; argv += optind; /* check number of arguments */ if (do_all) { - zfs_handle_t **dslist = NULL; - size_t i, count = 0; char *protocol = NULL; if (op == OP_SHARE && argc > 0) { if (strcmp(argv[0], "nfs") != 0 && strcmp(argv[0], "smb") != 0) { --- 6167,6176 ----
*** 6151,6187 **** (void) fprintf(stderr, gettext("too many arguments\n")); usage(B_FALSE); } start_progress_timer(); ! get_all_datasets(&dslist, &count, verbose); ! if (count == 0) return (0); ! qsort(dslist, count, sizeof (void *), libzfs_dataset_cmp); sa_init_selective_arg_t sharearg; ! sharearg.zhandle_arr = dslist; ! sharearg.zhandle_len = count; ! if ((ret = zfs_init_libshare_arg(zfs_get_handle(dslist[0]), SA_INIT_SHARE_API_SELECTIVE, &sharearg)) != SA_OK) { ! (void) fprintf(stderr, ! gettext("Could not initialize libshare, %d"), ret); return (ret); } - - for (i = 0; i < count; i++) { - if (verbose) - report_mount_progress(i, count); - - if (share_mount_one(dslist[i], op, flags, protocol, - B_FALSE, options) != 0) - ret = 1; - zfs_close(dslist[i]); } ! free(dslist); } else if (argc == 0) { struct mnttab entry; if ((op == OP_SHARE) || (options != NULL)) { (void) fprintf(stderr, gettext("missing filesystem " --- 6187,6234 ---- (void) fprintf(stderr, gettext("too many arguments\n")); usage(B_FALSE); } start_progress_timer(); ! get_all_cb_t cb = { 0 }; ! get_all_datasets(&cb, verbose); ! if (cb.cb_used == 0) return (0); ! if (op == OP_SHARE) { sa_init_selective_arg_t sharearg; ! sharearg.zhandle_arr = cb.cb_handles; ! sharearg.zhandle_len = cb.cb_used; ! if ((ret = zfs_init_libshare_arg(g_zfs, SA_INIT_SHARE_API_SELECTIVE, &sharearg)) != SA_OK) { ! (void) fprintf(stderr, gettext( ! "Could not initialize libshare, %d"), ret); return (ret); } } ! share_mount_state_t share_mount_state = { 0 }; ! share_mount_state.sm_op = op; ! share_mount_state.sm_verbose = verbose; ! share_mount_state.sm_flags = flags; ! share_mount_state.sm_options = options; ! share_mount_state.sm_proto = protocol; ! share_mount_state.sm_total = cb.cb_used; ! (void) mutex_init(&share_mount_state.sm_lock, USYNC_THREAD, ! NULL); ! /* ! * libshare isn't mt-safe, so only do the operation in parallel ! * if we're mounting. ! */ ! zfs_foreach_mountpoint(g_zfs, cb.cb_handles, cb.cb_used, ! share_mount_one_cb, &share_mount_state, op == OP_MOUNT); ! ret = share_mount_state.sm_status; ! ! for (int i = 0; i < cb.cb_used; i++) ! zfs_close(cb.cb_handles[i]); ! free(cb.cb_handles); } else if (argc == 0) { struct mnttab entry; if ((op == OP_SHARE) || (options != NULL)) { (void) fprintf(stderr, gettext("missing filesystem "