前回は本連載で紹介してきたソースコードリテラシーの実践編として、
P-Plamo とは?
P-Plamoとは、
Plamo Linuxでも過去にCD-Plamoという名称で CDメディアから起動して使えるシステムを開発したことがありましたが、
一方、
そこで、
トラブル発生
一般的なLiveLinuxではCDやDVDメディア上に置いた実際のルートファイルシステムを使う前に、
限られた容量に可能な限りファイルを詰め込むためのファイルシステムの圧縮にはSquashFSを、
これらLiveLinuxに必要な機能を提供するモジュールとCD-ROM関連のモジュールを、
とりあえず動くものができたので、
当初は、
P-Plamo 0.
さてどうしたものか…、
そのため処理的には多少面倒になりますが、
ところが、
.... CD_DEV:/dev/hda pivot_root to /loop pivot_root: Invalid argument chroot: cannot execute /loop/sbin/init: No such file or directory Kernel panic - not syncing: Attemted to kill init!
よく似た機能なのに switch_
pivot_root のソースコード
今回使っているswitch_
% less docs/BusyBox.1
...
pivot_root
pivot_root NEW_ROOT PUT_OLD
Move the current root file system to PUT_OLD and make
NEW_ROOT the new root file system
...
switch_root
switch_root [-c /dev/console] NEW_ROOT NEW_INIT [ARGUMENTS_TO_INIT]
Use from PID 1 under initramfs to free initramfs,
chroot to NEW_ROOT, and exec NEW_INIT
Options:
-c Redirect console to device on new root
...
BusyBox のマニュアルには上記のような使い方の簡単な記述しかなく、
仕方ないのでBusyBoxのソースコードを眺めてみました。
% cat -n busybox-1.13.2/util-linux/pivot_root.c
...
11 #include "libbb.h"
12
13 extern int pivot_root(const char * new_root,const char * put_old);
14
15 int pivot_root_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
16 int pivot_root_main(int argc, char **argv)
17 {
18 if (argc != 3)
19 bb_show_usage();
20
21 if (pivot_root(argv[1], argv[2]) < 0) {
22 /* prints "pivot_root: " */
23 bb_perror_nomsg_and_die();
24 }
25
26 return EXIT_SUCCESS;
27 }
BusyBoxのpivot_
紹介はしませんでしたが、
カーネルソースの調査
システムコールとなるとカーネルソースの中の話になるので簡単には手が出せそうにありませんが、
% find /usr/src/linux -follow | xargs grep -i pivot_root | cat -n
1 /usr/src/linux/arch/s390/include/asm/unistd.h:#define __NR_pivot_root 217
2 /usr/src/linux/arch/s390/kernel/syscalls.S:SYSCALL(sys_pivot_root,sys_pivot_root,sys32_pivot_root_wrapper)
...
88 /usr/src/linux/Documentation/early-userspace/README: filesystem via linuxrc and use the pivot_root syscall. The initrd is
89 /usr/src/linux/Documentation/arm/IXP4xx: a pivot_root to NFS.
90 /usr/src/linux/usr/include/asm/unistd_64.h:#define __NR_pivot_root 155
91 /usr/src/linux/usr/include/asm/unistd_64.h:__SYSCALL(__NR_pivot_root, sys_pivot_root)
92 /usr/src/linux/usr/include/asm/unistd_32.h:#define __NR_pivot_root 217
各種アークテクチャ
実際の処理はどこだろうな…、
% cat -n /usr/src/linux/fs/namespace.c
...
2157 /*
2158 * pivot_root Semantics:
2159 * Moves the root file system of the current process to the directory put_old,
2160 * makes new_root as the new root file system of the current process, and sets
2161 * root/cwd of all processes which had them on the current root to new_root.
2162 *
2163 * Restrictions:
2164 * The new_root and put_old must be directories, and must not be on the
2165 * same file system as the current process root. The put_old must be
2166 * underneath new_root, i.e. adding a non-zero number of /.. to the string
2167 * pointed to by put_old must yield the same directory as new_root. No other
2168 * file system may be mounted on put_old. After all, new_root is a mountpoint.
2169 *
2170 * Also, the current root cannot be on the 'rootfs' (initial ramfs) filesystem.
2171 * See Documentation/filesystems/ramfs-rootfs-initramfs.txt for alternatives
2172 * in this situation.
2173 *
2174 * Notes:
2175 * - we don't move root/cwd if they are not at the root (reason: if something
2176 * cared enough to change them, it's probably wrong to force them elsewhere)
2177 * - it's okay to pick a root that isn't the root of a file system, e.g.
2178 * /nfs/my_root where /nfs is the mount point. It must be a mountpoint,
2179 * though, so you may need to say mount --bind /nfs/my_root /nfs/my_root
2180 * first.
2181 */
2182 SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
2183 const char __user *, put_old)
2184 {
2185 struct vfsmount *tmp;
2186 struct path new, old, parent_path, root_parent, root;
2187 int error;
2188
2189 if (!capable(CAP_SYS_ADMIN))
2190 return -EPERM;
2191
どういう処理をしているのかを見る前に、
そもそもinitial ramfs(initramfs)をルートファイルシステムにしている状態ではpivot_
Documentation/
% cat -n /usr/src/linux/Documentation/filesystems/ramfs-rootfs-initramfs.txt
1 ramfs, rootfs and initramfs
2 October 17, 2005
3 Rob Landley
4 =============================
5
6 What is ramfs?
7 --------------
8
9 Ramfs is a very simple filesystem that exports Linux's disk caching
...
このファイルは以前、
このファイルでは、
そして、
70 What is rootfs?
71 ---------------
72
73 Rootfs is a special instance of ramfs (or tmpfs, if that's enabled), which is
74 always present in 2.6 systems. You can't unmount rootfs for approximately the
75 same reason you can't kill the init process; rather than having special code
76 to check for and handle an empty list, it's smaller and simpler for the kernel
77 to just make sure certain lists can't become empty.
78
79 Most systems just mount another filesystem over rootfs and ignore it. The
80 amount of space an empty instance of ramfs takes up is tiny.
81
rootfsはramfsで実現されたカーネル内蔵のファイルシステムで、
もう少し読み進めていくと、
114 - When switching another root device, initrd would pivot_root and then
115 umount the ramdisk. But initramfs is rootfs: you can neither pivot_root
116 rootfs, nor unmount it. Instead delete everything out of rootfs to
117 free up the space (find -xdev / -exec rm '{}' ';'), overmount rootfs
118 with the new root (cd /newmount; mount --move . /; chroot .), attach
119 stdin/stdout/stderr to the new /dev/console, and exec the new init.
以前、
initrdの場合はメモリ上に割りあてたram diskをrootfs上にマウントしているので、
実のところ、
実際にinitrd形式ならpivot_
# dd if=/dev/zero of=miniroot bs=1M count=4
4+0 records in
4+0 records out
4194304 bytes (4.2 MB) copied, 0.0188857 s, 222 MB/s
# mke2fs -i1024 -m0 miniroot
mke2fs 1.41.4 (27-Jan-2009)
initrd is not a block special device.
Proceed anyway? (y,n) y
...
# mount miniroot /loop -o loop
# ( cd ./initramfs ; tar cvf - * ) | ( cd /loop ; tar xf -)
bin/
bin/busybox
bin/sh
...
# umount /loop
# gzip -c miniroot > initrd.gz
まずddコマンドでinitrd用に固定サイズのファイルをあらかじめ確保しておきます。この例では4Mバイト分、
そのファイルをmke2fsでフォーマットし、
このinitrd.

起動直後はinitrdが/dev/
この状態で、
/ # cd /put_old
/put_old # /sbin/pivot_root . put_old
/ # ls /
bin etc loop proc shutdown
cdrom init lost_found put_old sys
dev lib new_root sbin
pivot_
今回はinitramfsでpivot_
前回のpmountもそうでしたが、
さて、