From 12ed3ac974c4b18c1f3023cb98c26040f319cc45 Mon Sep 17 00:00:00 2001 From: James Bunton Date: Sat, 10 Nov 2018 14:46:26 +1100 Subject: [PATCH] bsnap btrfs support --- bsnap-lvm | 118 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 94 insertions(+), 24 deletions(-) diff --git a/bsnap-lvm b/bsnap-lvm index 4648681..1f36d8e 100755 --- a/bsnap-lvm +++ b/bsnap-lvm @@ -7,36 +7,106 @@ function snap { mkdir -p /a - cat /etc/fstab | awk '{print $5 " " $1 " " $2;}' | while read -r dump dev mnt; do - if [ "$dump" = 1 ]; then - echo "bind mount $mnt" - mount --bind "${mnt}" "/a${mnt}" - elif [ "$dump" = 2 ]; then - read -r lvname vgname _ < <(lvdisplay --noheadings -C "$dev") - echo "snapshot ${vgname}/${lvname}" - lvcreate -L1G --snapshot --name "${lvname}snap" "${vgname}/${lvname}" - mount -o ro "${dev}snap" "/a${mnt}" - fi - done + dispatch snap < /etc/fstab } function unsnap { - tac /etc/fstab | awk '{print $5 " " $1 " " $2;}' | while read -r dump dev mnt; do - snapmnt="/a${mnt}" - snapdev="${dev}snap" - if [ "$dump" = 1 ]; then - echo "umount $snapmnt" - mountpoint -q "$snapmnt" && umount "$snapmnt" - elif [ "$dump" = 2 ]; then - echo "umount $snapmnt" - mountpoint -q "$snapmnt" && umount "$snapmnt" - - echo "unsnapshot $snapdev" - [ -b "$(readlink -f "$snapdev")" ] && echo y | lvremove "${dev}snap" + tac /etc/fstab | dispatch unsnap + + if [ -d "/a" ]; then + rmdir /a + fi +} + +function dispatch { + local action="" snaptype="" + local dev="" mnt="" fstype="" opts="" dump="" + + while read -r dev mnt fstype opts dump pass; do + snaptype="$(get_snaptype "$fstype" "$dump")" + if [ -z "$snaptype" ]; then + continue fi + action="${1}_${snaptype}" + echo "$action $mnt" + "$action" "$dev" "$mnt" "$opts" done +} + +function get_snaptype { + local fstype="$1" dump="$2" + if [ "$dump" = "1" ]; then + echo bind + elif [ "$dump" = "2" ] && [ "$fstype" = "btrfs" ]; then + echo btrfs + elif [ "$dump" = "2" ]; then + echo lvm + fi +} + +function snap_bind { + local mnt="$2" + mount --bind "${mnt}" "/a${mnt}" +} + +function unsnap_bind { + local snapmnt="/a$2" + if mountpoint -q "$snapmnt"; then + umount "$snapmnt" + fi +} + +function snap_lvm { + local dev="$1" mnt="$2" + local lvname="" vgname="" + read -r lvname vgname _ < <(lvdisplay --noheadings -C "$dev") + echo "snapshot ${vgname}/${lvname}" + lvcreate -L1G --snapshot --name "${lvname}snap" "${vgname}/${lvname}" + mount -o ro "${dev}snap" "/a${mnt}" +} + +function unsnap_lvm { + local snapdev="${1}snap" + local snapmnt="/a$2" + if mountpoint -q "$snapmnt"; then + umount "$snapmnt" + fi + if [ -b "$(readlink -f "$snapdev")" ]; then + lvremove -f "${dev}snap" + fi +} + +function snap_btrfs { + local mnt="$2" opts="$3" snapdir="" + + snapdir="$(get_btrfs_snapshot_dir "$opts" "$mnt")" + btrfs subvolume snapshot "$mnt" "$snapdir" + + mount --bind "$snapdir" "/a${mnt}" +} + +function unsnap_btrfs { + local mnt="$2" opts="$3" snapdir="" + + local snapmnt="/a$2" + if mountpoint -q "$snapmnt"; then + umount "$snapmnt" + fi + + snapdir="$(get_btrfs_snapshot_dir "$opts" "$mnt")" + if [ -d "$snapdir" ]; then + btrfs subvolume delete "$snapdir" + fi +} - rmdir /a || true +function get_btrfs_snapshot_dir { + local opts="$1" mnt="$2" subvol="" + subvol="$(echo "$opts" | sed -nE 's/^.*\bsubvol=([^,]+)\b.*$/\1/p')" + if [ -z "$subvol" ]; then + echo "Unknown subvol for mountpoint: $mnt" + exit 1 + fi + echo "/$(hostname -s)/${subvol}-snap" } if [ "$(id -u)" -ne 0 ]; then -- 2.39.2