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”.

I’m delving pretty deep into FreeBSD, time to grow an epic beard.

3 Replies to “FreeBSD manual multipath script”

  1. I have done further testing with the script and have determined that the issue appears to be with a character limit with the ‘name’ argument when used along with the ‘gmultipath create’ subcommand.

    The four paths are creating longer names when auto-generated by the $arg1 variable, one character longer than what is legal . While it fails with ‘create’, it succeeds with the ‘label’ subcommand.

    Unfortunately the man page says nothing about any character limit. The only solution is to use a different naming logic.

  2. Ah yes, I never tested this script with more than 2 paths. In fact looking at the code, it’s evident that I had no more than 2 paths in mind.

    Would you be willing to edit the script to make it support more than 2 paths and contribute it back?

    I might be able to do so but I don’t have a system to test it any more (so I’d need to rely on you for this), and I can’t say that it’s a top priority either :). although it’s probably a quick edit. What do you think?

  3. I am trying to use this script with a JBOD that has four active paths and it fails with the following error message:

    Dec 12 22:54:50 ######### kernel: GEOM_MULTIPATH: da65da77da81da3 created
    Dec 12 22:54:50 ######### kernel: GEOM_MULTIPATH: destroying da65da77da81da3
    Dec 12 22:54:50 ######### kernel: GEOM_MULTIPATH: da65da77da81da3 destroyed
    Dec 12 22:54:51 ######### kernel: GEOM_MULTIPATH: da66da76da82da4 created
    Dec 12 22:54:51 ######### kernel: GEOM_MULTIPATH: destroying da66da76da82da4
    Dec 12 22:54:51 ######### kernel: GEOM_MULTIPATH: da66da76da82da4 destroyed

    Interestingly, the script works with the same environment with only two active paths. Any ideas what might be happening?

    Thank you!

Leave a Reply

Your email address will not be published. Required fields are marked *