mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2025-02-08 16:23:22 +03:00
4a21ec0560
The delegate tests use `date(1)` to generate snapshot names, using the format '%F-%T-%N' to get nanosecond resolution (since multiple snapshots may be taken in the same second). '%N' is not portable, and causes tests to fail on FreeBSD. Since the only purpose these timestamps serve is to create a unique name, simply use $RANDOM instead. Reviewed-by: John Kennedy <john.kennedy@delphix.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Ryan Moeller <ryan@iXsystems.com> Closes #10170
1714 lines
34 KiB
Plaintext
1714 lines
34 KiB
Plaintext
#
|
|
# 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 http://www.opensolaris.org/os/licensing.
|
|
# 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 2008 Sun Microsystems, Inc. All rights reserved.
|
|
# Use is subject to license terms.
|
|
#
|
|
|
|
#
|
|
# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
|
|
# Copyright 2016 Nexenta Systems, Inc.
|
|
# Copyright (c) 2018 George Melikov. All Rights Reserved.
|
|
#
|
|
|
|
. $STF_SUITE/include/libtest.shlib
|
|
. $STF_SUITE/tests/functional/delegate/delegate.cfg
|
|
|
|
#
|
|
# Cleanup exist user/group.
|
|
#
|
|
function cleanup_user_group
|
|
{
|
|
typeset i
|
|
for i in $STAFF1 $STAFF2 $OTHER1 $OTHER2 ; do
|
|
del_user $i
|
|
done
|
|
for i in $STAFF_GROUP $OTHER_GROUP ; do
|
|
del_group $i
|
|
done
|
|
|
|
return 0
|
|
}
|
|
|
|
#
|
|
# Restore test file system to the original status.
|
|
#
|
|
function restore_root_datasets
|
|
{
|
|
destroy_dataset "$ROOT_TESTFS" "-Rf"
|
|
log_must zfs create $ROOT_TESTFS
|
|
|
|
if is_global_zone ; then
|
|
destroy_dataset "$ROOT_TESTVOL" "-Rf"
|
|
log_must zfs create -V $VOLSIZE $ROOT_TESTVOL
|
|
block_device_wait
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
#
|
|
# Verify the specified user have permission on the dataset
|
|
#
|
|
# $1 dataset
|
|
# $2 permissions which are separated by comma(,)
|
|
# $3-n users
|
|
#
|
|
function verify_perm
|
|
{
|
|
typeset dtst=$1
|
|
typeset permissions=$2
|
|
shift 2
|
|
|
|
if [[ -z $@ || -z $permissions || -z $dtst ]]; then
|
|
return 1
|
|
fi
|
|
|
|
typeset type=$(get_prop type $dtst)
|
|
permissions=$(echo $permissions | tr -s "," " ")
|
|
|
|
typeset user
|
|
for user in $@; do
|
|
typeset perm
|
|
for perm in $permissions; do
|
|
typeset -i ret=1
|
|
if [[ $type == "filesystem" ]]; then
|
|
check_fs_perm $user $perm $dtst
|
|
ret=$?
|
|
elif [[ $type == "volume" ]]; then
|
|
check_vol_perm $user $perm $dtst
|
|
ret=$?
|
|
fi
|
|
|
|
log_note "Check $type $user $perm $dtst"
|
|
if ((ret != 0)) ; then
|
|
log_note "Fail: $user should have $perm" \
|
|
"on $dtst"
|
|
return 1
|
|
fi
|
|
done
|
|
done
|
|
|
|
return 0
|
|
}
|
|
|
|
#
|
|
# Verify the specified user have no permission on the dataset
|
|
#
|
|
# $1 dataset
|
|
# $2 permissions which are separated by comma(,)
|
|
# $3-n users
|
|
#
|
|
function verify_noperm
|
|
{
|
|
typeset dtst=$1
|
|
typeset permissions=$2
|
|
shift 2
|
|
|
|
if [[ -z $@ || -z $permissions || -z $dtst ]]; then
|
|
return 1
|
|
fi
|
|
|
|
typeset type=$(get_prop type $dtst)
|
|
permissions=$(echo $permissions | tr -s "," " ")
|
|
|
|
typeset user
|
|
for user in $@; do
|
|
typeset perm
|
|
for perm in $permissions; do
|
|
typeset -i ret=1
|
|
if [[ $type == "filesystem" ]]; then
|
|
check_fs_perm $user $perm $dtst
|
|
ret=$?
|
|
elif [[ $type == "volume" ]]; then
|
|
check_vol_perm $user $perm $dtst
|
|
ret=$?
|
|
fi
|
|
|
|
if ((ret == 0)) ; then
|
|
log_note "Fail: $user should not have $perm " \
|
|
"on $dtst"
|
|
return 1
|
|
fi
|
|
done
|
|
done
|
|
|
|
return 0
|
|
}
|
|
|
|
function common_perm
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset dtst=$3
|
|
|
|
typeset -i ret=1
|
|
case $perm in
|
|
send)
|
|
verify_send $user $perm $dtst
|
|
ret=$?
|
|
;;
|
|
allow)
|
|
verify_allow $user $perm $dtst
|
|
ret=$?
|
|
;;
|
|
userprop)
|
|
verify_userprop $user $perm $dtst
|
|
ret=$?
|
|
;;
|
|
compression|checksum|readonly)
|
|
verify_ccr $user $perm $dtst
|
|
ret=$?
|
|
;;
|
|
copies)
|
|
verify_copies $user $perm $dtst
|
|
ret=$?
|
|
;;
|
|
reservation)
|
|
verify_reservation $user $perm $dtst
|
|
ret=$?
|
|
;;
|
|
*)
|
|
ret=1
|
|
;;
|
|
esac
|
|
|
|
return $ret
|
|
}
|
|
|
|
function check_fs_perm
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
typeset -i ret=1
|
|
case $perm in
|
|
create)
|
|
verify_fs_create $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
destroy)
|
|
verify_fs_destroy $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
snapshot)
|
|
verify_fs_snapshot $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
rollback)
|
|
verify_fs_rollback $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
clone)
|
|
verify_fs_clone $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
rename)
|
|
verify_fs_rename $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
mount)
|
|
verify_fs_mount $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
share)
|
|
verify_fs_share $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
mountpoint)
|
|
verify_fs_mountpoint $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
promote)
|
|
verify_fs_promote $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
canmount)
|
|
verify_fs_canmount $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
dnodesize)
|
|
verify_fs_dnodesize $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
recordsize)
|
|
verify_fs_recordsize $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
quota)
|
|
verify_fs_quota $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
aclmode)
|
|
verify_fs_aclmode $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
aclinherit)
|
|
verify_fs_aclinherit $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
snapdir)
|
|
verify_fs_snapdir $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
atime|exec|devices|setuid|xattr)
|
|
verify_fs_aedsx $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
zoned)
|
|
verify_fs_zoned $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
sharenfs)
|
|
verify_fs_sharenfs $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
receive)
|
|
verify_fs_receive $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
*)
|
|
common_perm $user $perm $fs
|
|
ret=$?
|
|
;;
|
|
esac
|
|
|
|
return $ret
|
|
}
|
|
|
|
function check_vol_perm
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset vol=$3
|
|
|
|
typeset -i ret=1
|
|
case $perm in
|
|
destroy)
|
|
verify_vol_destroy $user $perm $vol
|
|
ret=$?
|
|
;;
|
|
snapshot)
|
|
verify_vol_snapshot $user $perm $vol
|
|
ret=$?
|
|
;;
|
|
rollback)
|
|
verify_vol_rollback $user $perm $vol
|
|
ret=$?
|
|
;;
|
|
clone)
|
|
verify_vol_clone $user $perm $vol
|
|
ret=$?
|
|
;;
|
|
rename)
|
|
verify_vol_rename $user $perm $vol
|
|
ret=$?
|
|
;;
|
|
promote)
|
|
verify_vol_promote $user $perm $vol
|
|
ret=$?
|
|
;;
|
|
volsize)
|
|
verify_vol_volsize $user $perm $vol
|
|
ret=$?
|
|
;;
|
|
*)
|
|
common_perm $user $perm $vol
|
|
ret=$?
|
|
;;
|
|
esac
|
|
|
|
return $ret
|
|
}
|
|
|
|
function setup_unallow_testenv
|
|
{
|
|
log_must restore_root_datasets
|
|
|
|
log_must zfs create $SUBFS
|
|
|
|
for dtst in $DATASETS ; do
|
|
log_must zfs allow -l $STAFF1 $LOCAL_SET $dtst
|
|
log_must zfs allow -d $STAFF2 $DESC_SET $dtst
|
|
log_must zfs allow $OTHER1 $LOCAL_DESC_SET $dtst
|
|
log_must zfs allow $OTHER2 $LOCAL_DESC_SET $dtst
|
|
|
|
log_must verify_perm $dtst $LOCAL_SET $STAFF1
|
|
log_must verify_perm $dtst $LOCAL_DESC_SET $OTHER1
|
|
log_must verify_perm $dtst $LOCAL_DESC_SET $OTHER2
|
|
if [[ $dtst == $ROOT_TESTFS ]]; then
|
|
log_must verify_perm $SUBFS $DESC_SET $STAFF2
|
|
log_must verify_perm $SUBFS $LOCAL_DESC_SET $OTHER1
|
|
log_must verify_perm $SUBFS $LOCAL_DESC_SET $OTHER2
|
|
fi
|
|
done
|
|
|
|
return 0
|
|
}
|
|
|
|
#
|
|
# Verify permission send for specified user on the dataset
|
|
# $1 user
|
|
# $2 permission
|
|
# $3 dataset
|
|
#
|
|
function verify_send
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset dtst=$3
|
|
|
|
typeset oldval
|
|
typeset stamp=${perm}.${user}.$RANDOM
|
|
typeset snap=$dtst@snap.$stamp
|
|
|
|
typeset -i ret=1
|
|
|
|
log_must zfs snapshot $snap
|
|
typeset bak_user=$TEST_BASE_DIR/bak.$user.$stamp
|
|
typeset bak_root=$TEST_BASE_DIR/bak.root.$stamp
|
|
|
|
user_run $user eval "zfs send $snap > $bak_user"
|
|
log_must eval "zfs send $snap > $bak_root"
|
|
|
|
if [[ $(checksum $bak_user) == $(checksum $bak_root) ]]; then
|
|
ret=0
|
|
fi
|
|
|
|
rm -rf $bak_user > /dev/null
|
|
rm -rf $bak_root > /dev/null
|
|
|
|
return $ret
|
|
}
|
|
|
|
function verify_fs_receive
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
typeset dtst
|
|
typeset stamp=${perm}.${user}.$RANDOM
|
|
typeset newfs=$fs/newfs.$stamp
|
|
typeset newvol=$fs/newvol.$stamp
|
|
typeset bak_user=$TEST_BASE_DIR/bak.$user.$stamp
|
|
typeset bak_root=$TEST_BASE_DIR/bak.root.$stamp
|
|
|
|
log_must zfs create $newfs
|
|
typeset datasets="$newfs"
|
|
if is_global_zone ; then
|
|
log_must zfs create -V $VOLSIZE $newvol
|
|
block_device_wait
|
|
datasets="$newfs $newvol"
|
|
fi
|
|
|
|
for dtst in $datasets ; do
|
|
|
|
typeset dtstsnap=$dtst@snap.$stamp
|
|
log_must zfs snapshot $dtstsnap
|
|
|
|
log_must eval "zfs send $dtstsnap > $bak_root"
|
|
log_must_busy zfs destroy -rf $dtst
|
|
|
|
user_run $user eval "zfs receive $dtst < $bak_root"
|
|
if datasetexists $dtstsnap ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user create $fs
|
|
user_run $user eval "zfs receive $dtst < $bak_root"
|
|
log_must zfs unallow $user create $fs
|
|
if datasetexists $dtstsnap ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user mount $fs
|
|
user_run $user eval "zfs receive $dtst < $bak_root"
|
|
log_must zfs unallow $user mount $fs
|
|
if datasetexists $dtstsnap ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user mount,create $fs
|
|
user_run $user eval "zfs receive $dtst < $bak_root"
|
|
log_must zfs unallow $user mount,create $fs
|
|
if ! datasetexists $dtstsnap ; then
|
|
return 1
|
|
fi
|
|
|
|
# check the data integrity
|
|
log_must eval "zfs send $dtstsnap > $bak_user"
|
|
log_must_busy zfs destroy -rf $dtst
|
|
log_must eval "zfs receive $dtst < $bak_root"
|
|
log_must eval "zfs send $dtstsnap > $bak_root"
|
|
log_must_busy zfs destroy -rf $dtst
|
|
if [[ $(checksum $bak_user) != $(checksum $bak_root) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
rm -rf $bak_user > /dev/null
|
|
rm -rf $bak_root > /dev/null
|
|
|
|
done
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_userprop
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset dtst=$3
|
|
|
|
typeset stamp=${perm}.${user}.$RANDOM
|
|
|
|
user_run $user zfs set "$user:ts=$stamp" $dtst
|
|
zpool sync ${dtst%%/*}
|
|
if [[ $stamp != $(get_prop "$user:ts" $dtst) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_ccr
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset dtst=$3
|
|
|
|
typeset oldval
|
|
|
|
set -A modes "on" "off"
|
|
oldval=$(get_prop $perm $dtst)
|
|
if [[ $oldval == "on" ]]; then
|
|
n=1
|
|
elif [[ $oldval == "off" ]]; then
|
|
n=0
|
|
fi
|
|
log_note "$user zfs set $perm=${modes[$n]} $dtst"
|
|
user_run $user zfs set $perm=${modes[$n]} $dtst
|
|
if [[ ${modes[$n]} != $(get_prop $perm $dtst) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_copies
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset dtst=$3
|
|
|
|
typeset oldval
|
|
|
|
set -A modes 1 2 3
|
|
oldval=$(get_prop $perm $dtst)
|
|
if [[ $oldval -eq 1 ]]; then
|
|
n=1
|
|
elif [[ $oldval -eq 2 ]]; then
|
|
n=2
|
|
elif [[ $oldval -eq 3 ]]; then
|
|
n=0
|
|
fi
|
|
log_note "$user zfs set $perm=${modes[$n]} $dtst"
|
|
user_run $user zfs set $perm=${modes[$n]} $dtst
|
|
if [[ ${modes[$n]} != $(get_prop $perm $dtst) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_reservation
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset dtst=$3
|
|
|
|
typeset value32m=$(( 1024 * 1024 * 32 ))
|
|
typeset oldval=$(get_prop reservation $dtst)
|
|
user_run $user zfs set reservation=$value32m $dtst
|
|
if [[ $value32m != $(get_prop reservation $dtst) ]]; then
|
|
log_must zfs set reservation=$oldval $dtst
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs set reservation=$oldval $dtst
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_create
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
typeset stamp=${perm}.${user}.$RANDOM
|
|
typeset newfs=$fs/nfs.$stamp
|
|
typeset newvol=$fs/nvol.$stamp
|
|
|
|
user_run $user zfs create $newfs
|
|
if datasetexists $newfs ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user mount $fs
|
|
user_run $user zfs create $newfs
|
|
log_must zfs unallow $user mount $fs
|
|
if ! datasetexists $newfs ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs destroy $newfs
|
|
|
|
if is_global_zone ; then
|
|
# mount permission is required for sparse volume
|
|
user_run $user zfs create -V 150m -s $newvol
|
|
block_device_wait
|
|
if datasetexists $newvol ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user mount $fs
|
|
user_run $user zfs create -V 150m -s $newvol
|
|
log_must zfs unallow $user mount $fs
|
|
if ! datasetexists $newvol ; then
|
|
return 1
|
|
fi
|
|
|
|
block_device_wait
|
|
log_must zfs destroy $newvol
|
|
block_device_wait
|
|
|
|
# mount and reserveration permission are
|
|
# required for normal volume
|
|
user_run $user zfs create -V 150m $newvol
|
|
block_device_wait
|
|
if datasetexists $newvol ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user mount $fs
|
|
user_run $user zfs create -V 150m $newvol
|
|
block_device_wait
|
|
log_must zfs unallow $user mount $fs
|
|
if datasetexists $newvol ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user reservation $fs
|
|
user_run $user zfs create -V 150m $newvol
|
|
block_device_wait
|
|
log_must zfs unallow $user reservation $fs
|
|
if datasetexists $newvol ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user refreservation $fs
|
|
user_run $user zfs create -V 150m $newvol
|
|
block_device_wait
|
|
log_must zfs unallow $user refreservation $fs
|
|
if datasetexists $newvol ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user mount $fs
|
|
log_must zfs allow $user reservation $fs
|
|
log_must zfs allow $user refreservation $fs
|
|
user_run $user zfs create -V 150m $newvol
|
|
log_must zfs unallow $user mount $fs
|
|
log_must zfs unallow $user reservation $fs
|
|
log_must zfs unallow $user refreservation $fs
|
|
if ! datasetexists $newvol ; then
|
|
return 1
|
|
fi
|
|
|
|
block_device_wait
|
|
log_must zfs destroy $newvol
|
|
block_device_wait
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_destroy
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
if ! ismounted $fs ; then
|
|
user_run $user zfs destroy $fs
|
|
if datasetexists $fs ; then
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
if ismounted $fs ; then
|
|
user_run $user zfs destroy $fs
|
|
if ! datasetexists $fs ; then
|
|
return 1
|
|
fi
|
|
|
|
# mount permission is required
|
|
log_must zfs allow $user mount $fs
|
|
user_run $user zfs destroy $fs
|
|
if datasetexists $fs ; then
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Verify that given the correct delegation, a regular user can:
|
|
# Take a snapshot of an unmounted dataset
|
|
# Take a snapshot of a mounted dataset
|
|
# Create a snapshot by making a directory in the .zfs/snapshot directory
|
|
function verify_fs_snapshot
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
typeset stamp=${perm}.${user}.$RANDOM
|
|
typeset snap=$fs@snap.$stamp
|
|
typeset mntpt=$(get_prop mountpoint $fs)
|
|
|
|
if [[ "yes" == $(get_prop mounted $fs) ]]; then
|
|
log_must zfs umount $fs
|
|
fi
|
|
|
|
user_run $user zfs snapshot $snap
|
|
if ! datasetexists $snap ; then
|
|
return 1
|
|
fi
|
|
log_must zfs destroy $snap
|
|
|
|
if [[ "no" == $(get_prop mounted $fs) ]]; then
|
|
log_must zfs mount $fs
|
|
fi
|
|
|
|
user_run $user zfs snapshot $snap
|
|
if ! datasetexists $snap ; then
|
|
return 1
|
|
fi
|
|
log_must zfs destroy $snap
|
|
|
|
# Creating snaps via mkdir is not supported on FreeBSD
|
|
if ! is_freebsd; then
|
|
typeset snapdir=${mntpt}/.zfs/snapshot/snap.$stamp
|
|
user_run $user mkdir $snapdir
|
|
if ! datasetexists $snap ; then
|
|
return 1
|
|
fi
|
|
log_must zfs destroy $snap
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_rollback
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
typeset oldval
|
|
typeset stamp=${perm}.${user}.$RANDOM
|
|
typeset snap=$fs@snap.$stamp
|
|
typeset mntpt=$(get_prop mountpoint $fs)
|
|
|
|
oldval=$(datasetcksum $fs)
|
|
log_must zfs snapshot $snap
|
|
|
|
if ! ismounted $fs; then
|
|
log_must zfs mount $fs
|
|
fi
|
|
log_must touch $mntpt/testfile.$stamp
|
|
|
|
user_run $user zfs rollback -R $snap
|
|
if is_global_zone ; then
|
|
if [[ $oldval != $(datasetcksum $fs) ]]; then
|
|
return 1
|
|
fi
|
|
else
|
|
# datasetcksum can not be used in local zone
|
|
if [[ -e $mntpt/testfile.$stamp ]]; then
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_clone
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
typeset stamp=${perm}.${user}.$RANDOM
|
|
typeset basefs=${fs%/*}
|
|
typeset snap=$fs@snap.$stamp
|
|
typeset clone=$basefs/cfs.$stamp
|
|
|
|
log_must zfs snapshot $snap
|
|
user_run $user zfs clone $snap $clone
|
|
if datasetexists $clone ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user create $basefs
|
|
user_run $user zfs clone $snap $clone
|
|
log_must zfs unallow $user create $basefs
|
|
if datasetexists $clone ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user mount $basefs
|
|
user_run $user zfs clone $snap $clone
|
|
log_must zfs unallow $user mount $basefs
|
|
if datasetexists $clone ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user mount $basefs
|
|
log_must zfs allow $user create $basefs
|
|
user_run $user zfs clone $snap $clone
|
|
log_must zfs unallow $user create $basefs
|
|
log_must zfs unallow $user mount $basefs
|
|
if ! datasetexists $clone ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs destroy -R $snap
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_rename
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
typeset stamp=${perm}.${user}.$RANDOM
|
|
typeset basefs=${fs%/*}
|
|
typeset snap=$fs@snap.$stamp
|
|
typeset renamefs=$basefs/nfs.$stamp
|
|
|
|
if ! ismounted $fs; then
|
|
log_must zfs mount $fs
|
|
fi
|
|
|
|
# case 1
|
|
user_run $user zfs rename $fs $renamefs
|
|
if datasetexists $renamefs ; then
|
|
return 1
|
|
fi
|
|
|
|
# case 2
|
|
log_must zfs allow $user create $basefs
|
|
user_run $user zfs rename $fs $renamefs
|
|
log_must zfs unallow $user create $basefs
|
|
if datasetexists $renamefs ; then
|
|
return 1
|
|
fi
|
|
|
|
# case 3
|
|
log_must zfs allow $user mount $basefs
|
|
user_run $user zfs rename $fs $renamefs
|
|
log_must zfs unallow $user mount $basefs
|
|
if datasetexists $renamefs ; then
|
|
return 1
|
|
fi
|
|
|
|
# case 4
|
|
log_must zfs allow $user mount $fs
|
|
user_run $user zfs rename $fs $renamefs
|
|
if datasetexists $renamefs ; then
|
|
log_must zfs unallow $user mount $renamefs
|
|
return 1
|
|
fi
|
|
log_must zfs unallow $user mount $fs
|
|
|
|
# case 5
|
|
log_must zfs allow $user create $basefs
|
|
log_must zfs allow $user mount $fs
|
|
user_run $user zfs rename $fs $renamefs
|
|
log_must zfs unallow $user create $basefs
|
|
if datasetexists $renamefs ; then
|
|
log_must zfs unallow $user mount $renamefs
|
|
return 1
|
|
fi
|
|
log_must zfs unallow $user mount $fs
|
|
|
|
# case 6
|
|
log_must zfs allow $user mount $basefs
|
|
log_must zfs allow $user mount $fs
|
|
user_run $user zfs rename $fs $renamefs
|
|
log_must zfs unallow $user mount $basefs
|
|
if datasetexists $renamefs ; then
|
|
log_must zfs unallow $user mount $renamefs
|
|
return 1
|
|
fi
|
|
log_must zfs unallow $user mount $fs
|
|
|
|
# case 7
|
|
log_must zfs allow $user create $basefs
|
|
log_must zfs allow $user mount $basefs
|
|
user_run $user zfs rename $fs $renamefs
|
|
log_must zfs unallow $user mount $basefs
|
|
log_must zfs unallow $user create $basefs
|
|
if ! datasetexists $renamefs ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs rename $renamefs $fs
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_mount
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
typeset stamp=${perm}.${user}.$RANDOM
|
|
typeset mntpt=$(get_prop mountpoint $fs)
|
|
typeset newmntpt=$TEST_BASE_DIR/mnt.$stamp
|
|
|
|
if ismounted $fs ; then
|
|
user_run $user zfs unmount $fs
|
|
if ismounted $fs ; then
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
if ! ismounted $fs ; then
|
|
log_must zfs set mountpoint=$newmntpt $fs
|
|
log_must rm -rf $newmntpt
|
|
log_must mkdir $newmntpt
|
|
|
|
user_run $user zfs mount $fs
|
|
if ismounted $fs ; then
|
|
return 1
|
|
fi
|
|
|
|
# mountpoint's owner must be the user
|
|
log_must chown $user $newmntpt
|
|
user_run $user zfs mount $fs
|
|
if ! ismounted $fs ; then
|
|
return 1
|
|
fi
|
|
log_must zfs umount $fs
|
|
log_must rm -rf $newmntpt
|
|
log_must zfs set mountpoint=$mntpt $fs
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_share
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
typeset -i ret=0
|
|
|
|
svcadm enable -rs nfs/server
|
|
typeset stat=$(svcs -H -o STA nfs/server:default)
|
|
if [[ $stat != "ON" ]]; then
|
|
log_fail "Could not enable nfs/server"
|
|
fi
|
|
|
|
log_must zfs set sharenfs=on $fs
|
|
zfs unshare $fs
|
|
|
|
user_run $user zfs share $fs
|
|
if ! is_shared $fs; then
|
|
ret=1
|
|
fi
|
|
|
|
zfs unshare $fs
|
|
log_must zfs set sharenfs=off $fs
|
|
|
|
return $ret
|
|
}
|
|
|
|
function verify_fs_mountpoint
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
typeset stamp=${perm}.${user}.$RANDOM
|
|
typeset mntpt=$(get_prop mountpoint $fs)
|
|
typeset newmntpt=$TEST_BASE_DIR/mnt.$stamp
|
|
|
|
if ! ismounted $fs ; then
|
|
user_run $user zfs set mountpoint=$newmntpt $fs
|
|
if [[ $newmntpt != \
|
|
$(get_prop mountpoint $fs) ]] ; then
|
|
return 1
|
|
fi
|
|
log_must zfs set mountpoint=$mntpt $fs
|
|
fi
|
|
|
|
if ismounted $fs ; then
|
|
user_run $user zfs set mountpoint=$newmntpt $fs
|
|
if [[ $mntpt != $(get_prop mountpoint $fs) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
# require mount permission when fs is mounted
|
|
log_must zfs allow $user mount $fs
|
|
user_run $user zfs set mountpoint=$newmntpt $fs
|
|
log_must zfs unallow $user mount $fs
|
|
if [[ $newmntpt != \
|
|
$(get_prop mountpoint $fs) ]] ; then
|
|
return 1
|
|
fi
|
|
log_must zfs set mountpoint=$mntpt $fs
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_promote
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
typeset stamp=${perm}.${user}.$RANDOM
|
|
typeset basefs=${fs%/*}
|
|
typeset snap=$fs@snap.$stamp
|
|
typeset clone=$basefs/cfs.$stamp
|
|
|
|
log_must zfs snapshot $snap
|
|
log_must zfs clone $snap $clone
|
|
log_must zfs promote $clone
|
|
|
|
typeset fs_orig=$(get_prop origin $fs)
|
|
typeset clone_orig=$(get_prop origin $clone)
|
|
|
|
user_run $user zfs promote $fs
|
|
# promote should fail if original fs does not have
|
|
# promote permission
|
|
if [[ $fs_orig != $(get_prop origin $fs) || \
|
|
$clone_orig != $(get_prop origin $clone) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user promote $clone
|
|
user_run $user zfs promote $fs
|
|
log_must zfs unallow $user promote $clone
|
|
if [[ $fs_orig != $(get_prop origin $fs) || \
|
|
$clone_orig != $(get_prop origin $clone) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user mount $fs
|
|
user_run $user zfs promote $fs
|
|
log_must zfs unallow $user mount $fs
|
|
if [[ $fs_orig != $(get_prop origin $fs) || \
|
|
$clone_orig != $(get_prop origin $clone) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user mount $fs
|
|
log_must zfs allow $user promote $clone
|
|
user_run $user zfs promote $fs
|
|
log_must zfs unallow $user promote $clone
|
|
log_must zfs unallow $user mount $fs
|
|
if [[ $snap != $(get_prop origin $clone) || \
|
|
$clone_orig != $(get_prop origin $fs) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_canmount
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
typeset oldval
|
|
typeset stamp=${perm}.${user}.$RANDOM
|
|
|
|
if ! ismounted $fs ; then
|
|
set -A modes "on" "off"
|
|
oldval=$(get_prop $perm $fs)
|
|
if [[ $oldval == "on" ]]; then
|
|
n=1
|
|
elif [[ $oldval == "off" ]]; then
|
|
n=0
|
|
fi
|
|
log_note "$user zfs set $perm=${modes[$n]} $fs"
|
|
user_run $user zfs set $perm=${modes[$n]} $fs
|
|
if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
|
|
# fs is mounted
|
|
if ismounted $fs ; then
|
|
# property value does not change if
|
|
# no mount permission
|
|
set -A modes "on" "off"
|
|
oldval=$(get_prop $perm $fs)
|
|
if [[ $oldval == "on" ]]; then
|
|
n=1
|
|
elif [[ $oldval == "off" ]]; then
|
|
n=0
|
|
fi
|
|
log_note "$user zfs set $perm=${modes[$n]} $fs"
|
|
log_must zfs allow $user mount $fs
|
|
user_run $user zfs set $perm=${modes[$n]} $fs
|
|
log_must zfs unallow $user mount $fs
|
|
if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_recordsize
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
typeset value8k=$(( 1024 * 8 ))
|
|
user_run $user zfs set recordsize=$value8k $fs
|
|
if [[ $value8k != $(get_prop recordsize $fs) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_dnodesize
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
value="2k"
|
|
|
|
user_run $user zfs set dnodesize=$value $fs
|
|
if [[ $value != $(get_prop dnodesize $fs) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_quota
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
typeset value32m=$(( 1024 * 1024 * 32 ))
|
|
user_run $user zfs set quota=$value32m $fs
|
|
if [[ $value32m != $(get_prop quota $fs) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_aclmode
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
typeset oldval
|
|
set -A modes "discard" "groupmask" "passthrough"
|
|
oldval=$(get_prop $perm $fs)
|
|
if [[ $oldval == "discard" ]]; then
|
|
n=1
|
|
elif [[ $oldval == "groupmask" ]]; then
|
|
n=2
|
|
elif [[ $oldval == "passthrough" ]]; then
|
|
n=0
|
|
fi
|
|
log_note "$user zfs set aclmode=${modes[$n]} $fs"
|
|
user_run $user zfs set aclmode=${modes[$n]} $fs
|
|
if [[ ${modes[$n]} != $(get_prop aclmode $fs) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_aclinherit
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
#
|
|
# PSARC/2008/231 change the default value of aclinherit to "restricted"
|
|
# but still keep the old interface of "secure"
|
|
#
|
|
|
|
typeset oldval
|
|
set -A modes "discard" "noallow" "secure" "passthrough"
|
|
oldval=$(get_prop $perm $fs)
|
|
if [[ $oldval == "discard" ]]; then
|
|
n=1
|
|
elif [[ $oldval == "noallow" ]]; then
|
|
n=2
|
|
elif [[ $oldval == "secure" || $oldval == "restricted" ]]; then
|
|
n=3
|
|
elif [[ $oldval == "passthrough" ]]; then
|
|
n=0
|
|
fi
|
|
log_note "$user zfs set aclinherit=${modes[$n]} $fs"
|
|
user_run $user zfs set aclinherit=${modes[$n]} $fs
|
|
|
|
typeset newval=$(get_prop aclinherit $fs)
|
|
if [[ ${modes[$n]} == "secure" && $newval == "restricted" ]]; then
|
|
return 0
|
|
elif [[ ${modes[$n]} != $(get_prop aclinherit $fs) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_snapdir
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
typeset oldval
|
|
set -A modes "visible" "hidden"
|
|
oldval=$(get_prop $perm $fs)
|
|
if [[ $oldval == "visible" ]]; then
|
|
n=1
|
|
elif [[ $oldval == "hidden" ]]; then
|
|
n=0
|
|
fi
|
|
log_note "$user zfs set snapdir=${modes[$n]} $fs"
|
|
user_run $user zfs set snapdir=${modes[$n]} $fs
|
|
if [[ ${modes[$n]} != $(get_prop snapdir $fs) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_aedsx
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
typeset oldval
|
|
set -A modes "on" "off"
|
|
oldval=$(get_prop $perm $fs)
|
|
if [[ $oldval == "on" ]]; then
|
|
n=1
|
|
elif [[ $oldval == "off" ]]; then
|
|
n=0
|
|
fi
|
|
log_note "$user zfs set $perm=${modes[$n]} $fs"
|
|
user_run $user zfs set $perm=${modes[$n]} $fs
|
|
if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_zoned
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
|
|
typeset oldval
|
|
set -A modes "on" "off"
|
|
oldval=$(get_prop $perm $fs)
|
|
if [[ $oldval == "on" ]]; then
|
|
n=1
|
|
elif [[ $oldval == "off" ]]; then
|
|
n=0
|
|
fi
|
|
log_note "$user zfs set $perm=${modes[$n]} $fs"
|
|
if is_global_zone ; then
|
|
if ! ismounted $fs ; then
|
|
user_run $user zfs set \
|
|
$perm=${modes[$n]} $fs
|
|
if [[ ${modes[$n]} != \
|
|
$(get_prop $perm $fs) ]]; then
|
|
return 1
|
|
fi
|
|
if [[ $n -eq 0 ]]; then
|
|
log_mustnot zfs mount $fs
|
|
else
|
|
log_must zfs mount $fs
|
|
fi
|
|
fi
|
|
|
|
if ismounted $fs; then
|
|
# n always is 1 in this case
|
|
user_run $user zfs set \
|
|
$perm=${modes[$n]} $fs
|
|
if [[ $oldval != \
|
|
$(get_prop $perm $fs) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
# mount permission is needed
|
|
# to make zoned=on
|
|
log_must zfs allow $user mount $fs
|
|
user_run $user zfs set \
|
|
$perm=${modes[$n]} $fs
|
|
log_must zfs unallow $user mount $fs
|
|
if [[ ${modes[$n]} != \
|
|
$(get_prop $perm $fs) ]]; then
|
|
return 1
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if ! is_global_zone; then
|
|
user_run $user zfs set $perm=${modes[$n]} $fs
|
|
if [[ $oldval != $(get_prop $perm $fs) ]]; then
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_fs_sharenfs
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset fs=$3
|
|
typeset nmode omode
|
|
|
|
omode=$(get_prop $perm $fs)
|
|
if [[ $omode == "off" ]]; then
|
|
nmode="on"
|
|
else
|
|
nmode="off"
|
|
fi
|
|
|
|
log_note "$user zfs set $perm=$nmode $fs"
|
|
user_run $user zfs set $perm=$nmode $fs
|
|
if [[ $(get_prop $perm $fs) != $nmode ]]; then
|
|
return 1
|
|
fi
|
|
|
|
log_note "$user zfs set $perm=$omode $fs"
|
|
user_run $user zfs set $perm=$omode $fs
|
|
if [[ $(get_prop $perm $fs) != $omode ]]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_vol_destroy
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset vol=$3
|
|
|
|
user_run $user zfs destroy $vol
|
|
if ! datasetexists $vol ; then
|
|
return 1
|
|
fi
|
|
|
|
# mount permission is required
|
|
log_must zfs allow $user mount $vol
|
|
user_run $user zfs destroy $vol
|
|
if datasetexists $vol ; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_vol_snapshot
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset vol=$3
|
|
|
|
typeset stamp=${perm}.${user}.$RANDOM
|
|
typeset basevol=${vol%/*}
|
|
typeset snap=$vol@snap.$stamp
|
|
|
|
user_run $user zfs snapshot $snap
|
|
if datasetexists $snap ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user mount $vol
|
|
user_run $user zfs snapshot $snap
|
|
log_must zfs unallow $user mount $vol
|
|
if ! datasetexists $snap ; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_vol_rollback
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset vol=$3
|
|
|
|
typeset stamp=${perm}.${user}.$RANDOM
|
|
typeset basevol=${vol%/*}
|
|
typeset snap=$vol@snap.$stamp
|
|
|
|
typeset oldval
|
|
log_must zfs snapshot $snap
|
|
oldval=$(datasetcksum $vol)
|
|
|
|
log_must dd if=/dev/urandom of=$ZVOL_RDEVDIR/$vol \
|
|
bs=512 count=1
|
|
|
|
user_run $user zfs rollback -R $snap
|
|
sleep 10
|
|
if [[ $oldval == $(datasetcksum $vol) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
# rollback on volume has to be with mount permission
|
|
log_must zfs allow $user mount $vol
|
|
user_run $user zfs rollback -R $snap
|
|
sleep 10
|
|
log_must zfs unallow $user mount $vol
|
|
if [[ $oldval != $(datasetcksum $vol) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_vol_clone
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset vol=$3
|
|
|
|
typeset stamp=${perm}.${user}.$RANDOM
|
|
typeset basevol=${vol%/*}
|
|
typeset snap=$vol@snap.$stamp
|
|
typeset clone=$basevol/cvol.$stamp
|
|
|
|
log_must zfs snapshot $snap
|
|
|
|
user_run $user zfs clone $snap $clone
|
|
if datasetexists $clone ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user create $basevol
|
|
user_run $user zfs clone $snap $clone
|
|
log_must zfs unallow $user create $basevol
|
|
if datasetexists $clone ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user mount $basevol
|
|
user_run $user zfs clone $snap $clone
|
|
log_must zfs unallow $user mount $basevol
|
|
if datasetexists $clone ; then
|
|
return 1
|
|
fi
|
|
|
|
# require create permission on parent and
|
|
# mount permission on itself as well
|
|
log_must zfs allow $user mount $basevol
|
|
log_must zfs allow $user create $basevol
|
|
user_run $user zfs clone $snap $clone
|
|
log_must zfs unallow $user create $basevol
|
|
log_must zfs unallow $user mount $basevol
|
|
if ! datasetexists $clone ; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_vol_rename
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset vol=$3
|
|
|
|
typeset stamp=${perm}.${user}.$RANDOM
|
|
typeset basevol=${vol%/*}
|
|
typeset snap=$vol@snap.$stamp
|
|
typeset clone=$basevol/cvol.$stamp
|
|
typeset renamevol=$basevol/nvol.$stamp
|
|
|
|
user_run $user zfs rename $vol $renamevol
|
|
if datasetexists $renamevol ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user create $basevol
|
|
user_run $user zfs rename $vol $renamevol
|
|
log_must zfs unallow $user create $basevol
|
|
if datasetexists $renamevol ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user mount $basevol
|
|
user_run $user zfs rename $vol $renamevol
|
|
log_must zfs unallow $user mount $basevol
|
|
if datasetexists $renamevol ; then
|
|
return 1
|
|
fi
|
|
|
|
# require both create permission on parent and
|
|
# mount permission on parent as well
|
|
log_must zfs allow $user mount $basevol
|
|
log_must zfs allow $user create $basevol
|
|
user_run $user zfs rename $vol $renamevol
|
|
log_must zfs unallow $user mount $basevol
|
|
log_must zfs unallow $user create $basevol
|
|
if ! datasetexists $renamevol ; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs rename $renamevol $vol
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_vol_promote
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset vol=$3
|
|
|
|
typeset stamp=${perm}.${user}.$RANDOM
|
|
typeset basevol=${vol%/*}
|
|
typeset snap=$vol@snap.$stamp
|
|
typeset clone=$basevol/cvol.$stamp
|
|
|
|
log_must zfs snapshot $snap
|
|
log_must zfs clone $snap $clone
|
|
log_must zfs promote $clone
|
|
|
|
typeset vol_orig=$(get_prop origin $vol)
|
|
typeset clone_orig=$(get_prop origin $clone)
|
|
|
|
# promote should fail if $vol and $clone
|
|
# miss either mount or promote permission
|
|
# case 1
|
|
user_run $user zfs promote $vol
|
|
if [[ $vol_orig != $(get_prop origin $vol) || \
|
|
$clone_orig != $(get_prop origin $clone) ]];
|
|
then
|
|
return 1
|
|
fi
|
|
|
|
# promote should fail if $vol and $clone
|
|
# miss either mount or promote permission
|
|
# case 2
|
|
log_must zfs allow $user promote $clone
|
|
user_run $user zfs promote $vol
|
|
log_must zfs unallow $user promote $clone
|
|
if [[ $vol_orig != $(get_prop origin $vol) || \
|
|
$clone_orig != $(get_prop origin $clone) ]];
|
|
then
|
|
return 1
|
|
fi
|
|
|
|
# promote should fail if $vol and $clone
|
|
# miss either mount or promote permission
|
|
# case 3
|
|
log_must zfs allow $user mount $vol
|
|
user_run $user zfs promote $vol
|
|
log_must zfs unallow $user mount $vol
|
|
if [[ $vol_orig != $(get_prop origin $vol) || \
|
|
$clone_orig != $(get_prop origin $clone) ]];
|
|
then
|
|
return 1
|
|
fi
|
|
|
|
# promote should fail if $vol and $clone
|
|
# miss either mount or promote permission
|
|
# case 4
|
|
log_must zfs allow $user mount $clone
|
|
user_run $user zfs promote $vol
|
|
log_must zfs unallow $user mount $clone
|
|
if [[ $vol_orig != $(get_prop origin $vol) || \
|
|
$clone_orig != $(get_prop origin $clone) ]];
|
|
then
|
|
return 1
|
|
fi
|
|
|
|
# promote should fail if $vol and $clone
|
|
# miss either mount or promote permission
|
|
# case 5
|
|
log_must zfs allow $user promote $clone
|
|
log_must zfs allow $user mount $vol
|
|
user_run $user zfs promote $vol
|
|
log_must zfs unallow $user promote $clone
|
|
log_must zfs unallow $user mount $vol
|
|
if [[ $vol_orig != $(get_prop origin $vol) || \
|
|
$clone_orig != $(get_prop origin $clone) ]];
|
|
then
|
|
return 1
|
|
fi
|
|
|
|
# promote should fail if $vol and $clone
|
|
# miss either mount or promote permission
|
|
# case 6
|
|
log_must zfs allow $user promote $clone
|
|
log_must zfs allow $user mount $clone
|
|
user_run $user zfs promote $vol
|
|
log_must zfs unallow $user promote $clone
|
|
log_must zfs unallow $user mount $vol
|
|
if [[ $vol_orig != $(get_prop origin $vol) || \
|
|
$clone_orig != $(get_prop origin $clone) ]];
|
|
then
|
|
return 1
|
|
fi
|
|
|
|
# promote should fail if $vol and $clone
|
|
# miss either mount or promote permission
|
|
# case 7
|
|
log_must zfs allow $user mount $vol
|
|
log_must zfs allow $user mount $clone
|
|
user_run $user zfs promote $vol
|
|
log_must zfs unallow $user mount $vol
|
|
log_must zfs unallow $user mount $clone
|
|
if [[ $vol_orig != $(get_prop origin $vol) || \
|
|
$clone_orig != $(get_prop origin $clone) ]];
|
|
then
|
|
return 1
|
|
fi
|
|
|
|
# promote only succeeds when $vol and $clone
|
|
# have both mount and promote permission
|
|
# case 8
|
|
log_must zfs allow $user promote $clone
|
|
log_must zfs allow $user mount $vol
|
|
log_must zfs allow $user mount $clone
|
|
user_run $user zfs promote $vol
|
|
log_must zfs unallow $user promote $clone
|
|
log_must zfs unallow $user mount $vol
|
|
log_must zfs unallow $user mount $clone
|
|
if [[ $snap != $(get_prop origin $clone) || \
|
|
$clone_orig != $(get_prop origin $vol) ]]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_vol_volsize
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset vol=$3
|
|
|
|
typeset oldval
|
|
oldval=$(get_prop volsize $vol)
|
|
(( newval = oldval * 2 ))
|
|
|
|
reserv_size=$(get_prop refreservation $vol)
|
|
|
|
if [[ "0" == $reserv_size ]]; then
|
|
# sparse volume
|
|
user_run $user zfs set volsize=$newval $vol
|
|
if [[ $oldval == $(get_prop volsize $vol) ]];
|
|
then
|
|
return 1
|
|
fi
|
|
|
|
else
|
|
# normal volume, reservation permission
|
|
# is required
|
|
user_run $user zfs set volsize=$newval $vol
|
|
if [[ $newval == $(get_prop volsize $vol) ]];
|
|
then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user reservation $vol
|
|
log_must zfs allow $user refreservation $vol
|
|
user_run $user zfs set volsize=$newval $vol
|
|
log_must zfs unallow $user reservation $vol
|
|
log_must zfs unallow $user refreservation $vol
|
|
if [[ $oldval == $(get_prop volsize $vol) ]];
|
|
then
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
function verify_allow
|
|
{
|
|
typeset user=$1
|
|
typeset perm=$2
|
|
typeset dtst=$3
|
|
|
|
typeset -i ret
|
|
|
|
user_run $user zfs allow $user allow $dtst
|
|
ret=$?
|
|
if [[ $ret -eq 0 ]]; then
|
|
return 1
|
|
fi
|
|
|
|
log_must zfs allow $user copies $dtst
|
|
user_run $user zfs allow $user copies $dtst
|
|
ret=$?
|
|
log_must zfs unallow $user copies $dtst
|
|
if [[ $ret -eq 1 ]]; then
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
|
|
}
|