Add support for zpool user properties

Usage:

    zpool set org.freebsd:comment="this is my pool" poolname

Tests are based on zfs_set's user property tests.

Also stop truncating property values at MAXNAMELEN, use ZFS_MAXPROPLEN.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Allan Jude <allan@klarasystems.com>
Signed-off-by: Mateusz Piotrowski <mateusz.piotrowski@klarasystems.com>
Sponsored-by: Beckhoff Automation GmbH & Co. KG.
Sponsored-by: Klara Inc.
Closes #11680
This commit is contained in:
Allan Jude
2023-04-21 13:20:36 -04:00
committed by GitHub
parent 135d9a9048
commit 8eae2d214c
12 changed files with 691 additions and 112 deletions
+3
View File
@@ -1149,10 +1149,13 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zpool_set/setup.ksh \
functional/cli_root/zpool/setup.ksh \
functional/cli_root/zpool_set/vdev_set_001_pos.ksh \
functional/cli_root/zpool_set/zpool_set_common.kshlib \
functional/cli_root/zpool_set/zpool_set_001_pos.ksh \
functional/cli_root/zpool_set/zpool_set_002_neg.ksh \
functional/cli_root/zpool_set/zpool_set_003_neg.ksh \
functional/cli_root/zpool_set/zpool_set_ashift.ksh \
functional/cli_root/zpool_set/user_property_001_pos.ksh \
functional/cli_root/zpool_set/user_property_002_neg.ksh \
functional/cli_root/zpool_set/zpool_set_features.ksh \
functional/cli_root/zpool_split/cleanup.ksh \
functional/cli_root/zpool_split/setup.ksh \
@@ -0,0 +1,89 @@
#!/bin/ksh -p
#
# 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 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#
# Copyright (c) 2016 by Delphix. All rights reserved.
# Copyright (c) 2023 by Klara Inc.
#
. $STF_SUITE/tests/functional/cli_root/zpool_set/zpool_set_common.kshlib
#
# DESCRIPTION:
# ZFS can set any valid user-defined pool property.
#
# STRATEGY:
# 1. Combine all kind of valid characters into a valid user-defined
# property name.
# 2. Random get a string as the value.
# 3. Verify all the valid user-defined pool properties can be set to a
# pool.
#
verify_runnable "both"
log_assert "ZFS can set any valid user-defined pool property."
log_onexit cleanup_user_prop $TESTPOOL
typeset -a names=()
typeset -a values=()
# Longest property name (255 bytes, which is the 256-byte limit minus 1 byte
# for the null byte)
names+=("$(awk 'BEGIN { printf "x:"; while (c++ < (256 - 2 - 1)) printf "a" }')")
values+=("long-property-name")
# Longest property value (the limits are 1024 on FreeBSD and 4096 on Linux, so
# pick the right one; the longest value can use limit minus 1 bytes for the
# null byte)
if is_linux; then
typeset ZFS_MAXPROPLEN=4096
else
typeset ZFS_MAXPROPLEN=1024
fi
names+=("long:property:value")
values+=("$(awk -v max="$ZFS_MAXPROPLEN" 'BEGIN { while (c++ < (max - 1)) printf "A" }')")
# Valid property names
for i in {1..10}; do
typeset -i len
((len = RANDOM % 32))
names+=("$(valid_user_property $len)")
((len = RANDOM % 512))
values+=("$(user_property_value $len)")
done
typeset -i i=0
while ((i < ${#names[@]})); do
typeset name="${names[$i]}"
typeset value="${values[$i]}"
log_must eval "zpool set $name='$value' $TESTPOOL"
log_must eval "check_user_prop $TESTPOOL $name '$value'"
((i += 1))
done
log_pass "ZFS can set any valid user-defined pool property passed."
@@ -0,0 +1,88 @@
#!/bin/ksh -p
#
# 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 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#
# Copyright (c) 2016 by Delphix. All rights reserved.
# Copyright (c) 2023 by Klara Inc.
#
. $STF_SUITE/tests/functional/cli_root/zpool_set/zpool_set_common.kshlib
#
# DESCRIPTION:
# ZFS can handle any invalid user-defined pool property.
#
# STRATEGY:
# 1. Combine all kind of invalid user pool property names.
# 2. Random get a string as the value.
# 3. Verify all the invalid user-defined pool properties can not be set
# to the pool.
#
verify_runnable "both"
log_assert "ZFS can handle any invalid user pool property."
log_onexit cleanup_user_prop $TESTPOOL
typeset -a names=()
typeset -a values=()
# Too long property name (256 bytes, which is the 256-byte limit minus 1 byte
# for the null byte plus 1 byte to reach back over the limit)
names+=("$(awk 'BEGIN { printf "x:"; while (c++ < (256 - 2 - 1 + 1)) printf "a" }')")
values+=("too-long-property-name")
# Too long property value (the limits are 1024 on FreeBSD and 4096 on Linux, so
# pick the right one; the too long value is, e.g., the limit minus 1 bytes for the
# null byte plus 1 byte to reach back over the limit)
if is_linux; then
typeset ZFS_MAXPROPLEN=4096
else
typeset ZFS_MAXPROPLEN=1024
fi
names+=("too:long:property:value")
values+=("$(awk -v max="$ZFS_MAXPROPLEN" 'BEGIN { while (c++ < (max - 1 + 1)) printf "A" }')")
# Invalid property names
for i in {1..10}; do
typeset -i len
((len = RANDOM % 32))
names+=("$(invalid_user_property $len)")
((len = RANDOM % 512))
values+=("$(user_property_value $len)")
done
typeset -i i=0
while ((i < ${#names[@]})); do
typeset name="${names[$i]}"
typeset value="${values[$i]}"
log_mustnot zpool set $name=$value $TESTPOOL
log_mustnot check_user_prop $TESTPOOL \"$name\" \"$value\"
((i += 1))
done
log_pass "ZFS can handle invalid user pool property passed."
@@ -0,0 +1,178 @@
#
# 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 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#
# Copyright (c) 2014, 2016 by Delphix. All rights reserved.
# Copyright (c) 2023 by Klara Inc.
#
. $STF_SUITE/include/libtest.shlib
set -A VALID_NAME_CHAR a b c d e f g h i j k l m n o p q r s t u v w x y z \
0 1 2 3 4 5 6 7 8 9 ':' '-' '.' '_'
set -A INVALID_NAME_CHAR A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
'`' '~' '!' '@' '#' '$' '%' '^' '&' '(' ')' '+' '=' '|' "\\" '{' '[' ']' \
'}' ';' '"' '<' ',' '>' '?' '/' ' '
set -A ALL_CHAR ${VALID_NAME_CHAR[*]} ${INVALID_NAME_CHAR[*]}
#
# Cleanup all the user properties of the pool.
#
# $1 pool name
#
function cleanup_user_prop
{
typeset pool=$1
typeset user_prop
user_prop=$(zpool get -H -o property all $pool | grep ":")
typeset prop
for prop in $user_prop; do
zpool set $prop="" $pool ||
log_must zpool set $prop="" $pool
done
}
#
# Random select character from the specified character set and combine into a
# random string
#
# $1 character set name
# $2 String length
#
function random_string
{
typeset char_set=${1:-VALID_NAME_CHAR}
typeset -i len=${2:-5}
eval typeset -i count=\${#$char_set[@]}
# No consumers want an empty string.
((len == 0)) && len=3
typeset str
typeset -i i=0
while ((i < len)); do
typeset -i ind
((ind = RANDOM % count))
eval str=\${str}\${$char_set[\$ind]}
((i += 1))
done
echo "$str"
}
#
# Get valid user-defined property name
#
# $1 user-defined property name length
#
function valid_user_property
{
typeset -i sumlen=${1:-10}
((sumlen < 2 )) && sumlen=2
typeset -i len
((len = RANDOM % sumlen))
typeset part1 part2
while true; do
part1="$(random_string VALID_NAME_CHAR $len)"
if [[ "$part1" == "-"* ]]; then
continue
fi
break
done
((len = sumlen - (len + 1)))
while true; do
part2="$(random_string VALID_NAME_CHAR $len)"
if [[ -z $part1 && -z $part2 ]]; then
continue
fi
break
done
echo "${part1}:${part2}"
}
#
# Get invalid user-defined property name
#
# $1 user-defined property name length
#
function invalid_user_property
{
typeset -i sumlen=${1:-10}
((sumlen == 0)) && sumlen=1
typeset -i len
((len = RANDOM % sumlen))
typeset part1 part2
while true; do
part1="$(random_string VALID_NAME_CHAR $len)"
((len = sumlen - len))
part2="$(random_string INVALID_NAME_CHAR $len)"
# Avoid $part1 is *:* and $part2 is "=*"
if [[ "$part1" == *":"* && "$part2" == "="* ]]; then
continue
fi
break
done
echo "${part1}${part2}"
}
#
# Get user-defined property value
#
# $1 user-defined property name length
#
function user_property_value
{
typeset -i len=${1:-100}
random_string ALL_CHAR $len
}
#
# Check if the user-defined property is identical to the expected value.
#
# $1 pool
# $2 user property
# $3 expected value
#
function check_user_prop
{
typeset pool=$1
typeset user_prop="$2"
typeset expect_value="$3"
typeset value=$(zpool get -p -H -o value "$user_prop" $pool 2>&1)
[ "$expect_value" = "$value" ]
}