On Fri, Oct 28, 2022 at 02:56:02PM -0700, Catherine Hoang wrote: > From: Allison Henderson <allison.henderson@xxxxxxxxxx> > > 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@xxxxxxxxxx> > Signed-off-by: Catherine Hoang <catherine.hoang@xxxxxxxxxx> > --- Looks good to me, just a few typo problem as below ... > common/parent | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++ > common/rc | 3 + > common/xfs | 12 +++ > 3 files changed, 213 insertions(+) > create mode 100644 common/parent > > diff --git a/common/parent b/common/parent > new file mode 100644 > index 00000000..a0ba7d92 > --- /dev/null > +++ b/common/parent > @@ -0,0 +1,198 @@ > +# > +# 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 > +# > +_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 > +} > + > +# > +# _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 _verify_parent > +# > +# # 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 _verify_parent > +# > +# # 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" > +# > +_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 > + _fail "$SCRATCH_MNT/$parent_path not found" > + else > + echo "*** $parent_path OK" > + fi > + > + # Verify child exists > + if [ ! -f $SCRATCH_MNT/$child_path ]; then > + _fail "$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 > + _fail "$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 -f -i $pino -n $parent_pointer_name" $SCRATCH_MNT/$child_path)) > + if [[ $? != 0 ]]; then > + _fail "No parent pointers found for $child_path" > + fi > + > + # Parse parent pointer output. > + # This sets PPINO PPGEN PPNAME PPNAME_LEN > + _parse_parent_pointer $parents $pino $parent_pointer_name > + > + # If we didnt find one, bail out > + if [ $? -ne 0 ]; then > + _fail "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 > + _fail "Bad parent pointer name value for $child_path."\ > + "$SCRATCH_MNT/$parent_ppath belongs to inode $PPPINO,"\ > + "but should be $cino" > + fi > + > + echo "*** Verified parent pointer:"\ > + "name:$PPNAME, namelen:$PPNAME_LEN" > + echo "*** Parent pointer OK for child $child_path" > +} > + > +# > +# _verify_parent parent_pointer_name pino child_path _verify_no_parent > +# > +# Verify that the given child path contains no parent pointer entry > +# for the given inode and file name > +# > +_verify_no_parent() > +{ > + local parent_pname=$1 > + local pino=$2 > + local child_path=$3 > + > + # Verify child exists > + if [ ! -f $SCRATCH_MNT/$child_path ]; then > + _fail "$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 -f -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 > + _parse_parent_pointer $parents $pino $parent_pname > + > + # If we didnt find one, return sucess > + if [ $? -ne 0 ]; then > + return 0 > + fi > + > + _fail "Parent pointer entry found where none should:"\ > + "inode:$PPINO, gen:$PPGEN," > + "name:$PPNAME, namelen:$PPNAME_LEN" > +} > diff --git a/common/rc b/common/rc > index d1f3d56b..9fc0a785 100644 > --- a/common/rc > +++ b/common/rc > @@ -2539,6 +2539,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=" " > diff --git a/common/xfs b/common/xfs > index 170dd621..7233a2db 100644 > --- a/common/xfs > +++ b/common/xfs > @@ -1399,3 +1399,15 @@ _xfs_filter_mkfs() > print STDOUT "realtime =RDEV extsz=XXX blocks=XXX, rtextents=XXX\n"; > }' > } > + > +# 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 > +} > -- > 2.25.1 >