blob: ccdf2bb4bda8879afd1839e7e3896041737d3802 [file] [log] [blame]
#! /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"
}