generic/223: make sure all files get created on the data device
[xfstests-dev.git] / common / dmlogwrites
1 ##/bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2015 Facebook, Inc.  All Rights Reserved.
4 #
5 # common functions for setting up and tearing down a dm log-writes device
6
7 _require_log_writes()
8 {
9         [ -z "$LOGWRITES_DEV" -o ! -b "$LOGWRITES_DEV" ] && \
10                 _notrun "This test requires a valid \$LOGWRITES_DEV"
11
12         _exclude_scratch_mount_option dax
13         _require_dm_target log-writes
14         _require_test_program "log-writes/replay-log"
15 }
16
17 # Starting from v4.15-rc1, DAX support was added to dm-log-writes, but note
18 # that it doesn't track the data that we write via the mmap(), so we can't do
19 # any data integrity checking. We can only verify that the metadata writes for
20 # the page faults happened, e.g. when mmap(2) with MAP_SYNC flag.
21 #
22 # Introduce a new helper to check if dm-log-writes target supports DAX
23 # explicitly. But this is considered as a temporary workaround, we want to move
24 # all the DAX check back to _require_log_writes when dm-log-writes gains full
25 # DAX support and remove this helper.
26 #
27 # Check if dax mount options are supported
28 # $1 can be either 'dax=always' or 'dax'
29 # dax=always
30 #      Check for the new dax options (dax=inode, dax=always or dax=never)
31 #      by passing "dax=always".
32 # dax
33 #      Check for the old dax or new dax=always by passing "dax".
34 # This only accepts 'dax=always' because dax=always, dax=inode and
35 # dax=never are always supported together.  So if the other options are
36 # required checking for 'dax=always' indicates support for the other 2.
37 _require_log_writes_dax_mountopt()
38 {
39         [ -z "$LOGWRITES_DEV" -o ! -b "$LOGWRITES_DEV" ] && \
40                 _notrun "This test requires a valid \$LOGWRITES_DEV"
41
42         _require_dm_target log-writes
43         _require_test_program "log-writes/replay-log"
44
45         local ret=0
46         local mountopt=$1
47
48         _log_writes_init $SCRATCH_DEV
49         _log_writes_mkfs > /dev/null 2>&1
50         _log_writes_mount "-o $mountopt" > /dev/null 2>&1
51         # Check options to be sure.
52         # XFS ignores dax option(or changes it to dax=never)
53         # and goes on if dev underneath does not support dax.
54         _fs_options $LOGWRITES_DMDEV | egrep -q "dax(=always|,|$)"
55         ret=$?
56         _log_writes_cleanup
57         if [ $ret -ne 0 ]; then
58                 _notrun "$LOGWRITES_DMDEV $FSTYP does not support -o $mountopt"
59         fi
60 }
61
62 _log_writes_init()
63 {
64         blkdev=$1
65
66         [ -z "$blkdev" ] && _fail \
67         "block dev must be specified for _log_writes_init"
68
69         local BLK_DEV_SIZE=`blockdev --getsz $blkdev`
70         LOGWRITES_NAME=logwrites-test
71         LOGWRITES_DMDEV=/dev/mapper/$LOGWRITES_NAME
72         LOGWRITES_TABLE="0 $BLK_DEV_SIZE log-writes $blkdev $LOGWRITES_DEV"
73         _dmsetup_create $LOGWRITES_NAME --table "$LOGWRITES_TABLE" || \
74                 _fail "failed to create log-writes device"
75 }
76
77 _log_writes_mark()
78 {
79         [ $# -ne 1 ] && _fail "_log_writes_mark takes one argument"
80         $DMSETUP_PROG message $LOGWRITES_NAME 0 mark $1
81 }
82
83 _log_writes_mkfs()
84 {
85         _scratch_options mkfs
86         _mkfs_dev $SCRATCH_OPTIONS $@ $LOGWRITES_DMDEV
87         _log_writes_mark mkfs
88 }
89
90 _log_writes_mount()
91 {
92         _scratch_options mount
93         $MOUNT_PROG -t $FSTYP `_common_dev_mount_options $*` $SCRATCH_OPTIONS \
94                 $LOGWRITES_DMDEV $SCRATCH_MNT
95 }
96
97 _log_writes_unmount()
98 {
99         $UMOUNT_PROG $SCRATCH_MNT
100 }
101
102 # _log_writes_replay_log <mark>
103 #
104 # This replays the log contained on $LOGWRITES_DEV onto blkdev upto the
105 # mark passed in.
106 _log_writes_replay_log()
107 {
108         _mark=$1
109         _blkdev=$2
110
111         [ -z "$_blkdev" ] && _fail \
112         "block dev must be specified for _log_writes_replay_log"
113
114         $here/src/log-writes/replay-log --log $LOGWRITES_DEV --find \
115                 --end-mark $_mark >> $seqres.full 2>&1
116         [ $? -ne 0 ] && _fail "mark '$_mark' does not exist"
117
118         $here/src/log-writes/replay-log --log $LOGWRITES_DEV --replay $_blkdev \
119                 --end-mark $_mark >> $seqres.full 2>&1
120         [ $? -ne 0 ] && _fail "replay failed"
121 }
122
123 _log_writes_remove()
124 {
125         _dmsetup_remove $LOGWRITES_NAME
126 }
127
128 _log_writes_cleanup()
129 {
130         $UMOUNT_PROG $SCRATCH_MNT > /dev/null 2>&1
131         _log_writes_remove
132 }
133
134 # Convert log writes mark to entry number
135 # Result entry number is output to stdout, could be empty if not found
136 _log_writes_mark_to_entry_number()
137 {
138         local mark=$1
139         local ret
140
141         [ -z "$mark" ] && _fatal \
142                 "mark must be given for _log_writes_mark_to_entry_number"
143
144         ret=$($here/src/log-writes/replay-log --find --log $LOGWRITES_DEV \
145                 --end-mark $mark 2> /dev/null)
146         [ -z "$ret" ] && return
147         ret=$(echo "$ret" | cut -f1 -d\@)
148         echo "mark $mark has entry number $ret" >> $seqres.full
149         echo "$ret"
150 }
151
152 # Find next fua write entry number
153 # Result entry number is output to stdout, could be empty if not found
154 _log_writes_find_next_fua()
155 {
156         local start_entry=$1
157         local ret
158
159         [ -z "$start_entry" ] && start_entry=0
160         ret=$($here/src/log-writes/replay-log --find --log $LOGWRITES_DEV \
161               --next-fua --start-entry $start_entry 2> /dev/null)
162         [ -z "$ret" ] && return
163
164         # Result should be something like "1024@offset" where 1024 is the
165         # entry number we need
166         ret=$(echo "$ret" | cut -f1 -d\@)
167         echo "next fua is entry number $ret" >> $seqres.full
168         echo "$ret"
169 }
170
171 # Replay log range to specified entry
172 # $1:   End entry. The entry with this number *WILL* be replayed
173 _log_writes_replay_log_range()
174 {
175         local end=$1
176         local blkdev=$2
177
178         [ -z "$end" ] && _fail \
179         "end entry must be specified for _log_writes_replay_log_range"
180         [ -z "$blkdev" ] && _fail \
181         "block dev must be specified for _log_writes_replay_log_range"
182
183         # To ensure we replay the last entry,
184         # we need to manually increase the end entry number to ensure
185         # it's played
186         echo "=== replay to $end ===" >> $seqres.full
187         $here/src/log-writes/replay-log --log $LOGWRITES_DEV \
188                 --replay $blkdev --limit $(($end + 1)) \
189                 >> $seqres.full 2>&1
190         [ $? -ne 0 ] && _fail "replay failed"
191 }