pivot_root and starting services

Everything that does not fit anywhere else
Post Reply
langerak
Posts: 160
Joined: Sat May 29, 2010 6:37 pm

pivot_root and starting services

Post by langerak » Wed Apr 03, 2013 3:05 pm

Hi!

I have managed to get a Linksys MediaHub running on Debian using pivot_root, but I have a small question about the way it handles services:

It has a partition of 300MB (and may not be larger, else uBoot won't load the kernel off the disk), this contains a very basic Debian squeeze install with only the necessary options. I also have a larger 20GB partition where this same data stored on and there I have installed SSH, Samba etc on.

The problem is that I now have the pivot_root action in /etc/rc.local, where this is called at the end of the init process. What I would like to accomplish is that the pivot_root action is being handled before the system services like SSH and Samba are started, because they can only be started when the pivot_root has taken place.

I've search a while on Google and on the forums, but was not able to sort this out, anybody got a lead for me?

The script I've created is below should someone need it:

Code: Select all

#!/bin/bash
#
# Created by Jeffrey Langerak on 30-3-2013
#
# This script will pivot_root from the small 300MB
# partition to the bigger partition, allowing the
# installation of packages and configuration
#
# This script is delivered as is, no warranties are
# given and you should use this at your own risk!
#
# Version 1.0
#
# Setting colors and columns:
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
NORMAL=$(tput sgr0)
col=80 # change this to whatever column you want the output to start at
# Check for /overlay directory
echo -n "Checking for /overlay directory:"
if [ -d /overlay ];
then
        printf '%s%*s%s' "$GREEN" $col "[OK]" "$NORMAL"
else
        printf '%s%*s%s' "$RED" $col "[FAIL]" "$NORMAL"
        echo -n "Creating /overlay directory:"
        if mkdir /overlay > /dev/null 2>&1
        then
                printf '%s%*s%s' "$GREEN" $col "[OK]" "$NORMAL"
        else
                printf '%s%*s%s' "$RED" $col "[FAIL]" "$NORMAL"
                exit
        fi
fi
# Mount 3rd partition on /overlay
echo -n "Mounting /dev/sda3 on /overlay:"
if mount /dev/sda3 /overlay > /dev/null 2>&1
then
        printf '%s%*s%s' "$GREEN" $col "[OK]" "$NORMAL"
else
        printf '%s%*s%s' "$RED" $col "[FAIL]" "$NORMAL"
        exit
fi
# Checking for old-root directory in /overlay
echo -n "Checking for /overlay/old-root directory:"
if [ -d /overlay/old-root ];
then
        printf '%s%*s%s' "$GREEN" $col "[OK]" "$NORMAL"
else
        printf '%s%*s%s' "$RED" $col "[FAIL]" "$NORMAL"
        echo -n "Creating /overlay/old-root directory:"
        if mkdir /overlay/old-root > /dev/null 2>&1
        then
                printf '%s%*s%s' "$GREEN" $col "[OK]" "$NORMAL"
        else
                printf '%s%*s%s' "$RED" $col "[FAIL]" "$NORMAL"
                exit
        fi
fi
# Pivot_root to the new root filesystem mounted on /overlay
echo -n "Switching filesystem to overlay filesystem:"
if /sbin/pivot_root /overlay /overlay/old-root > /dev/null 2>&1
then
        printf '%s%*s%s' "$GREEN" $col "[OK]" "$NORMAL"
else
        printf '%s%*s%s' "$RED" $col "[FAIL" "$NORMAL"
        exit
fi
# Mount /proc
echo -n "Mounting /proc:"
if mount -t proc proc /proc > /dev/null 2>&1
then
        printf '%s%*s%s' "$GREEN" $col "[OK]" "$NORMAL"
else
        printf '%s%*s%s' "$RED" $col "[FAIL" "$NORMAL"
        exit
fi
# Done
exit

Mijzelf
Posts: 6224
Joined: Mon Jun 16, 2008 10:45 am

Re: pivot_root and starting services

Post by Mijzelf » Thu Apr 04, 2013 8:14 am

A few points:
  • pivot_root should be called *before* init. The most common way is to exchange /sbin/init (or /initrc, or whatever the kernel will call first, as specified by the command line) by a script which mounts the target rootfs, does a pivot_root, and exec's the new /sbin/init. That exec is important, it means that the process will run another executable, instead of starting a new process. (The kernel doesn't like it when init stops)
    This way a rather complicated 2nd rootfs can be used (raid array, cryptfs, nfs, ...). Normally this is done by a busybox based initramfs, but a full blown enterprise rootfs can do the same.
  • Why don't you specify your 2nd partition as rootfs in the kernel command line? There is no actual reason why the partition containing the kernel should be the rootfs.
  • You can also move the contents of /usr to your 2nd partition, and mount it in fstab. Debian doesn't need anything from /usr before mount -a is executed, and additional packages are mainly installed in /usr

langerak
Posts: 160
Joined: Sat May 29, 2010 6:37 pm

Re: pivot_root and starting services

Post by langerak » Thu Apr 04, 2013 9:09 am

I already suspected something like that, but didn't want to mess around too much :)!

The NAS has some variables for uBoot which cannot be set, that is in this case the "bootcmd" and wants the rootfs on either sda2 or sdb2, depending on the slot the harddisk is in (it has 2 bays) and sets the init process at the file /linuxrc, which for now is a symlink to /sbin/init on the NAS.

If uBoot was open, I wouldn't go through all this hassle to get it working :P!

So in order to change this I should point /linuxrc to my overlay script and at the end execute the /sbin/init script right? So something like:

Code: Select all

exec /sbin/init

Mijzelf
Posts: 6224
Joined: Mon Jun 16, 2008 10:45 am

Re: pivot_root and starting services

Post by Mijzelf » Thu Apr 04, 2013 9:52 am

Indeed. BTW there is a bug in your script:

Code: Select all

/sbin/pivot_root /overlay /overlay/old-root
Afaik that *must be*

Code: Select all

cd /overlay
/sbin/pivot_root . old-root
In other words, the current directory must be in the new rootfs before switching away the old one.
And I'm not sure if pivot_root has a meaningful return value. I've never seen a different pattern than:

Code: Select all

# mount stuff

cd /overlay
/sbin/pivot_root . old-root
exec /sbin/init

echo "Panic! Not supposed to be here!"
By the way, on a headless server it is a good practice to have a Panic function, which you call on all places you have an exit now. The contents of the Panic function is:
  • Maybe write some loginfo somewhere
  • Assign a static IP address to the NIC
  • Start a login less telnet daemon:

    Code: Select all

    telnetd -l /bin/bash
  • Start a shell

    Code: Select all

    /bin/bash
    This shell is accessible over serial, if applicable, and causes the init script to stay alive until this shell is exited (or killed)
This way you can connect over telnet when something goes wrong, and solve the problem. An 'exit' in init will just cause a kernel panic, maybe followed by a reboot, which will of course also fail.
In your case, having a complete Debian rootfs handy, you could also exec the /sbin/init of the current rootfs.

langerak
Posts: 160
Joined: Sat May 29, 2010 6:37 pm

Re: pivot_root and starting services

Post by langerak » Thu Apr 04, 2013 11:57 am

Thanks for the suggestions! I will try them tonight on the NAS to see if all works well, I'll let you know :).

The bug found actually works for me, when I log in, it sees the 20GB as root disk, although I understand why it's nicer to first jump in the overlay folder :).

langerak
Posts: 160
Joined: Sat May 29, 2010 6:37 pm

Re: pivot_root and starting services

Post by langerak » Fri Apr 05, 2013 10:14 am

I've changed the script in a way that the last line now contains the "exec /sbin/init" line and pointed the /linuxrc file to my overlay script.

All is working great now and the services are now being started from the bigger partition! Thanks!

Post Reply