[lvm-devel] [PATCH 1/3] - add btrfs support into fsadm
Ondrej Kozina
okozina at redhat.com
Fri Nov 23 14:48:36 UTC 2012
---
scripts/fsadm.sh | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 133 insertions(+), 8 deletions(-)
diff --git a/scripts/fsadm.sh b/scripts/fsadm.sh
index 4624a1c..6adbe09 100755
--- a/scripts/fsadm.sh
+++ b/scripts/fsadm.sh
@@ -17,11 +17,12 @@
# Script for resizing devices (usable for LVM resize)
#
# Needed utilities:
-# mount, umount, grep, readlink, blockdev, blkid, fsck, xfs_check
+# mount, umount, grep, readlink, blockdev, blkid, fsck, xfs_check, btrfs-progs, lsblk, findmnt
#
# ext2/ext3/ext4: resize2fs, tune2fs
# reiserfs: resize_reiserfs, reiserfstune
# xfs: xfs_growfs, xfs_info
+# btrfs: btrfs, btrfsck
#
# Return values:
# 0 success
@@ -41,6 +42,7 @@ TUNE_REISER=reiserfstune
RESIZE_REISER=resize_reiserfs
TUNE_XFS=xfs_info
RESIZE_XFS=xfs_growfs
+BTRFS=btrfs
MOUNT=mount
UMOUNT=umount
@@ -48,12 +50,15 @@ MKDIR=mkdir
RMDIR=rmdir
BLOCKDEV=blockdev
BLKID=blkid
+# set by check_findmnt()
+FINDMNT=
DATE=date
GREP=grep
READLINK=readlink
READLINK_E="-e"
FSCK=fsck
XFS_CHECK=xfs_check
+BTRFS_CHECK=btrfsck
# user may override lvm location by setting LVM_BINARY
LVM=${LVM_BINARY:-lvm}
@@ -74,12 +79,16 @@ MOUNTPOINT=
MOUNTED=
REMOUNT=
PROCMOUNTS="/proc/mounts"
+PROCPARTITIONS="/proc/partitions"
NULL="$DM_DEV_DIR/null"
+BTRFS_DEVID=
+UUID=
IFS_OLD=$IFS
# without bash $'\n'
NL='
'
+READ_IFS=" $(echo -n -e '\t')"
tool_usage() {
echo "${TOOL}: Utility to resize or check the filesystem on a device"
@@ -152,6 +161,10 @@ cleanup() {
exit ${1:-1}
}
+check_findmnt() {
+ FINDMNT=$(which findmnt 2> $NULL);
+}
+
# convert parameter from Exa/Peta/Tera/Giga/Mega/Kilo/Bytes and blocks
# (2^(60/50/40/30/20/10/0))
decode_size() {
@@ -196,15 +209,87 @@ detect_fs() {
verbose "\"$FSTYPE\" filesystem found on \"$VOLUME\""
}
+detect_fs_uuid() {
+ UUID=$($BLKID -o value -c $NULL -s UUID "$VOLUME" 2>$NULL)
+
+ test -n "$UUID"
+}
+
+# example:
+# 'btrfs fi show' output :
+# devid 3 size 1.00GB used 894.50MB path /dev/sdb
+# need: ^
+btrfs_parse_devid() {
+ local a devid b
+ while read -r a devid b;
+ do
+ echo -n "$devid";
+ done;
+}
+
+btrfs_get_devid() {
+ local STR_IFS=$IFS
+
+ TMP=$(lsblk -Pdno MAJ:MIN $VOLUME)
+ TMP=${TMP##*=\"}
+ MAJOR=${TMP%%:*}
+ MINOR=${TMP##*:}
+ MINOR=${MINOR%%\"*}
+
+ test -n "$MAJOR" -a -n "$MINOR" || error "Can't get \"$VOLUME\" major:minor numbers"
+
+ IFS=$READ_IFS
+ test -e "$PROCPARTITIONS" || error "Can't read $PROCPARTITIONS"
+ while read -r RMAJOR RMINOR RSIZE RDEV;
+ do
+ if [ "$RMAJOR" = "$MAJOR" -a "$RMINOR" = "$MINOR" ] ; then
+ BTRFS_DEVICE=$RDEV
+ break;
+ fi
+ done <$PROCPARTITIONS
+
+ test -z $BTRFS_DEVICE || $BTRFS filesystem show "$UUID" 2> $NULL | $GREP "/dev/$BTRFS_DEVICE" | btrfs_parse_devid
+ IFS=$STR_IFS
+}
+
+
+# The whole btrfs volume (subvolid=0) is identified by UUID.
+# Also there can be multiple subvolumes mounted as well
+# identified by same UUID
+get_first_mounted_subvolume() {
+ local TMP
+ local STR_IFS=$IFS
+ IFS=$READ_IFS
+
+ read -r TMP<<EOF
+$($FINDMNT -nuP -o TARGET,UUID 2>$NULL | $GREP "$UUID")
+EOF
+
+ TMP=${TMP##*TARGET=\"}
+ TMP=${TMP%%\"*}
+ echo -n $TMP
+
+ IFS=$STR_IFS
+}
+
+detect_mounted_findmnt() {
+ MOUNTED=$(get_first_mounted_subvolume)
+
+ verbose "found $MOUNTED"
+ test -n "$MOUNTED"
+}
+
# check if the given device is already mounted and where
# FIXME: resolve swap usage and device stacking
-detect_mounted() {
- test -e "$PROCMOUNTS" || error "Cannot detect mounted device \"$VOLUME\""
+# $1 - VOLUME
+# $2 - RVOLUME
+detect_mounted_classic() {
+ test -e "$PROCMOUNTS" || error "Cannot detect mounted device \"$1\""
- MOUNTED=$("$GREP" "^$VOLUME[ \t]" "$PROCMOUNTS")
+ MOUNTED=$("$GREP" "^$1[ \t]" "$PROCMOUNTS")
# for empty string try again with real volume name
- test -z "$MOUNTED" && MOUNTED=$("$GREP" "^$RVOLUME[ \t]" "$PROCMOUNTS")
+ test -z "$MOUNTED" && MOUNTED=$("$GREP" "^$2[ \t]" "$PROCMOUNTS")
# cut device name prefix and trim everything past mountpoint
# echo translates \040 to spaces
@@ -213,8 +298,8 @@ detect_mounted() {
# for systems with different device names - check also mount output
if test -z "$MOUNTED" ; then
- MOUNTED=$(LANG=C "$MOUNT" | "$GREP" "^$VOLUME[ \t]")
- test -z "$MOUNTED" && MOUNTED=$(LANG=C "$MOUNT" | "$GREP" "^$RVOLUME[ \t]")
+ MOUNTED=$(LANG=C "$MOUNT" | "$GREP" "^$1[ \t]")
+ test -z "$MOUNTED" && MOUNTED=$(LANG=C "$MOUNT" | "$GREP" "^$2[ \t]")
MOUNTED=${MOUNTED##* on }
MOUNTED=${MOUNTED% type *} # allow type in the mount name
fi
@@ -222,6 +307,17 @@ detect_mounted() {
test -n "$MOUNTED"
}
+
+detect_mounted() {
+ if test "$FSTYPE" = "btrfs" ; then
+ detect_fs_uuid || verbose "Can't get fs UUID from \"$VOLUME\" volume"
+ test -n "$FINDMNT" || error "Need 'findmnt' utility to work with btrfs filesystem"
+ detect_mounted_findmnt
+ else
+ detect_mounted_classic "$VOLUME" "$RVOLUME"
+ fi
+}
+
# get the full size of device in bytes
detect_device_size() {
# check if blockdev supports getsize64
@@ -366,6 +462,31 @@ resize_xfs() {
fi
}
+
+################################
+# Resize Btrfs filesystem
+# - mounted for upsize/downsize
+# - need to find btrfs devid
+################################
+resize_btrfs() {
+ detect_mounted
+ MOUNTPOINT=$MOUNTED
+ if [ -z "$MOUNTED" ]; then
+ MOUNTPOINT=$TEMPDIR
+ temp_mount || error "Cannot mount Btrfs filesystem"
+ fi
+
+ # need to find btrfs devid to resize right btrfs volume
+ BTRFS_DEVID=$(btrfs_get_devid)
+ test -n "$BTRFS_DEVID" || error "Cannot find btrfs devid for \"$VOLUME ($RVOLUME)\""
+
+ # btrfs tool doesn't decode units above GiB
+ decode_size "$1" 1
+
+ verbose "Resizing \"$VOLUME\" btrfs filesystem to $NEWSIZE bytes (btrfs devid: $BTRFS_DEVID)"
+ dry "$BTRFS" filesystem resize $BTRFS_DEVID:$NEWSIZE $MOUNTPOINT
+}
+
####################
# Resize filesystem
####################
@@ -382,6 +503,7 @@ resize() {
"ext3"|"ext2"|"ext4") resize_ext $NEWSIZE ;;
"reiserfs") resize_reiser $NEWSIZE ;;
"xfs") resize_xfs $NEWSIZE ;;
+ "btrfs") resize_btrfs $NEWSIZE ;;
*) error "Filesystem \"$FSTYPE\" on device \"$VOLUME\" is not supported by this tool" ;;
esac || error "Resize $FSTYPE failed"
cleanup 0
@@ -431,6 +553,7 @@ check() {
case "$FSTYPE" in
"xfs") dry "$XFS_CHECK" "$VOLUME" ;;
+ "btrfs") dry "$BTRFS_CHECK" "$VOLUME" ;;
*) # check if executed from interactive shell environment
case "$-" in
*i*) dry "$FSCK" $YES $FORCE "$VOLUME" ;;
@@ -453,6 +576,7 @@ test -n "$TUNE_EXT" -a -n "$RESIZE_EXT" -a -n "$TUNE_REISER" -a -n "$RESIZE_REIS
-a -n "$TUNE_XFS" -a -n "$RESIZE_XFS" -a -n "$MOUNT" -a -n "$UMOUNT" -a -n "$MKDIR" \
-a -n "$RMDIR" -a -n "$BLOCKDEV" -a -n "$BLKID" -a -n "$GREP" -a -n "$READLINK" \
-a -n "$DATE" -a -n "$FSCK" -a -n "$XFS_CHECK" -a -n "$LVM" \
+ -a -n "$BTRFS" -a -n "$BTRFS_CHECK" -a -z "$FINDMNT" \
|| error "Required command definitions in the script are missing!"
"$LVM" version >"$NULL" 2>&1 || error "Could not run lvm binary \"$LVM\""
@@ -462,11 +586,12 @@ test "$TEST64BIT" -eq 1000000000000000 || error "Shell does not handle 64bit ari
$(echo Y | "$GREP" Y >"$NULL") || error "Grep does not work properly"
test $("$DATE" -u -d"Jan 01 00:00:01 1970" +%s) -eq 1 || error "Date translation does not work"
-
if [ "$#" -eq 0 ] ; then
tool_usage
fi
+check_findmnt
+
while [ "$#" -ne 0 ]
do
case "$1" in
--
1.8.0
More information about the lvm-devel
mailing list