generic/019: don't dump cores when fio/fsstress hit io errors
[xfstests-dev.git] / common / dmthin
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2015 Red Hat, Inc.  All Rights Reserved.
4 #
5 # common functions for setting up and tearing down a dmthin device
6
7 # SOOO many devices!
8 # Create the 2 pool devices on lvs so we can build the whole thing
9 # from a single scratch device
10
11 # Backing data dev
12 DMTHIN_DATA_NAME="thin-data"
13 DMTHIN_DATA_DEV="/dev/mapper/$DMTHIN_DATA_NAME"
14 # Backing metadata dev
15 DMTHIN_META_NAME="thin-meta"
16 DMTHIN_META_DEV="/dev/mapper/$DMTHIN_META_NAME"
17 # Backing pool dev (combination of above)
18 DMTHIN_POOL_NAME="thin-provision-pool"
19 DMTHIN_POOL_DEV="/dev/mapper/$DMTHIN_POOL_NAME"
20 # Thin volume
21 DMTHIN_VOL_NAME="thin-vol"
22 DMTHIN_VOL_DEV="/dev/mapper/$DMTHIN_VOL_NAME"
23
24 _dmthin_cleanup()
25 {
26         $UMOUNT_PROG $SCRATCH_MNT > /dev/null 2>&1
27         _dmsetup_remove $DMTHIN_VOL_NAME
28         _dmsetup_remove $DMTHIN_POOL_NAME
29         _dmsetup_remove $DMTHIN_META_NAME
30         _dmsetup_remove $DMTHIN_DATA_NAME
31 }
32
33 _dmthin_check_fs()
34 {
35         $UMOUNT_PROG $SCRATCH_MNT > /dev/null 2>&1
36         _check_scratch_fs $DMTHIN_VOL_DEV
37 }
38
39 # Set up a dm-thin device on $SCRATCH_DEV
40 #
41 # All arguments are optional, and in this order; defaults follows:
42 # data_dev_size: half of $SCRATCH_DEV
43 # virtual_size: 10x $data_dev_size
44 # cluster_size: 512k
45 # low_water: 100M
46 #
47 # You may specify 0 to 4 of these arguments, but they
48 # must be in the above order.
49 _dmthin_init()
50 {
51         local data_dev_size=$1  # Backing pool data size in sectors
52         local virtual_size=$2   # Virtual size in sectors
53         local cluster_size=$3   # cluster/alloc size, sectors
54         local low_water=$4      # low water mark, sectors
55
56         local dm_backing_dev=$SCRATCH_DEV
57         local blk_dev_size=`blockdev --getsz $dm_backing_dev`
58
59         local pool_id=$RANDOM
60
61         # Default to something small-ish
62         if [ -z "$data_dev_size" ]; then
63                 data_dev_size=$(($blk_dev_size / 2))
64         fi
65
66         # Default to something big-is; 10x backing
67         if [ -z "$virtual_size" ]; then
68                 virtual_size=$(($data_dev_size * 10))
69         fi
70
71         # Default to 512k
72         if [ -z "$cluster_size" ]; then
73                 cluster_size=1024       # 512k in sectors
74         fi
75
76         # Default to 100M
77         if [ -z "$low_water" ]; then
78                 low_water=204800        # 100M, in sectors
79         fi
80         # low_water is expressed in blocks of size $cluster_size
81         low_water=$((low_water / cluster_size))
82
83         # Need to make linear metadata and data devs.  From kernel docs:
84         # As a guide, we suggest you calculate the number of bytes to use in the
85         # metadata device as 48 * $data_dev_size / $data_block_size but round it up
86         # to 2MB (4096 sectors) if the answer is smaller.
87         # So do that:
88
89         local meta_dev_size=$((48 * $data_dev_size / $cluster_size))
90         if [ "$meta_dev_size" -lt "4096" ]; then
91                 meta_dev_size=4096      # 2MB
92         fi
93
94         # scratch dev gets a metadata vol & data vol, start at this offset
95         local meta_dev_offset=10240
96
97         local total_data_dev_size=$(($meta_dev_offset + $meta_dev_size + $data_dev_size))
98         if [ "$total_data_dev_size" -gt "$blk_dev_size" ]; then
99                 _notrun "$SCRATCH_DEV too small"
100         fi
101
102         # Unmount & tear down old stuff
103         _dmthin_cleanup
104
105         # Metadata device
106         DMTHIN_META_TABLE="0 $meta_dev_size linear $dm_backing_dev $meta_dev_offset"
107         _dmsetup_create $DMTHIN_META_NAME --table "$DMTHIN_META_TABLE" || \
108                 _fatal "failed to create dm thin meta device"
109
110         # Data device
111         local data_dev_offset=$((meta_dev_offset + $meta_dev_size))
112         DMTHIN_DATA_TABLE="0 $data_dev_size linear $dm_backing_dev $data_dev_offset"
113         _dmsetup_create $DMTHIN_DATA_NAME --table "$DMTHIN_DATA_TABLE" || \
114                 _fatal "failed to create dm thin data device"
115
116         # Zap the pool metadata dev.  Explicitly fsync the zeroes to disk
117         # because a slow-running udev running concurrently with dd can maintain
118         # an open file descriptor.  The block layer only flushes the page cache
119         # on last close, which means that the thin pool creation below will
120         # see the (stale) ondisk contents and fail.
121         dd if=/dev/zero of=$DMTHIN_META_DEV bs=4096 count=1 conv=fsync &>/dev/null
122
123         # Thin pool
124         # "start length thin-pool metadata_dev data_dev data_block_size low_water_mark"
125         DMTHIN_POOL_TABLE="0 $data_dev_size thin-pool $DMTHIN_META_DEV $DMTHIN_DATA_DEV $cluster_size $low_water"
126         _dmsetup_create $DMTHIN_POOL_NAME --table "$DMTHIN_POOL_TABLE" || \
127                 _fatal "failed to create dm thin pool device"
128
129         # Thin volume
130         $DMSETUP_PROG message $DMTHIN_POOL_DEV 0 "create_thin $pool_id" || \
131                 _fatal "failed to message pool device"
132
133         # start length thin pool_dev dev_id [external_origin_dev]
134         DMTHIN_VOL_TABLE="0 $virtual_size thin $DMTHIN_POOL_DEV $pool_id"
135         _dmsetup_create $DMTHIN_VOL_NAME --table "$DMTHIN_VOL_TABLE" || \
136                 _fatal "failed to create dm thin volume device"
137
138 }
139
140 # for internal use
141 _dmthin_reload_table()
142 {
143         local dev_name=$1
144         local table="$2"
145
146         $DMSETUP_PROG suspend $dev_name || \
147                 _fail  "dmsetup suspend of $dev_name failed"
148
149         $DMSETUP_PROG load $dev_name --table "$table" || \
150                 _fail "dmsetup failed to reload $dev_name table"
151
152         $DMSETUP_PROG resume $dev_name || \
153                 _fail  "dmsetup resume of $dev_name failed"
154
155 }
156
157 # Grow the dm-thin device by the given amount
158 # Argument is number of sectors to add, if not specified
159 # defaults to 1/4 of the $SCRATCH_DEV size
160 _dmthin_grow()
161 {
162         local add_sectors=$1    # Number of sectors to add
163
164         local dm_backing_dev=$SCRATCH_DEV
165         local blk_dev_size=`blockdev --getsz $dm_backing_dev`
166
167         # Get current sizes & values
168         local   meta_dev_size=`$DMSETUP_PROG table | grep ^$DMTHIN_META_NAME | awk '{print $3}'`
169         local meta_dev_offset=`$DMSETUP_PROG table | grep ^$DMTHIN_META_NAME | awk '{print $6}'`
170         local   data_dev_size=`$DMSETUP_PROG table | grep ^$DMTHIN_DATA_NAME | awk '{print $3}'`
171         local   pool_dev_size=`$DMSETUP_PROG table | grep ^$DMTHIN_POOL_NAME | awk '{print $3}'`
172         local    cluster_size=`$DMSETUP_PROG table | grep ^$DMTHIN_POOL_NAME | awk '{print $7}'`
173         local       low_water=`$DMSETUP_PROG table | grep ^$DMTHIN_POOL_NAME | awk '{print $8}'`
174
175         # default to 25% growth
176         if [ -z "$add_sectors" ]; then
177                 add_sectors=$(($data_dev_size / 4))
178         fi
179
180         local data_dev_offset=$(($meta_dev_offset + $meta_dev_size))
181
182         # Figure new sizes
183         data_dev_size=$(($data_dev_size + $add_sectors))
184         pool_dev_size=$(($pool_dev_size + $add_sectors))
185
186         # Can we do this?
187         local total_data_dev_size=$(($meta_dev_offset + $meta_dev_size + $data_dev_size))
188         if [ "$total_data_dev_size" -gt "$blk_dev_size" ]; then
189                 _fail "$SCRATCH_DEV too small"
190         fi
191
192         # Grow the data device
193         DMTHIN_DATA_TABLE="0 $data_dev_size linear $dm_backing_dev $data_dev_offset"
194         _dmthin_reload_table $DMTHIN_DATA_NAME "$DMTHIN_DATA_TABLE"
195
196         # Grow the pool
197         DMTHIN_POOL_TABLE="0 $data_dev_size thin-pool $DMTHIN_META_DEV $DMTHIN_DATA_DEV $cluster_size $low_water"
198         _dmthin_reload_table $DMTHIN_POOL_NAME "$DMTHIN_POOL_TABLE"
199 }
200
201 # Queue IOs when full
202 _dmthin_set_queue()
203 {
204         local   data_dev_size=`$DMSETUP_PROG table | grep $DMTHIN_DATA_NAME | awk '{print $3}'`
205         local    cluster_size=`$DMSETUP_PROG table | grep $DMTHIN_POOL_NAME | awk '{print $7}'`
206         local       low_water=`$DMSETUP_PROG table | grep $DMTHIN_POOL_NAME | awk '{print $8}'`
207
208         DMTHIN_POOL_TABLE="0 $data_dev_size thin-pool $DMTHIN_META_DEV $DMTHIN_DATA_DEV $cluster_size $low_water"
209         _dmthin_reload_table $DMTHIN_POOL_NAME "$DMTHIN_POOL_TABLE"
210 }
211
212 # Fail IOs when full
213 _dmthin_set_fail()
214 {
215         local   data_dev_size=`$DMSETUP_PROG table | grep $DMTHIN_DATA_NAME | awk '{print $3}'`
216         local    cluster_size=`$DMSETUP_PROG table | grep $DMTHIN_POOL_NAME | awk '{print $7}'`
217         local       low_water=`$DMSETUP_PROG table | grep $DMTHIN_POOL_NAME | awk '{print $8}'`
218
219         DMTHIN_POOL_TABLE="0 $data_dev_size thin-pool $DMTHIN_META_DEV $DMTHIN_DATA_DEV $cluster_size $low_water 1 error_if_no_space"
220         _dmthin_reload_table $DMTHIN_POOL_NAME "$DMTHIN_POOL_TABLE"
221 }
222
223 _dmthin_mount_options()
224 {
225         _scratch_options mount
226         echo `_common_dev_mount_options $*` $SCRATCH_OPTIONS $DMTHIN_VOL_DEV $SCRATCH_MNT
227 }
228
229 _dmthin_mount()
230 {
231         _mount -t $FSTYP `_dmthin_mount_options $*`
232 }
233
234 _dmthin_mkfs()
235 {
236         _scratch_options mkfs
237         _mkfs_dev $SCRATCH_OPTIONS $@ $DMTHIN_VOL_DEV
238 }