mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-04-13 07:01:46 +03:00
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`.
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Rob Norris <robn@despairlabs.com>
Signed-off-by: Ivan Shapovalov <intelfx@intelfx.name>
Closes #17000
This commit is contained in:
parent
2f3f1ab1ba
commit
8531621aba
@ -292,12 +292,13 @@ get_usage(zfs_help_t idx)
|
||||
{
|
||||
switch (idx) {
|
||||
case HELP_CLONE:
|
||||
return (gettext("\tclone [-pu] [-o property=value] ... "
|
||||
return (gettext("\tclone [-p[p]u] [-o property=value] ... "
|
||||
"<snapshot> <filesystem|volume>\n"));
|
||||
case HELP_CREATE:
|
||||
return (gettext("\tcreate [-Pnpuv] [-o property=value] ... "
|
||||
return (gettext("\tcreate [-Pnp[p]uv] [-o property=value] ... "
|
||||
"<filesystem>\n"
|
||||
"\tcreate [-Pnpsv] [-b blocksize] [-o property=value] ... "
|
||||
"\tcreate [-Pnp[p]sv] [-b blocksize] "
|
||||
"[-o property=value] ... "
|
||||
"-V <size> <volume>\n"));
|
||||
case HELP_DESTROY:
|
||||
return (gettext("\tdestroy [-fnpRrv] <filesystem|volume>\n"
|
||||
@ -338,7 +339,8 @@ get_usage(zfs_help_t idx)
|
||||
case HELP_RENAME:
|
||||
return (gettext("\trename [-f] <filesystem|volume|snapshot> "
|
||||
"<filesystem|volume|snapshot>\n"
|
||||
"\trename -p [-f] <filesystem|volume> <filesystem|volume>\n"
|
||||
"\trename -p[p] [-f] <filesystem|volume> "
|
||||
"<filesystem|volume>\n"
|
||||
"\trename -u [-f] <filesystem> <filesystem>\n"
|
||||
"\trename -r <snapshot> <snapshot>\n"));
|
||||
case HELP_ROLLBACK:
|
||||
@ -766,6 +768,26 @@ finish_progress(const char *done)
|
||||
pt_header = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
makeprops_parents(nvlist_t **ptr, boolean_t parents_nomount)
|
||||
{
|
||||
nvlist_t *props = NULL;
|
||||
|
||||
if (parents_nomount) {
|
||||
if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
|
||||
nomem();
|
||||
|
||||
if (nvlist_add_string(props,
|
||||
zfs_prop_to_name(ZFS_PROP_CANMOUNT),
|
||||
"off") != 0) {
|
||||
nvlist_free(props);
|
||||
nomem();
|
||||
}
|
||||
}
|
||||
|
||||
*ptr = props;
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_mount_and_share(libzfs_handle_t *hdl, const char *dataset, zfs_type_t type)
|
||||
{
|
||||
@ -826,6 +848,7 @@ zfs_mount_and_share(libzfs_handle_t *hdl, const char *dataset, zfs_type_t type)
|
||||
* the clone exists.
|
||||
*
|
||||
* The '-p' flag creates all the non-existing ancestors of the target first.
|
||||
* If repeated twice, the ancestors are created with `canmount=off`.
|
||||
*
|
||||
* The '-u' flag prevents the newly created file system from being mounted.
|
||||
*/
|
||||
@ -834,8 +857,10 @@ zfs_do_clone(int argc, char **argv)
|
||||
{
|
||||
zfs_handle_t *zhp = NULL;
|
||||
boolean_t parents = B_FALSE;
|
||||
boolean_t parents_nomount = B_FALSE;
|
||||
boolean_t nomount = B_FALSE;
|
||||
nvlist_t *props;
|
||||
nvlist_t *props_parents = NULL;
|
||||
int ret = 1;
|
||||
int c;
|
||||
|
||||
@ -852,7 +877,10 @@ zfs_do_clone(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
parents = B_TRUE;
|
||||
if (!parents)
|
||||
parents = B_TRUE;
|
||||
else
|
||||
parents_nomount = B_TRUE;
|
||||
break;
|
||||
case 'u':
|
||||
nomount = B_TRUE;
|
||||
@ -900,9 +928,11 @@ zfs_do_clone(int argc, char **argv)
|
||||
ret = 0;
|
||||
goto error;
|
||||
}
|
||||
if (zfs_create_ancestors(g_zfs, argv[1]) != 0) {
|
||||
|
||||
makeprops_parents(&props_parents, parents_nomount);
|
||||
if (zfs_create_ancestors_props(g_zfs, argv[1],
|
||||
props_parents) != 0)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* pass to libzfs */
|
||||
@ -930,11 +960,13 @@ error:
|
||||
zfs_close(zhp);
|
||||
error_open:
|
||||
nvlist_free(props);
|
||||
nvlist_free(props_parents);
|
||||
return (!!ret);
|
||||
|
||||
usage:
|
||||
ASSERT0P(zhp);
|
||||
nvlist_free(props);
|
||||
nvlist_free(props_parents);
|
||||
usage(B_FALSE);
|
||||
return (-1);
|
||||
}
|
||||
@ -1068,6 +1100,7 @@ default_volblocksize(zpool_handle_t *zhp, nvlist_t *props)
|
||||
* SPA_VERSION_REFRESERVATION, we set a refreservation instead.
|
||||
*
|
||||
* The '-p' flag creates all the non-existing ancestors of the target first.
|
||||
* If repeated twice, the ancestors are created with `canmount=off`.
|
||||
*
|
||||
* The '-n' flag is no-op (dry run) mode. This will perform a user-space sanity
|
||||
* check of arguments and properties, but does not check for permissions,
|
||||
@ -1090,12 +1123,14 @@ zfs_do_create(int argc, char **argv)
|
||||
boolean_t noreserve = B_FALSE;
|
||||
boolean_t bflag = B_FALSE;
|
||||
boolean_t parents = B_FALSE;
|
||||
boolean_t parents_nomount = B_FALSE;
|
||||
boolean_t dryrun = B_FALSE;
|
||||
boolean_t nomount = B_FALSE;
|
||||
boolean_t verbose = B_FALSE;
|
||||
boolean_t parseable = B_FALSE;
|
||||
int ret = 1;
|
||||
nvlist_t *props;
|
||||
nvlist_t *props_parents = NULL;
|
||||
uint64_t intval;
|
||||
const char *strval;
|
||||
|
||||
@ -1124,7 +1159,10 @@ zfs_do_create(int argc, char **argv)
|
||||
parseable = B_TRUE;
|
||||
break;
|
||||
case 'p':
|
||||
parents = B_TRUE;
|
||||
if (!parents)
|
||||
parents = B_TRUE;
|
||||
else
|
||||
parents_nomount = B_TRUE;
|
||||
break;
|
||||
case 'b':
|
||||
bflag = B_TRUE;
|
||||
@ -1274,6 +1312,8 @@ zfs_do_create(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (parents && zfs_name_valid(argv[0], type)) {
|
||||
makeprops_parents(&props_parents, parents_nomount);
|
||||
|
||||
/*
|
||||
* Now create the ancestors of target dataset. If the target
|
||||
* already exists and '-p' option was used we should not
|
||||
@ -1289,7 +1329,8 @@ zfs_do_create(int argc, char **argv)
|
||||
"create ancestors of %s\n", argv[0]);
|
||||
}
|
||||
if (!dryrun) {
|
||||
if (zfs_create_ancestors(g_zfs, argv[0]) != 0) {
|
||||
if (zfs_create_ancestors_props(g_zfs, argv[0],
|
||||
props_parents) != 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@ -1348,9 +1389,11 @@ zfs_do_create(int argc, char **argv)
|
||||
(void) zfs_mount_and_share(g_zfs, argv[0], ZFS_TYPE_DATASET);
|
||||
error:
|
||||
nvlist_free(props);
|
||||
nvlist_free(props_parents);
|
||||
return (ret);
|
||||
badusage:
|
||||
nvlist_free(props);
|
||||
nvlist_free(props_parents);
|
||||
usage(B_FALSE);
|
||||
return (2);
|
||||
}
|
||||
@ -4039,6 +4082,8 @@ found3:;
|
||||
* Renames the given dataset to another of the same type.
|
||||
*
|
||||
* The '-p' flag creates all the non-existing ancestors of the target first.
|
||||
* If repeated twice, the ancestors are created with `canmount=off`.
|
||||
*
|
||||
* The '-u' flag prevents file systems from being remounted during rename.
|
||||
*/
|
||||
static int
|
||||
@ -4050,12 +4095,17 @@ zfs_do_rename(int argc, char **argv)
|
||||
int ret = 1;
|
||||
int types;
|
||||
boolean_t parents = B_FALSE;
|
||||
boolean_t parents_nomount = B_FALSE;
|
||||
nvlist_t *props_parents = NULL;
|
||||
|
||||
/* check options */
|
||||
while ((c = getopt(argc, argv, "pruf")) != -1) {
|
||||
switch (c) {
|
||||
case 'p':
|
||||
parents = B_TRUE;
|
||||
if (parents)
|
||||
parents_nomount = B_TRUE;
|
||||
else
|
||||
parents = B_TRUE;
|
||||
break;
|
||||
case 'r':
|
||||
flags.recursive = B_TRUE;
|
||||
@ -4122,9 +4172,13 @@ zfs_do_rename(int argc, char **argv)
|
||||
goto error_open;
|
||||
|
||||
/* If we were asked and the name looks good, try to create ancestors. */
|
||||
if (parents && zfs_name_valid(argv[1], zfs_get_type(zhp)) &&
|
||||
zfs_create_ancestors(g_zfs, argv[1]) != 0) {
|
||||
goto error;
|
||||
if (parents && zfs_name_valid(argv[1], zfs_get_type(zhp))) {
|
||||
|
||||
makeprops_parents(&props_parents, parents_nomount);
|
||||
if (zfs_create_ancestors_props(g_zfs, argv[1],
|
||||
props_parents) != 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
ret = (zfs_rename(zhp, argv[1], flags) != 0);
|
||||
@ -4132,6 +4186,7 @@ zfs_do_rename(int argc, char **argv)
|
||||
error:
|
||||
zfs_close(zhp);
|
||||
error_open:
|
||||
nvlist_free(props_parents);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
@ -3657,7 +3657,7 @@ ancestorerr:
|
||||
int
|
||||
zfs_create_ancestors(libzfs_handle_t *hdl, const char *path)
|
||||
{
|
||||
return zfs_create_ancestors_props(hdl, path, NULL);
|
||||
return (zfs_create_ancestors_props(hdl, path, NULL));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -62,6 +62,10 @@ Creates all the non-existing parent datasets.
|
||||
Datasets created in this manner are automatically mounted according to the
|
||||
.Sy mountpoint
|
||||
property inherited from their parent.
|
||||
If the
|
||||
.Fl p
|
||||
option is specified multiple times, parent datasets are created with
|
||||
.Sy canmount Ns = Ns Ar off .
|
||||
If the target filesystem or volume already exists, the operation completes
|
||||
successfully.
|
||||
.It Fl u
|
||||
|
||||
@ -85,6 +85,10 @@ property inherited from their parent.
|
||||
Any property specified on the command line using the
|
||||
.Fl o
|
||||
option is ignored.
|
||||
If the
|
||||
.Fl p
|
||||
option is specified multiple times, parent datasets are created with
|
||||
.Sy canmount Ns = Ns Ar off .
|
||||
If the target filesystem already exists, the operation completes successfully.
|
||||
.It Fl n
|
||||
Do a dry-run
|
||||
@ -177,6 +181,10 @@ property inherited from their parent.
|
||||
Any property specified on the command line using the
|
||||
.Fl o
|
||||
option is ignored.
|
||||
If the
|
||||
.Fl p
|
||||
option is specified multiple times, parent datasets are created with
|
||||
.Sy canmount Ns = Ns Ar off .
|
||||
If the target filesystem already exists, the operation completes successfully.
|
||||
.It Fl s
|
||||
Creates a sparse volume with no reservation.
|
||||
|
||||
@ -103,6 +103,10 @@ Creates all the non-existing parent datasets.
|
||||
Datasets created in this manner are automatically mounted according to the
|
||||
.Sy mountpoint
|
||||
property inherited from their parent.
|
||||
Alernatively, if the
|
||||
.Fl p
|
||||
option is specified multiple times, parent datasets are created with
|
||||
.Sy canmount Ns = Ns Ar off .
|
||||
.It Fl u
|
||||
Do not remount file systems during rename.
|
||||
If a file system's
|
||||
|
||||
@ -196,8 +196,8 @@ tags = ['functional', 'cli_root', 'zfs_change-key']
|
||||
tests = ['zfs_clone_001_neg', 'zfs_clone_002_pos', 'zfs_clone_003_pos',
|
||||
'zfs_clone_004_pos', 'zfs_clone_005_pos', 'zfs_clone_006_pos',
|
||||
'zfs_clone_007_pos', 'zfs_clone_008_neg', 'zfs_clone_009_neg',
|
||||
'zfs_clone_010_pos', 'zfs_clone_encrypted', 'zfs_clone_deeply_nested',
|
||||
'zfs_clone_rm_nested', 'zfs_clone_nomount']
|
||||
'zfs_clone_010_pos', 'zfs_clone_011_pos', 'zfs_clone_encrypted',
|
||||
'zfs_clone_deeply_nested', 'zfs_clone_rm_nested', 'zfs_clone_nomount']
|
||||
tags = ['functional', 'cli_root', 'zfs_clone']
|
||||
|
||||
[tests/functional/cli_root/zfs_copies]
|
||||
@ -210,9 +210,9 @@ tests = ['zfs_create_001_pos', 'zfs_create_002_pos', 'zfs_create_003_pos',
|
||||
'zfs_create_004_pos', 'zfs_create_005_pos', 'zfs_create_006_pos',
|
||||
'zfs_create_007_pos', 'zfs_create_008_neg', 'zfs_create_009_neg',
|
||||
'zfs_create_010_neg', 'zfs_create_011_pos', 'zfs_create_012_pos',
|
||||
'zfs_create_013_pos', 'zfs_create_014_pos', 'zfs_create_encrypted',
|
||||
'zfs_create_crypt_combos', 'zfs_create_dryrun', 'zfs_create_nomount',
|
||||
'zfs_create_verbose']
|
||||
'zfs_create_013_pos', 'zfs_create_014_pos', 'zfs_create_015_pos',
|
||||
'zfs_create_encrypted', 'zfs_create_crypt_combos', 'zfs_create_dryrun',
|
||||
'zfs_create_nomount', 'zfs_create_verbose']
|
||||
tags = ['functional', 'cli_root', 'zfs_create']
|
||||
|
||||
[tests/functional/cli_root/zpool_prefetch]
|
||||
@ -300,8 +300,9 @@ tests = ['zfs_rename_001_pos', 'zfs_rename_002_pos', 'zfs_rename_003_pos',
|
||||
'zfs_rename_004_neg', 'zfs_rename_005_neg', 'zfs_rename_006_pos',
|
||||
'zfs_rename_007_pos', 'zfs_rename_008_pos', 'zfs_rename_009_neg',
|
||||
'zfs_rename_010_neg', 'zfs_rename_011_pos', 'zfs_rename_012_neg',
|
||||
'zfs_rename_013_pos', 'zfs_rename_014_neg', 'zfs_rename_encrypted_child',
|
||||
'zfs_rename_to_encrypted', 'zfs_rename_mountpoint', 'zfs_rename_nounmount']
|
||||
'zfs_rename_013_pos', 'zfs_rename_014_neg', 'zfs_rename_015_pos',
|
||||
'zfs_rename_encrypted_child', 'zfs_rename_to_encrypted', 'zfs_rename_mountpoint',
|
||||
'zfs_rename_nounmount']
|
||||
tags = ['functional', 'cli_root', 'zfs_rename']
|
||||
|
||||
[tests/functional/cli_root/zfs_reservation]
|
||||
|
||||
@ -1171,6 +1171,22 @@ function datasetnonexists
|
||||
return 0
|
||||
}
|
||||
|
||||
# Check if the specified dataset property has the expected value or fail
|
||||
function dataset_has_prop # property expected_value dataset
|
||||
{
|
||||
typeset prop=$1
|
||||
typeset expected=$2
|
||||
typeset dataset=$3
|
||||
|
||||
typeset value=""
|
||||
|
||||
value="$(get_prop "$prop" "$dataset")"
|
||||
[[ "$value" == "$expected" ]] || {
|
||||
log_note "dataset $dataset: property $prop == $value (!= $expected)"
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
# FreeBSD breaks exports(5) at whitespace and doesn't process escapes
|
||||
# Solaris just breaks
|
||||
#
|
||||
@ -2629,11 +2645,16 @@ function verify_opt_p_ops
|
||||
typeset datatype=$2
|
||||
typeset dataset=$3
|
||||
typeset newdataset=$4
|
||||
typeset popt=$5
|
||||
|
||||
if [[ $datatype != "fs" && $datatype != "vol" ]]; then
|
||||
log_fail "$datatype is not supported."
|
||||
fi
|
||||
|
||||
if [[ -z "$popt" ]]; then
|
||||
popt=-p
|
||||
fi
|
||||
|
||||
# check parameters accordingly
|
||||
case $ops in
|
||||
create)
|
||||
@ -2671,7 +2692,7 @@ function verify_opt_p_ops
|
||||
log_mustnot datasetexists $newdataset ${newdataset%/*}
|
||||
|
||||
# with -p option, operation should succeed
|
||||
log_must zfs $ops -p $dataset $newdataset
|
||||
log_must zfs $ops $popt $dataset $newdataset
|
||||
block_device_wait
|
||||
|
||||
if ! datasetexists $newdataset ; then
|
||||
@ -2680,7 +2701,7 @@ function verify_opt_p_ops
|
||||
|
||||
# when $ops is create or clone, redo the operation still return zero
|
||||
if [[ $ops != "rename" ]]; then
|
||||
log_must zfs $ops -p $dataset $newdataset
|
||||
log_must zfs $ops $popt $dataset $newdataset
|
||||
fi
|
||||
|
||||
return 0
|
||||
|
||||
@ -677,6 +677,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
|
||||
functional/cli_root/zfs_clone/zfs_clone_008_neg.ksh \
|
||||
functional/cli_root/zfs_clone/zfs_clone_009_neg.ksh \
|
||||
functional/cli_root/zfs_clone/zfs_clone_010_pos.ksh \
|
||||
functional/cli_root/zfs_clone/zfs_clone_011_pos.ksh \
|
||||
functional/cli_root/zfs_clone/zfs_clone_deeply_nested.ksh \
|
||||
functional/cli_root/zfs_clone/zfs_clone_encrypted.ksh \
|
||||
functional/cli_root/zfs_clone/zfs_clone_nomount.ksh \
|
||||
@ -705,6 +706,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
|
||||
functional/cli_root/zfs_create/zfs_create_012_pos.ksh \
|
||||
functional/cli_root/zfs_create/zfs_create_013_pos.ksh \
|
||||
functional/cli_root/zfs_create/zfs_create_014_pos.ksh \
|
||||
functional/cli_root/zfs_create/zfs_create_015_pos.ksh \
|
||||
functional/cli_root/zfs_create/zfs_create_crypt_combos.ksh \
|
||||
functional/cli_root/zfs_create/zfs_create_dryrun.ksh \
|
||||
functional/cli_root/zfs_create/zfs_create_encrypted.ksh \
|
||||
@ -864,6 +866,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
|
||||
functional/cli_root/zfs_rename/zfs_rename_012_neg.ksh \
|
||||
functional/cli_root/zfs_rename/zfs_rename_013_pos.ksh \
|
||||
functional/cli_root/zfs_rename/zfs_rename_014_neg.ksh \
|
||||
functional/cli_root/zfs_rename/zfs_rename_015_pos.ksh \
|
||||
functional/cli_root/zfs_rename/zfs_rename_encrypted_child.ksh \
|
||||
functional/cli_root/zfs_rename/zfs_rename_mountpoint.ksh \
|
||||
functional/cli_root/zfs_rename/zfs_rename_nounmount.ksh \
|
||||
|
||||
94
tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_011_pos.ksh
Executable file
94
tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_011_pos.ksh
Executable file
@ -0,0 +1,94 @@
|
||||
#!/bin/ksh -p
|
||||
# SPDX-License-Identifier: CDDL-1.0
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2026 Ivan Shapovalov <intelfx@intelfx.name>
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# `zfs clone -pp` should create the parent of the new filesystem with `canmount=off`.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Prepare snapshots
|
||||
# 2. Make sure the parent of the clone target does not exist
|
||||
# 3. Make sure that `zfs clone -pp` works the same as `-p`
|
||||
# 4. Make sure that the newly created parent has `canmount=off`
|
||||
#
|
||||
|
||||
verify_runnable "both"
|
||||
|
||||
function setup
|
||||
{
|
||||
log_note "Create snapshots and mount them..."
|
||||
|
||||
for snap in $SNAPFS $SNAPFS1 ; do
|
||||
if ! snapexists "$snap" ; then
|
||||
log_must zfs snapshot "$snap"
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
function cleanup
|
||||
{
|
||||
|
||||
datasetexists "$TESTPOOL/notexist" && destroy_dataset "$TESTPOOL/notexist" -rRf
|
||||
|
||||
for snap in $SNAPFS $SNAPFS1 ; do
|
||||
snapexists "$snap" && destroy_dataset "$snap" -Rf
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
log_assert "'zfs clone -pp' should work as expected."
|
||||
|
||||
setup
|
||||
|
||||
log_mustnot datasetexists "$TESTPOOL/notexist"
|
||||
log_mustnot datasetexists "$TESTPOOL/notexist/new"
|
||||
log_mustnot datasetexists "$TESTPOOL/notexist/new2"
|
||||
|
||||
log_must verify_opt_p_ops "clone" "fs" "$SNAPFS" \
|
||||
"$TESTPOOL/notexist/new/clonefs$$" "-pp"
|
||||
|
||||
log_must dataset_has_prop canmount off "$TESTPOOL/notexist"
|
||||
log_must dataset_has_prop canmount off "$TESTPOOL/notexist/new"
|
||||
log_mustnot ismounted "$TESTPOOL/notexist"
|
||||
log_mustnot ismounted "$TESTPOOL/notexist/new"
|
||||
|
||||
if is_global_zone ; then
|
||||
log_must verify_opt_p_ops "clone" "vol" "$SNAPFS1" \
|
||||
"$TESTPOOL/notexist/new2/clonevol$$" "-pp"
|
||||
|
||||
log_must dataset_has_prop canmount off "$TESTPOOL/notexist/new2"
|
||||
log_mustnot ismounted "$TESTPOOL/notexist/new2"
|
||||
fi
|
||||
|
||||
log_pass "'zfs clone -pp' works as expected."
|
||||
74
tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_015_pos.ksh
Executable file
74
tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_015_pos.ksh
Executable file
@ -0,0 +1,74 @@
|
||||
#!/bin/ksh -p
|
||||
# SPDX-License-Identifier: CDDL-1.0
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2026 Ivan Shapovalov <intelfx@intelfx.name>
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# `zfs create -pp` should create the parent of the new filesystem with `canmount=off`.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Make sure the parent of the dataset to be created does not exist
|
||||
# 2. Make sure that `zfs create -pp` works the same as `-p`
|
||||
# 3. Make sure that the newly created parent has `canmount=off`
|
||||
|
||||
verify_runnable "both"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
datasetexists "$TESTPOOL/notexist" && \
|
||||
destroy_dataset "$TESTPOOL/notexist" -rRf
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
log_assert "'zfs create -p' should work as expected."
|
||||
|
||||
log_mustnot datasetexists "$TESTPOOL/notexist"
|
||||
log_mustnot datasetexists "$TESTPOOL/notexist/new"
|
||||
log_mustnot datasetexists "$TESTPOOL/notexist/new2"
|
||||
|
||||
log_must verify_opt_p_ops "create" "fs" \
|
||||
"$TESTPOOL/notexist/new/create$$" "" "-pp"
|
||||
|
||||
log_must dataset_has_prop canmount off "$TESTPOOL/notexist"
|
||||
log_must dataset_has_prop canmount off "$TESTPOOL/notexist/new"
|
||||
log_mustnot ismounted "$TESTPOOL/notexist"
|
||||
log_mustnot ismounted "$TESTPOOL/notexist/new"
|
||||
|
||||
# verify volume creation
|
||||
if is_global_zone; then
|
||||
log_must verify_opt_p_ops "create" "vol" \
|
||||
"$TESTPOOL/notexist/new2/volume$$" "" "-pp"
|
||||
|
||||
log_must dataset_has_prop canmount off "$TESTPOOL/notexist/new2"
|
||||
log_mustnot ismounted "$TESTPOOL/notexist/new2"
|
||||
fi
|
||||
|
||||
log_pass "'zfs create -p' works as expected."
|
||||
86
tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_015_pos.ksh
Executable file
86
tests/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_015_pos.ksh
Executable file
@ -0,0 +1,86 @@
|
||||
#!/bin/ksh -p
|
||||
# SPDX-License-Identifier: CDDL-1.0
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2026 Ivan Shapovalov <intelfx@intelfx.name>
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# DESCRIPTION
|
||||
# `zfs rename -pp` should create the parent of the new filesystem with `canmount=off`.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Make sure the parent of the rename target does not exist
|
||||
# 2. Make sure that `zfs rename -pp` works the same as `-p`
|
||||
# 3. Make sure that the newly created parent has `canmount=off`
|
||||
#
|
||||
|
||||
verify_runnable "both"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
datasetexists "$TESTPOOL/notexist" && \
|
||||
destroy_dataset "$TESTPOOL/notexist" -Rf
|
||||
|
||||
datasetexists "$TESTPOOL/$TESTFS" && \
|
||||
destroy_dataset "$TESTPOOL/$TESTFS" -Rf
|
||||
|
||||
log_must zfs create "$TESTPOOL/$TESTFS"
|
||||
|
||||
if is_global_zone ; then
|
||||
datasetexists "$TESTPOOL/$TESTVOL" && \
|
||||
destroy_dataset "$TESTPOOL/$TESTVOL" -Rf
|
||||
|
||||
log_must zfs create -V "$VOLSIZE" "$TESTPOOL/$TESTVOL"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
log_assert "'zfs rename -pp' should work as expected."
|
||||
|
||||
log_must_not datasetexists "$TESTPOOL/notexist"
|
||||
log_must_not datasetexists "$TESTPOOL/notexist/new"
|
||||
log_must_not datasetexists "$TESTPOOL/notexist/new2"
|
||||
|
||||
log_must verify_opt_p_ops "rename" "fs" "$TESTPOOL/$TESTFS" \
|
||||
"$TESTPOOL/notexist/new/$TESTFS1" "-pp"
|
||||
|
||||
log_must dataset_has_prop canmount off "$TESTPOOL/notexist"
|
||||
log_must dataset_has_prop canmount off "$TESTPOOL/notexist/new"
|
||||
log_mustnot ismounted "$TESTPOOL/notexist"
|
||||
log_mustnot ismounted "$TESTPOOL/notexist/new"
|
||||
|
||||
if is_global_zone; then
|
||||
log_must verify_opt_p_ops "rename" "vol" "$TESTPOOL/$TESTVOL" \
|
||||
"$TESTPOOL/notexist/new2/$TESTVOL1" "-pp"
|
||||
|
||||
log_must dataset_has_prop canmount off "$TESTPOOL/notexist/new2"
|
||||
log_mustnot ismounted "$TESTPOOL/notexist/new2"
|
||||
fi
|
||||
|
||||
log_pass "'zfs rename -pp' works as expected."
|
||||
Loading…
Reference in New Issue
Block a user