#!/usr/bin/env bash

function stop_mdadm
{
	sleep 2
	TARGET=$(readlink -f "$1")
	BASENAME=$(basename "$TARGET")
	while [ $(cat /proc/mdstat | grep "$BASENAME" | cut -d ' ' -f 1 | wc -l) -gt 0 ]; do
		MD_LIST=$(cat /proc/mdstat | grep "$BASENAME" | cut -d ' ' -f 1 | tr '\n\r' ' ')
		for MD in $MD_LIST; do
			echo "Stopping $MD"
			mdadm --stop "$MD" >/dev/null 2>/dev/null
		done
	done
}

if [ $# -eq 0 ]; then
	echo "usage: bdsnap <base> <cowfile>"
	exit 1
fi
if [ $# -eq 1 -a "$1" = "-h" ]; then
	echo "usage: bdsnap <base> <cowfile>"
	exit 1
fi

BASE="$1"
shift
COWFILE="$1"
shift

#------------------------------------------------------------------------------
# prepare environment

# verify loop devices are supported
losetup -f >/dev/null 2>/dev/null || modprobe loop
if [ $? -ne 0 ]; then
	echo "error: loop devices are not supported by this kernel"
	exit 1
fi

#------------------------------------------------------------------------------
# begin execution

if [ -f "$BASE" ]; then
	losetup --read-only -f "$BASE"
	DEVICE=$(losetup -j "$BASE" | cut -d ':' -f 1)
	stop_mdadm "$DEVICE"
else
	DEVICE="$BASE"
fi

DEVICE_SIZE_BYTES=$(blockdev --getsize64 "$DEVICE")
DEVICE_SIZE_SECTORS=$(($DEVICE_SIZE_BYTES/512))

dd status=none if=/dev/zero bs=1 count=0 seek=8000000000000 of="$COWFILE"
losetup -f "$COWFILE"
COWDEV=$(losetup -j "$COWFILE" | cut -d ':' -f 1)
COWDEV_SIZE_BYTES=$(blockdev --getsize64 "$COWDEV")
COWDEV_SIZE_SECTORS=$(($COWDEV_SIZE_BYTES/512))

dmsetup create bdsnap-$$-origin --table "0 $DEVICE_SIZE_SECTORS snapshot-origin $DEVICE"
stop_mdadm /dev/mapper/bdsnap-$$-origin
dmsetup create bdsnap-$$-snapshot --table "0 $DEVICE_SIZE_SECTORS snapshot /dev/mapper/bdsnap-$$-origin $COWDEV P 8"

echo "The writable snapshot is /dev/mapper/bdsnap-$$-snapshot"

dmsetup ls --tree
