[lvm-devel] [PATCH 1/3] fsadm: add support to resize & check btrfs filesystem

Heming Zhao heming.zhao at suse.com
Wed Jun 30 14:32:42 UTC 2021


resize:
btrfs volume may spanning across multiple block devices. resize action should
specific subvolume to not to break the filesystem on LV about to get resized
with lvresize.

this patch finds the mount point first and resizes the filesystem after
getting the device id since there are maybe several devices underneath btrfs
filesystem

check:
check the data integrity.
this patch mounts the device first and then runs `btrfs filesystem scrub
start -B` command

refer legacy patches:
- Ondrej Kozina <okozina at redhat.com>
  https://listman.redhat.com/archives/lvm-devel/2012-November/msg00052.html
- Lidong Zhong <lzhong at suse.com>
  https://listman.redhat.com/archives/lvm-devel/2015-March/msg00053.html

Signed-off-by: Heming Zhao <heming.zhao at suse.com>
---
 scripts/fsadm.sh | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 86 insertions(+), 2 deletions(-)

diff --git a/scripts/fsadm.sh b/scripts/fsadm.sh
index 9ae422f55edf..a7345c503f77 100755
--- a/scripts/fsadm.sh
+++ b/scripts/fsadm.sh
@@ -22,6 +22,7 @@
 # ext2/ext3/ext4: resize2fs, tune2fs
 # reiserfs: resize_reiserfs, reiserfstune
 # xfs: xfs_growfs, xfs_info
+# btrfs: btrfs
 #
 # Return values:
 #   0 success
@@ -59,6 +60,7 @@ XFS_CHECK="xfs_check"
 # XFS_REPAIR -n is used when XFS_CHECK is not found
 XFS_REPAIR="xfs_repair"
 CRYPTSETUP="cryptsetup"
+BTRFS="btrfs"
 
 # user may override lvm location by setting LVM_BINARY
 LVM=${LVM_BINARY:-lvm}
@@ -78,6 +80,9 @@ BLOCKCOUNT=
 MOUNTPOINT=
 MOUNTED=
 REMOUNT=
+FINDMNT=
+UUID=
+BTRFS_DEVID=
 PROCDIR="/proc"
 PROCMOUNTS="$PROCDIR/mounts"
 PROCSELFMOUNTINFO="$PROCDIR/self/mountinfo"
@@ -237,6 +242,33 @@ detect_fs() {
 	verbose "\"$FSTYPE\" filesystem found on \"$VOLUME\"."
 }
 
+check_findmnt() {
+	FINDMNT=$(which findmnt 2>$NULL)
+	test -n "$FINDMNT"
+}
+
+detect_fs_uuid() {
+	UUID=$($BLKID -o value -c $NULL -s UUID "$VOLUME" 2>$NULL)
+	test -n "$UUID"
+}
+
+#find the mountpoint of this device
+detect_mounted_findmnt() {
+	local TMP
+	local STR_IFS=$IFS
+	IFS=" $(echo -n -e '\t')"
+
+	read -r TMP<<EOF
+$($FINDMNT -nuP -o TARGET,UUID 2>$NULL | $GREP "$UUID")
+EOF
+
+	TMP=${TMP##*TARGET=\"}
+	TMP=${TMP%%\"*}
+	MOUNTED=$TMP
+	test -n "$MOUNTED"
+
+	IFS=$STR_IFS
+}
 
 # Check that passed mounted MAJOR:MINOR is not matching $MAJOR:MINOR of resized $VOLUME
 validate_mounted_major_minor() {
@@ -365,7 +397,11 @@ detect_mounted_with_proc_mounts() {
 # check if the given device is already mounted and where
 # FIXME: resolve swap usage and device stacking
 detect_mounted() {
-	if test -e "$PROCSELFMOUNTINFO"; then
+	if test "$FSTYPE" = "btrfs" ; then
+		check_findmnt || error "Need 'findmnt' utility to work with btrfs filesystem"
+		detect_fs_uuid || verbose "Can't get fs UUID from \"$VOLUME\" volume"
+		detect_mounted_findmnt
+	elif test -e "$PROCSELFMOUNTINFO"; then
 		detect_mounted_with_proc_self_mountinfo
 	elif test -e "$PROCMOUNTS"; then
 		detect_mounted_with_proc_mounts
@@ -662,6 +698,47 @@ resize_crypt() {
 	dry "$CRYPTSETUP" resize "$1" --size $CRYPT_RESIZE_BLOCKS || error "$CRYPTSETUP failed to resize device $1"
 }
 
+########################
+# Resize btrfs filesystem
+# - mounted for upsize/downsize
+# - cannot resize when unmounted
+########################
+resize_btrfs() {
+	detect_mounted
+	MOUNTPOINT=$MOUNTED
+	if [ -z "$MOUNTED" ]; then
+		MOUNTPOINT=$TEMPDIR
+		temp_mount || error "Cannot mount Btrfs filesystem"
+	fi
+
+	verbose "Parsing $BTRFS filesystem show \"$MOUNTPOINT\""
+	for i in $(LC_ALL=C "$BTRFS" filesystem show "$MOUNTPOINT"); do
+		case "$i" in
+		  *"$VOLUME") BTRFS_DEVID=${i##*devid};;
+		esac
+	done
+
+	# If dev doesn't locate in "/dev", 'btrfs filesystem show' will mistakely
+	# report path. Below is a work around to get correct lvm dev path.
+	if [ -z "$BTRFS_DEVID" ];then
+		for i in $(LC_ALL=C "$BTRFS" filesystem show "$MOUNTPOINT"); do
+			case "$i" in
+				*" path "*)
+					path_str=${i##*path}
+					path_str=$(echo $path_str|sed 's/^[ \t]*//g'|sed 's/[ \t]*$'//g)
+					result=$(echo $VOLUME | grep -E "${path_str}$")
+					test -n "$result" && BTRFS_DEVID=${i##*devid}
+					;;
+			esac
+		done
+	fi
+	BTRFS_DEVID=${BTRFS_DEVID%%size*}
+	BTRFS_DEVID=$(echo $BTRFS_DEVID|sed 's/^[ \t]*//g'|sed 's/[ \t]*$'//g)
+	decode_size $1 1
+	verbose "Resizing filesystem on device \"$VOLUME\" to $NEWSIZE bytes(btrfs devid: $BTRFS_DEVID) "
+	dry "$BTRFS" filesystem resize "$BTRFS_DEVID":"$NEWSIZE" "$MOUNTPOINT"
+}
+
 ####################
 # Resize filesystem
 ####################
@@ -685,6 +762,7 @@ resize() {
 	  "crypto_LUKS")
 		which "$CRYPTSETUP" >"$NULL" 2>&1 || error "$CRYPTSETUP utility required to resize LUKS volume"
 		CMD=resize_luks ;;
+	  "btrfs") CMD=resize_btrfs ;;
 	  *) error "Filesystem \"$FSTYPE\" on device \"$VOLUME\" is not supported by this tool." ;;
 	esac
 
@@ -762,6 +840,12 @@ check() {
 		which "$CRYPTSETUP" >"$NULL" 2>&1 || error "$CRYPTSETUP utility required."
 		check_luks || error "Crypto luks check failed."
 		;;
+	  "btrfs") #mount the device first and then run scrub
+		 MOUNTPOINT=$TEMPDIR
+		 temp_mount || error "Cannot mount btrfs filesystem"
+		 dry "$BTRFS" scrub start -B "$VOLUME"
+		 test "$MOUNTPOINT" = "$TEMPDIR" && MOUNTPOINT="" temp_umount
+		 ;;
 	  *)
 		error "Filesystem \"$FSTYPE\" on device \"$VOLUME\" is not supported by this tool." ;;
 	esac
@@ -780,7 +864,7 @@ test -n "${FSADM_RUNNING-}" && exit 0
 for i in "$TUNE_EXT" "$RESIZE_EXT" "$TUNE_REISER" "$RESIZE_REISER" \
 	"$TUNE_XFS" "$RESIZE_XFS" "$MOUNT" "$UMOUNT" "$MKDIR" \
 	"$RMDIR" "$BLOCKDEV" "$BLKID" "$GREP" "$READLINK" \
-	"$DATE" "$FSCK" "$XFS_CHECK" "$XFS_REPAIR" "$LVM" ; do
+	"$DATE" "$FSCK" "$XFS_CHECK" "$XFS_REPAIR" "$LVM" "$BTRFS" ; do
 	test -n "$i" || error "Required command definitions in the script are missing!"
 done
 
-- 
1.8.3.1





More information about the lvm-devel mailing list