From 0d2412396a8a09e7747bce7315ded3db1956b0dc Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Mon, 14 Nov 2016 14:35:35 -0500 Subject: [PATCH] Let lvm create metadata volume automatically Right now we create lvm metadata volume first and then data volume and then pass it to lvm to convert it into a thin pool (lvconvert). This means lvm internally creates an spare logical volume (used during repair) and needs free space in volume group for that spare volume. But lvm does not tell how big an spare volume will be so caller does not know how much free space to leave in volume group. And that means if user passes in DATA_SIZE=100%FREE by the time we call lvconvert, there is no free space left and lvconvert fails. And we leave the system in uncleaned state (metadata and data volumes behind). Dusty came up with idea that why not let lvm create metadata, data and spare volume. That way docker-storage-setup does not have to deal with how much free space to leave. Also use option --poolmetadatasize option to specify size of metadata, so that we retain control on how big metadata volume should be. This should allow users to pass in DATA_SIZE as 100%FREE. Though lvm developers say it is not a good idea to fill up volume group completely and leave some space free so that later either metadata, data or spare volume can grow as need be. This patch changes behavior of MIN_DATA_SIZE. Previously we will make sure free space in VG is more than MIN_DATA_SIZE before creating data volume (and after crating metadata volume). Now we do the same check before creating metadata volume. Given metadata volume is very small (.1% of data size). This can be considered sort of round off error and should not be a real problem. Reported-by: Dusty Mabe Signed-off-by: Vivek Goyal --- docker-storage-setup.sh | 62 +++++++++++++---------------------------- 1 file changed, 19 insertions(+), 43 deletions(-) diff --git a/docker-storage-setup.sh b/docker-storage-setup.sh index 048ba82..33d63a7 100755 --- a/docker-storage-setup.sh +++ b/docker-storage-setup.sh @@ -55,8 +55,6 @@ set -e # Note: lvm2 version should be same or higher than lvm2-2.02.112 for lvm # thin pool functionality to work properly. POOL_LV_NAME="docker-pool" -DATA_LV_NAME=$POOL_LV_NAME -META_LV_NAME="${POOL_LV_NAME}meta" DOCKER_STORAGE="/etc/sysconfig/docker-storage" STORAGE_DRIVERS="devicemapper overlay overlay2" @@ -209,7 +207,7 @@ get_devicemapper_config_options() { # docker expects device mapper device and not lvm device. Do the conversion. eval $( lvs --nameprefixes --noheadings -o lv_name,kernel_major,kernel_minor $VG | while read line; do eval $line - if [ "$LVM2_LV_NAME" = "$DATA_LV_NAME" ]; then + if [ "$LVM2_LV_NAME" = "$POOL_LV_NAME" ]; then echo POOL_DEVICE_PATH=/dev/mapper/$( cat /sys/dev/block/${LVM2_LV_KERNEL_MAJOR}:${LVM2_LV_KERNEL_MINOR}/dm/name ) fi done ) @@ -246,27 +244,6 @@ EOF mv -Z $DOCKER_STORAGE.tmp $DOCKER_STORAGE } -create_metadata_lv() { - # If metadata lvm already exists (failures from previous run), then - # don't create it. - # TODO: Modify script to cleanup meta and data lvs if failure happened - # later. Don't exit with error leaving partially created lvs behind. - - if lvs -a $VG/${META_LV_NAME} --noheadings &>/dev/null; then - Info "Metadata volume $META_LV_NAME already exists. Not creating a new one." - return 0 - fi - - # Reserve 0.1% of the free space in the VG for docker metadata. - # Calculating the based on actual data size might be better, but is - # more difficult do to the range of possible inputs. - VG_SIZE=$( vgs --noheadings --nosuffix --units s -o vg_size $VG ) - META_SIZE=$(( $VG_SIZE / 1000 + 1 )) - if [ ! -n "$META_LV_SIZE" ]; then - lvcreate -y -L ${META_SIZE}s -n $META_LV_NAME $VG - fi -} - convert_size_in_bytes() { local size=$1 prefix suffix @@ -368,9 +345,13 @@ check_min_data_size_condition() { fi } -create_data_lv() { +create_lvm_thin_pool () { + if [ -z "$DEVS_ABS" ] && [ -z "$VG_EXISTS" ]; then + Fatal "Specified volume group $VG does not exist, and no devices were specified" + fi + if [ ! -n "$DATA_SIZE" ]; then - Fatal "Data volume creation failed. No DATA_SIZE specified" + Fatal "DATA_SIZE not specified." fi if ! check_data_size_syntax $DATA_SIZE; then @@ -379,27 +360,22 @@ create_data_lv() { check_min_data_size_condition - # TODO: Error handling when DATA_SIZE > available space. - if [[ $DATA_SIZE == *%* ]]; then - lvcreate -y -l $DATA_SIZE -n $DATA_LV_NAME $VG - else - lvcreate -y -L $DATA_SIZE -n $DATA_LV_NAME $VG - fi -} - -create_lvm_thin_pool () { - if [ -z "$DEVS_ABS" ] && [ -z "$VG_EXISTS" ]; then - Fatal "Specified volume group $VG does not exist, and no devices were specified" - fi - - # First create metadata lv. Down the line let lvm2 create it automatically. - create_metadata_lv - create_data_lv + # Calculate size of metadata lv. Reserve 0.1% of the free space in the VG + # for docker metadata. + VG_SIZE=$(vgs --noheadings --nosuffix --units s -o vg_size $VG) + META_SIZE=$(( $VG_SIZE / 1000 + 1 )) if [ -n "$CHUNK_SIZE" ]; then CHUNK_SIZE_ARG="-c $CHUNK_SIZE" fi - lvconvert -y --zero n $CHUNK_SIZE_ARG --thinpool $VG/$DATA_LV_NAME --poolmetadata $VG/$META_LV_NAME + + if [[ $DATA_SIZE == *%* ]]; then + DATA_SIZE_ARG="-l $DATA_SIZE" + else + DATA_SIZE_ARG="-L $DATA_SIZE" + fi + + lvcreate -y --type thin-pool --zero n $CHUNK_SIZE_ARG --poolmetadatasize ${META_SIZE}s $DATA_SIZE_ARG -n $POOL_LV_NAME $VG } get_configured_thin_pool() {