The test is relying on the fact that an fsync on directory "a" will
result in persisting the changes of its subdirectory "b", namely the
rename of "/a/b/foo" to "/c/foo". For this particular filesystem layout,
that will happen on btrfs, because all the directory entries end up in
the same metadata leaf. However that is not a behaviour we can always
guarantee on btrfs. For example, if we add more files to directory
"a" before and after creating subdirectory "b", like this:
mkdir $SCRATCH_MNT/a
for ((i = 0; i < 1000; i++)); do
echo -n > $SCRATCH_MNT/a/file_$i
done
mkdir $SCRATCH_MNT/a/b
for ((i = 1000; i < 2000; i++)); do
echo -n > $SCRATCH_MNT/a/file_$i
done
mkdir $SCRATCH_MNT/c
touch $SCRATCH_MNT/a/b/foo
sync
# The rest of the test remains unchanged...
(...)
Then after fsyncing only directory "a", the rename of file "foo" from
"/a/b/foo" to "/c/foo" is not persisted.
Guaranteeing that on btrfs would be expensive on large directories, as
it would require scanning for every subdirectory. It's also not required
by posix for the fsync on a directory to persist changes inside its
subdirectories. So add an explicit fsync on file "foo" when the filesystem
being tested is btrfs.
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Eryu Guan <guaneryu@gmail.com>
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
touch $SCRATCH_MNT/a/bar
$XFS_IO_PROG -c "fsync" $SCRATCH_MNT/a
+# btrfs can not guarantee that when we fsync a directory all its subdirectories
+# created on past transactions are fsynced as well. It may do it sometimes, but
+# it's not guaranteed, giving such guarantees would be too expensive for large
+# directories and posix does not require that recursive behaviour. So if we want
+# the rename of "foo" to be persisted, explicitly fsync "foo".
+if [ $FSTYP == "btrfs" ]; then
+ $XFS_IO_PROG -c "fsync" $SCRATCH_MNT/c/foo
+fi
+
echo "Filesystem content before power failure:"
ls -R $SCRATCH_MNT/a $SCRATCH_MNT/c | _filter_scratch