#!/bin/bash
#
#%stage: softraid
#
mdblockdev=

# Full mdadm.conf generated by mdadm.
# Contains all created MD RAIDs
mdadm_conf=

cont_list=
md_devs=
mpath_found=

# blockdev contains real devices (/dev/X) for root, resume, journal, dumb
for bd in $blockdev ; do
    is_part_dev=false
    case $bd in
	/dev/md[0-9]*p[0-9]*)
	    # Partitionable MD RAID. This is partition on RAID. Get the RAID
	    bd=${bd%%p[0-9]*}
	    is_part_dev=true
	    ;;
	/dev/md[0-9]*)
	    ;;
	*)
	    mdblockdev="$mdblockdev $bd"
	    continue
	    ;;
    esac
    # Check if this device is already added (possible for partitionable).
    md_dev=${bd##/dev/}
    dup_found=false
    for dup in $md_devs; do
	if [ x"$dup" = x"$md_dev" ]; then
	    dup_found=true
	    break
	fi
    done
    if $dup_found; then
	if ! $is_part_dev; then
	    echo "setup-md.sh: $md_dev found multiple times" >&2
	fi
        continue
    fi
    # Convert to stable name
    MD_DEVNAME= mdbd=$bd
    eval `mdadm -Db --export "$mdbd" | grep MD_DEVNAME`
    if [ -n "$MD_DEVNAME" -a -b "/dev/md/$MD_DEVNAME" ]
    then mdbd=/dev/md/$MD_DEVNAME
    fi
    mdconf=$(mdadm -Db "$mdbd")
    if test -z "$mdconf"; then
        mdblockdev="$mdblockdev $bd"
        continue
    fi
    md_tmpblockdev=$(mdadm -Dbv $bd | sed -n "1D;s/,/ /g;s/^ *devices=//p")
    # This is sub-optimal.
    # MD on top of multipath needs to filter the devices during
    # scan, otherwise it might start and activate the underlying
    # block devices, causing multipath to fail.
    # However, we can only set a global filter, not a per-MD one.
    # So whenever we have one MD on multipath _all_ MDs need to
    # run on multipath.
    for tmp_bd in $md_tmpblockdev ; do
	dm_target=$(dmsetup table $tmp_bd | sed -n 's/[0-9]* [0-9]* \([a-z]*\) .*/\1/p')
	if [ "$dm_target" = "linear" ] ; then
	    # MD might run on partitions, check the holder
	    tmp_bd=$(dmsetup table $tmp_bd | sed -n 's/.* linear \([0-9]*\):\([0-9]*\) .*/-j \1 -m \2/p')
	fi
	dm_table=$(dmsetup table --target multipath $tmp_bd)
	if [ $? -eq 0 ] && [ -n "$dm_table" ] ; then
	    if [ -z "$mpath_found" ] ; then
		mpath_found=1
	    elif [ "$mpath_found" -eq 0 ] ; then
		echo "Activating multipath for MD $bd"
		mpath_found=1
	    fi
	else
	    if [ -z "$mpath_found" ] ; then
		mpath_found=0
	    fi
	fi
    done

    mdblockdev="$mdblockdev $md_tmpblockdev"
    md_devs="$md_devs $md_dev"
    container=$(echo "$mdconf" | sed -rn 's/.* container=([^ ]*) .*/\1/p')
    for cnt in $cont_list; do
        if [ x"$container" = x"$cnt" ]; then
            container=
            break
        fi
    done
    cont_list="$container $cont_list"
    case "$container" in
    "")
        ;;
    /dev/*)
        mdconf="$(mdadm -Db "$container")\\n$mdconf"
        ;;
    [0-9a-f]*[0-9a-f])
        if test -z "$mdadm_conf"; then
            mdadm_conf=$(mdadm --examine --brief --scan)
        fi
        mdconf="$(echo "$mdadm_conf" | grep "UUID=$container")\\n$mdconf"
        ;;
    *)
        echo "unrecognized container for $md_dev: $container"
        ;;
    esac
    eval md_conf_${md_dev}=\"$mdconf\"
    root_md=1
done

# Any 'md' device is replaced by it's component disks.
blockdev="$mdblockdev"

if [ -n "$root_md" ] ; then
    need_mdadm=1
    echo -n "" > $tmp_mnt/etc/mdadm.conf
    if [ "x$mpath_found" = x1 ] ; then
	# QLOGIC uses async scanning, so we must enable
	# udev triggered assembly.
	echo 'AUTO -all' >> $tmp_mnt/etc/mdadm.conf
	# Disable udev for all but dm devices.
	echo 'KERNEL!="dm*", ENV{MDADM_INCR_DISABLED}="1"' > $tmp_mnt/etc/udev/rules.d/63-md-on-dm-only.rules
    fi
    for md in $md_devs; do
        eval echo -e \"\$md_conf_$md\" >> $tmp_mnt/etc/mdadm.conf
    done
fi
# Remember which arrays are needed for the root or swap device and assemble
# them all during boot. The root= or resume= option might not directly refer to
# the array.
md_devs=$(printf '/dev/%s ' $md_devs)

save_var need_mdadm
save_var md_devs
