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 "