Skip to content

Commit 4e16964

Browse files
author
Umer Saleem
authored
Add '-u' - nomount flag for zfs set
This commit adds '-u' flag for zfs set operation. With this flag, mountpoint, sharenfs and sharesmb properties can be updated without actually mounting or sharing the dataset. Previously, if dataset was unmounted, and mountpoint property was updated, dataset was not mounted after the update. This behavior is changed in #15240. We mount the dataset whenever mountpoint property is updated, regardless if it's mounted or not. To provide the user with option to keep the dataset unmounted and still update the mountpoint without mounting the dataset, '-u' flag can be used. If any of mountpoint, sharenfs or sharesmb properties are updated with '-u' flag, the property is set to desired value but the operation to (re/un)mount and/or (re/un)share the dataset is not performed and dataset remains as it was before. Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Umer Saleem <[email protected]> Closes #15322
1 parent 249d759 commit 4e16964

File tree

11 files changed

+216
-33
lines changed

11 files changed

+216
-33
lines changed

cmd/zfs/zfs_main.c

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ get_usage(zfs_help_t idx)
339339
"\tsend [-nVvPe] -t <receive_resume_token>\n"
340340
"\tsend [-PnVv] --saved filesystem\n"));
341341
case HELP_SET:
342-
return (gettext("\tset <property=value> ... "
342+
return (gettext("\tset [-u] <property=value> ... "
343343
"<filesystem|volume|snapshot> ...\n"));
344344
case HELP_SHARE:
345345
return (gettext("\tshare [-l] <-a [nfs|smb] | filesystem>\n"));
@@ -4206,8 +4206,8 @@ zfs_do_rollback(int argc, char **argv)
42064206
static int
42074207
set_callback(zfs_handle_t *zhp, void *data)
42084208
{
4209-
nvlist_t *props = data;
4210-
int ret = zfs_prop_set_list(zhp, props);
4209+
zprop_set_cbdata_t *cb = data;
4210+
int ret = zfs_prop_set_list_flags(zhp, cb->cb_proplist, cb->cb_flags);
42114211

42124212
if (ret != 0 || libzfs_errno(g_zfs) != EZFS_SUCCESS) {
42134213
switch (libzfs_errno(g_zfs)) {
@@ -4227,25 +4227,35 @@ set_callback(zfs_handle_t *zhp, void *data)
42274227
static int
42284228
zfs_do_set(int argc, char **argv)
42294229
{
4230-
nvlist_t *props = NULL;
4230+
zprop_set_cbdata_t cb = { 0 };
42314231
int ds_start = -1; /* argv idx of first dataset arg */
42324232
int ret = 0;
4233-
int i;
4233+
int i, c;
42344234

4235-
/* check for options */
4236-
if (argc > 1 && argv[1][0] == '-') {
4237-
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
4238-
argv[1][1]);
4239-
usage(B_FALSE);
4235+
/* check options */
4236+
while ((c = getopt(argc, argv, "u")) != -1) {
4237+
switch (c) {
4238+
case 'u':
4239+
cb.cb_flags |= ZFS_SET_NOMOUNT;
4240+
break;
4241+
case '?':
4242+
default:
4243+
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
4244+
optopt);
4245+
usage(B_FALSE);
4246+
}
42404247
}
42414248

4249+
argc -= optind;
4250+
argv += optind;
4251+
42424252
/* check number of arguments */
4243-
if (argc < 2) {
4253+
if (argc < 1) {
42444254
(void) fprintf(stderr, gettext("missing arguments\n"));
42454255
usage(B_FALSE);
42464256
}
4247-
if (argc < 3) {
4248-
if (strchr(argv[1], '=') == NULL) {
4257+
if (argc < 2) {
4258+
if (strchr(argv[0], '=') == NULL) {
42494259
(void) fprintf(stderr, gettext("missing property=value "
42504260
"argument(s)\n"));
42514261
} else {
@@ -4256,7 +4266,7 @@ zfs_do_set(int argc, char **argv)
42564266
}
42574267

42584268
/* validate argument order: prop=val args followed by dataset args */
4259-
for (i = 1; i < argc; i++) {
4269+
for (i = 0; i < argc; i++) {
42604270
if (strchr(argv[i], '=') != NULL) {
42614271
if (ds_start > 0) {
42624272
/* out-of-order prop=val argument */
@@ -4274,20 +4284,20 @@ zfs_do_set(int argc, char **argv)
42744284
}
42754285

42764286
/* Populate a list of property settings */
4277-
if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
4287+
if (nvlist_alloc(&cb.cb_proplist, NV_UNIQUE_NAME, 0) != 0)
42784288
nomem();
4279-
for (i = 1; i < ds_start; i++) {
4280-
if (!parseprop(props, argv[i])) {
4289+
for (i = 0; i < ds_start; i++) {
4290+
if (!parseprop(cb.cb_proplist, argv[i])) {
42814291
ret = -1;
42824292
goto error;
42834293
}
42844294
}
42854295

42864296
ret = zfs_for_each(argc - ds_start, argv + ds_start, 0,
4287-
ZFS_TYPE_DATASET, NULL, NULL, 0, set_callback, props);
4297+
ZFS_TYPE_DATASET, NULL, NULL, 0, set_callback, &cb);
42884298

42894299
error:
4290-
nvlist_free(props);
4300+
nvlist_free(cb.cb_proplist);
42914301
return (ret);
42924302
}
42934303

include/libzfs.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,7 @@ _LIBZFS_H nvlist_t *zfs_valid_proplist(libzfs_handle_t *, zfs_type_t,
532532
_LIBZFS_H const char *zfs_prop_to_name(zfs_prop_t);
533533
_LIBZFS_H int zfs_prop_set(zfs_handle_t *, const char *, const char *);
534534
_LIBZFS_H int zfs_prop_set_list(zfs_handle_t *, nvlist_t *);
535+
_LIBZFS_H int zfs_prop_set_list_flags(zfs_handle_t *, nvlist_t *, int);
535536
_LIBZFS_H int zfs_prop_get(zfs_handle_t *, zfs_prop_t, char *, size_t,
536537
zprop_source_t *, char *, size_t, boolean_t);
537538
_LIBZFS_H int zfs_prop_get_recvd(zfs_handle_t *, const char *, char *, size_t,
@@ -654,6 +655,13 @@ typedef struct zprop_get_cbdata {
654655
vdev_cbdata_t cb_vdevs;
655656
} zprop_get_cbdata_t;
656657

658+
#define ZFS_SET_NOMOUNT 1
659+
660+
typedef struct zprop_set_cbdata {
661+
int cb_flags;
662+
nvlist_t *cb_proplist;
663+
} zprop_set_cbdata_t;
664+
657665
_LIBZFS_H void zprop_print_one_property(const char *, zprop_get_cbdata_t *,
658666
const char *, const char *, zprop_source_t, const char *,
659667
const char *);

lib/libzfs/libzfs.abi

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@
396396
<elf-symbol name='zfs_prop_readonly' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
397397
<elf-symbol name='zfs_prop_set' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
398398
<elf-symbol name='zfs_prop_set_list' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
399+
<elf-symbol name='zfs_prop_set_list_flags' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
399400
<elf-symbol name='zfs_prop_setonce' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
400401
<elf-symbol name='zfs_prop_string_to_index' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
401402
<elf-symbol name='zfs_prop_to_name' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -4428,6 +4429,12 @@
44284429
<parameter type-id='5ce45b60' name='props'/>
44294430
<return type-id='95e97e5e'/>
44304431
</function-decl>
4432+
<function-decl name='zfs_prop_set_list_flags' mangled-name='zfs_prop_set_list_flags' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_set_list_flags'>
4433+
<parameter type-id='9200a744' name='zhp'/>
4434+
<parameter type-id='5ce45b60' name='props'/>
4435+
<parameter type-id='95e97e5e' name='flags'/>
4436+
<return type-id='95e97e5e'/>
4437+
</function-decl>
44314438
<function-decl name='zfs_prop_inherit' mangled-name='zfs_prop_inherit' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_prop_inherit'>
44324439
<parameter type-id='9200a744' name='zhp'/>
44334440
<parameter type-id='80f4b756' name='propname'/>

lib/libzfs/libzfs_changelist.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,15 @@ changelist_prefix(prop_changelist_t *clp)
105105
clp->cl_prop != ZFS_PROP_SHARESMB)
106106
return (0);
107107

108+
/*
109+
* If CL_GATHER_DONT_UNMOUNT is set, don't want to unmount/unshare and
110+
* later (re)mount/(re)share the filesystem in postfix phase, so we
111+
* return from here. If filesystem is mounted or unmounted, leave it
112+
* as it is.
113+
*/
114+
if (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT)
115+
return (0);
116+
108117
if ((walk = uu_avl_walk_start(clp->cl_tree, UU_WALK_ROBUST)) == NULL)
109118
return (-1);
110119

@@ -129,8 +138,6 @@ changelist_prefix(prop_changelist_t *clp)
129138
*/
130139
switch (clp->cl_prop) {
131140
case ZFS_PROP_MOUNTPOINT:
132-
if (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT)
133-
break;
134141
if (zfs_unmount(cn->cn_handle, NULL,
135142
clp->cl_mflags) != 0) {
136143
ret = -1;
@@ -164,9 +171,8 @@ changelist_prefix(prop_changelist_t *clp)
164171
* reshare the filesystems as necessary. In changelist_gather() we recorded
165172
* whether the filesystem was previously shared or mounted. The action we take
166173
* depends on the previous state, and whether the value was previously 'legacy'.
167-
* For non-legacy properties, we only remount/reshare the filesystem if it was
168-
* previously mounted/shared. Otherwise, we always remount/reshare the
169-
* filesystem.
174+
* For non-legacy properties, we always remount/reshare the filesystem,
175+
* if CL_GATHER_DONT_UNMOUNT is not set.
170176
*/
171177
int
172178
changelist_postfix(prop_changelist_t *clp)
@@ -177,6 +183,14 @@ changelist_postfix(prop_changelist_t *clp)
177183
boolean_t commit_smb_shares = B_FALSE;
178184
boolean_t commit_nfs_shares = B_FALSE;
179185

186+
/*
187+
* If CL_GATHER_DONT_UNMOUNT is set, it means we don't want to (un)mount
188+
* or (re/un)share the filesystem, so we return from here. If filesystem
189+
* is mounted or unmounted, leave it as it is.
190+
*/
191+
if (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT)
192+
return (0);
193+
180194
/*
181195
* If we're changing the mountpoint, attempt to destroy the underlying
182196
* mountpoint. All other datasets will have inherited from this dataset
@@ -239,8 +253,7 @@ changelist_postfix(prop_changelist_t *clp)
239253
needs_key = (zfs_prop_get_int(cn->cn_handle,
240254
ZFS_PROP_KEYSTATUS) == ZFS_KEYSTATUS_UNAVAILABLE);
241255

242-
mounted = (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT) ||
243-
zfs_is_mounted(cn->cn_handle, NULL);
256+
mounted = zfs_is_mounted(cn->cn_handle, NULL);
244257

245258
if (!mounted && !needs_key && (cn->cn_mounted ||
246259
(((clp->cl_prop == ZFS_PROP_MOUNTPOINT &&

lib/libzfs/libzfs_dataset.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,14 +1771,24 @@ zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
17711771
return (ret);
17721772
}
17731773

1774-
1775-
17761774
/*
17771775
* Given an nvlist of property names and values, set the properties for the
17781776
* given dataset.
17791777
*/
17801778
int
17811779
zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
1780+
{
1781+
return (zfs_prop_set_list_flags(zhp, props, 0));
1782+
}
1783+
1784+
/*
1785+
* Given an nvlist of property names, values and flags, set the properties
1786+
* for the given dataset. If ZFS_SET_NOMOUNT is set, it allows to update
1787+
* mountpoint, sharenfs and sharesmb properties without (un/re)mounting
1788+
* and (un/re)sharing the dataset.
1789+
*/
1790+
int
1791+
zfs_prop_set_list_flags(zfs_handle_t *zhp, nvlist_t *props, int flags)
17821792
{
17831793
zfs_cmd_t zc = {"\0"};
17841794
int ret = -1;
@@ -1848,7 +1858,9 @@ zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
18481858
if (prop != ZFS_PROP_CANMOUNT ||
18491859
(fnvpair_value_uint64(elem) == ZFS_CANMOUNT_OFF &&
18501860
zfs_is_mounted(zhp, NULL))) {
1851-
cls[cl_idx] = changelist_gather(zhp, prop, 0, 0);
1861+
cls[cl_idx] = changelist_gather(zhp, prop,
1862+
((flags & ZFS_SET_NOMOUNT) ?
1863+
CL_GATHER_DONT_UNMOUNT : 0), 0);
18521864
if (cls[cl_idx] == NULL)
18531865
goto error;
18541866
}

man/man7/zfsprops.7

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,10 +1248,18 @@ Otherwise, they are automatically remounted in the new location if the property
12481248
was previously
12491249
.Sy legacy
12501250
or
1251-
.Sy none ,
1252-
or if they were mounted before the property was changed.
1251+
.Sy none .
12531252
In addition, any shared file systems are unshared and shared in the new
12541253
location.
1254+
.Pp
1255+
When the
1256+
.Sy mountpoint
1257+
property is set with
1258+
.Nm zfs Cm set Fl u
1259+
, the
1260+
.Sy mountpoint
1261+
property is updated but dataset is not mounted or unmounted and remains
1262+
as it was before.
12551263
.It Sy nbmand Ns = Ns Sy on Ns | Ns Sy off
12561264
Controls whether the file system should be mounted with
12571265
.Sy nbmand
@@ -1656,6 +1664,13 @@ by default.
16561664
This means that any additional access control
16571665
(disallow specific user specific access etc) must be done on the underlying file
16581666
system.
1667+
.Pp
1668+
When the
1669+
.Sy sharesmb
1670+
property is updated with
1671+
.Nm zfs Cm set Fl u
1672+
, the property is set to desired value, but the operation to share, reshare
1673+
or unshare the the dataset is not performed.
16591674
.It Sy sharenfs Ns = Ns Sy on Ns | Ns Sy off Ns | Ns Ar opts
16601675
Controls whether the file system is shared via NFS, and what options are to be
16611676
used.
@@ -1699,6 +1714,13 @@ or if they were shared before the property was changed.
16991714
If the new property is
17001715
.Sy off ,
17011716
the file systems are unshared.
1717+
.Pp
1718+
When the
1719+
.Sy sharenfs
1720+
property is updated with
1721+
.Nm zfs Cm set Fl u
1722+
, the property is set to desired value, but the operation to share, reshare
1723+
or unshare the the dataset is not performed.
17021724
.It Sy logbias Ns = Ns Sy latency Ns | Ns Sy throughput
17031725
Provide a hint to ZFS about handling of synchronous requests in this dataset.
17041726
If

man/man8/zfs-set.8

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
.Sh SYNOPSIS
4040
.Nm zfs
4141
.Cm set
42+
.Op Fl u
4243
.Ar property Ns = Ns Ar value Oo Ar property Ns = Ns Ar value Oc Ns
4344
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns
4445
.Nm zfs
@@ -60,6 +61,7 @@
6061
.It Xo
6162
.Nm zfs
6263
.Cm set
64+
.Op Fl u
6365
.Ar property Ns = Ns Ar value Oo Ar property Ns = Ns Ar value Oc Ns
6466
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns
6567
.Xc
@@ -79,6 +81,11 @@ For more information, see the
7981
.Em User Properties
8082
section of
8183
.Xr zfsprops 7 .
84+
.Bl -tag -width "-u"
85+
.It Fl u
86+
Update mountpoint, sharenfs, sharesmb property but do not mount or share the
87+
dataset.
88+
.El
8289
.It Xo
8390
.Nm zfs
8491
.Cm get

tests/runfiles/common.run

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ tests = ['cache_001_pos', 'cache_002_neg', 'canmount_001_pos',
281281
'user_property_004_pos', 'version_001_neg', 'zfs_set_001_neg',
282282
'zfs_set_002_neg', 'zfs_set_003_neg', 'property_alias_001_pos',
283283
'mountpoint_003_pos', 'ro_props_001_pos', 'zfs_set_keylocation',
284-
'zfs_set_feature_activation']
284+
'zfs_set_feature_activation', 'zfs_set_nomount']
285285
tags = ['functional', 'cli_root', 'zfs_set']
286286

287287
[tests/functional/cli_root/zfs_share]

tests/runfiles/sanity.run

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ tests = ['cache_001_pos', 'cache_002_neg', 'canmount_001_pos',
212212
'user_property_001_pos', 'user_property_003_neg', 'readonly_001_pos',
213213
'user_property_004_pos', 'version_001_neg',
214214
'zfs_set_003_neg', 'property_alias_001_pos',
215-
'zfs_set_keylocation', 'zfs_set_feature_activation']
215+
'zfs_set_keylocation', 'zfs_set_feature_activation', 'zfs_set_nomount']
216216
tags = ['functional', 'cli_root', 'zfs_set']
217217

218218
[tests/functional/cli_root/zfs_snapshot]

tests/zfs-tests/tests/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
870870
functional/cli_root/zfs_set/zfs_set_003_neg.ksh \
871871
functional/cli_root/zfs_set/zfs_set_feature_activation.ksh \
872872
functional/cli_root/zfs_set/zfs_set_keylocation.ksh \
873+
functional/cli_root/zfs_set/zfs_set_nomount.ksh \
873874
functional/cli_root/zfs_share/cleanup.ksh \
874875
functional/cli_root/zfs_share/setup.ksh \
875876
functional/cli_root/zfs_share/zfs_share_001_pos.ksh \

0 commit comments

Comments
 (0)