Some useful Logical Volume management procedures

Contents

Create a new logical volume

Set the following environment variables:

X__VOLGROUP=VolGroup00
X__LV_NAME=lv_staging
X__LV_SIZE_GB=8
X__MOUNT_POINT=staging

Run the following commands:

X__FS_LABEL=$(echo ${X__LV_NAME:3} | tr '[a-z]' '[A-Z]')
[ -d /r ] && X__MNT_PATH=/r || X__MNT_PATH=/tmp
lvcreate --size ${X__LV_SIZE_GB}G -n $X__LV_NAME $X__VOLGROUP
mke2fs -m0 -j -L $X__FS_LABEL /dev/mapper/$X__VOLGROUP-$X__LV_NAME
mkdir $X__MNT_PATH/$X__MOUNT_POINT
mount -L $X__FS_LABEL $X__MNT_PATH/$X__MOUNT_POINT
echo -e "LABEL=${X__FS_LABEL}\t\t\t$X__MNT_PATH/${X__MOUNT_POINT}\text3\tdefaults 0 2" >>/etc/fstab
unset X__VOLGROUP X__LV_NAME X__LV_SIZE_GB X__FS_LABEL X__MOUNT_PATH X__MOUNT_POINT
vim /etc/fstab

Increase the size of a logical volume

Set the following environment variables:

X__VOLGROUP=VolGroup00
X__MOUNT_POINT=/srv     # or /home for user home directories
X__LV_NAME=lv_${X__MOUNT_POINT/\//}
X__EXTEND_GB=4

Run the following commands:

X__MNT_PATH=
jdf | grep $X__LV_NAME
umount $X__MNT_PATH/$X__MOUNT_POINT; RC=$?
[ $RC = 0 ] && echo "--- e2fsck"
[ $RC = 0 ] && time e2fsck -f -C0 /dev/mapper/$X__VOLGROUP-$X__LV_NAME; RC=$?
[ $RC = 0 ] && echo "--- lvresize"
[ $RC = 0 ] && time lvresize --size +${X__EXTEND_GB}G --resizefs $X__VOLGROUP/$X__LV_NAME; RC=$?
mount $X__MNT_PATH/$X__MOUNT_POINT
jdf | grep $X__LV_NAME
unset X__VOLGROUP X__MNT_PATH X__MOUNT_POINT X__LV_NAME X__EXTEND_GB

Reduce the size of a logical volume

Set the following environment variables:

X__VOLGROUP=VolGroup00
X__MOUNT_POINT=ci.connect.re-trac.com
X__LV_NAME=lv_rt2_ci

Determine the amount of free space currently available on the volume:

jdf | grep -e Filesystem -e $X__LV_NAME

Note the number in the “Used” column. The new size must be no less than this, plus 1 GB, and rounded up to the nearest whole number. For example, if the “Used” column shows 2.7 GB, the new logical volume size can be no less than 4 GB (2.7 + 1 = 3.7, round up to 4.)

Set the following environment variable. Note that we specify the total size of the logical volume as opposed to stating how much we want to remove:

X__NEW_LV_SIZE_GB=7G

Run the following commands:

[ -d /r ] && X__MNT_PATH=/r || X__MNT_PATH=/tmp
jdf | grep $X__LV_NAME
umount $X__MNT_PATH/$X__MOUNT_POINT; RC=$?
[ $RC = 0 ] && echo "--- e2fsck"
[ $RC = 0 ] && time e2fsck -f -C0 /dev/mapper/$X__VOLGROUP-$X__LV_NAME; RC=$?
[ $RC = 0 ] && echo "--- lvresize"
[ $RC = 0 ] && time lvresize --size ${X__NEW_LV_SIZE_GB}G --resizefs $X__VOLGROUP/$X__LV_NAME; RC=$?
mount $X__MNT_PATH/$X__MOUNT_POINT
jdf | grep $X__LV_NAME
[ $RC = 0 ] && unset X__VOLGROUP X__LV_NAME X__MNT_PATH X__MOUNT_POINT X__NEW_LV_SIZE_GB

Move a logical volume from one volume group to another

Set the following environment variables:

X__LV_NAME=lv_vmhost2
X__FROM_VG=VolGroup00
X__TO_VG=VolGroup01

Run the following commands:

# Gather information about the LV
X__FS_LABEL="$(e2label /dev/$X__FROM_VG/$X__LV_NAME)"
dumpe2fs -h /dev/$X__FROM_VG/$X__LV_NAME 2>/dev/null | grep -q has_journal \
  && X__FS_JOURNAL_SW='-j' || X__FS_JOURNAL_SW=''
X__LV_SIZE_MB="$(lvs --units m | awk "/$X__LV_NAME/{print substr(\$4,1,length(\$4)-4)}")"
jdf | grep $X__LV_NAME

# Unmount the current LV
umount /dev/mapper/${X__FROM_VG}-${X__LV_NAME}
 RC=$?

# Create a new LV with the same parameters as the old one
[ $RC = 0 ] && lvcreate --size ${X__LV_SIZE_MB}M -n $X__LV_NAME $X__TO_VG; RC=$?
[ $RC = 0 ] && mke2fs -m0 $X__FS_JOURNAL_SW -L $X__FS_LABEL /dev/$X__TO_VG/$X__LV_NAME; RC=$?

# Copy the contents of the old LV to the new
[ $RC = 0 ] && (sleep 2; while DDPID=$(pidof dd); do kill -USR1 $DDPID; sleep 10; done) &
[ $RC = 0 ] && dd if=/dev/$X__FROM_VG/$X__LV_NAME of=/dev/$X__TO_VG/$X__LV_NAME bs=1M; RC=0
echo "Return code from 'dd' is $RC"

# Mark the old volume as unused
[ $RC = 0 ] && e2label /dev/$X__FROM_VG/$X__LV_NAME "X_${X__FS_LABEL}"; RC=$?
[ $RC = 0 ] && lvchange -a n -f /dev/$X__FROM_VG/$X__LV_NAME; RC=$?
[ $RC = 0 ] && lvrename /dev/$X__FROM_VG/$X__LV_NAME ${X__LV_NAME}_moved
 RC=$?

# Mount the new LV
[ $RC = 0 ] && mount -a
jdf | grep $X__LV_NAME
unset X__FROM_VG X__TO_VG X__LV_NAME X__LV_SIZE_MB X__FS_JOURNAL_SW X__FS_LABEL

Note that the above commands do not delete the source LV; it’s merely off-line, so it’s still available if needed.

Backout:

umount /mnt/vmhost2.oliniasystems.com; RC=$?
[ $RC = 0 ] && lvremove -f /dev/VolGroup01/lv_vmhost2; RC=$?
[ $RC = 0 ] && lvrename /dev/VolGroup00/lv_vmhost2_moved /dev/VolGroup00/lv_vmhost2; RC=$?
[ $RC = 0 ] && lvchange -a y /dev/VolGroup00/lv_vmhost2; RC=$?
[ $RC = 0 ] && e2label /dev/VolGroup00/lv_vmhost2 VMHOST2; RC=$?
[ $RC = 0 ] && mount -L VMHOST2 /mnt/vmhost2.oliniasystems.com

Locate and mount unused logical volumes

(The following script was designed for rbackup)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#!/bin/bash
#  For each logical volume that is not mounted, creates a mount point for it in
#  the format '/r/unused-LVs/#-NAME' (where # is the LV's parent VolGroup (0 or
#  1) and NAME is the LV's name less the leading 'lv_') and mounts the LV there
ULV_PATH="/r/unused-LVs"
[ -d $ULV_PATH ] || mkdir $ULV_PATH
TEMP_FN='/r/rmount-unused-LVs.tmp'
mount | awk -F'[ /-]' '/VolGroup/{print $5 ".*" $4}' >$TEMP_FN
lvs | grep -v Attr | grep -v -f $TEMP_FN -e LogVol | awk '{print $2 "/" $1}' | sort | while read LV
do
    MOUNT_PT="$(echo $LV | cut -b10- | tr '/' '-')"
    MOUNT_PT="$ULV_PATH/${MOUNT_PT/lv_/}"
    [ -d $MOUNT_PT ] || mkdir $MOUNT_PT
    echo "mount /dev/$LV $MOUNT_PT"
    mount /dev/$LV $MOUNT_PT
done
rm -f $TEMP_FN

Cleanup:

umount /r/unused-LVs/* && rmdir /r/unused-LVs/* && rmdir /r/unused-LVs