summaryrefslogtreecommitdiff
path: root/scripts/lvresize_fs_helper.sh
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/lvresize_fs_helper.sh')
-rwxr-xr-xscripts/lvresize_fs_helper.sh475
1 files changed, 475 insertions, 0 deletions
diff --git a/scripts/lvresize_fs_helper.sh b/scripts/lvresize_fs_helper.sh
new file mode 100755
index 000000000..94eb4c775
--- /dev/null
+++ b/scripts/lvresize_fs_helper.sh
@@ -0,0 +1,475 @@
+#!/bin/bash
+#
+# Copyright (C) 2022 Red Hat, Inc. All rights reserved.
+#
+# This file is part of LVM2.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+errorexit() {
+ echo "$1" >&2
+ exit 1
+}
+
+logmsg() {
+ echo "$1"
+ logger "${SCRIPTNAME}: $1"
+}
+
+# Set to 1 while the fs is temporarily mounted on $TMPDIR
+TMP_MOUNT_DONE=0
+# Set to 1 if the fs resize command fails
+RESIZEFS_FAILED=0
+
+fsextend() {
+ if [ "$DO_UNMOUNT" -eq 1 ]; then
+ logmsg "unmount ${MOUNTDIR}"
+ umount "$MOUNTDIR"
+ if [ $? -eq 0 ]; then
+ logmsg "unmount done"
+ else
+ logmsg "unmount failed"
+ exit 1
+ fi
+ fi
+
+ if [ "$DO_FSCK" -eq 1 ]; then
+ logmsg "e2fsck ${DEVPATH}"
+ e2fsck -f -p "$DEVPATH"
+ if [ $? -eq 0 ]; then
+ logmsg "e2fsck done"
+ else
+ logmsg "e2fsck failed"
+ exit 1
+ fi
+ fi
+
+ if [ "$DO_CRYPTRESIZE" -eq 1 ]; then
+ logmsg "cryptsetup resize ${DEVPATH}"
+ cryptsetup resize "$DEVPATH"
+ if [ $? -eq 0 ]; then
+ logmsg "cryptsetup done"
+ else
+ logmsg "cryptsetup failed"
+ exit 1
+ fi
+ fi
+
+ if [ "$DO_MOUNT" -eq 1 ]; then
+ logmsg "mount ${DEVPATH} ${TMPDIR}"
+ mount -t "$FSTYPE" "$DEVPATH" "$TMPDIR"
+ if [ $? -eq 0 ]; then
+ logmsg "mount done"
+ TMP_MOUNT_DONE=1
+ else
+ logmsg "mount failed"
+ exit 1
+ fi
+ fi
+
+ if [[ "$FSTYPE" == "ext"* ]]; then
+ logmsg "resize2fs ${DEVPATH}"
+ resize2fs "$DEVPATH"
+ if [ $? -eq 0 ]; then
+ logmsg "resize2fs done"
+ else
+ logmsg "resize2fs failed"
+ RESIZEFS_FAILED=1
+ fi
+ elif [[ "$FSTYPE" == "xfs" ]]; then
+ logmsg "xfs_growfs ${DEVPATH}"
+ xfs_growfs "$DEVPATH"
+ if [ $? -eq 0 ]; then
+ logmsg "xfs_growfs done"
+ else
+ logmsg "xfs_growfs failed"
+ RESIZEFS_FAILED=1
+ fi
+ fi
+
+ # If the fs was temporarily mounted, now unmount it.
+ if [ $TMP_MOUNT_DONE -eq 1 ]; then
+ logmsg "cleanup unmount ${TMPDIR}"
+ umount "$TMPDIR"
+ if [ $? -eq 0 ]; then
+ logmsg "cleanup unmount done"
+ TMP_MOUNT_DONE=0
+ rmdir "$TMPDIR"
+ else
+ logmsg "cleanup unmount failed"
+ exit 1
+ fi
+ fi
+
+ # If the fs was temporarily unmounted, now remount it.
+ # Not considered a command failure if this fails.
+ if [[ $DO_UNMOUNT -eq 1 && $REMOUNT -eq 1 ]]; then
+ logmsg "remount ${DEVPATH} ${MOUNTDIR}"
+ mount -t "$FSTYPE" "$DEVPATH" "$MOUNTDIR"
+ if [ $? -eq 0 ]; then
+ logmsg "remount done"
+ else
+ logmsg "remount failed"
+ fi
+ fi
+
+ if [ $RESIZEFS_FAILED -eq 1 ]; then
+ logmsg "File system extend failed."
+ exit 1
+ fi
+
+ exit 0
+}
+
+fsreduce() {
+ if [ "$DO_UNMOUNT" -eq 1 ]; then
+ logmsg "unmount ${MOUNTDIR}"
+ umount "$MOUNTDIR"
+ if [ $? -eq 0 ]; then
+ logmsg "unmount done"
+ else
+ logmsg "unmount failed"
+ exit 1
+ fi
+ fi
+
+ if [ "$DO_FSCK" -eq 1 ]; then
+ logmsg "e2fsck ${DEVPATH}"
+ e2fsck -f -p "$DEVPATH"
+ if [ $? -eq 0 ]; then
+ logmsg "e2fsck done"
+ else
+ logmsg "e2fsck failed"
+ exit 1
+ fi
+ fi
+
+ if [ "$DO_MOUNT" -eq 1 ]; then
+ logmsg "mount ${DEVPATH} ${TMPDIR}"
+ mount -t "$FSTYPE" "$DEVPATH" "$TMPDIR"
+ if [ $? -eq 0 ]; then
+ logmsg "mount done"
+ TMP_MOUNT_DONE=1
+ else
+ logmsg "mount failed"
+ exit 1
+ fi
+ fi
+
+ if [[ "$FSTYPE" == "ext"* ]]; then
+ NEWSIZEKB=$(($NEWSIZEBYTES/1024))
+ logmsg "resize2fs ${DEVPATH} ${NEWSIZEKB}k"
+ resize2fs "$DEVPATH" "$NEWSIZEKB"k
+ if [ $? -eq 0 ]; then
+ logmsg "resize2fs done"
+ else
+ logmsg "resize2fs failed"
+ # will exit after cleanup unmount
+ RESIZEFS_FAILED=1
+ fi
+ fi
+
+ # If the fs was temporarily mounted, now unmount it.
+ if [ $TMP_MOUNT_DONE -eq 1 ]; then
+ logmsg "cleanup unmount ${TMPDIR}"
+ umount "$TMPDIR"
+ if [ $? -eq 0 ]; then
+ logmsg "cleanup unmount done"
+ TMP_MOUNT_DONE=0
+ rmdir "$TMPDIR"
+ else
+ logmsg "cleanup unmount failed"
+ exit 1
+ fi
+ fi
+
+ if [ $RESIZEFS_FAILED -eq 1 ]; then
+ logmsg "File system reduce failed."
+ exit 1
+ fi
+
+ if [ "$DO_CRYPTRESIZE" -eq 1 ]; then
+ NEWSIZESECTORS=$(($NEWSIZEBYTES/512))
+ logmsg "cryptsetup resize ${NEWSIZESECTORS} sectors ${DEVPATH}"
+ cryptsetup resize --size "$NEWSIZESECTORS" "$DEVPATH"
+ if [ $? -eq 0 ]; then
+ logmsg "cryptsetup done"
+ else
+ logmsg "cryptsetup failed"
+ exit 1
+ fi
+ fi
+
+ # If the fs was temporarily unmounted, now remount it.
+ # Not considered a command failure if this fails.
+ if [[ $DO_UNMOUNT -eq 1 && $REMOUNT -eq 1 ]]; then
+ logmsg "remount ${DEVPATH} ${MOUNTDIR}"
+ mount -t "$FSTYPE" "$DEVPATH" "$MOUNTDIR"
+ if [ $? -eq 0 ]; then
+ logmsg "remount done"
+ else
+ logmsg "remount failed"
+ fi
+ fi
+
+ exit 0
+}
+
+cryptresize() {
+ NEWSIZESECTORS=$(($NEWSIZEBYTES/512))
+ logmsg "cryptsetup resize ${NEWSIZESECTORS} sectors ${DEVPATH}"
+ cryptresize resize --size "$NEWSIZESECTORS" "$DEVPATH"
+ if [ $? -eq 0 ]; then
+ logmsg "cryptsetup done"
+ else
+ logmsg "cryptsetup failed"
+ exit 1
+ fi
+
+ exit 0
+}
+
+usage() {
+ echo "${SCRIPTNAME}: helper script called by lvresize to resize file systems."
+ echo ""
+ echo "${SCRIPTNAME} --fsextend --fstype name --lvpath path"
+ echo " [ --mountdir path ]"
+ echo " [ --mount ]"
+ echo " [ --unmount ]"
+ echo " [ --remount ]"
+ echo " [ --fsck ]"
+ echo " [ --cryptresize ]"
+ echo " [ --cryptpath path ]"
+ echo ""
+ echo "${SCRIPTNAME} --fsreduce --fstype name --lvpath path"
+ echo " [ --newsizebytes num ]"
+ echo " [ --mountdir path ]"
+ echo " [ --mount ]"
+ echo " [ --unmount ]"
+ echo " [ --remount ]"
+ echo " [ --fsck ]"
+ echo " [ --cryptresize ]"
+ echo " [ --cryptpath path ]"
+ echo ""
+ echo "${SCRIPTNAME} --cryptresize --cryptpath path --newsizebytes num"
+ echo ""
+ echo "Options:"
+ echo " --fsextend"
+ echo " Extend the file system."
+ echo " --fsreduce"
+ echo " Reduce the file system."
+ echo " --fstype name"
+ echo " The type of file system (ext*, xfs)."
+ echo " --lvpath path"
+ echo " The path to the LV being resized."
+ echo " --mountdir path"
+ echo " The file system is currently mounted here."
+ echo " --mount"
+ echo " Mount the file system on a temporary directory before resizing."
+ echo " --unmount"
+ echo " Unmount the file system before resizing."
+ echo " --remount"
+ echo " Remount the file system after resizing if unmounted."
+ echo " --fsck"
+ echo " Run fsck on the file system before resizing (only with ext*)."
+ echo " --newsizebytes num"
+ echo " The new size of the file system."
+ echo " --cryptresize"
+ echo " Resize the crypt device between the LV and file system."
+ echo " --cryptpath path"
+ echo " The path to the crypt device."
+ echo ""
+}
+
+#
+# BEGIN SCRIPT
+#
+PATH="/sbin:/usr/sbin:/bin:/usr/sbin:$PATH"
+SCRIPTNAME=$(basename "$0")
+
+# These are the only commands that this script will run.
+# Each is enabled (1) by the corresponding command options:
+# --fsextend, --fsreduce, --cryptresize, --mount, --unmount, --fsck
+DO_FSEXTEND=0
+DO_FSREDUCE=0
+DO_CRYPTRESIZE=0
+DO_MOUNT=0
+DO_UNMOUNT=0
+DO_FSCK=0
+
+# --remount: attempt to remount the fs if it was originally
+# mounted and the script unmounted it.
+REMOUNT=0
+
+if [ "$UID" != 0 ] && [ "$EUID" != 0 ]; then
+ errorexit "${SCRIPTNAME} must be run as root."
+fi
+
+GETOPT="getopt"
+
+OPTIONS=$("$GETOPT" -o hv -l help,debug,fsextend,fsreduce,cryptresize,mount,unmount,remount,fsck,fstype:,lvpath:,newsizebytes:,mountdir:,cryptpath: -n "${SCRIPTNAME}" -- "$@")
+eval set -- "$OPTIONS"
+
+while true
+do
+ case $1 in
+ --fsextend)
+ DO_FSEXTEND=1
+ shift
+ ;;
+ --fsreduce)
+ DO_FSREDUCE=1
+ shift
+ ;;
+ --cryptresize)
+ DO_CRYPTRESIZE=1
+ shift
+ ;;
+ --mount)
+ DO_MOUNT=1
+ shift
+ ;;
+ --unmount)
+ DO_UNMOUNT=1
+ shift
+ ;;
+ --fsck)
+ DO_FSCK=1
+ shift
+ ;;
+ --remount)
+ REMOUNT=1
+ shift
+ ;;
+ --fstype)
+ FSTYPE=$2;
+ shift; shift
+ ;;
+ --lvpath)
+ LVPATH=$2;
+ shift; shift
+ ;;
+ --newsizebytes)
+ NEWSIZEBYTES=$2;
+ shift; shift
+ ;;
+ --mountdir)
+ MOUNTDIR=$2;
+ shift; shift
+ ;;
+ --cryptpath)
+ CRYPTPATH=$2;
+ shift; shift
+ ;;
+ --debug)
+ DEBUG=1
+ set -x
+ shift
+ ;;
+ -h|--help)
+ usage
+ shift
+ exit 0
+ ;;
+ -v)
+ VERBOSE=1
+ shift
+ ;;
+ --)
+ shift
+ break
+ ;;
+ *)
+ errorexit "Unknown option \"$1\."
+ exit 1
+ ;;
+ esac
+done
+
+#
+# Input arg checking
+#
+
+# There are three top level commands: --fsextend, --fsreduce, --cryptresize.
+if [[ "$DO_FSEXTEND" -eq 0 && "$DO_FSREDUCE" -eq 0 && "$DO_CRYPTRESIZE" -eq 0 ]]; then
+ errorexit "Missing --fsextend|--fsreduce|--cryptresize."
+fi
+
+if [[ "$DO_FSEXTEND" -eq 1 || "$DO_FSREDUCE" -eq 1 ]]; then
+ case "$FSTYPE" in
+ ext[234]) ;;
+ "xfs") ;;
+ *) errorexit "Cannot resize --fstype \"$FSTYPE\"."
+ esac
+
+ if [ -z "$LVPATH" ]; then
+ errorexit "Missing required --lvpath."
+ fi
+fi
+
+if [[ "$DO_CRYPTRESIZE" -eq 1 && -z "$CRYPTPATH" ]]; then
+ errorexit "Missing required --cryptpath for --cryptresize."
+fi
+
+if [ "$DO_CRYPTRESIZE" -eq 1 ]; then
+ DEVPATH=$CRYPTPATH
+else
+ DEVPATH=$LVPATH
+fi
+
+if [ -z "$DEVPATH" ]; then
+ errorexit "Missing path to device."
+fi
+
+if [ ! -e "$DEVPATH" ]; then
+ errorexit "Device does not exist \"$DEVPATH\"."
+fi
+
+if [[ "$DO_UNMOUNT" -eq 1 && -z "$MOUNTDIR" ]]; then
+ errorexit "Missing required --mountdir for --unmount."
+fi
+
+if [[ "$DO_FSREDUCE" -eq 1 && "$FSTYPE" == "xfs" ]]; then
+ errorexit "Cannot reduce xfs."
+fi
+
+if [[ "$DO_FSCK" -eq 1 && "$FSTYPE" == "xfs" ]]; then
+ errorexit "Cannot use --fsck with xfs."
+fi
+
+if [ "$DO_MOUNT" -eq 1 ]; then
+ TMPDIR=$(mktemp --suffix _lvresize_$$ -d -p /tmp)
+ if [ ! -e "$TMPDIR" ]; then
+ errorexit "Failed to create temp dir."
+ fi
+ # In case the script terminates without doing cleanup
+ function finish {
+ if [ "$TMP_MOUNT_DONE" -eq 1 ]; then
+ logmsg "exit unmount ${TMPDIR}"
+ umount "$TMPDIR"
+ rmdir "$TMPDIR"
+ fi
+ }
+ trap finish EXIT
+fi
+
+#
+# Main program function:
+# - the two main functions are fsextend and fsreduce.
+# - one special case function is cryptresize.
+#
+
+if [ "$DO_FSEXTEND" -eq 1 ]; then
+ fsextend
+elif [ "$DO_FSREDUCE" -eq 1 ]; then
+ fsreduce
+elif [ "$DO_CRYPTRESIZE" -eq 1 ]; then
+ cryptresize
+fi
+