I had an idea, have a machine that has more memory than it needs for what it does (32GB Ram), and I read about freebsds reboot(8) -r flag to use a kenv variable to soft reload the kernel and keep a created memory disk persistent across the reboot.. This sparked the idea.

It started of as a manual process, morphed into some ugly lines in /etc/rc.local, mulled it over for some time and finally I wrote a script that does what I want, /etc/rc.d/reboot2md, I've so far tested it on very few systems so if you got an idea for a improvement let me know.

The script is controlled by a few variables in rc.conf

reboot2md_enable := <no default>

traditional YES/NO to enable the script, with no default NO so it complaints that there's something wrong

reboot2md_mdparam := -s 4g

parameters passed to mdconfig for disc createion -s is a highly recomended option

reboot2md_fixfstab := YES

manipulate fstab as part of the reboot process (lets reboot2md_oldroot do it's thing)

reboot2md_oldroot := rootdisk

string appended to / mount line in /etc/fstab to allow for easy remount of / to edit something in the "base" system, this is handled by the sed line so for instance

/dev/gpt/usbstick   /   ufs rw  0   0

becomes

/dev/gpt/usbstick /rootdisk ufs noauto,rw 0 0

So in my simple testsetup I added this to rc.conf

reboot2md_enable="YES"
reboot2md_mdparam="-s 4g"
reboot2md_oldroot="diskroot"
reboot2md_fixfstab="YES"

And here's the script, and yeah, the sed line is not pretty to look at.

#!/bin/sh
#
# $FreeBSD reboot2md$
#

# BEFORE: root
# REQUIRE: fsck
# KEYWORD: nojail

. /etc/rc.subr

name="reboot2md"
desc="Move root to md device and reboot2md from there"
rcvar="reboot2md_enable reboot2md_oldroot reboot2md_size reboot2md_fixfstab"
start_cmd="reboot2md_start"
stop_cmd=sync

: ${reboot2md_semaphore:="etc/.REBOOTED2MD"}
: ${reboot2md_oldroot:="oldroot"}
: ${reboot2md_mdparam:="-s 4g"}
: ${reboot2md_fixfstab:="YES"}

reboot2md_start()
{
  if [ ! -r /${reboot2md_semaphore} ]; then
    echo -n "Rerooting: md"
    md=$(/sbin/mdconfig ${reboot2md_mdparam})
    echo -n " is $md"
    echo -n ", fsbuild"
    /sbin/newfs /dev/$md 2>/dev/null >/dev/null
    /sbin/mount /dev/$md /mnt 2>/dev/null >/dev/null
    echo ", file copy"
    mkdir -p /mnt/tmp
    chmod 1777 /mnt/tmp
    env TMPDIR=/mnt/tmp /bin/pax -Xrw -pe / /mnt 2>/dev/null >/dev/null
    if checkyesno reboot2md_fixfstab; then
      mkdir -p /mnt/${reboot2md_oldroot}
      echo ", fstab fixups"
      /bin/cat /etc/fstab|/rescue/sed -e "s/^\([^[:space:]]*\)[[:space:]]*[[:space:]]\(\/\)[[:space:]][[:space:]]*\([^[:space:]]*\)[[:space:]]*\([^[:space:]]*\)[[:space:]]*\([^[:space:]]*\)[[:space:]]*\([^[:space:]]*\)/\1 \2${reboot2md_oldroot} \3 noauto,\4 \5 \6/g">/mnt/etc/fstab
      echo "/dev/${md} / ufs rw 0 0">>/mnt/etc/fstab
    fi
    echo ", semaphore"
    touch /mnt/${reboot2md_semaphore}
    echo -n ", reboot2md"
    if [ -r /mnt/${reboot2md_semaphore} -a -r /mnt/boot/kernel/kernel ]; then
      echo " now"
      kenv vfs.root.mountfrom=ufs:/dev/$md
      reboot -r
    else
      echo " aborted"
    fi
  fi
}

load_rc_config $name
run_rc_command "$1"

Comments

comments powered by Disqus