FreeBSD manual multipath script

I recently ran into an issue installing FreeBSD on a system that already had some disks & zpools. Because the disks were partitioned previously, automatic multipath was not an option as the last sector of all hard drives isn’t available to store an ID. The remaining option is to do manual multipath, and it needs to be done every time the system boots.

Here’s an rc script that will run early in the sequence and create a multipath “link” between drives based on their serial number.

/etc/rc.d/manual_multipath

#!/bin/sh

# PROVIDES: manual_multipath
# REQUIRE: sysctl
# BEFORE: hostid

. /etc/rc.subr

name="manual_multipath"
start_cmd="${name}_start"
stop_cmd=":"

manual_multipath_start()
{
        echo "> manual_multipath script started"
        echo "> linking drives with the same serial number with gmultipath"
        counter=0
        serials=""
        devices=`/usr/bin/find /dev -maxdepth 1 -regex '.*da[0-9]*' | /usr/bin/cut -d '/' -f 3`
        for device in $devices
        do
                echo $device
                serial=`camcontrol inquiry $device -S`
                substring=`echo "$serials" | /usr/bin/sed -n "s/\|$serial\|.*//p" | /usr/bin/wc -c`
                if [ $substring -eq 0 ]
                then
                        found_multi=0
                        arg1="$device"
                        arg2="$device"
                        for newdevice in $devices
                        do
                                newserial=`camcontrol inquiry $newdevice -S`
                                if [ "$device" != "$newdevice" -a "$serial" == "$newserial" ]
                                then
                                        echo "  same as $newdevice!"
                                        counter=`expr $counter + 1`
                                        found_multi=1
                                        arg1=$arg1"$newdevice"
                                        arg2=$arg2" $newdevice"
                                fi
                        done
                        if [ $found_multi -eq 1 ]
                        then
                                gmultipath create $arg1 $arg2
                        fi
                fi
                serials=$serials"|$serial|"
        done
        echo "> manual_multipath script finished, found $counter matches"
}

load_rc_config $name
run_rc_command "$1"

Don’t forget to “chmod 555 /etc/rc.d/manual_multipath”.

Lastly, when importing a zpool from the drives you just multipathed, make sure to specify where to look for devices or you might end up importing a mix of multipath and regular devices. Make sure to “zpool import -d /dev/multipath”.