[RFC PATCH v4 1/8] ext4: add common helper to check whether dirdata is applied
Artem Blagodarenko <[email protected]> Mon, 27 Jul 2026 17:13:33 -0400
| Newsgroups | org.kernel.vger.linux-ext4 |
|---|---|
| Message-ID | <[email protected]> |
From: Artem Blagodarenko <[email protected]> Add a helper that lists a directory with the -lD flags and checks whether any dirdata fields exist. This helper will be used by subsequent dirdata-related patches. Signed-off-by: Artem Blagodarenko <[email protected]> --- common/ext4 | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/common/ext4 b/common/ext4 index a2ce456d..d36ae40a 100644 --- a/common/ext4 +++ b/common/ext4 @@ -242,3 +242,66 @@ _ext4_get_inum_iflags() { debugfs -R "stat <${inumber}>" "${dev}" 2> /dev/null | \ sed -n 's/^.*Flags: \([0-9a-fx]*\).*$/\1/p' } + +# Helper to dump directory structure with hash info (requires dirdata feature) +# This is useful for verifying that dirdata is storing hash information +_dump_dir_structure() +{ + local dir=$1 + local filename=$2 + local dir_name=$(basename $dir) + local expected=$3 + + # Flush dirty filesystem buffers before reading the raw device via debugfs. + # ext4 with journaling writes directory-block changes to the journal first; + # the actual block in the backing file is not updated until checkpoint/sync. + # Without this sync, debugfs (which reads the loop device directly) may see + # stale pre-transaction data and show empty or missing dirdata fields. + sync + + local debugfs_output=$({ + echo "cd $dir_name" + echo "ls -lD ." + echo "quit" + } | debugfs $SCRATCH_DEV 2>/dev/null) + + echo " [DEBUG] debugfs output for $dir_name:" >>$seqres.full + echo "$debugfs_output" | grep -v "^debugfs:" | sed 's/^/ /' >>$seqres.full + + # When a specific filename is given, restrict to that entry's line only. + # For encrypted directories the on-disk name is ciphertext, so match by + # inode number (first field in debugfs ls -lD output) instead of name. + local search_scope="$debugfs_output" + if [ -n "$filename" ]; then + local inum + inum=$(stat -c '%i' "$dir/$filename" 2>/dev/null) + if [ -n "$inum" ]; then + search_scope=$(echo "$debugfs_output" | awk -v n="$inum" '$1 == n') + # Plain-text fallback: if inode match is empty (old debugfs + # format or different column order) try by filename. + [ -z "$search_scope" ] && \ + search_scope=$(echo "$debugfs_output" | grep -F " $filename") + else + search_scope=$(echo "$debugfs_output" | grep -F " $filename") + fi + fi + + # Check if hash data is present (encryption+casefold+dirdata case) + # or if fid data is present (dirdata+encryption or dirdata only case) + if echo "$search_scope" | grep -q "fid="; then + local fid_value=$(echo "$search_scope" | grep -o "fid=[^ ]*" | head -1 | sed 's/^fid=//') + if [ "$fid_value" = "$expected" ]; then + echo " Directory structure of $dir_name: OK (dirdata verified)" + return 0 + else + echo " Directory structure of $dir_name: FAILED (fid mismatch: got '$fid_value', expected '$expected')" + return 1 + fi + elif echo "$search_scope" | grep -q "hash="; then + echo " Directory structure of $dir_name: OK (dirdata verified)" + return 0 + else + echo " Directory structure of $dir_name: FAILED (no dirdata)" + return 1 + fi +} -- 2.43.7