#!/bin/bash

MNT=$1
shift
DISKS=( $@ )

dev_removed=0
removed_dev_htl=""
dev=""

_fail () {
	echo $@
	_cleanup
	exit 1
}

# arg 1 is dev to remove and is output of the below eg.
# ls -l /sys/class/block/sdd | rev | cut -d "/" -f 3 | rev
_devmgt_remove()
{
	local lun=$1
	local disk=$2

	echo 1 > /sys/class/scsi_device/${lun}/device/delete || _fail "Remove disk failed"

	stat $disk > /dev/null 2>&1
	while [ $? -eq 0 ]; do
		sleep 1
		stat $disk > /dev/null 2>&1
	done
}

# arg 1 is dev to add and is output of the below eg.
# ls -l /sys/class/block/sdd | rev | cut -d "/" -f 3 | rev
_devmgt_add()
{
	local h
	local tdl
	local i
	local j
	# arg 1 will be in h:t:d:l format now in the h and "t d l" format
	h=`echo ${1} | cut -d":" -f 1`
	tdl=`echo ${1} | cut -d":" -f 2-|sed 's/:/ /g'`

	echo ${tdl} >  /sys/class/scsi_host/host${h}/scan || _fail "Add disk failed"

	# ensure the device comes online
	dev_back_oneline=0
	for i in `seq 1 10`; do
		if [ -d /sys/class/scsi_device/${1}/device/block ]; then
			dev=`ls /sys/class/scsi_device/${1}/device/block`
			for j in `seq 1 10`;
			do
				stat /dev/$dev > /dev/null 2>&1
				if [ $? -eq 0 ]; then
					dev_back_oneline=1
					break
				fi
				sleep 1
			done
			break
		else
			sleep 1
		fi
	done
	if [ $dev_back_oneline -eq 0 ]; then
		echo "/dev/$dev online failed"
	else
		echo "/dev/$dev is back online"
	fi
}




trap "_cleanup; exit \$status" 0 1 2 3 15

_cleanup() {
	umount $MNT >/dev/null 2>&1

	if [ $dev_removed == 1 ]; then
		_devmgt_add "${removed_dev_htl}"
	fi
}



wait_for() {
	cmd=$1
	substr=$2
	interval=$3

	if [ -z "$interval" ]; then
		interval=1
	fi

	echo -n "Waiting for '$substr' in output of '$cmd' command..."

	while ! ($cmd | grep -q -e "$substr"); do
		[ $interval -gt 0 ] && sleep $interval
	done
	echo " found"
}


if [ $# -lt 2 ]; then
	echo "Usage: $0 <FS mountpoint> <disks>" >&2
	exit 1;
fi

n=${#DISKS[@]}

umount $MNT >/dev/null 2>&1

echo "${DISKS[@]} -> $MNT"

for i in ${DISKS[@]}; do
	wipefs -a $i >/dev/null 2>&1
done

# Create FS
mkfs.btrfs -d raid5 -m raid5 ${DISKS[@]}

mount ${DISKS[0]} $MNT
dd if=/dev/zero of=$MNT/test.dat bs=10M count=4
sync

for i in `seq $n -1 $((n-2))`; do
	d=`basename ${DISKS[$((i-1))]}`

	echo "Remove $d"

	removed_dev_htl=`ls -l /sys/class/block/${d} | rev | cut -d "/" -f 3 | rev`
	_devmgt_remove ${removed_dev_htl} ${failed_disk}
	dev_removed=1
	btrfs fi sync $MNT
	sleep 3
#	wait_for "btrfs fi show $MNT" "degraded"

	echo "Insert $d"

	_devmgt_add "${removed_dev_htl}"
	d=$dev
	dev_removed=0

	sleep 1

	wipefs -a /dev/$d

	umount $MNT
	mount -o degraded ${DISKS[0]} $MNT || exit 1

	echo "Start replacing DEVID $i by /dev/$d"

	btrfs replace start -B $i /dev/$d $MNT
	echo "Replace finished"

#	btrfs fi sync $MNT
#	umount $MNT
#	rmmod btrfs
#	modprobe btrfs
#	btrfs device scan
#	mount -o degraded ${DISKS[0]} $MNT || exit 1

	btrfs-debug-tree ${DISKS[0]} > btrfs-replace-devid$i.log 2>&1
	btrfs balance start $MNT
	echo "Balance finished"
done

echo "Done."
