> On Oct 31, 2022, at 11:18 PM, Zorro Lang <zlang@xxxxxxxxxx> wrote: > > 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 ... Thanks for the reviews! I’ll fix the typos in the next version > >> 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 >> >