#
# 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
# 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 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
#
#
# DESCRIPTION:
# Test that properties are correctly inherited using 'zfs set',
# 'zfs inherit' and 'zfs inherit -r'.
#
# STRATEGY:
# 1) Read a configX.cfg file and create the specified datasets
# 2) Read a stateX.cfg file and execute the commands within it
# and verify that the properties have the correct values
# 3) Repeat steps 1-2 for each configX and stateX files found.
#
verify_runnable "global"
log_assert "Test properties are inherited correctly"
#
# Simple function to create specified datasets.
#
typeset dataset=$1
typeset type=$2
typeset disks=$3
else
fi
}
#
# Function to walk through all the properties in a
# dataset, setting them to a 'local' value if required.
#
typeset dataset=$1
typeset init_code=$2
typeset dir=$3
typeset -i i=0
#
# Though the effect of '-' and 'default' is the same we
# call them out via a log_note to aid in debugging the
# config files
#
[[ $def_recordsize == 0 ]] && \
return;
[[ $def_recordsize == 0 ]] && \
return;
while (( i < ${#prop[*]} )); do
else
set_n_verify_prop ${prop[i]} \
else
set_n_verify_prop ${prop[i]} \
fi
fi
((i = i + 2))
done
else
log_fail "Unrecognised init code $init_code"
fi
}
#
# We enter this function either to update the recordsize value
# in the default array, or to update the local value array.
#
typeset dataset=$1
typeset init_code=$2
typeset idx=0
typeset record_val
#
# First need to find where the recordsize property is
# located in the arrays
#
done
fi
}
#
# The mountpoint property is slightly different from other properties and
# so is handled here. For all other properties if they are set to a specific
# value at a higher level in the data hierarchy (i.e. checksum=on) then that
# value propogates down the hierarchy unchanged, with the source field being
# set to 'inherited from <higher dataset>'.
#
# The mountpoint property is different in that while the value propogates
# down the hierarchy, the value at each level is determined by a combination
# of the top-level value and the current level in the hierarchy.
#
# For example consider the case where we have a pool (called pool1), containing
# a dataset (ctr) which in turn contains a filesystem (fs). If we set the
# mountpoint of the pool to '/mnt2' then the mountpoints for the dataset and
# field being set to 'inherited from pool1'.
#
# So at the filesystem level to calculate what our mountpoint property should
# be set to we walk back up the hierarchy sampling the mountpoint property at
# each level and forming up the expected mountpoint value piece by piece until
# we reach the level specified in the 'source' field, which in this example is
# the top-level pool.
#
function get_mntpt_val #dataset src index
{
typeset dataset=$1
typeset src=$2
typeset idx=$3
typeset new_path=""
typeset dset
typeset mntpt=""
# Extract mount points specific to datasets
else
fi
else
# Walk back up the hierarchy building up the
# expected mountpoint property value.
mod_prop_val=${mnt_val##*/}
done
fi
echo $mntpt
}
#
# Simple function to verify that a property has the
# expected value.
#
function verify_prop_val #property dataset src index
{
typeset prop=$1
typeset dataset=$2
typeset src=$3
typeset idx=$4
typeset new_path=""
typeset dset
typeset exp_val
typeset prop_val
# mountpoint property is handled as a special case
else
else
#
# We are inheriting the value from somewhere
# up the hierarchy.
#
fi
fi
# After putback PSARC/2008/231 Apr,09,2008,
# the default value of aclinherit has changed to be
# 'restricted' instead of 'secure',
# but the old interface of 'secure' still exist
"than [$exp_val]"
fi
fi
}
#
# Function to read the configX.cfg files and create the specified
# dataset hierarchy
#
typeset config_file=$1
list=""
typeset -i mount_dir=1
done
}
}
#
# Function to check an exit flag, calling log_fail if that exit flag
# is non-zero. Can be used from code that runs in a tight loop, which
# would otherwise result in a lot of journal output.
#
typeset -i exit_flag=$1
if [[ $exit_flag -ne 0 ]]; then
fi
}
#
# Main function. Executes the commands specified in the stateX.cfg
# files and then verifies that all the properties have the correct
# values and 'source' fields.
#
typeset state_file=$1
typeset -i i=0
typeset -i j=0
log_note "Reading state from $state_file"
while ((i < ${#prop[*]})); do
#
# The user can if they wish specify that no
# operation be performed (by specifying '-'
# rather than a command). This is not as
# useless as it sounds as it allows us to
# verify that the dataset hierarchy has been
# set up correctly as specified in the
# configX.cfg file (which includes 'set'ting
# properties at a higher level and checking
# that they propogate down to the lower levels.
#
# Note in a few places here, we use
# check_failure, rather than log_must - this
# substantially reduces journal output.
#
log_note "No operation specified"
else
export __ZFS_POOL_RESTRICT="$TESTPOOL"
unset __ZFS_POOL_RESTRICT
ret=$?
check_failure $ret "zfs $op $p \
done
fi
# check_failure to keep journal small
ret=$?
# Again, to keep journal size down.
$final_src $j
ret=$?
done
done
done
}
((i = i + 2))
((j = j + 1))
done
}
#
# Note that we keep this list relatively short so that this test doesn't
# time out (after taking more than 10 minutes).
#
"compression" "" \
"atime" "" \
"sharenfs" "" \
"recordsize" "recsize" \
"mountpoint" "" \
"snapdir" "" \
"aclmode" "" \
"readonly" ""
#
# Note except for the mountpoint default value (which is handled in
# the routine itself), each property specified in the 'prop' array
# above must have a corresponding entry in the two arrays below.
#
"off" "" \
"" "hidden" "discard" \
"off"
"on" "" \
"off"
#
# Global flag indicating whether the default record size had been
# read.
#
typeset def_recordsize=0
set -A config_files $(ls $STF_SUITE/tests/functional/inheritance/config*[1-9]*.cfg)
set -A state_files $(ls $STF_SUITE/tests/functional/inheritance/state*.cfg)
#
# Global list of datasets created.
#
list=""
typeset -i k=0
if [[ ${#config_files[*]} != ${#state_files[*]} ]]; then
" (${#config_files[*]}) and state files ${#state_files[*]}"
fi
while ((k < ${#config_files[*]})); do
log_note "Testing configuration ${config_files[k]}"
scan_config ${config_files[k]}
scan_state ${state_files[k]}
((k = k + 1))
done
log_pass "Properties correctly inherited as expected"