Changeset View
Changeset View
Standalone View
Standalone View
cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
Show First 20 Lines • Show All 5,806 Lines • ▼ Show 20 Lines | zfs_do_holds(int argc, char **argv) | ||||
nvlist_free(nvl); | nvlist_free(nvl); | ||||
return (0 != errors); | return (0 != errors); | ||||
} | } | ||||
#define CHECK_SPINNER 30 | #define CHECK_SPINNER 30 | ||||
#define SPINNER_TIME 3 /* seconds */ | #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 | static int | ||||
get_one_dataset(zfs_handle_t *zhp, void *data) | get_one_dataset(zfs_handle_t *zhp, void *data) | ||||
{ | { | ||||
static char *spin[] = { "-", "\\", "|", "/" }; | static char *spin[] = { "-", "\\", "|", "/" }; | ||||
static int spinval = 0; | static int spinval = 0; | ||||
static int spincheck = 0; | static int spincheck = 0; | ||||
static time_t last_spin_time = (time_t)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); | zfs_type_t type = zfs_get_type(zhp); | ||||
if (cbp->cb_verbose) { | if (state->ga_verbose) { | ||||
if (--spincheck < 0) { | if (--spincheck < 0) { | ||||
time_t now = time(NULL); | time_t now = time(NULL); | ||||
if (last_spin_time + SPINNER_TIME < now) { | if (last_spin_time + SPINNER_TIME < now) { | ||||
update_progress(spin[spinval++ % 4]); | update_progress(spin[spinval++ % 4]); | ||||
last_spin_time = now; | last_spin_time = now; | ||||
} | } | ||||
spincheck = CHECK_SPINNER; | spincheck = CHECK_SPINNER; | ||||
} | } | ||||
Show All 9 Lines | get_one_dataset(zfs_handle_t *zhp, void *data) | ||||
/* | /* | ||||
* Skip any datasets whose type does not match. | * Skip any datasets whose type does not match. | ||||
*/ | */ | ||||
if ((type & ZFS_TYPE_FILESYSTEM) == 0) { | if ((type & ZFS_TYPE_FILESYSTEM) == 0) { | ||||
zfs_close(zhp); | zfs_close(zhp); | ||||
return (0); | return (0); | ||||
} | } | ||||
libzfs_add_handle(cbp, zhp); | libzfs_add_handle(state->ga_cbp, zhp); | ||||
assert(cbp->cb_used <= cbp->cb_alloc); | assert(state->ga_cbp->cb_used <= state->ga_cbp->cb_alloc); | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | 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 }; | get_all_state_t state = { | ||||
cb.cb_verbose = verbose; | .ga_verbose = verbose, | ||||
cb.cb_getone = get_one_dataset; | .ga_cbp = cbp | ||||
}; | |||||
if (verbose) | if (verbose) | ||||
set_progress_header(gettext("Reading ZFS config")); | set_progress_header(gettext("Reading ZFS config")); | ||||
(void) zfs_iter_root(g_zfs, get_one_dataset, &cb); | (void) zfs_iter_root(g_zfs, get_one_dataset, &state); | ||||
*dslist = cb.cb_handles; | |||||
*count = cb.cb_used; | |||||
if (verbose) | if (verbose) | ||||
finish_progress(gettext("done.")); | finish_progress(gettext("done.")); | ||||
} | } | ||||
/* | /* | ||||
* Generic callback for sharing or mounting filesystems. Because the code is so | * 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 | * similar, we have a common function with an extra parameter to determine which | ||||
* mode we are using. | * mode we are using. | ||||
*/ | */ | ||||
#define OP_SHARE 0x1 | typedef enum { OP_SHARE, OP_MOUNT } share_mount_op_t; | ||||
#define OP_MOUNT 0x2 | |||||
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. | * Share or mount a dataset. | ||||
*/ | */ | ||||
static int | static int | ||||
share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol, | share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol, | ||||
boolean_t explicit, const char *options) | boolean_t explicit, const char *options) | ||||
{ | { | ||||
char mountpoint[ZFS_MAXPROPLEN]; | char mountpoint[ZFS_MAXPROPLEN]; | ||||
▲ Show 20 Lines • Show All 224 Lines • ▼ Show 20 Lines | report_mount_progress(int current, int total) | ||||
(void) sprintf(info, "(%d/%d)", current, total); | (void) sprintf(info, "(%d/%d)", current, total); | ||||
if (current == total) | if (current == total) | ||||
finish_progress(info); | finish_progress(info); | ||||
else | else | ||||
update_progress(info); | update_progress(info); | ||||
} | } | ||||
/* | |||||
* zfs_foreach_mountpoint() callback that mounts or shares on 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 | static void | ||||
append_options(char *mntopts, char *newopts) | append_options(char *mntopts, char *newopts) | ||||
{ | { | ||||
int len = strlen(mntopts); | int len = strlen(mntopts); | ||||
/* original length plus new string to append plus 1 for the comma */ | /* original length plus new string to append plus 1 for the comma */ | ||||
if (len + 1 + strlen(newopts) >= MNT_LINE_MAX) { | if (len + 1 + strlen(newopts) >= MNT_LINE_MAX) { | ||||
(void) fprintf(stderr, gettext("the opts argument for " | (void) fprintf(stderr, gettext("the opts argument for " | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | while ((c = getopt(argc, argv, op == OP_MOUNT ? ":avo:O" : "a")) | ||||
} | } | ||||
} | } | ||||
argc -= optind; | argc -= optind; | ||||
argv += optind; | argv += optind; | ||||
/* check number of arguments */ | /* check number of arguments */ | ||||
if (do_all) { | if (do_all) { | ||||
zfs_handle_t **dslist = NULL; | |||||
size_t i, count = 0; | |||||
char *protocol = NULL; | char *protocol = NULL; | ||||
if (op == OP_SHARE && argc > 0) { | if (op == OP_SHARE && argc > 0) { | ||||
if (strcmp(argv[0], "nfs") != 0 && | if (strcmp(argv[0], "nfs") != 0 && | ||||
strcmp(argv[0], "smb") != 0) { | strcmp(argv[0], "smb") != 0) { | ||||
(void) fprintf(stderr, gettext("share type " | (void) fprintf(stderr, gettext("share type " | ||||
"must be 'nfs' or 'smb'\n")); | "must be 'nfs' or 'smb'\n")); | ||||
usage(B_FALSE); | usage(B_FALSE); | ||||
} | } | ||||
protocol = argv[0]; | protocol = argv[0]; | ||||
argc--; | argc--; | ||||
argv++; | argv++; | ||||
} | } | ||||
if (argc != 0) { | if (argc != 0) { | ||||
(void) fprintf(stderr, gettext("too many arguments\n")); | (void) fprintf(stderr, gettext("too many arguments\n")); | ||||
usage(B_FALSE); | usage(B_FALSE); | ||||
} | } | ||||
start_progress_timer(); | 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); | return (0); | ||||
} | |||||
qsort(dslist, count, sizeof (void *), libzfs_dataset_cmp); | |||||
#ifdef illumos | #ifdef illumos | ||||
if (op == OP_SHARE) { | |||||
sa_init_selective_arg_t sharearg; | sa_init_selective_arg_t sharearg; | ||||
sharearg.zhandle_arr = dslist; | sharearg.zhandle_arr = cb.cb_handles; | ||||
sharearg.zhandle_len = count; | sharearg.zhandle_len = cb.cb_used; | ||||
if ((ret = zfs_init_libshare_arg(zfs_get_handle(dslist[0]), | if ((ret = zfs_init_libshare_arg(g_zfs, | ||||
SA_INIT_SHARE_API_SELECTIVE, &sharearg)) != SA_OK) { | SA_INIT_SHARE_API_SELECTIVE, &sharearg)) != SA_OK) { | ||||
(void) fprintf(stderr, | (void) fprintf(stderr, gettext( | ||||
gettext("Could not initialize libshare, %d"), ret); | "Could not initialize libshare, %d"), ret); | ||||
return (ret); | return (ret); | ||||
} | } | ||||
} | |||||
#endif | #endif | ||||
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) | * libshare isn't mt-safe, so only do the operation in parallel | ||||
report_mount_progress(i, count); | * 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, | for (int i = 0; i < cb.cb_used; i++) | ||||
B_FALSE, options) != 0) | zfs_close(cb.cb_handles[i]); | ||||
ret = 1; | free(cb.cb_handles); | ||||
zfs_close(dslist[i]); | |||||
} | |||||
free(dslist); | |||||
} else if (argc == 0) { | } else if (argc == 0) { | ||||
struct mnttab entry; | struct mnttab entry; | ||||
if ((op == OP_SHARE) || (options != NULL)) { | if ((op == OP_SHARE) || (options != NULL)) { | ||||
(void) fprintf(stderr, gettext("missing filesystem " | (void) fprintf(stderr, gettext("missing filesystem " | ||||
"argument (specify -a for all)\n")); | "argument (specify -a for all)\n")); | ||||
usage(B_FALSE); | usage(B_FALSE); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,231 Lines • Show Last 20 Lines |