]> git.apps.os.sepia.ceph.com Git - xfstests-dev.git/commitdiff
common: add helpers for parent pointer tests
authorAllison Henderson <allison.henderson@oracle.com>
Thu, 20 Jun 2024 20:59:01 +0000 (13:59 -0700)
committerZorro Lang <zlang@kernel.org>
Sun, 23 Jun 2024 15:04:36 +0000 (23:04 +0800)
Add helper functions in common/parent to parse and verify parent
pointers. Also add functions to check that mkfs, kernel, and xfs_io
support parent pointers.

Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
Signed-off-by: Catherine Hoang <catherine.hoang@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
[djwong: add license and copyright, dont _fail tests immediately, make
 sure the pptr-generated paths match the dir-generated paths]
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Zorro Lang <zlang@kernel.org>
common/parent [new file with mode: 0644]
common/rc
common/xfs

diff --git a/common/parent b/common/parent
new file mode 100644 (file)
index 0000000..ccdf2bb
--- /dev/null
@@ -0,0 +1,209 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2022-2024 Oracle and/or its affiliates.  All Rights Reserved.
+#
+# Parent pointer common functions
+#
+
+#
+# parse_parent_pointer parents parent_inode parent_pointer_name
+#
+# Given a list of parent pointers, find the record that matches
+# the given inode and filename
+#
+# inputs:
+# parents      : A list of parent pointers in the format of:
+#                inode/generation/name_length/name
+# parent_inode : The parent inode to search for
+# parent_name  : The parent name to search for
+#
+# outputs:
+# PPINO         : Parent pointer inode
+# PPGEN         : Parent pointer generation
+# PPNAME        : Parent pointer name
+# PPNAME_LEN    : Parent pointer name length
+#
+_xfs_parse_parent_pointer()
+{
+       local parents=$1
+       local pino=$2
+       local parent_pointer_name=$3
+
+       local found=0
+
+       # Find the entry that has the same inode as the parent
+       # and parse out the entry info
+       while IFS=':' read PPINO PPGEN PPNAME_LEN PPNAME; do
+               if [ "$PPINO" != "$pino" ]; then
+                       continue
+               fi
+
+               if [ "$PPNAME" != "$parent_pointer_name" ]; then
+                       continue
+               fi
+
+               found=1
+               break
+       done <<< $(echo "$parents")
+
+       # Check to see if we found anything
+       # We do not fail the test because we also use this
+       # routine to verify when parent pointers should
+       # be removed or updated  (ie a rename or a move
+       # operation changes your parent pointer)
+       if [ $found -eq "0" ]; then
+               return 1
+       fi
+
+       # Verify the parent pointer name length is correct
+       if [ "$PPNAME_LEN" -ne "${#parent_pointer_name}" ]
+       then
+               echo "*** Bad parent pointer:"\
+                       "name:$PPNAME, namelen:$PPNAME_LEN"
+       fi
+
+       #return sucess
+       return 0
+}
+
+#
+# _xfs_verify_parent parent_path parent_pointer_name child_path
+#
+# Verify that the given child path lists the given parent as a parent pointer
+# and that the parent pointer name matches the given name
+#
+# Examples:
+#
+# #simple example
+# mkdir testfolder1
+# touch testfolder1/file1
+# verify_parent testfolder1 file1 testfolder1/file1
+#
+# # In this above example, we want to verify that "testfolder1"
+# # appears as a parent pointer of "testfolder1/file1".  Additionally
+# # we verify that the name record of the parent pointer is "file1"
+#
+#
+# #hardlink example
+# mkdir testfolder1
+# mkdir testfolder2
+# touch testfolder1/file1
+# ln testfolder1/file1 testfolder2/file1_ln
+# verify_parent testfolder2 file1_ln testfolder1/file1
+#
+# # In this above example, we want to verify that "testfolder2"
+# # appears as a parent pointer of "testfolder1/file1".  Additionally
+# # we verify that the name record of the parent pointer is "file1_ln"
+#
+_xfs_verify_parent()
+{
+       local parent_path=$1
+       local parent_pointer_name=$2
+       local child_path=$3
+
+       local parent_ppath="$parent_path/$parent_pointer_name"
+
+       # Verify parent exists
+       if [ ! -d $SCRATCH_MNT/$parent_path ]; then
+               echo "$SCRATCH_MNT/$parent_path not found"
+       else
+               echo "*** $parent_path OK"
+       fi
+
+       # Verify child exists
+       if [ ! -f $SCRATCH_MNT/$child_path ]; then
+               echo "$SCRATCH_MNT/$child_path not found"
+       else
+               echo "*** $child_path OK"
+       fi
+
+       # Verify the parent pointer name exists as a child of the parent
+       if [ ! -f $SCRATCH_MNT/$parent_ppath ]; then
+               echo "$SCRATCH_MNT/$parent_ppath not found"
+       else
+               echo "*** $parent_ppath OK"
+       fi
+
+       # Get the inodes of both parent and child
+       pino="$(stat -c '%i' $SCRATCH_MNT/$parent_path)"
+       cino="$(stat -c '%i' $SCRATCH_MNT/$child_path)"
+
+       # Get all the parent pointers of the child
+       parents=($($XFS_IO_PROG -x -c \
+        "parent -s -i $pino -n $parent_pointer_name" $SCRATCH_MNT/$child_path))
+       if [[ $? != 0 ]]; then
+                echo "No parent pointers found for $child_path"
+       fi
+
+       # Parse parent pointer output.
+       # This sets PPINO PPGEN PPNAME PPNAME_LEN
+       _xfs_parse_parent_pointer $parents $pino $parent_pointer_name
+
+       # If we didnt find one, bail out
+       if [ $? -ne 0 ]; then
+               echo "No parent pointer record found for $parent_path"\
+                       "in $child_path"
+       fi
+
+       # Verify the inode generated by the parent pointer name is
+       # the same as the child inode
+       pppino="$(stat -c '%i' $SCRATCH_MNT/$parent_ppath)"
+       if [ $cino -ne $pppino ]
+       then
+               echo "Bad parent pointer name value for $child_path."\
+                       "$SCRATCH_MNT/$parent_ppath belongs to inode $PPPINO,"\
+                       "but should be $cino"
+       fi
+
+       # Make sure path printing works by checking that the paths returned
+       # all point to the same inode.
+       local tgt="$SCRATCH_MNT/$child_path"
+       $XFS_IO_PROG -x -c 'parent -p' "$tgt" | while read pptr_path; do
+               test "$tgt" -ef "$pptr_path" || \
+                       echo "$tgt parent pointer $pptr_path should be the same file"
+       done
+
+       echo "*** Verified parent pointer:"\
+                       "name:$PPNAME, namelen:$PPNAME_LEN"
+       echo "*** Parent pointer OK for child $child_path"
+}
+
+#
+# _xfs_verify_parent parent_pointer_name pino child_path
+#
+# Verify that the given child path contains no parent pointer entry
+# for the given inode and file name
+#
+_xfs_verify_no_parent()
+{
+       local parent_pname=$1
+       local pino=$2
+       local child_path=$3
+
+       # Verify child exists
+       if [ ! -f $SCRATCH_MNT/$child_path ]; then
+               echo "$SCRATCH_MNT/$child_path not found"
+       else
+               echo "*** $child_path OK"
+       fi
+
+       # Get all the parent pointers of the child
+       local parents=($($XFS_IO_PROG -x -c \
+        "parent -s -i $pino -n $parent_pname" $SCRATCH_MNT/$child_path))
+       if [[ $? != 0 ]]; then
+               return 0
+       fi
+
+       # Parse parent pointer output.
+       # This sets PPINO PPGEN PPNAME PPNAME_LEN
+       _xfs_parse_parent_pointer $parents $pino $parent_pname
+
+       # If we didnt find one, return sucess
+       if [ $? -ne 0 ]; then
+               return 0
+       fi
+
+       echo "Parent pointer entry found where none should:"\
+                       "inode:$PPINO, gen:$PPGEN,"
+                       "name:$PPNAME, namelen:$PPNAME_LEN"
+}
index 2dcb6d7bf1d648b98e9d0d4bd6915fce78338cbc..7100373cbf6a6b9f2e51ade5d0529ffba41e639f 100644 (file)
--- a/common/rc
+++ b/common/rc
@@ -2796,6 +2796,9 @@ _require_xfs_io_command()
                echo $testio | grep -q "invalid option" && \
                        _notrun "xfs_io $command support is missing"
                ;;
+       "parent")
+               testio=`$XFS_IO_PROG -x -c "parent" $TEST_DIR 2>&1`
+               ;;
        "pwrite")
                # -N (RWF_NOWAIT) only works with direct vectored I/O writes
                local pwrite_opts=" "
index b392237575381de78133daeadd20544ce37b0bc5..7706b562603490ca3ef5e3a5f8b72ab22dcd51a7 100644 (file)
@@ -1863,3 +1863,15 @@ _xfs_force_no_pptrs()
 
        MKFS_OPTIONS="$MKFS_OPTIONS -n parent=0"
 }
+
+# this test requires the xfs parent pointers feature
+#
+_require_xfs_parent()
+{
+       _scratch_mkfs_xfs_supported -n parent > /dev/null 2>&1 \
+               || _notrun "mkfs.xfs does not support parent pointers"
+       _scratch_mkfs_xfs -n parent > /dev/null 2>&1
+       _try_scratch_mount >/dev/null 2>&1 \
+               || _notrun "kernel does not support parent pointers"
+       _scratch_unmount
+}