Added limited/recursive operation to `zfs mount`
This commit introduces limited/recursive filesystem mounting by leveraging the existing `zfs mount -a` codebase with minor additions and modifications. Now, when running `zfs mount <-a|-A> zpool/dataset`, the command will mount all datasets that are the specified dataset itself or it's children, provided they are available. In addition, `-A` flag will also mount datasets with `canmount=noauto` property. Changes in `zfs_main.c`: - `HELP_MOUNT` - Updated `usage()` message to reflect the changes. - `get_all_state_t` - Added `const char *ga_parent`; used to specify the parent dataset. - `get_one_dataset()` - Added a check; if `ga_parent` is set, skips any datasets that are not `ga_parent` itself or it's children. - `get_all_datasets()` - Added `const char *parent` property; used to pass the parent dataset to the `get_all_state_t` struct. - `share_mount_state_t` - Added `boolean_t sm_mount_noauto`; used to treat datasets with `canmount=noauto` property as as if it were `canmount=on`. - `share_mount_one()`; - Added `boolean_t mount_noauto` property. - Modified the 'noauto' check; when mounting datasets, if `mount_noauto` is true, treat the mount as if `canmount=on` or `explicit` is `B_TRUE`. - `share_mount_one_cb()` - Updated `share_mount_one()` call to include the new property, passes the value of `sm_mount_noauto`. - `share_mount()` - Changed `do_all` from `int` to `boolean_t` - Added `boolean_t do_noauto` property; used for mounting datasets with `canmount=noauto` as `canmount=on`. - Added the `-A` flag; when used sets `do_noauto` to `B_TRUE`. - Updated argument check; displaies the correct error messages. - Limited the usage of `<-a|-A> filesystem` to `zfs mount` only - Added a check; to validate that the specified filesystem is indeed a valid ZFS filesystem. - Updated `get_all_datasets()` call to include the new property, passes the value of `filesystem`. - Added `share_mount_state.sm_mount_noauto`; the `share_mount_state_t` has a new member, uses value of `do_noauto` - Updated `share_mount_one()` call to include the new property, passes the value `B_FALSE`. Signed-off-by: QORTEC <lowell.bv@gmail.com>
This commit is contained in:
parent
f476a37b37
commit
a1295cd96a
|
@ -307,7 +307,8 @@ get_usage(zfs_help_t idx)
|
|||
"[filesystem|volume|snapshot] ...\n"));
|
||||
case HELP_MOUNT:
|
||||
return (gettext("\tmount\n"
|
||||
"\tmount [-flvO] [-o opts] <-a | filesystem>\n"));
|
||||
"\tmount [-flvO] [-o opts] "
|
||||
"<-a [filesystem] | [-A] filesystem>\n"));
|
||||
case HELP_PROMOTE:
|
||||
return (gettext("\tpromote <clone-filesystem>\n"));
|
||||
case HELP_RECEIVE:
|
||||
|
@ -6731,6 +6732,7 @@ zfs_do_holds(int argc, char **argv)
|
|||
typedef struct get_all_state {
|
||||
boolean_t ga_verbose;
|
||||
get_all_cb_t *ga_cbp;
|
||||
const char *ga_parent;
|
||||
} get_all_state_t;
|
||||
|
||||
static int
|
||||
|
@ -6769,6 +6771,16 @@ get_one_dataset(zfs_handle_t *zhp, void *data)
|
|||
zfs_close(zhp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip any dataset that's not related to ga_parent.
|
||||
*/
|
||||
if (state->ga_parent != NULL &&
|
||||
!zfs_dataset_related(zhp, state->ga_parent)) {
|
||||
zfs_close(zhp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
libzfs_add_handle(state->ga_cbp, zhp);
|
||||
assert(state->ga_cbp->cb_used <= state->ga_cbp->cb_alloc);
|
||||
|
||||
|
@ -6776,11 +6788,12 @@ get_one_dataset(zfs_handle_t *zhp, void *data)
|
|||
}
|
||||
|
||||
static void
|
||||
get_all_datasets(get_all_cb_t *cbp, boolean_t verbose)
|
||||
get_all_datasets(get_all_cb_t *cbp, boolean_t verbose, const char *parent)
|
||||
{
|
||||
get_all_state_t state = {
|
||||
.ga_verbose = verbose,
|
||||
.ga_cbp = cbp
|
||||
.ga_cbp = cbp,
|
||||
.ga_parent = parent
|
||||
};
|
||||
|
||||
if (verbose)
|
||||
|
@ -6808,6 +6821,7 @@ typedef struct share_mount_state {
|
|||
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 */
|
||||
boolean_t sm_mount_noauto; /* treat 'canmount=noauto' as 'on' */
|
||||
} share_mount_state_t;
|
||||
|
||||
/*
|
||||
|
@ -6815,7 +6829,7 @@ typedef struct share_mount_state {
|
|||
*/
|
||||
static int
|
||||
share_mount_one(zfs_handle_t *zhp, int op, int flags, enum sa_protocol protocol,
|
||||
boolean_t explicit, const char *options)
|
||||
boolean_t explicit, const char *options, boolean_t mount_noauto)
|
||||
{
|
||||
char mountpoint[ZFS_MAXPROPLEN];
|
||||
char shareopts[ZFS_MAXPROPLEN];
|
||||
|
@ -6905,13 +6919,14 @@ share_mount_one(zfs_handle_t *zhp, int op, int flags, enum sa_protocol protocol,
|
|||
}
|
||||
|
||||
/*
|
||||
* canmount explicit outcome
|
||||
* on no pass through
|
||||
* on yes pass through
|
||||
* off no return 0
|
||||
* off yes display error, return 1
|
||||
* noauto no return 0
|
||||
* noauto yes pass through
|
||||
* canmount explicit mount_noauto outcome
|
||||
* on no n/a pass through
|
||||
* on yes n/a pass through
|
||||
* off no n/a return 0
|
||||
* off yes n/a display error, return 1
|
||||
* noauto no no return 0
|
||||
* noauto no yes pass through
|
||||
* noauto yes yes/no pass through
|
||||
*/
|
||||
canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT);
|
||||
if (canmount == ZFS_CANMOUNT_OFF) {
|
||||
|
@ -6922,11 +6937,13 @@ share_mount_one(zfs_handle_t *zhp, int op, int flags, enum sa_protocol protocol,
|
|||
"'canmount' property is set to 'off'\n"), cmdname,
|
||||
zfs_get_name(zhp));
|
||||
return (1);
|
||||
} else if (canmount == ZFS_CANMOUNT_NOAUTO && !explicit) {
|
||||
} else if (canmount == ZFS_CANMOUNT_NOAUTO &&
|
||||
!explicit && !mount_noauto) {
|
||||
/*
|
||||
* When performing a 'zfs mount -a', we skip any mounts for
|
||||
* datasets that have 'noauto' set. Sharing a dataset with
|
||||
* 'noauto' set is only allowed if it's mounted.
|
||||
* datasets that have 'noauto' set. However, 'zfs mount -A'
|
||||
* will mount datasets with 'noauto' set. Sharing a dataset
|
||||
* with 'noauto' set is only allowed if it's mounted.
|
||||
*/
|
||||
if (op == OP_MOUNT)
|
||||
return (0);
|
||||
|
@ -7082,7 +7099,7 @@ share_mount_one_cb(zfs_handle_t *zhp, void *arg)
|
|||
int ret;
|
||||
|
||||
ret = share_mount_one(zhp, sms->sm_op, sms->sm_flags, sms->sm_proto,
|
||||
B_FALSE, sms->sm_options);
|
||||
B_FALSE, sms->sm_options, sms->sm_mount_noauto);
|
||||
|
||||
pthread_mutex_lock(&sms->sm_lock);
|
||||
if (ret != 0)
|
||||
|
@ -7132,18 +7149,22 @@ sa_protocol_decode(const char *protocol)
|
|||
static int
|
||||
share_mount(int op, int argc, char **argv)
|
||||
{
|
||||
int do_all = 0;
|
||||
boolean_t do_all = B_FALSE;
|
||||
boolean_t do_noauto = B_FALSE;
|
||||
boolean_t verbose = B_FALSE;
|
||||
int c, ret = 0;
|
||||
char *options = NULL;
|
||||
int flags = 0;
|
||||
|
||||
/* check options */
|
||||
while ((c = getopt(argc, argv, op == OP_MOUNT ? ":alvo:Of" : "al"))
|
||||
while ((c = getopt(argc, argv, op == OP_MOUNT ? ":aAlvo:Of" : "al"))
|
||||
!= -1) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
do_all = 1;
|
||||
do_all = B_TRUE;
|
||||
break;
|
||||
case 'A':
|
||||
do_noauto = B_TRUE;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = B_TRUE;
|
||||
|
@ -7186,7 +7207,7 @@ share_mount(int op, int argc, char **argv)
|
|||
argv += optind;
|
||||
|
||||
/* check number of arguments */
|
||||
if (do_all) {
|
||||
if (do_all || do_noauto) {
|
||||
enum sa_protocol protocol = SA_NO_PROTOCOL;
|
||||
|
||||
if (op == OP_SHARE && argc > 0) {
|
||||
|
@ -7194,15 +7215,40 @@ share_mount(int op, int argc, char **argv)
|
|||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (argc != 0) {
|
||||
/* check number of arguments */
|
||||
if (do_noauto && argc < 1) {
|
||||
(void) fprintf(stderr, gettext("missing "
|
||||
"dataset argument\n"));
|
||||
usage(B_FALSE);
|
||||
}
|
||||
if ((op == OP_SHARE && argc != 0) || argc > 1) {
|
||||
(void) fprintf(stderr, gettext("too many arguments\n"));
|
||||
usage(B_FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Limit `-a filesystem` to mount only
|
||||
*/
|
||||
const char *filesystem = NULL;
|
||||
if (op == OP_MOUNT)
|
||||
filesystem = argv[0];
|
||||
|
||||
/*
|
||||
* Validate filesystem is actually a valid zfs filesystem
|
||||
*/
|
||||
if (filesystem != NULL) {
|
||||
zfs_handle_t *zhp = zfs_open(g_zfs, filesystem,
|
||||
ZFS_TYPE_FILESYSTEM);
|
||||
if (zhp == NULL) {
|
||||
free(options);
|
||||
return (1);
|
||||
}
|
||||
zfs_close(zhp);
|
||||
}
|
||||
|
||||
start_progress_timer();
|
||||
get_all_cb_t cb = { 0 };
|
||||
get_all_datasets(&cb, verbose);
|
||||
get_all_datasets(&cb, verbose, filesystem);
|
||||
|
||||
if (cb.cb_used == 0) {
|
||||
free(options);
|
||||
|
@ -7216,6 +7262,7 @@ share_mount(int op, int argc, char **argv)
|
|||
share_mount_state.sm_options = options;
|
||||
share_mount_state.sm_proto = protocol;
|
||||
share_mount_state.sm_total = cb.cb_used;
|
||||
share_mount_state.sm_mount_noauto = do_noauto;
|
||||
pthread_mutex_init(&share_mount_state.sm_lock, NULL);
|
||||
|
||||
/* For a 'zfs share -a' operation start with a clean slate. */
|
||||
|
@ -7283,7 +7330,7 @@ share_mount(int op, int argc, char **argv)
|
|||
ret = 1;
|
||||
} else {
|
||||
ret = share_mount_one(zhp, op, flags, SA_NO_PROTOCOL,
|
||||
B_TRUE, options);
|
||||
B_TRUE, options, B_FALSE);
|
||||
zfs_commit_shares(NULL);
|
||||
zfs_close(zhp);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue