3 # Copyright (c) 2015 Red Hat, Inc. All Rights Reserved.
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License as
7 # published by the Free Software Foundation.
9 # This program is distributed in the hope that it would be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write the Free Software Foundation,
16 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 # common functions for setting up and tearing down a dmthin device
22 # Create the 2 pool devices on lvs so we can build the whole thing
23 # from a single scratch device
26 DMTHIN_DATA_NAME="thin-data"
27 DMTHIN_DATA_DEV="/dev/mapper/$DMTHIN_DATA_NAME"
28 # Backing metadata dev
29 DMTHIN_META_NAME="thin-meta"
30 DMTHIN_META_DEV="/dev/mapper/$DMTHIN_META_NAME"
31 # Backing pool dev (combination of above)
32 DMTHIN_POOL_NAME="thin-pool"
33 DMTHIN_POOL_DEV="/dev/mapper/$DMTHIN_POOL_NAME"
35 DMTHIN_VOL_NAME="thin-vol"
36 DMTHIN_VOL_DEV="/dev/mapper/$DMTHIN_VOL_NAME"
40 $UMOUNT_PROG $SCRATCH_MNT > /dev/null 2>&1
41 $DMSETUP_PROG remove $DMTHIN_VOL_NAME> /dev/null 2>&1
42 $DMSETUP_PROG remove $DMTHIN_POOL_NAME> /dev/null 2>&1
43 $DMSETUP_PROG remove $DMTHIN_META_NAME> /dev/null 2>&1
44 $DMSETUP_PROG remove $DMTHIN_DATA_NAME> /dev/null 2>&1
49 $UMOUNT_PROG $SCRATCH_MNT > /dev/null 2>&1
50 _check_scratch_fs $DMTHIN_VOL_DEV
53 # Set up a dm-thin device on $SCRATCH_DEV
55 # All arguments are optional, and in this order; defaults follows:
56 # data_dev_size: half of $SCRATCH_DEV
57 # virtual_size: 10x $data_dev_size
61 # You may specify 0 to 4 of these arguments, but they
62 # must be in the above order.
65 local data_dev_size=$1 # Backing pool data size in sectors
66 local virtual_size=$2 # Virtual size in sectors
67 local cluster_size=$3 # cluster/alloc size, sectors
68 local low_water=$4 # low water mark, sectors
70 local dm_backing_dev=$SCRATCH_DEV
71 local blk_dev_size=`blockdev --getsz $dm_backing_dev`
75 # Default to something small-ish
76 if [ -z "$data_dev_size" ]; then
77 data_dev_size=$(($blk_dev_size / 2))
80 # Default to something big-is; 10x backing
81 if [ -z "$virtual_size" ]; then
82 virtual_size=$(($data_dev_size * 10))
86 if [ -z "$cluster_size" ]; then
87 cluster_size=1024 # 512k in sectors
91 if [ -z "$low_water" ]; then
92 low_water=204800 # 100M, in sectors
95 # Need to make linear metadata and data devs. From kernel docs:
96 # As a guide, we suggest you calculate the number of bytes to use in the
97 # metadata device as 48 * $data_dev_size / $data_block_size but round it up
98 # to 2MB (4096 sectors) if the answer is smaller.
101 local meta_dev_size=$((48 * $data_dev_size / $cluster_size))
102 if [ "$meta_dev_size" -lt "4096" ]; then
103 meta_dev_size=4096 # 2MB
106 # scratch dev gets a metadata vol & data vol, start at this offset
107 local meta_dev_offset=10240
109 local total_data_dev_size=$(($meta_dev_offset + $meta_dev_size + $data_dev_size))
110 if [ "$total_data_dev_size" -gt "$blk_dev_size" ]; then
111 _notrun "$SCRATCH_DEV too small"
114 # Unmount & tear down old stuff
118 DMTHIN_META_TABLE="0 $meta_dev_size linear $dm_backing_dev $meta_dev_offset"
119 $DMSETUP_PROG create $DMTHIN_META_NAME --table "$DMTHIN_META_TABLE" || \
120 _fatal "failed to create dm thin meta device"
123 local data_dev_offset=$((meta_dev_offset + $meta_dev_size))
124 DMTHIN_DATA_TABLE="0 $data_dev_size linear $dm_backing_dev $data_dev_offset"
125 $DMSETUP_PROG create $DMTHIN_DATA_NAME --table "$DMTHIN_DATA_TABLE" || \
126 _fatal "failed to create dm thin data device"
128 # Zap the pool metadata dev
129 dd if=/dev/zero of=$DMTHIN_META_DEV bs=4096 count=1 &>/dev/null
132 # "start length thin-pool metadata_dev data_dev data_block_size low_water_mark"
133 DMTHIN_POOL_TABLE="0 $data_dev_size thin-pool $DMTHIN_META_DEV $DMTHIN_DATA_DEV $cluster_size $low_water"
134 $DMSETUP_PROG create $DMTHIN_POOL_NAME --table "$DMTHIN_POOL_TABLE" || \
135 _fatal "failed to create dm thin pool device"
138 $DMSETUP_PROG message $DMTHIN_POOL_DEV 0 "create_thin $pool_id" || \
139 _fatal "failed to message pool device"
141 # start length thin pool_dev dev_id [external_origin_dev]
142 DMTHIN_VOL_TABLE="0 $virtual_size thin $DMTHIN_POOL_DEV $pool_id"
143 $DMSETUP_PROG create $DMTHIN_VOL_NAME --table "$DMTHIN_VOL_TABLE" || \
144 _fatal "failed to create dm thin volume device"
149 _dmthin_reload_table()
154 $DMSETUP_PROG suspend $dev_name || \
155 _fail "dmsetup suspend of $dev_name failed"
157 $DMSETUP_PROG load $dev_name --table "$table" || \
158 _fail "dmsetup failed to reload $dev_name table"
160 $DMSETUP_PROG resume $dev_name || \
161 _fail "dmsetup resume of $dev_name failed"
165 # Grow the dm-thin device by the given amount
166 # Argument is number of sectors to add, if not specified
167 # defaults to 1/4 of the $SCRATCH_DEV size
170 local add_sectors=$1 # Number of sectors to add
172 local dm_backing_dev=$SCRATCH_DEV
173 local blk_dev_size=`blockdev --getsz $dm_backing_dev`
175 # Get current sizes & values
176 local meta_dev_size=`$DMSETUP_PROG table | grep $DMTHIN_META_NAME | awk '{print $3}'`
177 local meta_dev_offset=`$DMSETUP_PROG table | grep $DMTHIN_META_NAME | awk '{print $6}'`
178 local data_dev_size=`$DMSETUP_PROG table | grep $DMTHIN_DATA_NAME | awk '{print $3}'`
179 local pool_dev_size=`$DMSETUP_PROG table | grep $DMTHIN_POOL_NAME | awk '{print $3}'`
180 local cluster_size=`$DMSETUP_PROG table | grep $DMTHIN_POOL_NAME | awk '{print $7}'`
181 local low_water=`$DMSETUP_PROG table | grep $DMTHIN_POOL_NAME | awk '{print $8}'`
183 # default to 25% growth
184 if [ -z "$add_sectors" ]; then
185 add_sectors=$(($data_dev_size / 4))
188 local data_dev_offset=$(($meta_dev_offset + $meta_dev_size))
191 data_dev_size=$(($data_dev_size + $add_sectors))
192 pool_dev_size=$(($pool_dev_size + $add_sectors))
195 local total_data_dev_size=$(($meta_dev_offset + $meta_dev_size + $data_dev_size))
196 if [ "$total_data_dev_size" -gt "$blk_dev_size" ]; then
197 _fail "$SCRATCH_DEV too small"
200 # Grow the data device
201 DMTHIN_DATA_TABLE="0 $data_dev_size linear $dm_backing_dev $data_dev_offset"
202 _dmthin_reload_table $DMTHIN_DATA_NAME "$DMTHIN_DATA_TABLE"
205 DMTHIN_POOL_TABLE="0 $data_dev_size thin-pool $DMTHIN_META_DEV $DMTHIN_DATA_DEV $cluster_size $low_water"
206 _dmthin_reload_table $DMTHIN_POOL_NAME "$DMTHIN_POOL_TABLE"
209 # Queue IOs when full
212 local data_dev_size=`$DMSETUP_PROG table | grep $DMTHIN_DATA_NAME | awk '{print $3}'`
213 local cluster_size=`$DMSETUP_PROG table | grep $DMTHIN_POOL_NAME | awk '{print $7}'`
214 local low_water=`$DMSETUP_PROG table | grep $DMTHIN_POOL_NAME | awk '{print $8}'`
216 DMTHIN_POOL_TABLE="0 $data_dev_size thin-pool $DMTHIN_META_DEV $DMTHIN_DATA_DEV $cluster_size $low_water"
217 _dmthin_reload_table $DMTHIN_POOL_NAME "$DMTHIN_POOL_TABLE"
223 local data_dev_size=`$DMSETUP_PROG table | grep $DMTHIN_DATA_NAME | awk '{print $3}'`
224 local cluster_size=`$DMSETUP_PROG table | grep $DMTHIN_POOL_NAME | awk '{print $7}'`
225 local low_water=`$DMSETUP_PROG table | grep $DMTHIN_POOL_NAME | awk '{print $8}'`
227 DMTHIN_POOL_TABLE="0 $data_dev_size thin-pool $DMTHIN_META_DEV $DMTHIN_DATA_DEV $cluster_size $low_water 1 error_if_no_space"
228 _dmthin_reload_table $DMTHIN_POOL_NAME "$DMTHIN_POOL_TABLE"
231 _dmthin_mount_options()
233 echo `_common_dev_mount_options $*` $DMTHIN_VOL_DEV $SCRATCH_MNT
238 _mount -t $FSTYP `_dmthin_mount_options $*`