Skip to content

Commit 395fafc

Browse files
committed
zfs_main: create, clone, rename: accept -pp for non-mountable parents
Teach `zfs {create,clone,rename}` to accept a doubled `-p` flag (`-pp`) to create non-existing ancestor datasets with `canmount=off`. Signed-off-by: Ivan Shapovalov <intelfx@intelfx.name>
1 parent 55d1a87 commit 395fafc

File tree

4 files changed

+78
-9
lines changed

4 files changed

+78
-9
lines changed

cmd/zfs/zfs_main.c

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,26 @@ finish_progress(const char *done)
766766
pt_header = NULL;
767767
}
768768

769+
static void
770+
makeprops_parents(nvlist_t **ptr, boolean_t parents_nomount)
771+
{
772+
nvlist_t *props = NULL;
773+
774+
if (parents_nomount) {
775+
if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
776+
nomem();
777+
778+
if (nvlist_add_string(props,
779+
zfs_prop_to_name(ZFS_PROP_CANMOUNT),
780+
"off") != 0) {
781+
nvlist_free(props);
782+
nomem();
783+
}
784+
}
785+
786+
*ptr = props;
787+
}
788+
769789
static int
770790
zfs_mount_and_share(libzfs_handle_t *hdl, const char *dataset, zfs_type_t type)
771791
{
@@ -826,13 +846,16 @@ zfs_mount_and_share(libzfs_handle_t *hdl, const char *dataset, zfs_type_t type)
826846
* the clone exists.
827847
*
828848
* The '-p' flag creates all the non-existing ancestors of the target first.
849+
* If repeated twice, the ancestors are created with `canmount=off`.
829850
*/
830851
static int
831852
zfs_do_clone(int argc, char **argv)
832853
{
833854
zfs_handle_t *zhp = NULL;
834855
boolean_t parents = B_FALSE;
856+
boolean_t parents_nomount = B_FALSE;
835857
nvlist_t *props;
858+
nvlist_t *props_parents = NULL;
836859
int ret = 1;
837860
int c;
838861

@@ -849,7 +872,10 @@ zfs_do_clone(int argc, char **argv)
849872
}
850873
break;
851874
case 'p':
852-
parents = B_TRUE;
875+
if (!parents)
876+
parents = B_TRUE;
877+
else
878+
parents_nomount = B_TRUE;
853879
break;
854880
case '?':
855881
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
@@ -894,9 +920,11 @@ zfs_do_clone(int argc, char **argv)
894920
ret = 0;
895921
goto error;
896922
}
897-
if (zfs_create_ancestors(g_zfs, argv[1]) != 0) {
923+
924+
makeprops_parents(&props_parents, parents_nomount);
925+
if (zfs_create_ancestors(g_zfs, argv[1],
926+
props_parents) != 0)
898927
goto error;
899-
}
900928
}
901929

902930
/* pass to libzfs */
@@ -921,11 +949,13 @@ zfs_do_clone(int argc, char **argv)
921949
zfs_close(zhp);
922950
error_open:
923951
nvlist_free(props);
952+
nvlist_free(props_parents);
924953
return (!!ret);
925954

926955
usage:
927956
ASSERT0P(zhp);
928957
nvlist_free(props);
958+
nvlist_free(props_parents);
929959
usage(B_FALSE);
930960
return (-1);
931961
}
@@ -1059,6 +1089,7 @@ default_volblocksize(zpool_handle_t *zhp, nvlist_t *props)
10591089
* SPA_VERSION_REFRESERVATION, we set a refreservation instead.
10601090
*
10611091
* The '-p' flag creates all the non-existing ancestors of the target first.
1092+
* If repeated twice, the ancestors are created with `canmount=off`.
10621093
*
10631094
* The '-n' flag is no-op (dry run) mode. This will perform a user-space sanity
10641095
* check of arguments and properties, but does not check for permissions,
@@ -1081,12 +1112,14 @@ zfs_do_create(int argc, char **argv)
10811112
boolean_t noreserve = B_FALSE;
10821113
boolean_t bflag = B_FALSE;
10831114
boolean_t parents = B_FALSE;
1115+
boolean_t parents_nomount = B_FALSE;
10841116
boolean_t dryrun = B_FALSE;
10851117
boolean_t nomount = B_FALSE;
10861118
boolean_t verbose = B_FALSE;
10871119
boolean_t parseable = B_FALSE;
10881120
int ret = 1;
10891121
nvlist_t *props;
1122+
nvlist_t *props_parents = NULL;
10901123
uint64_t intval;
10911124
const char *strval;
10921125

@@ -1115,7 +1148,10 @@ zfs_do_create(int argc, char **argv)
11151148
parseable = B_TRUE;
11161149
break;
11171150
case 'p':
1118-
parents = B_TRUE;
1151+
if (!parents)
1152+
parents = B_TRUE;
1153+
else
1154+
parents_nomount = B_TRUE;
11191155
break;
11201156
case 'b':
11211157
bflag = B_TRUE;
@@ -1265,6 +1301,8 @@ zfs_do_create(int argc, char **argv)
12651301
}
12661302

12671303
if (parents && zfs_name_valid(argv[0], type)) {
1304+
makeprops_parents(&props_parents, parents_nomount);
1305+
12681306
/*
12691307
* Now create the ancestors of target dataset. If the target
12701308
* already exists and '-p' option was used we should not
@@ -1280,7 +1318,8 @@ zfs_do_create(int argc, char **argv)
12801318
"create ancestors of %s\n", argv[0]);
12811319
}
12821320
if (!dryrun) {
1283-
if (zfs_create_ancestors(g_zfs, argv[0]) != 0) {
1321+
if (zfs_create_ancestors(g_zfs, argv[0],
1322+
props_parents) != 0) {
12841323
goto error;
12851324
}
12861325
}
@@ -1339,9 +1378,11 @@ zfs_do_create(int argc, char **argv)
13391378
(void) zfs_mount_and_share(g_zfs, argv[0], ZFS_TYPE_DATASET);
13401379
error:
13411380
nvlist_free(props);
1381+
nvlist_free(props_parents);
13421382
return (ret);
13431383
badusage:
13441384
nvlist_free(props);
1385+
nvlist_free(props_parents);
13451386
usage(B_FALSE);
13461387
return (2);
13471388
}
@@ -4036,6 +4077,8 @@ found3:;
40364077
* Renames the given dataset to another of the same type.
40374078
*
40384079
* The '-p' flag creates all the non-existing ancestors of the target first.
4080+
* If repeated twice, the ancestors are created with `canmount=off`.
4081+
*
40394082
* The '-u' flag prevents file systems from being remounted during rename.
40404083
*/
40414084
static int
@@ -4047,12 +4090,17 @@ zfs_do_rename(int argc, char **argv)
40474090
int ret = 1;
40484091
int types;
40494092
boolean_t parents = B_FALSE;
4093+
boolean_t parents_nomount = B_FALSE;
4094+
nvlist_t *props_parents = NULL;
40504095

40514096
/* check options */
40524097
while ((c = getopt(argc, argv, "pruf")) != -1) {
40534098
switch (c) {
40544099
case 'p':
4055-
parents = B_TRUE;
4100+
if (parents)
4101+
parents_nomount = B_TRUE;
4102+
else
4103+
parents = B_TRUE;
40564104
break;
40574105
case 'r':
40584106
flags.recursive = B_TRUE;
@@ -4119,16 +4167,21 @@ zfs_do_rename(int argc, char **argv)
41194167
goto error_open;
41204168

41214169
/* If we were asked and the name looks good, try to create ancestors. */
4122-
if (parents && zfs_name_valid(argv[1], zfs_get_type(zhp)) &&
4123-
zfs_create_ancestors(g_zfs, argv[1]) != 0) {
4124-
goto error;
4170+
if (parents && zfs_name_valid(argv[1], zfs_get_type(zhp))) {
4171+
4172+
makeprops_parents(&props_parents, parents_nomount);
4173+
if (zfs_create_ancestors(g_zfs, argv[1],
4174+
props_parents) != 0) {
4175+
goto error;
4176+
}
41254177
}
41264178

41274179
ret = (zfs_rename(zhp, argv[1], flags) != 0);
41284180

41294181
error:
41304182
zfs_close(zhp);
41314183
error_open:
4184+
nvlist_free(props_parents);
41324185
return (ret);
41334186
}
41344187

man/man8/zfs-clone.8

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ Creates all the non-existing parent datasets.
6262
Datasets created in this manner are automatically mounted according to the
6363
.Sy mountpoint
6464
property inherited from their parent.
65+
If the
66+
.Fl p
67+
option is specified multiple times, parent datasets are created with
68+
.Sy canmount Ns = Ns Ar off .
6569
If the target filesystem or volume already exists, the operation completes
6670
successfully.
6771
.El

man/man8/zfs-create.8

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ property inherited from their parent.
8585
Any property specified on the command line using the
8686
.Fl o
8787
option is ignored.
88+
If the
89+
.Fl p
90+
option is specified multiple times, parent datasets are created with
91+
.Sy canmount Ns = Ns Ar off .
8892
If the target filesystem already exists, the operation completes successfully.
8993
.It Fl n
9094
Do a dry-run
@@ -177,6 +181,10 @@ property inherited from their parent.
177181
Any property specified on the command line using the
178182
.Fl o
179183
option is ignored.
184+
If the
185+
.Fl p
186+
option is specified multiple times, parent datasets are created with
187+
.Sy canmount Ns = Ns Ar off .
180188
If the target filesystem already exists, the operation completes successfully.
181189
.It Fl s
182190
Creates a sparse volume with no reservation.

man/man8/zfs-rename.8

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ Creates all the nonexistent parent datasets.
103103
Datasets created in this manner are automatically mounted according to the
104104
.Sy mountpoint
105105
property inherited from their parent.
106+
Alernatively, if the
107+
.Fl p
108+
option is specified multiple times, parent datasets are created with
109+
.Sy canmount Ns = Ns Ar off .
106110
.It Fl u
107111
Do not remount file systems during rename.
108112
If a file system's

0 commit comments

Comments
 (0)