No functional change. The MAX_ATTRS and MAX_ATTRVAL_SIZE exports are only used by generic/020. In preparation for taking into account the attr name length when calculating MAX_ATTRVAL_SIZE, split the current logic out into a _attr_get_max() helper function. Signed-off-by: David Disseldorp <ddiss@xxxxxxx> --- common/attr | 163 +++++++++++++++++++++++++--------------------- tests/generic/020 | 10 ++- 2 files changed, 95 insertions(+), 78 deletions(-) diff --git a/common/attr b/common/attr index dae8a1bb..a80b10a1 100644 --- a/common/attr +++ b/common/attr @@ -264,80 +264,93 @@ _getfattr() return ${PIPESTATUS[0]} } -# set maximum total attr space based on fs type -case "$FSTYP" in -xfs|udf|pvfs2|9p|ceph|nfs) - MAX_ATTRS=1000 - ;; -ext2|ext3|ext4) - # For 4k blocksizes, most of the attributes have an attr_name of - # "attribute_NN" which is 12, and "value_NN" which is 8. - # But for larger block sizes, we start having extended attributes of the - # form "attribute_NNN" or "attribute_NNNN", and "value_NNN" and - # "value_NNNN", which causes the round(len(..), 4) to jump up by 4 - # bytes. So round_up(len(attr_name, 4)) becomes 16 instead of 12, and - # round_up(len(value, 4)) becomes 12 instead of 8. - # - # For 64K blocksize the calculation becomes - # max_attrs = (block_size - 32) / (16 + 12 + 16) - # or - # max_attrs = (block_size - 32) / 44 - # - # For 4K blocksize:- - # max_attrs = (block_size - 32) / (16 + 8 + 12) - # or - # max_attrs = (block_size - 32) / 36 - # - # Note (for 4K bs) above are exact calculations for attrs of type - # attribute_NN with values of type value_NN. - # With above calculations, for 4k blocksize max_attrs becomes 112. - # This means we can have few attrs of type attribute_NNN with values of - # type value_NNN. To avoid/handle this we need to add extra 4 bytes of - # headroom. - # - # So for 4K, the calculations becomes:- - # max_attrs = (block_size - 32) / (16 + 8 + 12 + 4) - # or - # max_attrs = (block_size - 32) / 40 - # - # Assume max ~1 block of attrs - BLOCK_SIZE=`_get_block_size $TEST_DIR` - if [ $BLOCK_SIZE -le 4096 ]; then - let MAX_ATTRS=$((($BLOCK_SIZE - 32) / (16 + 8 + 12 + 4))) - else - let MAX_ATTRS=$((($BLOCK_SIZE - 32) / (16 + 12 + 16 ))) - fi - ;; -*) - # Assume max ~1 block of attrs - BLOCK_SIZE=`_get_block_size $TEST_DIR` - # user.attribute_XXX="value.XXX" is about 32 bytes; leave some overhead - let MAX_ATTRS=$BLOCK_SIZE/40 -esac - -export MAX_ATTRS - -# Set max attr value size based on fs type -case "$FSTYP" in -xfs|udf|btrfs) - MAX_ATTRVAL_SIZE=64 - ;; -pvfs2) - MAX_ATTRVAL_SIZE=8192 - ;; -9p|ceph|nfs) - MAX_ATTRVAL_SIZE=65536 - ;; -bcachefs) - MAX_ATTRVAL_SIZE=1024 - ;; -*) - # Assume max ~1 block of attrs - BLOCK_SIZE=`_get_block_size $TEST_DIR` - # leave a little overhead - let MAX_ATTRVAL_SIZE=$BLOCK_SIZE-256 -esac - -export MAX_ATTRVAL_SIZE +# export fs-specific MAX_ATTRS and MAX_ATTRVAL_SIZE values. The parameter +# @max_attrval_namelen is required for filesystems which take into account attr +# name lengths (including namespace prefix) when determining limits. +_attr_get_max() +{ + local max_attrval_namelen="$1" + + # set maximum total attr space based on fs type + case "$FSTYP" in + xfs|udf|pvfs2|9p|ceph|nfs) + MAX_ATTRS=1000 + ;; + ext2|ext3|ext4) + # For 4k blocksizes, most of the attributes have an attr_name of + # "attribute_NN" which is 12, and "value_NN" which is 8. + # But for larger block sizes, we start having extended + # attributes of the + # form "attribute_NNN" or "attribute_NNNN", and "value_NNN" and + # "value_NNNN", which causes the round(len(..), 4) to jump up by + # 4 bytes. So round_up(len(attr_name, 4)) becomes 16 instead of + # 12, and round_up(len(value, 4)) becomes 12 instead of 8. + # + # For 64K blocksize the calculation becomes + # max_attrs = (block_size - 32) / (16 + 12 + 16) + # or + # max_attrs = (block_size - 32) / 44 + # + # For 4K blocksize:- + # max_attrs = (block_size - 32) / (16 + 8 + 12) + # or + # max_attrs = (block_size - 32) / 36 + # + # Note (for 4K bs) above are exact calculations for attrs of + # type attribute_NN with values of type value_NN. + # With above calculations, for 4k blocksize max_attrs becomes + # 112. + # This means we can have few attrs of type attribute_NNN with + # values of + # type value_NNN. To avoid/handle this we need to add extra 4 + # bytes of headroom. + # + # So for 4K, the calculations becomes:- + # max_attrs = (block_size - 32) / (16 + 8 + 12 + 4) + # or + # max_attrs = (block_size - 32) / 40 + # + # Assume max ~1 block of attrs + BLOCK_SIZE=`_get_block_size $TEST_DIR` + if [ $BLOCK_SIZE -le 4096 ]; then + let MAX_ATTRS=$((($BLOCK_SIZE - 32) / (16 + 8 + 12 + 4))) + else + let MAX_ATTRS=$((($BLOCK_SIZE - 32) / (16 + 12 + 16 ))) + fi + ;; + *) + # Assume max ~1 block of attrs + BLOCK_SIZE=`_get_block_size $TEST_DIR` + # user.attribute_XXX="value.XXX" is about 32 bytes; leave some + # overhead + let MAX_ATTRS=$BLOCK_SIZE/40 + esac + + export MAX_ATTRS + + # Set max attr value size based on fs type + case "$FSTYP" in + xfs|udf|btrfs) + MAX_ATTRVAL_SIZE=64 + ;; + pvfs2) + MAX_ATTRVAL_SIZE=8192 + ;; + 9p|ceph|nfs) + MAX_ATTRVAL_SIZE=65536 + ;; + bcachefs) + MAX_ATTRVAL_SIZE=1024 + ;; + *) + # Assume max ~1 block of attrs + BLOCK_SIZE=`_get_block_size $TEST_DIR` + # leave a little overhead + let MAX_ATTRVAL_SIZE=$BLOCK_SIZE-256 + esac + + export MAX_ATTRVAL_SIZE +} + # make sure this script returns success /bin/true diff --git a/tests/generic/020 b/tests/generic/020 index 29ef853c..34861401 100755 --- a/tests/generic/020 +++ b/tests/generic/020 @@ -88,6 +88,9 @@ _attr_list $testfile echo "*** add lots of attributes" v=0 +max_attrval_name="long_attr" # add 5 for "user." prefix +_attr_get_max "$(( 5 + ${#max_attrval_name} ))" + while [ $v -lt $MAX_ATTRS ] do echo -n "value_$v" | attr -s "attribute_$v" $testfile >>$seqres.full @@ -128,11 +131,12 @@ _attr_list $testfile echo "*** really long value" dd if=/dev/zero bs=1 count=$MAX_ATTRVAL_SIZE 2>/dev/null \ - | _attr -s "long_attr" $testfile >/dev/null + | _attr -s "$max_attrval_name" $testfile >/dev/null OCTAL_SIZE=`echo "obase=8; $MAX_ATTRVAL_SIZE" | bc` -_attr -q -g "long_attr" $testfile | od -t x1 | sed -e "s/^0*$OCTAL_SIZE$/ATTRSIZE/" -_attr -r "long_attr" $testfile >/dev/null +_attr -q -g "$max_attrval_name" $testfile | od -t x1 \ + | sed -e "s/^0*$OCTAL_SIZE$/ATTRSIZE/" +_attr -r "$max_attrval_name" $testfile >/dev/null echo "*** set/get/remove really long names (expect failure)" short="XXXXXXXXXX" -- 2.34.1