#!/bin/sh set -e mkdir -p /mnt/urbackup_snaps CDIR=`dirname $0` SNAP_ID=$1 SNAP_MOUNTPOINT="$2" SNAP_DEST=/mnt/urbackup_snaps/$SNAP_ID CDIR=`dirname $0` . $CDIR/filesystem_snapshot_common exit_exclude_snapshot_mountpoints "$SNAP_MOUNTPOINT" DEVICE=$(df -T -P | egrep " ${SNAP_MOUNTPOINT}\$" | head -n 1 | tr -s " " | cut -d" " -f1) set_filesystem_type "${SNAP_MOUNTPOINT}" if [ "x$TYPE" = "x" ] then if btrfs subvolume list -o "$SNAP_MOUNTPOINT" > /dev/null 2>&1 then TYPE="btrfs" fi fi if [ "x$TYPE" = "xbtrfs" ] then $CDIR/btrfs_create_filesystem_snapshot "$@" exit $? fi if [ "x$TYPE" != "xxfs" ] && [ "x$TYPE" != "xext4" ] then echo "File system $TYPE not supported" exit 1 fi if [ "x$DEVICE" = "x" ] then echo "Cannot get device for filesystem $SNAP_MOUNTPOINT" exit 1 fi echo "Snapshotting device $DEVICE via dm..." if ! dmsetup table "$DEVICE" > /dev/null 2>&1 then echo "$DEVICE is not a device mapper device. Cannot snapshot via dm." exit 1 fi modprobe dm_snapshot DEV_SIZE=$(blockdev --getsz "$DEVICE") if [ "x$DEV_SIZE" = "x" ] then echo "Cannot get device size of device $DEVICE" exit 1 fi DEVNAME=$(basename $DEVICE) RUUID="a31725acca86421d" ORIG_DEVICE="/dev/mapper/$DEVNAME-$RUUID-clone" ERA_META_FN=".era-meta_3d41c58e-6724-4d47-8981-11c766a08a24" ERA_RESET=0 if ! command -v era_dump >/dev/null 2>&1 then echo "thin-provisioning-tools not installed. CBT not enabled." elif modprobe dm_era && ! dmsetup table "$DEVICE" | grep " era " > /dev/null 2>&1 && ! dmsetup table "$DEVICE" | grep " snapshot-origin " > /dev/null 2>&1 then echo "Layering in dm-era device..." META_SIZE=$(( (((DEV_SIZE*4)/1024)/512)*512 + 1*1024*1024 )) if [ $META_SIZE -lt $((2*1024*1024)) ] then META_SIZE=$((2*1024*1024)) fi if [ -e "$SNAP_MOUNTPOINT/$ERA_META_FN" ] then chattr -i "$SNAP_MOUNTPOINT/$ERA_META_FN" || true rm "$SNAP_MOUNTPOINT/$ERA_META_FN" fi fallocate -l $META_SIZE "$SNAP_MOUNTPOINT/$ERA_META_FN" chattr +i "$SNAP_MOUNTPOINT/$ERA_META_FN" echo "FLOCK_PERM=$SNAP_MOUNTPOINT/$ERA_META_FN" ORIG_DEVICE="/dev/mapper/$DEVNAME-$RUUID-clone-era" dmsetup table "$DEVICE" | dmsetup create "$DEVNAME-$RUUID-clone-era" urbackupclientbackend --internal --print-dm-file-extents "$SNAP_MOUNTPOINT/$ERA_META_FN" --file-dm-block-dev "$ORIG_DEVICE" | dmsetup create "$DEVNAME-$RUUID-era-metadata" dmsetup table "$DEVNAME-$RUUID-era-metadata" | dmsetup create "$DEVNAME-$RUUID-era-metadata-access" dd if=/dev/zero of=/dev/mapper/$DEVNAME-$RUUID-era-metadata bs=512 count=$((META_SIZE/512)) > /dev/null 2>&1 echo "0 $DEV_SIZE era /dev/mapper/$DEVNAME-$RUUID-era-metadata $ORIG_DEVICE 1024" | dmsetup create "$DEVNAME-$RUUID-clone" echo "CBT=type=era&reset=1" ERA_RESET=1 fi OVERLAY_FN="$SNAP_MOUNTPOINT/.overlay_2fefd007-3e48-4162-b2c6-45ccdda22f37_$SNAP_ID" if [ -e "$OVERLAY_FN" ] then chattr -i "$OVERLAY_FN" || true rm "$OVERLAY_FN" fi fallocate -l 5G "$OVERLAY_FN" chattr +i "$OVERLAY_FN" echo "FLOCK=$OVERLAY_FN" if ! [ -e "/dev/mapper/$DEVNAME-$RUUID-clone" ] then dmsetup table "$DEVICE" | dmsetup create "$DEVNAME-$RUUID-clone" fi urbackupclientbackend --internal --print-dm-file-extents "$OVERLAY_FN" --file-dm-block-dev "$ORIG_DEVICE" | dmsetup create "$DEVNAME-$SNAP_ID-cow-storage" UDEVCOOKIE=$(dmsetup udevcreatecookie) dmsetup suspend "$DEVICE" if dmsetup table "$DEVNAME-$RUUID-clone" | grep " era " > /dev/null 2>&1 then echo "Checkpointing device for CBT..." dmsetup message "$DEVNAME-$RUUID-clone" 0 checkpoint if [ $ERA_RESET != 1 ] then echo "CBT=type=era" echo "CBT_FILE=/dev/mapper/$DEVNAME-$RUUID-era-metadata-access" fi fi echo "Creating snapshot device..." echo "0 $DEV_SIZE snapshot /dev/mapper/$DEVNAME-$RUUID-clone /dev/mapper/$DEVNAME-$SNAP_ID-cow-storage N 32" | dmsetup create -r --udevcookie "$UDEVCOOKIE" "$DEVNAME-$SNAP_ID" if ! [ -e "/dev/mapper/$DEVNAME-$RUUID-origin" ] then echo "Creating snapshot origin device..." echo "0 $DEV_SIZE snapshot-origin /dev/mapper/$DEVNAME-$RUUID-clone" | dmsetup create --udevcookie "$UDEVCOOKIE" "$DEVNAME-$RUUID-origin" fi if ! dmsetup table "$DEVICE" | grep " snapshot-origin " > /dev/null 2>&1 then dmsetup table "$DEVNAME-$RUUID-origin" | dmsetup load "$DEVICE" fi dmsetup resume "$DEVICE" dmsetup udevreleasecookie "$UDEVCOOKIE" truncate -s100M $SNAP_MOUNTPOINT/.overlay_2fefd007-3e48-4162-b2c6-45ccdda22f37_$SNAP_ID-wsnap LODEV=`losetup -f` if [ "x$LODEV" = x ] then echo "TODO: Cleanup" exit 1 fi losetup $LODEV $SNAP_MOUNTPOINT/.overlay_2fefd007-3e48-4162-b2c6-45ccdda22f37_$SNAP_ID-wsnap echo "0 $DEV_SIZE snapshot /dev/mapper/$DEVNAME-$SNAP_ID $LODEV N 8" | dmsetup create "$DEVNAME-$SNAP_ID-wsnap" echo "Mounting /dev/mapper/$DEVNAME-$SNAP_ID-wsnap..." MOUNTOPTS="ro" if [ $TYPE = "xfs" ] then MOUNTOPTS="ro,nouuid" fi mkdir -p "$SNAP_DEST" if ! mount -o $MOUNTOPTS "/dev/mapper/$DEVNAME-$SNAP_ID-wsnap" "$SNAP_DEST" then echo "Mounting filesystem failed" #TODO: CLEANUP exit 1 fi echo "$DEVNAME" > ${SNAP_DEST}-name echo "/dev/mapper/$DEVNAME-$SNAP_ID" > ${SNAP_DEST}-dev echo "SNAPSHOT=$SNAP_DEST"