switch_root and centos

Rob Landley rob at landley.net
Thu Dec 31 10:39:32 UTC 2009


You'd think this would be a FAQ by now...

The following shell script is more or less what switch_root is doing, minus 
the sanity checks (and ignoring the -c console handling):

  find / -type f -xdev | xargs rm -f
  find / -type d -depth -xdev | xargs rmdir
  cd "$1"
  mount --move . /
  chroot .
  shift
  exec "$@"  

I.E. delete the contents of initramfs to free up the memory, chroot into the 
new directory, and exec the new init.

In practice, deleting your old /bin and /lib directories before doing the 
chroot leaves a shell script sort of hanging before it does chroot, and I've 
seen it made to work by statically linking things and running binaries out of 
the new directory before you've chrooted into it, but just having it be one 
executable is a lot less fiddly.

However, doing any variant of "find / | xargs rm" is EXTREMELY DANGEROUS, and a 
good way to eat your development system if you ever let your guard down, so 
switch_root has some fairly stringent sanity checks:

  1) The new root directory can't be the same filesystem as / (or its contents
      would get deleted before you switched into it).
  2) The old / has to be a ramfs or tmpfs.  (Sort of the point of deleting its
      contents to free space.)
  3) You must be running as PID 1.

If any of these aren't true, you're not using it right anyway, and it aborts 
rather than potentially eat your development system.

That clear anything up?

On Monday 14 December 2009 14:53:07 Michael Di Domenico wrote:
> Mount move what though?  I thought switchroot was support to do that
> under the covers, basically swapping
>
> /dev/ram0 rootfs /
>
> with
>
> /dev/hda ext3 /newroot
>
> then do a chroot into /

Nope.  If you have any other filesystems mounted under /, moving them into the 
new filesystem (or unmounting them) is your job.

> and then run what?  this seems to be where i'm getting stuck...  :(

switch_root does a chroot for you.  It's rm -rf, mount --move, and chroot all 
in one.

> though once the above fails and i end up back in busybox i see
>
> /dev/ram0 /
> and
> /dev/hda /

If you're using a ramdisk instead of a ramfs, switch_root is the wrong tool.

The rm -rf behavior frees space from a ramfs.  But a ram disk takes the same 
amount of space whether its contents are being used or not, that's a ram based 
_block_device_ (of fixed size).  Not a dynamically resizing ram based 
filesystem.

initrd != initramfs.

The reason you see both at / is the mount --move is essentially going to 
overmount.  (Note that the directory you mount a filesystem on doesn't have to 
be empty.  You can even have one filesystem mounted on top of another.  The old 
contents of the directory are hidden until you unmount the new filesystem.)

Note that "rootfs" is the ramfs instance that the initramfs cpio archive 
populates.  It's always there, about the same way PID 1 is always there, and 
attempts to unmount it would be ignored the same way PID 1 ignores unhandled 
signals (even kill -9).

When you're using another root filesystem, it's mounted over rootfs, but if you 
"cat /proc/mounts" rootfs should always be the first entry in that.

Rob
-- 
Latency is more important than throughput. It's that simple. - Linus Torvalds


More information about the busybox mailing list