summaryrefslogtreecommitdiff
path: root/tests/generic/677
blob: 84146c5e04ece49290c930241d01586195a01790 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2022 SUSE Linux Products GmbH.  All Rights Reserved.
#
# FS QA Test 677
#
# Test that after a full fsync of a file with preallocated extents beyond the
# file's size, if a power failure happens, the preallocated extents still exist
# after we mount the filesystem.
#
. ./common/preamble
_begin_fstest auto quick log prealloc fiemap

_cleanup()
{
	_cleanup_flakey
	cd /
	rm -r -f $tmp.*
}

. ./common/filter
. ./common/dmflakey
. ./common/punch

# real QA test starts here

_supported_fs generic
_require_scratch
_require_dm_target flakey
_require_xfs_io_command "falloc" "-k"
_require_xfs_io_command "fiemap"
_require_odirect

rm -f $seqres.full

_scratch_mkfs >>$seqres.full 2>&1
_require_metadata_journaling $SCRATCH_DEV
_init_flakey
_mount_flakey

# The fiemap results in the golden output requires file allocations to align to
# 1MB boundaries.
_require_congruent_file_oplen $SCRATCH_MNT 1048576

# Create our test file with many extents.
# On btrfs this results in having multiple leaves of metadata full of file
# extent items, a condition necessary to trigger the original bug.
#
# We use direct IO here because:
#
# 1) It's faster then doing fsync after each buffered write;
#
# 2) For btrfs, the first fsync would clear the inode's full sync runtime flag,
#    and we want the fsync below to trigger the full fsync code path of btrfs.
$XFS_IO_PROG -f -d -c "pwrite -b 4K 0 16M" $SCRATCH_MNT/foo | _filter_xfs_io

# Now add two preallocated extents to our file without extending the file's size.
# One right at i_size, and another further beyond, leaving a gap between the two
# prealloc extents.
$XFS_IO_PROG -c "falloc -k 16M 1M" $SCRATCH_MNT/foo
$XFS_IO_PROG -c "falloc -k 20M 1M" $SCRATCH_MNT/foo

# Make sure everything is durably persisted.
# On btrfs this commits the current transaction and it makes all the created
# extents to have a generation lower than the generation of the transaction used
# by the next write and fsync.
sync

# Now overwrite only the first extent.
# On btrfs, due to COW (both data and metadata), that results in modifying only
# the first leaf of metadata for our inode (we replace a file extent item and
# update the inode item). Then fsync it. On btrfs this fsync will use the slow
# code path because it's the first fsync since the inode was created/loaded.
$XFS_IO_PROG -c "pwrite 0 4K" -c "fsync" $SCRATCH_MNT/foo | _filter_xfs_io

# Simulate a power failure and then mount again the filesystem to replay the log
# tree.
_flakey_drop_and_remount

# After the power failure we expect that the preallocated extents, beyond the
# inode's i_size, still exist.
echo "List of extents after power failure:"
$XFS_IO_PROG -c "fiemap -v" $SCRATCH_MNT/foo | _filter_fiemap

_unmount_flakey

# success, all done
status=0
exit