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.
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.
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?
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!