2016-05-09 10:55:13 +10:00
|
|
|
#!/bin/bash
|
2018-06-09 11:34:49 +10:00
|
|
|
# SPDX-License-Identifier: GPL-2.0
|
2016-05-09 10:55:13 +10:00
|
|
|
# Copyright (c) 2015 Red Hat, Inc. All Rights Reserved.
|
|
|
|
|
#
|
|
|
|
|
# common functions for setting up and tearing down a dmthin device
|
|
|
|
|
|
|
|
|
|
# SOOO many devices!
|
|
|
|
|
# Create the 2 pool devices on lvs so we can build the whole thing
|
|
|
|
|
# from a single scratch device
|
|
|
|
|
|
|
|
|
|
# Backing data dev
|
|
|
|
|
DMTHIN_DATA_NAME="thin-data"
|
|
|
|
|
DMTHIN_DATA_DEV="/dev/mapper/$DMTHIN_DATA_NAME"
|
|
|
|
|
# Backing metadata dev
|
|
|
|
|
DMTHIN_META_NAME="thin-meta"
|
|
|
|
|
DMTHIN_META_DEV="/dev/mapper/$DMTHIN_META_NAME"
|
|
|
|
|
# Backing pool dev (combination of above)
|
|
|
|
|
DMTHIN_POOL_NAME="thin-pool"
|
|
|
|
|
DMTHIN_POOL_DEV="/dev/mapper/$DMTHIN_POOL_NAME"
|
|
|
|
|
# Thin volume
|
|
|
|
|
DMTHIN_VOL_NAME="thin-vol"
|
|
|
|
|
DMTHIN_VOL_DEV="/dev/mapper/$DMTHIN_VOL_NAME"
|
|
|
|
|
|
2018-01-18 09:07:37 -07:00
|
|
|
echo $MOUNT_OPTIONS | grep -q dax
|
|
|
|
|
if [ $? -eq 0 ]; then
|
|
|
|
|
_notrun "Cannot run tests with DAX on dmthin devices"
|
|
|
|
|
fi
|
|
|
|
|
|
2016-05-09 10:55:13 +10:00
|
|
|
_dmthin_cleanup()
|
|
|
|
|
{
|
|
|
|
|
$UMOUNT_PROG $SCRATCH_MNT > /dev/null 2>&1
|
2017-01-18 17:27:23 +08:00
|
|
|
# wait for device to be fully settled so that 'dmsetup remove' doesn't
|
|
|
|
|
# fail due to EBUSY
|
|
|
|
|
$UDEV_SETTLE_PROG >/dev/null 2>&1
|
2016-05-09 10:55:13 +10:00
|
|
|
$DMSETUP_PROG remove $DMTHIN_VOL_NAME> /dev/null 2>&1
|
|
|
|
|
$DMSETUP_PROG remove $DMTHIN_POOL_NAME> /dev/null 2>&1
|
|
|
|
|
$DMSETUP_PROG remove $DMTHIN_META_NAME> /dev/null 2>&1
|
|
|
|
|
$DMSETUP_PROG remove $DMTHIN_DATA_NAME> /dev/null 2>&1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_dmthin_check_fs()
|
|
|
|
|
{
|
|
|
|
|
$UMOUNT_PROG $SCRATCH_MNT > /dev/null 2>&1
|
|
|
|
|
_check_scratch_fs $DMTHIN_VOL_DEV
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Set up a dm-thin device on $SCRATCH_DEV
|
|
|
|
|
#
|
|
|
|
|
# All arguments are optional, and in this order; defaults follows:
|
|
|
|
|
# data_dev_size: half of $SCRATCH_DEV
|
|
|
|
|
# virtual_size: 10x $data_dev_size
|
|
|
|
|
# cluster_size: 512k
|
|
|
|
|
# low_water: 100M
|
|
|
|
|
#
|
|
|
|
|
# You may specify 0 to 4 of these arguments, but they
|
|
|
|
|
# must be in the above order.
|
|
|
|
|
_dmthin_init()
|
|
|
|
|
{
|
|
|
|
|
local data_dev_size=$1 # Backing pool data size in sectors
|
|
|
|
|
local virtual_size=$2 # Virtual size in sectors
|
|
|
|
|
local cluster_size=$3 # cluster/alloc size, sectors
|
|
|
|
|
local low_water=$4 # low water mark, sectors
|
|
|
|
|
|
|
|
|
|
local dm_backing_dev=$SCRATCH_DEV
|
|
|
|
|
local blk_dev_size=`blockdev --getsz $dm_backing_dev`
|
|
|
|
|
|
|
|
|
|
local pool_id=$RANDOM
|
|
|
|
|
|
|
|
|
|
# Default to something small-ish
|
|
|
|
|
if [ -z "$data_dev_size" ]; then
|
|
|
|
|
data_dev_size=$(($blk_dev_size / 2))
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Default to something big-is; 10x backing
|
|
|
|
|
if [ -z "$virtual_size" ]; then
|
|
|
|
|
virtual_size=$(($data_dev_size * 10))
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Default to 512k
|
|
|
|
|
if [ -z "$cluster_size" ]; then
|
|
|
|
|
cluster_size=1024 # 512k in sectors
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Default to 100M
|
|
|
|
|
if [ -z "$low_water" ]; then
|
|
|
|
|
low_water=204800 # 100M, in sectors
|
|
|
|
|
fi
|
2016-06-17 18:54:28 +08:00
|
|
|
# low_water is expressed in blocks of size $cluster_size
|
|
|
|
|
low_water=$((low_water / cluster_size))
|
2016-05-09 10:55:13 +10:00
|
|
|
|
|
|
|
|
# Need to make linear metadata and data devs. From kernel docs:
|
|
|
|
|
# As a guide, we suggest you calculate the number of bytes to use in the
|
|
|
|
|
# metadata device as 48 * $data_dev_size / $data_block_size but round it up
|
|
|
|
|
# to 2MB (4096 sectors) if the answer is smaller.
|
|
|
|
|
# So do that:
|
|
|
|
|
|
|
|
|
|
local meta_dev_size=$((48 * $data_dev_size / $cluster_size))
|
|
|
|
|
if [ "$meta_dev_size" -lt "4096" ]; then
|
|
|
|
|
meta_dev_size=4096 # 2MB
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# scratch dev gets a metadata vol & data vol, start at this offset
|
|
|
|
|
local meta_dev_offset=10240
|
|
|
|
|
|
|
|
|
|
local total_data_dev_size=$(($meta_dev_offset + $meta_dev_size + $data_dev_size))
|
|
|
|
|
if [ "$total_data_dev_size" -gt "$blk_dev_size" ]; then
|
|
|
|
|
_notrun "$SCRATCH_DEV too small"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Unmount & tear down old stuff
|
|
|
|
|
_dmthin_cleanup
|
|
|
|
|
|
|
|
|
|
# Metadata device
|
|
|
|
|
DMTHIN_META_TABLE="0 $meta_dev_size linear $dm_backing_dev $meta_dev_offset"
|
|
|
|
|
$DMSETUP_PROG create $DMTHIN_META_NAME --table "$DMTHIN_META_TABLE" || \
|
|
|
|
|
_fatal "failed to create dm thin meta device"
|
|
|
|
|
|
|
|
|
|
# Data device
|
|
|
|
|
local data_dev_offset=$((meta_dev_offset + $meta_dev_size))
|
|
|
|
|
DMTHIN_DATA_TABLE="0 $data_dev_size linear $dm_backing_dev $data_dev_offset"
|
|
|
|
|
$DMSETUP_PROG create $DMTHIN_DATA_NAME --table "$DMTHIN_DATA_TABLE" || \
|
|
|
|
|
_fatal "failed to create dm thin data device"
|
|
|
|
|
|
|
|
|
|
# Zap the pool metadata dev
|
|
|
|
|
dd if=/dev/zero of=$DMTHIN_META_DEV bs=4096 count=1 &>/dev/null
|
|
|
|
|
|
|
|
|
|
# Thin pool
|
|
|
|
|
# "start length thin-pool metadata_dev data_dev data_block_size low_water_mark"
|
|
|
|
|
DMTHIN_POOL_TABLE="0 $data_dev_size thin-pool $DMTHIN_META_DEV $DMTHIN_DATA_DEV $cluster_size $low_water"
|
|
|
|
|
$DMSETUP_PROG create $DMTHIN_POOL_NAME --table "$DMTHIN_POOL_TABLE" || \
|
|
|
|
|
_fatal "failed to create dm thin pool device"
|
|
|
|
|
|
|
|
|
|
# Thin volume
|
|
|
|
|
$DMSETUP_PROG message $DMTHIN_POOL_DEV 0 "create_thin $pool_id" || \
|
|
|
|
|
_fatal "failed to message pool device"
|
|
|
|
|
|
|
|
|
|
# start length thin pool_dev dev_id [external_origin_dev]
|
|
|
|
|
DMTHIN_VOL_TABLE="0 $virtual_size thin $DMTHIN_POOL_DEV $pool_id"
|
|
|
|
|
$DMSETUP_PROG create $DMTHIN_VOL_NAME --table "$DMTHIN_VOL_TABLE" || \
|
|
|
|
|
_fatal "failed to create dm thin volume device"
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# for internal use
|
|
|
|
|
_dmthin_reload_table()
|
|
|
|
|
{
|
|
|
|
|
local dev_name=$1
|
|
|
|
|
local table="$2"
|
|
|
|
|
|
|
|
|
|
$DMSETUP_PROG suspend $dev_name || \
|
|
|
|
|
_fail "dmsetup suspend of $dev_name failed"
|
|
|
|
|
|
|
|
|
|
$DMSETUP_PROG load $dev_name --table "$table" || \
|
|
|
|
|
_fail "dmsetup failed to reload $dev_name table"
|
|
|
|
|
|
|
|
|
|
$DMSETUP_PROG resume $dev_name || \
|
|
|
|
|
_fail "dmsetup resume of $dev_name failed"
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Grow the dm-thin device by the given amount
|
|
|
|
|
# Argument is number of sectors to add, if not specified
|
|
|
|
|
# defaults to 1/4 of the $SCRATCH_DEV size
|
|
|
|
|
_dmthin_grow()
|
|
|
|
|
{
|
|
|
|
|
local add_sectors=$1 # Number of sectors to add
|
|
|
|
|
|
|
|
|
|
local dm_backing_dev=$SCRATCH_DEV
|
|
|
|
|
local blk_dev_size=`blockdev --getsz $dm_backing_dev`
|
|
|
|
|
|
|
|
|
|
# Get current sizes & values
|
2017-03-16 16:01:25 +05:30
|
|
|
local meta_dev_size=`$DMSETUP_PROG table | grep ^$DMTHIN_META_NAME | awk '{print $3}'`
|
|
|
|
|
local meta_dev_offset=`$DMSETUP_PROG table | grep ^$DMTHIN_META_NAME | awk '{print $6}'`
|
|
|
|
|
local data_dev_size=`$DMSETUP_PROG table | grep ^$DMTHIN_DATA_NAME | awk '{print $3}'`
|
|
|
|
|
local pool_dev_size=`$DMSETUP_PROG table | grep ^$DMTHIN_POOL_NAME | awk '{print $3}'`
|
|
|
|
|
local cluster_size=`$DMSETUP_PROG table | grep ^$DMTHIN_POOL_NAME | awk '{print $7}'`
|
|
|
|
|
local low_water=`$DMSETUP_PROG table | grep ^$DMTHIN_POOL_NAME | awk '{print $8}'`
|
2016-05-09 10:55:13 +10:00
|
|
|
|
|
|
|
|
# default to 25% growth
|
|
|
|
|
if [ -z "$add_sectors" ]; then
|
|
|
|
|
add_sectors=$(($data_dev_size / 4))
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
local data_dev_offset=$(($meta_dev_offset + $meta_dev_size))
|
|
|
|
|
|
|
|
|
|
# Figure new sizes
|
|
|
|
|
data_dev_size=$(($data_dev_size + $add_sectors))
|
|
|
|
|
pool_dev_size=$(($pool_dev_size + $add_sectors))
|
|
|
|
|
|
|
|
|
|
# Can we do this?
|
|
|
|
|
local total_data_dev_size=$(($meta_dev_offset + $meta_dev_size + $data_dev_size))
|
|
|
|
|
if [ "$total_data_dev_size" -gt "$blk_dev_size" ]; then
|
|
|
|
|
_fail "$SCRATCH_DEV too small"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Grow the data device
|
|
|
|
|
DMTHIN_DATA_TABLE="0 $data_dev_size linear $dm_backing_dev $data_dev_offset"
|
|
|
|
|
_dmthin_reload_table $DMTHIN_DATA_NAME "$DMTHIN_DATA_TABLE"
|
|
|
|
|
|
|
|
|
|
# Grow the pool
|
|
|
|
|
DMTHIN_POOL_TABLE="0 $data_dev_size thin-pool $DMTHIN_META_DEV $DMTHIN_DATA_DEV $cluster_size $low_water"
|
|
|
|
|
_dmthin_reload_table $DMTHIN_POOL_NAME "$DMTHIN_POOL_TABLE"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Queue IOs when full
|
|
|
|
|
_dmthin_set_queue()
|
|
|
|
|
{
|
|
|
|
|
local data_dev_size=`$DMSETUP_PROG table | grep $DMTHIN_DATA_NAME | awk '{print $3}'`
|
|
|
|
|
local cluster_size=`$DMSETUP_PROG table | grep $DMTHIN_POOL_NAME | awk '{print $7}'`
|
|
|
|
|
local low_water=`$DMSETUP_PROG table | grep $DMTHIN_POOL_NAME | awk '{print $8}'`
|
|
|
|
|
|
|
|
|
|
DMTHIN_POOL_TABLE="0 $data_dev_size thin-pool $DMTHIN_META_DEV $DMTHIN_DATA_DEV $cluster_size $low_water"
|
|
|
|
|
_dmthin_reload_table $DMTHIN_POOL_NAME "$DMTHIN_POOL_TABLE"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Fail IOs when full
|
|
|
|
|
_dmthin_set_fail()
|
|
|
|
|
{
|
|
|
|
|
local data_dev_size=`$DMSETUP_PROG table | grep $DMTHIN_DATA_NAME | awk '{print $3}'`
|
|
|
|
|
local cluster_size=`$DMSETUP_PROG table | grep $DMTHIN_POOL_NAME | awk '{print $7}'`
|
|
|
|
|
local low_water=`$DMSETUP_PROG table | grep $DMTHIN_POOL_NAME | awk '{print $8}'`
|
|
|
|
|
|
|
|
|
|
DMTHIN_POOL_TABLE="0 $data_dev_size thin-pool $DMTHIN_META_DEV $DMTHIN_DATA_DEV $cluster_size $low_water 1 error_if_no_space"
|
|
|
|
|
_dmthin_reload_table $DMTHIN_POOL_NAME "$DMTHIN_POOL_TABLE"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_dmthin_mount_options()
|
|
|
|
|
{
|
|
|
|
|
echo `_common_dev_mount_options $*` $DMTHIN_VOL_DEV $SCRATCH_MNT
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_dmthin_mount()
|
|
|
|
|
{
|
|
|
|
|
_mount -t $FSTYP `_dmthin_mount_options $*`
|
|
|
|
|
}
|