fsdb と find で破損したファイルを探す on NetBSD

fsdb の使い方

まず fsdb の意味を説明し、 最後に dmesg のエラーからファイルを探す例を紹介します。

(1) fsdb を起動します。検索の際には書き込む必要がないわけですから、 念のため(書き込まないという宣言をするフラッグ) -n をつけておくとよいです。

# fsdb -n -f /dev/rwd1a
** /dev/rwd1a (NO WRITE)
Editing file system `/dev/rwd1a'
Last Mounted on /altroot
current inode: directory
I=2 MODE=40755 SIZE=512
        MTIME=Dec 21 00:11:08 2007 [525685000 nsec]
        CTIME=Dec 21 00:11:08 2007 [525685000 nsec]
        ATIME=Dec 21 00:11:11 2007 [386094000 nsec]
OWNER=root GRP=wheel LINKCNT=4 FLAGS=0x0 BLKCNT=0x2 GEN=0x2f31579b

当然 I=2 つまり inode 2 でスタートです。 プロンプトにも inum: 2 と現在の参照している inode が表示されています。

(2) 現在のディレクトリ内容の表示は ls コマンドで出来ます。 struct inode の dump のようなものなので、 読みにくいですが ls -i 相当の動作です。

fsdb (inum: 2)> ls
slot 0 ino 2 reclen 12: directory, `.'
slot 1 ino 2 reclen 12: directory, `..'
slot 2 ino 67584 reclen 12: directory, `usr'
slot 3 ino 3 reclen 48: regular, `.00_ALTROOT_FILE_SYSTEM'
slot 4 ino 78848 reclen 428: directory, `tmp'

(3) 操作対象の inode を変えます。 ここでは例として tmp ディレクトリ( inode 78848 )へ移りましょう。 「lookup ファイル名」か 「cd ディレクトリ」を実行すると、その inode へ操作対象が変わります。

fsdb (inum: 2)> lookup tmp
component `tmp': current inode: directory
I=78848 MODE=41777 SIZE=512
        MTIME=Dec 20 23:17:46 2007 [667813000 nsec]
        CTIME=Dec 20 23:17:46 2007 [667813000 nsec]
        ATIME=Dec 20 23:17:55 2007 [429064000 nsec]
OWNER=root GRP=wheel LINKCNT=2 FLAGS=0x0 BLKCNT=0x2 GEN=0x289847

(4) inode 78848 の中身を表示させるには blks コマンドを使います。 blks コマンドは disk inode のデータを読みこみ、 その inode が参照しているブロックナンバーを表示します。

fsdb (inum: 78848)> blks
I=78848 2 blocks
Direct blocks:
0: 325872 
ここでは tmp が 325872 という direct block を使っていることが分かります。 この例は小さいので direct block だけですが、 大きなファイルであれば、もちろん indirect blocks も表示されます。

(5) 次は、逆にブロックナンバーから inode を探すことを考えましょう。 残念ながら findblk の引数と blks の表示するブロックナンバーは単位が異 なるので変換する必要があります。変換パラメータは dumpfs で分かるのです が、fsdb を実行する前に調べておく必要があります。

(5.1) dumpfs して fsbtodb パラメータの値を確認します。

# dumpfs /dev/rwd1a | grep fsbtodb
frag    8       shift   3       fsbtodb 1

(5.2) 変換式は block number * 2^(fsbtodb の値)です。 この場合、

325872 * 2 ^ (1) = 325872 * = 651744

(5.3) この値で findblk を実行すると inode 78848 のデータブロックだと表 示されます。

fsdb (inum: 78848)> findblk 651744
651744: data block of inode 78848

(6) ブロックナンバーからファイル名を探すには fsdb と find を組み合わせます。 普通は、壊れたブロックナンバーから inode を求め、その壊れている部分が、 どのファイルにあたるのかを調べたいわけですから、最終的に実行したいコマ ンドは次のものです。

find /altroot -inum 78848 -print 
を実行すれば良いことになります。やってみてください。

まとめると、上の例では 「block number 325872 → inode 78848 → ファイル名」 と検索してきたことになっているわけです。

(7) 終了。

fsdb (inum: 78848)> quit

カーネルエラーメッセージから破損ファイルを探す

dmesg の表示が次のようなものを考えましょう。

wd1g: error reading fsbn 136415616 of 136415616-136415647
(wd1 bn 268435455; cn 266305 tn 0 sn 15)wd1: (id not found)
「ここのブロックが読めません」というエラーです。これはカーネルが /usr/src/sys/kern/subr_disk.c のエラー表示ルーチンを使って表示しています。

このブロックナンバー 136415616 は、 すでに findblk の引数に入れて良い単位になっているので

fsdb (inum: 2)> findblk 136415616
136415616: data block of inode 7460109
とすれば inode が分かります。

この意味で fsdb findblk は始めから使いやすくできています。 ですが fsdb の findblk 以外のコマンドとは引数の体系が異なるわけで、 あまり初心者向きとは言えません(いや、そもそもカーネルエラーメッセージ からファイルを探すような人は初心者じゃないのか?:-)。

ま、それはともかく、 あとは find を使うと、壊れているファイル /disk/example/broken_file が 突き止められます。

% find /disk -inum 7460109 -print
/disk/example/broken_file

ちなみに、 このファイルシステムでは fsbtodb = 2 なので 34103904 * 2^2 = 136415616 です。 inode 7460109 の参照ブロックを表示すれば、

fsdb (inum: 7460109)> blks
	... snip ..
7832: 34103904 34103912 34103920 34103928 34103936 34103944 34103952 
	... snip ..
と 34103904 が参照先として存在することが確認できます。

my homepage is www.fml.org/home/fukachan/.
my free softwares are found at www.fml.org/software/.
fml 4.0 project homepage is www.fml.org/fml/menu.ja.html.
fml 8.0 (fml-devel) project homepage is www.fml.org/software/fml8/.
about one floppy bsd routers, see www.bsdrouter.org/.
Also, visit nuinui's world :) at www.nuinui.net.
For questions about me, e-mail <fukachan@fml.org>.
Copyright (C) 1993-2008 Ken'ichi Fukamachi

Powered by NetBSD.