Path: sran124!katsu From: katsu@sra.co.jp (WATANABE Katsuhiro) Message-ID: Date: 22 Jul 90 21:44:06 Organization: Software Research Associates, Inc.,Japan In-reply-to: hironobu@sra.co.jp's message of 20 Jul 90 18:18:08 GMT Newsgroups: sra.unix Subject: Re: error-of-making-dir(by testprogram) Distribution: sra References: <347@sran51.sra.co.JP> 記事 で hironobu@sra.co.jp (Hironobu Suzuki) さんいはく > fsckをするのは正解だけど、カーネル内のイメージとディスク上のイメージが > 一緒になるのは難しい(これは始めから無理なのかも知れない。)ので一筋縄 > では行きません。 これは確かにその通りだろうとは思うのですが、m-cho@sran49.sra.co.jp (Masao Cho) さんが | ところが、( シングルユーザモードでのfsck) をお客様のところでも実行 |して頂きましたが、次のような結果に終りました。 | |REMOVE? y 入力 |sd0a: RAW DEVICE WRITE PROTECTED : sn = 0x47bc0(293824), off = 0x82378 |(533368) |CANNOT WRITE: BLK 293824 と書いているのに対しての答えとしては的を得ていないと思います。 fsck を実行して修復を試みたところ、そもそもディスクに書き込めなくて 修復できなかったということですから、カーネルのイメージとディスクの イメージの差異以前の問題です。 なぜ書き込めなかったかについてですが、実は「sd0a: RAW DEVICE ....」 というのは、fsck が出しているのではなくて、scsi disk device driver が 出しています。(「CANNOT WRITE...」の方は fsck が出しています。) さて、man 4 sd としてみてください。設定によっては、partition を block device としてオープンしている時(mount している時がこの典型)に、 その partition に raw device としての書き込みを禁止することができる旨の 記述があります。そして普通はこういう設定のようです。 お客さまのところでは single user mode で fsck をしたとのことですが、 一旦 multi user で立ち上がっていたものを shutdown しただけで、問題の partition が mount されたままになっている状態、すなわち block device が オープンされている状態で raw device (ここでは /dev/rsd0a)に対して fsck をしたなんてことはありませんか?多分 block device すなわち /dev/sd0a に 対してやっていれば fsck は通ったはずです。(もしくは umount してもよい。) ------ 以下はヨタ話で、file system 修復とは関係ありません ------ さて、fsck が正しく通って、ディレクトリへの hard link が切れた後、 元となったディレクトリが削除できないという話ですが、 > single user modeへ移る。 > > hostname # sync;sync;sync man 2 sync には、fsck や df では sync(2) をやっていると書いてありますが、 やっぱり{不安で,癖で}自分の手でもやってしまいまうものですねえ...... > hostname # fsck -y /dev/your-disk-system > hostname # /etc/reboot > > 実際に不正なディレクトリとリンクカウントを直すまではfsckで出来るんだけ > ど、実体のディレクトリがrebootがかからないと、どうしても正しく消せませ > んでした。(実際に試した) > > ファイルのキャッシュとかなんとか色々やっているから、うまく行かないのか、 > それとも別の理由なのかは分かりませんが、最後のrebootというのが味噌です。 確かにカーネル内のテーブルが更新されていないようです。(考えてみれば、 fsck がディスクを直接書き換えてしまったことをカーネルが知るのはとても 難しいことのような気もします。)reboot するのが簡単だと思いますが、 テーブルを手動で書き換えるという手があると思います。「思います」じゃあ 弱いので、実際に試してみましょう。 今、NEWS830(sran14) の /dev/fh0 を /fd に mount していたとします。 ここに x というディレクトリを作って、y という hard link をつけました。 sran14# cd /fd /fd sran14# ls -li total 5 3 drwxr-xr-x 2 root 4096 May 6 14:24 lost+found 32 drwxrwxr-x 3 root 512 Jul 22 13:19 x 32 drwxrwxr-x 3 root 512 Jul 22 13:19 y fsck で、hard link の一つを切ります。 sran14# fsck /dev/fh0 ** /dev/fh0 ** Last Mounted on /fd ** Phase 1 - Check Blocks and Sizes ** Phase 2 - Check Pathnames /y IS AN EXTRANEOUS HARD LINK TO DIRECTORY /x REMOVE? y : : : : : sran14# ls -li total 5 3 drwxr-xr-x 2 root 4096 May 6 14:24 lost+found 32 drwxrwxr-x 3 root 512 Jul 22 13:19 x ‾‾‾ y という link が切れました。ではディレクトリ x を rmdir してみます。 sran14# rmdir x rmdir: x: Directory not empty sran14# ls -la x total 1 drwxrwxr-x 3 root 512 Jul 22 13:59 . ‾‾‾ drwxr-xr-x 4 root 512 Jul 22 13:59 .. というように rmdir できませんでした。ではカーネルの inode のテーブルはどう なっているでしょうか?これを pstat -i でみるために、あらかじめ major device number と minor device number を調べておきます。 sran14# ls -l /dev/fh0 brw-rw-rw- 1 root 1, 0 Jul 22 13:20 /dev/fh0 で、pstat -i の出力から、IDEVICE = 1, 0 で、 INO = 32(ディレクトリ x の inode number) の行に注目すると、 sran14# pstat -i 168/340 active inodes ILOC IFLAG IDEVICE INO MODE NLK UID SIZE/DEV VFLAG CNT SHC EXC TYPE : : : : : 800aa05c R 1, 0 32 40775 3 0 512 2 0 0 VDIR ‾‾‾‾‾‾‾‾ ‾‾‾ : : : : : 確かに NLK が 3 になっています。このせいで rmdir ができないのでしょう。 これの正しい値は今や 2 ですから、カーネルにそのことを教えてやった後で、 rmdir を再び試してみます。 sran14# adb -w -k /vmunix /dev/mem sbr 6000 slr 400 <- adb 出力 p0br b000 p0lr 27 p1br c000 p1lr fffc <- 出力 0x800aa05c+0x56/x <- 入力 (1) 800aa0b2: 3 <- 出力 (2) 0x800aa0b2/w 2 <- 入力 (3) 800aa0b2: 3 = 2 <- 出力 ^D <- 入力終り (1)の「0x800aa05c」は、pstat の ILOC フィールドの値です。「0x56」は 魔術的な数ですが、struct inode の中の、ic_nlink のある位置です。当然 機械や OS によって異なります。これは BSD ならば /usr/include/ufs/inode.h と /usr/include/sys/vnode.h を見て計算します。(実は私はそんなことしないで、 adb に入った直後に「0x800aa05c,80/x」とかやって前後関係から見当をつけた だけでした。:-) この位置に、x の link の数がはいっています。 その結果表示された(2) が、現在のカーネルが覚えている link の数です。ここを これから書き換えますから、一応値を確認しておきます。 (3) で、link 数を書き換えます。ここで「0x800aa0b2」は「0x800aa05c+0x56」と 書いたのと同じことです。 では rmdir できるでしょうか? sran14# ls -li total 5 3 drwxr-xr-x 2 root 4096 May 6 14:24 lost+found 32 drwxrwxr-x 2 root 512 Jul 22 13:19 x ‾‾‾ sran14# rmdir x sran14# ls -li total 4 3 drwxr-xr-x 2 root 4096 May 6 14:24 lost+found というわけで、これで reboot しなくともうまくいきました。 遊んでいるうちに副作用的にわかったこと。 (1)案の定、/usr/lib/adb/inode も使いものにならなかった。(これが 動いてくれれば、ic_nlink の位置を捜すのがとても楽なはず。) (2)NEWS OS 3.9R では、pstat -i が正しく動かない。やーい RISC NEWS。 遊んでいるうちに副作用的にわからなくなったこと。X-) (1)動いている kernel に patch を当てるには、 adb -w -k /vmunix /dev/mem と adb -w /vmunix /dev/kmem のどちらが正しいのだろう? -- ----____----____ 渡邊克宏 ソフトウェア工学研究所(四谷) 今月の標語:「あけみちゃんはかわいい」