mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-25 03:37:45 +03:00
OpenZFS 8115 - parallel zfs mount
Porting Notes: * Use thread pools (tpool) API instead of introducing taskq interfaces to libzfs. * Use pthread_mutext for locks as mutex_t isn't available. * Ignore alternative libshare initialization since OpenZFS-7955 is not present on zfsonlinux. Authored by: Sebastien Roy <seb@delphix.com> Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: Pavel Zakharov <pavel.zakharov@delphix.com> Reviewed by: Brad Lewis <brad.lewis@delphix.com> Reviewed by: George Wilson <george.wilson@delphix.com> Reviewed by: Paul Dagnelie <pcd@delphix.com> Reviewed by: Prashanth Sreenivasa <pks@delphix.com> Authored by: Brian Behlendorf <behlendorf1@llnl.gov> Approved by: Matt Ahrens <mahrens@delphix.com> Ported-by: Don Brady <don.brady@delphix.com> OpenZFS-issue: https://www.illumos.org/issues/8115 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/a3f0e2b569 Closes #8092
This commit is contained in:
committed by
Brian Behlendorf
parent
af2e8411da
commit
a10d50f999
+73
-30
@@ -6059,7 +6059,12 @@ zfs_do_holds(int argc, char **argv)
|
||||
|
||||
#define CHECK_SPINNER 30
|
||||
#define SPINNER_TIME 3 /* seconds */
|
||||
#define MOUNT_TIME 5 /* 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)
|
||||
@@ -6068,10 +6073,10 @@ get_one_dataset(zfs_handle_t *zhp, void *data)
|
||||
static int spinval = 0;
|
||||
static int spincheck = 0;
|
||||
static time_t last_spin_time = (time_t)0;
|
||||
get_all_cb_t *cbp = data;
|
||||
get_all_state_t *state = data;
|
||||
zfs_type_t type = zfs_get_type(zhp);
|
||||
|
||||
if (cbp->cb_verbose) {
|
||||
if (state->ga_verbose) {
|
||||
if (--spincheck < 0) {
|
||||
time_t now = time(NULL);
|
||||
if (last_spin_time + SPINNER_TIME < now) {
|
||||
@@ -6097,25 +6102,23 @@ get_one_dataset(zfs_handle_t *zhp, void *data)
|
||||
zfs_close(zhp);
|
||||
return (0);
|
||||
}
|
||||
libzfs_add_handle(cbp, zhp);
|
||||
assert(cbp->cb_used <= cbp->cb_alloc);
|
||||
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(zfs_handle_t ***dslist, size_t *count, boolean_t verbose)
|
||||
get_all_datasets(get_all_cb_t *cbp, boolean_t verbose)
|
||||
{
|
||||
get_all_cb_t cb = { 0 };
|
||||
cb.cb_verbose = verbose;
|
||||
cb.cb_getone = get_one_dataset;
|
||||
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, &cb);
|
||||
|
||||
*dslist = cb.cb_handles;
|
||||
*count = cb.cb_used;
|
||||
(void) zfs_iter_root(g_zfs, get_one_dataset, &state);
|
||||
|
||||
if (verbose)
|
||||
finish_progress(gettext("done."));
|
||||
@@ -6126,8 +6129,19 @@ get_all_datasets(zfs_handle_t ***dslist, size_t *count, boolean_t verbose)
|
||||
* 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
|
||||
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 */
|
||||
pthread_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.
|
||||
@@ -6385,6 +6399,29 @@ report_mount_progress(int current, int total)
|
||||
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);
|
||||
|
||||
pthread_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);
|
||||
pthread_mutex_unlock(&sms->sm_lock);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
append_options(char *mntopts, char *newopts)
|
||||
{
|
||||
@@ -6459,8 +6496,6 @@ share_mount(int op, int argc, char **argv)
|
||||
|
||||
/* 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) {
|
||||
@@ -6481,27 +6516,35 @@ share_mount(int op, int argc, char **argv)
|
||||
}
|
||||
|
||||
start_progress_timer();
|
||||
get_all_datasets(&dslist, &count, verbose);
|
||||
get_all_cb_t cb = { 0 };
|
||||
get_all_datasets(&cb, verbose);
|
||||
|
||||
if (count == 0) {
|
||||
if (cb.cb_used == 0) {
|
||||
if (options != NULL)
|
||||
free(options);
|
||||
return (0);
|
||||
}
|
||||
|
||||
qsort(dslist, count, sizeof (void *), libzfs_dataset_cmp);
|
||||
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;
|
||||
pthread_mutex_init(&share_mount_state.sm_lock, NULL);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (verbose)
|
||||
report_mount_progress(i, count);
|
||||
/*
|
||||
* 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;
|
||||
|
||||
if (share_mount_one(dslist[i], op, flags, protocol,
|
||||
B_FALSE, options) != 0)
|
||||
ret = 1;
|
||||
zfs_close(dslist[i]);
|
||||
}
|
||||
|
||||
free(dslist);
|
||||
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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user