[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[debian-users:39333] Re: make-kpkg --initrd (Re: Kernel panic: No init found)



末廣と申します。

一週間ほど前の話題で済みませんが...
ちょっと面白そうなので調べてみました。

On Tue, Jan 13, 2004 at 11:37:36AM +0900,
 SATOH Fumiyasu wrote:

> つい最近、私も make-kpkg の --initrd オプションを試したことが
> あるのですが、ブート時になぜか cramfs な initrd のマウントに失敗し
> ブートできない (kernel panic) カーネルになってしまいます。
> カーネルのソースは、cramfs な initrd に対応するパッチが
> 取り込まれた Linux 2.4.22 と Linux 2.4.23 で試しました。
> (Debian のカーネルソース (kernel-source-*) も試したような気がするが、
>  記憶が定かではない…)

kernel-source-2.4.23ではcramfsなinitrdで無事にブートできました。
debianのカーネルパッチの中で次の部分が効いているようです。
# が、副作用がどれくらいあるのか良く分かりません。

======================================================================
diff -urN kernel-source-2.4.23/fs/block_dev.c kernel-source-2.4.23-1/fs/block_dev.c
--- kernel-source-2.4.23/fs/block_dev.c	2003-06-14 00:51:37.000000000 +1000
+++ kernel-source-2.4.23-1/fs/block_dev.c	2003-06-01 20:43:53.000000000 +1000
@@ -95,7 +95,7 @@
 	sync_buffers(dev, 2);
 	blksize_size[MAJOR(dev)][MINOR(dev)] = size;
 	bdev->bd_inode->i_blkbits = blksize_bits(size);
-	kill_bdev(bdev);
+	invalidate_bdev(bdev, 1);
 	bdput(bdev);
 	return 0;
 }
======================================================================

このパッチはset_blocksize関数の中のkill_bdev関数をinvalidate_bdev
関数で置きかえるものです。実はkill_bdev関数の中身はこのinvalidate_bdev
関数とtruncate_inode_pages関数です。多分、truncate_inode_pages関数
によってramdisk用のpageが切り捨てられてファイルシステムが壊れて
しまっていたのだと思います。

set_blocksize関数は、ファイルシステムのマウントの過程で呼出される
{ext2,cramfs..}_read_super関数の中で使用されています。

> 具体的にはどうなるかと言うと、
> 
>     RAMDISK: cramfs filesystem found at block 0
> 
> と initrd が cramfs であると認識できるのに、

ここではcramfs_read_super関数を使用せずに、ramdiskデバイスを
直接読んでファイルシステムのタイプを検査しているので問題なしです。

>     RAMDISK: Loading 1016 blocks [1 disk] into ram disk...done.
>     Freeing initrd memory: 1016k freed
>     cramfs: wrong magic
>     Kernel panic: VFS: Unable to mout root fs on 03:02
> 
> と、実際にマウントしようとすると cramfs な magic ではないと
> 認識されてしまいます。

ここでマウントしようとしたときにset_blocksize関数が呼ばれています。

> 以下の (アドホックな?) スクリプトを用いることで initrd を ext2 に
> したところ、問題は起りませんでした。

set_blocksize関数は新旧のブロックサイズを比較して、等しければ
直ちにリターンします。元々のramdiskのブロックサイズが1kバイト
であるのに対して、ext2は1kバイトでcramfsは4kバイトです。
したがって、ext2では(たまたま)上手くいくが、cramfsでは問題が
具現化してしまうようです。

たとえば、次のようにすればext2でも失敗します。

# cat cramfs.img > /dev/ram0
# mount -t cramfs /dev/ram0 /mnt/foo	==> cramfsは失敗
# cat ext2.img > /dev/ram0
# mount -t ext2 /dev/ram0 /mnt/foo	==> ext2でも失敗

でも、2回くりかえすとどちらのファイルシステムでも成功します。

# cat cramfs.img > /dev/ram0
# mount -t cramfs /dev/ram0 /mnt/foo	==> 失敗
# cat cramfs.img > /dev/ram0
# mount -t cramfs /dev/ram0 /mnt/foo	==> 成功

-- 
    末廣雅利 E-mail: gully@xxxxxxxxxxxxx