[HOME] [github] [twitter] [blog] [fml4] [fml8] [北海道] Powered by NetBSD and [nuinui.net] .

運用: 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 [1] つまり 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) 次は、 逆にブロック番号(例 325872)から inode 番号(例 78848)を探す方法を考えましょう。

残念ながら 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 * 2 = 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 (dmesg で読めないといっている fsbn の値)です。 inode 7460109 の参照ブロックを表示すれば、

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

Notes

[1]

ここで、なぜ 2 なのか疑問に思う人は fsdb を使うべきではないのでしょう。

fsdb は危ないので、先に進む前に Unix の勉強をしてください。

[HOME] [github] [twitter] [blog] [fml4] [fml8] [北海道] Powered by NetBSD and [nuinui.net] .
Copyright (C) 1993-2022 Ken'ichi Fukamachi mail:< fukachan at fml.org >