common/attr: Reduce MAX_ATTRS to leave some overhead for 64K blocksize
[xfstests-dev.git] / common / attr
index 6fdcbf2ba5112d8dfbb12f2ad2149a54a64ffd72..35682d7c56cdf7af91b488fcf60853ee93d4e0de 100644 (file)
@@ -1,24 +1,7 @@
 ##/bin/bash
-#-----------------------------------------------------------------------
-#  Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
-#  This program is free software; you can redistribute it and/or modify
-#  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
 #
-#  This program is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#  GNU General Public License for more details.
-#
-#  You should have received a copy of the GNU General Public License
-#  along with this program; if not, write to the Free Software
-#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
-#  USA
-#
-#  Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
-#  Mountain View, CA 94043, USA, or: http://www.sgi.com
-#-----------------------------------------------------------------------
 # common extended attribute and ACL support
 
 # filesystems that want to test maximum supported acl counts need to
@@ -30,7 +13,7 @@ _acl_get_max()
                # CRC format filesystems have much larger ACL counts. The actual
                # number is into the thousands, but testing that meany takes too
                # long, so just test well past the old limit of 25.
-               xfs_info $TEST_DIR | _filter_mkfs > /dev/null 2> $tmp.info
+               $XFS_INFO_PROG $TEST_DIR | _filter_mkfs > /dev/null 2> $tmp.info
                . $tmp.info
                rm $tmp.info
                if [ $_fs_has_crcs -eq 0 ]; then
@@ -39,6 +22,20 @@ _acl_get_max()
                        echo 5461
                fi
                ;;
+       jfs)
+               echo 8191
+               ;;
+       f2fs)
+               _fs_options $TEST_DEV | grep "inline_xattr" >/dev/null 2>&1
+               if [ $? -eq 0 ]; then
+                       echo 531
+               else
+                       echo 506
+               fi
+               ;;
+       bcachefs)
+               echo 251
+               ;;
        *)
                echo 0
                ;;
@@ -62,10 +59,10 @@ _acl_setup_ids()
         j=1
         for(i=1; i<1000000 && j<=3;i++){
           if (! (i in ids)) {
-            printf "acl%d=%d;", j, i;           
+            printf "acl%d=%d;", j, i;
             j++
           }
-        }      
+        }
       }'`
 }
 
@@ -104,18 +101,6 @@ _getfacl_filter_id()
 _acl_ls()
 {
     _ls_l -n $* | awk '{ print $1, $3, $4, $NF }' | _acl_filter_id
-} 
-
-#
-_acl_list()
-{
-    _file1=$1
-
-    if [ $HOSTOS = "IRIX" ]; then
-       ls -dD $_file1 | _acl_filter_id
-    else 
-        chacl -l $_file1 | _acl_filter_id
-    fi
 }
 
 # create an ACL with n ACEs in it
@@ -143,7 +128,7 @@ _filter_aces()
        BEGIN {
            FS=":"
            while ( getline <tmpfile > 0 ) {
-               idlist[$1] = $3 
+               idlist[$1] = $3
            }
        }
        /^user/ { if ($2 in idlist) sub($2, idlist[$2]); print; next}
@@ -162,9 +147,7 @@ _filter_aces_notypes()
 
 _require_acls()
 {
-    if [ ! -x /bin/chacl -a ! -x /usr/bin/chacl -a ! -x /sbin/chacl ]; then
-       _notrun "chacl command not found"
-    fi
+    [ -n "$CHACL_PROG" ] || _notrun "chacl command not found"
 
     #
     # Test if chacl is able to list ACLs on the target filesystems.  On really
@@ -195,30 +178,42 @@ _list_acl()
 
 _require_attrs()
 {
-    [ -n $ATTR_PROG ] || _notrun "attr command not found"
-    [ -n $GETFATTR_PROG ] || _notrun "getfattr command not found"
-    [ -n $SETFATTR_PROG ] || _notrun "setfattr command not found"
+       local args
+       local nsp
 
-    #
-    # Test if chacl is able to write an attribute on the target filesystems.
-    # On really old kernels the system calls might not be implemented at all,
-    # but the more common case is that the tested filesystem simply doesn't
-    # support attributes.  Note that we can't simply list attributes as
-    # various security modules generate synthetic attributes not actually
-    # stored on disk.
-    #
-    touch $TEST_DIR/syscalltest
-    attr -s "user.xfstests" -V "attr" $TEST_DIR > $TEST_DIR/syscalltest.out 2>&1
-    cat $TEST_DIR/syscalltest.out >> $seqres.full
+       if [ $# -eq 0 ]; then
+               args="user"
+       else
+               args="$*"
+       fi
 
-    if grep -q 'Function not implemented' $TEST_DIR/syscalltest.out; then
-      _notrun "kernel does not support attrs"
-    fi
-    if grep -q 'Operation not supported' $TEST_DIR/syscalltest.out; then
-      _notrun "attrs not supported by this filesystem type: $FSTYP"
-    fi
+       [ -n "$ATTR_PROG" ] || _notrun "attr command not found"
+       [ -n "$GETFATTR_PROG" ] || _notrun "getfattr command not found"
+       [ -n "$SETFATTR_PROG" ] || _notrun "setfattr command not found"
 
-    rm -f $TEST_DIR/syscalltest.out
+       for nsp in $args; do
+               #
+               # Test if chacl is able to write an attribute on the target
+               # filesystems.  On really old kernels the system calls might
+               # not be implemented at all, but the more common case is that
+               # the tested filesystem simply doesn't support attributes.
+               # Note that we can't simply list attributes as various security
+               # modules generate synthetic attributes not actually stored on
+               # disk.
+               #
+               touch $TEST_DIR/syscalltest
+               $SETFATTR_PROG -n "$nsp.xfstests" -v "attr" $TEST_DIR/syscalltest > $TEST_DIR/syscalltest.out 2>&1
+               cat $TEST_DIR/syscalltest.out >> $seqres.full
+
+               if grep -q 'Function not implemented' $TEST_DIR/syscalltest.out; then
+                       _notrun "kernel does not support attrs"
+               fi
+               if grep -q 'Operation not supported' $TEST_DIR/syscalltest.out; then
+                       _notrun "attr namespace $nsp not supported by this filesystem type: $FSTYP"
+               fi
+
+               rm -f $TEST_DIR/syscalltest.out
+       done
 }
 
 _require_attr_v1()
@@ -232,7 +227,7 @@ _require_noattr2()
 {
        _scratch_mkfs_xfs > /dev/null 2>&1 \
                || _fail "_scratch_mkfs_xfs failed on $SCRATCH_DEV"
-       _mount -o noattr2 $SCRATCH_DEV > /dev/null 2>&1 \
+       _try_scratch_mount -o noattr2 > /dev/null 2>&1 \
                || _notrun "noattr2 mount option not supported on $SCRATCH_DEV"
        _scratch_unmount
 }
@@ -244,25 +239,91 @@ _sort_getfattr_output()
     awk '{a[FNR]=$0}END{n = asort(a); for(i=1; i <= n; i++) print a[i]"\n"}' RS=''
 }
 
+# Previously, when getfattr dumps values of all extended attributes, it prints
+# empty attr as 'user.name', but new getfattr (since attr-2.4.48) prints it as
+# 'user.name=""'. Filter out the ending '=""' so that both old and new getfattr
+# pints the same output.
+#
+# Note: This function returns the getfattr command result.
+_getfattr()
+{
+       $GETFATTR_PROG "$@" | sed -e 's/=\"\"//'
+       return ${PIPESTATUS[0]}
+}
+
 # set maximum total attr space based on fs type
-if [ "$FSTYP" == "xfs" -o "$FSTYP" == "udf" ]; then
+case "$FSTYP" in
+xfs|udf|pvfs2|9p|ceph|nfs)
        MAX_ATTRS=1000
-else # Assume max ~1 block of attrs
-       BLOCK_SIZE=`stat -f $TEST_DIR | grep "Block size" | cut -d " " -f3`
+       ;;
+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
-fi
+esac
 
 export MAX_ATTRS
 
 # Set max attr value size based on fs type
-if [ "$FSTYP" == "xfs" -o "$FSTYP" == "udf" -o "$FSTYP" == "btrfs" ]; then
+case "$FSTYP" in
+xfs|udf|btrfs)
        MAX_ATTRVAL_SIZE=64
-else # Assume max ~1 block of attrs
-       BLOCK_SIZE=`stat -f $TEST_DIR | grep "Block size" | cut -d " " -f3`
+       ;;
+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
-fi
+esac
 
 export MAX_ATTRVAL_SIZE
 # make sure this script returns success