From patchwork Tue Jun 18 00:51:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13701617 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A01705C89; Tue, 18 Jun 2024 00:51:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718671887; cv=none; b=oe5DyxL+iBuF5PYsDkQP2F0vWC+rxnV56FEnNPXBM79XpirakCBE2CLtu5UX5vH8DELY/3bptQWZoluNA8hLVnjS4y6+0z/Nuvl8JvVzieiLeBdN//l3KrUt0Fb6NSgX9vKNBDLCte7aN+a4P+wTHA6kj5Olb0Hu1ypkBs14rrM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718671887; c=relaxed/simple; bh=CBjH4gAtfkBRO17FvLcsMb+COe/3rtjE68YenzoGUd8=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=BFmmHvHur3u9Zix4VSv7aA94yePwTCCGWp+xe7tq4ZhfNomkihl9U6K3Fz7Lu+jJ+vp3cib0Z4vI/Kg/q7XvJvBBGPlvV4W6clNtxE/AwiLHzOzHORCN7wLyfbp6wC2IL2yeuUvbirWJ9AV7614cQk7GlYndQO+w7nc6VsjMo2g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IwAK4VcB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IwAK4VcB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6CE75C4AF4D; Tue, 18 Jun 2024 00:51:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1718671887; bh=CBjH4gAtfkBRO17FvLcsMb+COe/3rtjE68YenzoGUd8=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=IwAK4VcBjSSxH3xTDgWDhwHf7D1e3QFsUcBGlwr1iisnoKiUTMkez/lY+hM1wlQ5B J1f4vsSCt87EYiB/c4Y0SDb4Apha1Z8qpUrTr//C1dYAd/lw6ihVLEOd0I7CAnjanU C8tm2/0glg1+yF5JwnBERmeiRB7Co74SP7cJM8ICeLRfok45ODLQwok3BQam0X5TPa vygT5Imf72Xpc2DCltjpoSDOOJYMnLzkb6tz/bOveMQGWgVbYnx6ozqntr8Pk77W9o eQ2j6Xv2u/RG1kMtINuoypX6J9UynAUqogbyZFCBRqQzm66yjdHACmijoJ2EEZHvug 5HVuR2IEztcmw== Date: Mon, 17 Jun 2024 17:51:27 -0700 Subject: [PATCH 08/11] common: add helpers for parent pointer tests From: "Darrick J. Wong" To: djwong@kernel.org, zlang@redhat.com Cc: Allison Henderson , Catherine Hoang , fstests@vger.kernel.org, guan@eryu.me, linux-xfs@vger.kernel.org, allison.henderson@oracle.com, catherine.hoang@oracle.com Message-ID: <171867145930.793846.17850395645232280136.stgit@frogsfrogsfrogs> In-Reply-To: <171867145793.793846.15869014995794244448.stgit@frogsfrogsfrogs> References: <171867145793.793846.15869014995794244448.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Allison Henderson 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 Signed-off-by: Catherine Hoang Reviewed-by: Darrick J. Wong [djwong: add license and copyright, dont _fail tests immediately, make sure the pptr-generated paths match the dir-generated paths] Signed-off-by: Darrick J. Wong --- common/parent | 209 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ common/rc | 3 + common/xfs | 12 +++ 3 files changed, 224 insertions(+) create mode 100644 common/parent diff --git a/common/parent b/common/parent new file mode 100644 index 0000000000..5ef0172bef --- /dev/null +++ b/common/parent @@ -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 +# +_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 +# +# # 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" +# +_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 + _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" +} + +# +# _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 +# +_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 + _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" +} diff --git a/common/rc b/common/rc index ba26fda6e6..0e0d49b87a 100644 --- a/common/rc +++ b/common/rc @@ -2742,6 +2742,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 6fc7d83251..fc1ef60dbb 100644 --- a/common/xfs +++ b/common/xfs @@ -1862,3 +1862,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 +}