overlay: run unionmount testsuite test cases
[xfstests-dev.git] / tests / xfs / 438
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2018 Huawei Technologies Co., Ltd. All Rights Reserved.
4 #
5 # FS QA Test No. 438
6 #
7 # Test for XFS umount hang problem caused by the unceasing push
8 # of dquot log item in AIL. Because xfs_qm_dqflush_done() will
9 # not be invoked, so each time xfsaild initiates the push,
10 # the push will return early after checking xfs_dqflock_nowait().
11 #
12 # xfs_qm_dqflush_done() should be invoked by xfs_buf_do_callbacks().
13 # However after the first write and the retried write of dquota buffer
14 # get the same IO error, XFS will let xfsaild to restart the write and
15 # xfs_buf_do_callbacks() will not be inovked.
16 #
17 # This test emulates the write error by using dm-flakey. The log
18 # area of the XFS filesystem is excluded from the range covered by
19 # dm-flakey, so the XFS will not be shutdown prematurely.
20 #
21 # Fixed by upstream commit 373b058 ("xfs: Properly retry failed dquot
22 # items in case of error during buffer writeback")
23 seq=`basename $0`
24 seqres=$RESULT_DIR/$seq
25 echo "QA output created by $seq"
26
27 here=`pwd`
28 tmp=/tmp/$$
29 status=1        # failure is the default!
30 trap "_cleanup; exit \$status" 0 1 2 3 15
31
32 _cleanup()
33 {
34         [ -z "${interval}" ] || \
35                 sysctl -w fs.xfs.xfssyncd_centisecs=${interval} >/dev/null 2>&1
36         cd /
37         rm -f $tmp.*
38         _unmount_flakey >/dev/null 2>&1
39         _cleanup_flakey > /dev/null 2>&1
40 }
41
42 # inject IO write error for the XFS filesystem except its log section
43 make_xfs_scratch_flakey_table()
44 {
45         local tgt=flakey
46         local opt="0 1 1 error_writes"
47         local dev=${SCRATCH_DEV}
48         local dev_sz=$(blockdev --getsz $dev)
49
50         # If using an external log device, just making the writing of
51         # entire data/metadata area fail forever.
52         if [ "${USE_EXTERNAL}" = "yes" -a ! -z "$SCRATCH_LOGDEV" ]; then
53                 echo "0 ${dev_sz} $tgt $dev 0 $opt"
54                 return
55         fi
56
57         local blk_sz=$(_scratch_xfs_get_sb_field blocksize)
58         local log_ofs=$(_scratch_xfs_get_sb_field logstart)
59         local log_sz=$(_scratch_xfs_get_sb_field logblocks)
60         local table=""
61         local ofs=0
62         local sz
63
64         log_ofs=$(_scratch_xfs_db -r -c "convert fsb ${log_ofs} bb" | \
65                           $AWK_PROG '{gsub("[()]", "", $2); print $2}')
66         let "log_sz *= blk_sz / 512"
67
68         # Add a flakey target for the area before the log section
69         # to make the data/metadata write fail forever
70         if [ "$ofs" -lt "${log_ofs}" ]; then
71                 let "sz = log_ofs - ofs"
72                 table="$ofs $sz $tgt $dev $ofs $opt"
73         fi
74
75         # Add a linear target for the log section, so the log write
76         # will work normally
77         table="$table\n${log_ofs} ${log_sz} linear $dev ${log_ofs}"
78
79         # Add a flakey target for the area after the log section
80         # to make the data/metadata write fail forever
81         let "ofs = log_ofs + log_sz"
82         if [ "$ofs" -lt "${dev_sz}" ]; then
83                 let "sz = dev_sz - ofs"
84                 table="$table\n$ofs $sz $tgt $dev $ofs $opt"
85         fi
86
87         echo -e $table
88 }
89
90 # get standard environment, filters and checks
91 . ./common/rc
92 . ./common/dmflakey
93 . ./common/quota
94
95 _supported_fs xfs
96 _supported_os Linux
97
98 # due to the injection of write IO error, the fs will be inconsistent
99 _require_scratch_nocheck
100 _require_flakey_with_error_writes
101 _require_user
102 _require_xfs_quota
103 _require_freeze
104
105 rm -f $seqres.full
106
107 echo "Silence is golden"
108
109 _scratch_mkfs > $seqres.full 2>&1
110
111 # no error will be injected
112 _init_flakey
113 $DMSETUP_PROG info >> $seqres.full
114 $DMSETUP_PROG table >> $seqres.full
115
116 # save the old value for _cleanup()
117 interval=$(sysctl -n fs.xfs.xfssyncd_centisecs 2>/dev/null)
118 # shorten the time waiting for the push of ail items
119 sysctl -w fs.xfs.xfssyncd_centisecs=100 >> $seqres.full 2>&1
120
121 _qmount_option "usrquota"
122 _mount_flakey
123
124 # We need to set the quota limitation twice, and inject the write error
125 # after the second setting. If we try to inject the write error after
126 # the first setting, the initialization of the dquota buffer will get
127 # IO error and also be retried, and during the umount process the
128 # write will be ended, and xfs_qm_dqflush_done() will be inovked, and
129 # the umount will exit normally.
130 $XFS_QUOTA_PROG -x -c "limit -u isoft=500 $qa_user" $SCRATCH_MNT
131 $XFS_QUOTA_PROG -x -c "report -ih" $SCRATCH_MNT >> $seqres.full
132
133 # ensure the initialization of the dquota buffer is done
134 xfs_freeze -f $SCRATCH_MNT
135 xfs_freeze -u $SCRATCH_MNT
136
137 # inject write IO error
138 FLAKEY_TABLE_ERROR=$(make_xfs_scratch_flakey_table)
139 _load_flakey_table ${FLAKEY_ERROR_WRITES}
140 $DMSETUP_PROG info >> $seqres.full
141 $DMSETUP_PROG table >> $seqres.full
142
143 # update the dquota buffer
144 $XFS_QUOTA_PROG -x -c "limit -u isoft=400 $qa_user" $SCRATCH_MNT
145 $XFS_QUOTA_PROG -x -c "report -ih" $SCRATCH_MNT >> $seqres.full
146
147 sync
148
149 # wait for the push of the dquota log item in AIL and
150 # the completion of the retried write of dquota buffer
151 sleep 2
152
153 _unmount_flakey
154
155 _cleanup_flakey
156
157 # success, all done
158 status=0
159 exit