File: //usr/local/share/urbackup/dm_create_snapshot
#!/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"
# Needs to run with mlockall for root device -> cannot do that in bash
urbackupclient_dmsnaptool --dev "$DEVICE" --clone-dev "/dev/mapper/$DEVNAME-$RUUID-clone" --snap-dev "/dev/mapper/$DEVNAME-$SNAP_ID" --cow-dev "/dev/mapper/$DEVNAME-$SNAP_ID-cow-storage" --origin-dev "/dev/mapper/$DEVNAME-$RUUID-origin" --era-access-dev "/dev/mapper/$DEVNAME-$RUUID-era-metadata-access" --dev-size "$DEV_SIZE"
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"