ASUSルーターで使用していたNTFSが壊れたのでext3にした
先日、ASUSルーターRT-AC56Sに接続して使用していたUSBストレージのファイルシステムが壊れ、いくつかのファイルを失ってしまいました。
使用していたUSBストレージは、IO DATA製のUSB2.0接続の古い1TB HDDで、NTFSでフォーマットされていたものです(ちなみにこのHDDは過去にPogoplugに接続していたこともあるのですが、その際もやはりファイルシステムが壊れました)。
ASUSルーター(やPogoplug)の中身はLinuxですから、MicrosoftのNTFSよりもext4などのLinuxの世界で標準的なファイルシステムを利用した方が、壊れにくいのではないかと思ったため作業してみました。
異常検知からext3利用までの一連の流れを参考までに記載します。
異常検知
そもそもHDD内のデータが損傷していることに気付いたのは、空き容量を確認するためにdfコマンドを叩いたり、ディレクトリ別の使用量を確認しようとduコマンドを叩いたところ、以下のようにInput/output errorが表示されたことがきっかけでした。
# du -h -d 0 data/ du: data/images/IMG_0575_20140125_063532.JPG: Input/output error du: data/images/IMG_0576_20140125_063836.JPG: Input/output error du: data/images/IMG_0577_20140125_063848.JPG: Input/output error … 中略… 163.8G data/
ファイルシステムチェック
ルーターのWeb管理画面から該当するDISKを[ヘルススキャナー]⇒[スキャン]したところ、ボロボロでした。このスキャン機能の実体はntfsckで、修復も試みられていますが最終的には"this seems to be endless."と、打ち切られてしまいます(同一inodeの修復を何度も試みているが、何度やっても無理なので諦めている)。
ntfsck 3014.5.21 Checking NTFS Superblock ... Device name : /dev/sdc1 NTFS volume version: 3.1 Cluster size : 65536 bytes Current volume size: 1000203026944 bytes (1000204 MB) Current device size: 1000203091968 bytes (1000204 MB) Checking for bad sectors ... Scanning $MFT ... Could not read "$RECYCLE.BIN" (inode=3414). Checking directory structure ... Corrupt directory found, inode=5 (0x5) Repairing corrupt directories started. 0.00 percent completed … 中略 … No file name found in inode 3706 No file name found in inode 3722 No file name found in inode 3743 No file name found in inode 3767 Could not read "IMG_0579_20140125_064015.JPG" (inode=3409). Could not read "IndexerVolumeGuid" (inode=3413). … 中略 … Repairing corrupt directories completed. Corrupt directory found, inode=54 (0x36) Corrupt directory found, inode=767 (0x2ff) Corrupt directory found, inode=35 (0x23) … 中略 … Repairing corrupt directories started. 0.00 percent completed … 中略 … No file name found in inode 3706 No file name found in inode 3722 No file name found in inode 3743 No file name found in inode 3767 … 中略 … 100.00 percent completed Repairing corrupt directories completed. Repairing corrupt directories started. 0.00 percent completed … 中略 … No file name found in inode 3706 No file name found in inode 3722 No file name found in inode 3743 No file name found in inode 3767 … 中略 … 100.00 percent completed Repairing corrupt directories completed. Repairing corrupt directories started. 0.00 percent completed … 中略 … this seems to be endless. Repairing corrupt directories completed. Space in use : 972925 MB (97.3%) Done NTFS checking and repair on device '/dev/sdc1'. Syncing device ...
他のマシンへのデータ移動を試行
du等のコマンドで、Input/output errorと表示されたファイルを他のマシンからsamba経由で回収を試みたり、scpでコピーしようとしても、既に読み取れませんでした。
この時dmesgには以下のような出力が大量に吐かれていました。
# dmesg | grep err … 中略 … tntfs error (device sdc1, pid 26973): ntfs_read_locked_inode(): Failed (error 5). Marking corrupt inode 0x14c6 as bad. Run chkdsk. tntfs error (device sdc1, pid 26973): ntfs_mft_record_map(): Mft record 0x7f5 is corrupt (magic is 0x30 [0 tntfs error (device sdc1, pid 26973): ntfs_mft_record_map(): Failed with error code 5. tntfs error (device sdc1, pid 26973): ntfs_read_locked_inode(): Failed (error 5). Marking corrupt inode 0x7f5 as bad. Run chkdsk. tntfs error (device sdc1, pid 26973): ntfs_mft_record_map(): Mft record 0x156a is corrupt (magic is 0x30 [0 tntfs error (device sdc1, pid 26973): ntfs_mft_record_map(): Failed with error code 5. tntfs error (device sdc1, pid 26973): ntfs_read_locked_inode(): Failed (error 5). Marking corrupt inode 0x156a as bad. Run chkdsk. tntfs error (device sdc1, pid 26973): ntfs_mft_record_map(): Mft record 0x14d9 is corrupt (magic is 0x30 [0 tntfs error (device sdc1, pid 26973): ntfs_mft_record_map(): Failed with error code 5. … 中略 … # ps -w | grep 26973 | grep -v grep 26973 admin 1624 D scp -r -f /tmp/mnt/sdc1/data
読み出せるファイルを退避
適当なPCで根こそぎファイルコピーするのが手っ取り早いですが、障害が発生しているDISKをルーターからマウント解除して、他のマシンでマウントできなかったり、ルーターにも二度とマウントできなかったりするのは怖いので、現状の接続を維持したまま、(ルーターではない)LinuxマシンにUSB接続した別のHDDにscpすることにしました。
duコマンドなどで"Input/output error"が発生していたファイルは、scpでもエラーとなりスキップされますが、一応コピーは完了します。
差分チェック
が、元のDISKの状態を鑑みるに、正しく読み出せていたのかは怪しい気がするので、各ファイルを比較することにします。
当初Linuxでdiffコマンドで差分チェックしようと考えたのですが、多数のディレクトリ階層下の大量のファイルを比較するには不適だと思えたため、Windowsのfcコマンドを使うことにしました(fcコマンドの比較対象にはディレクトリを指定することもできるためです)。ただし、再帰的にサブディレクトリを比較してくれないので、dirコマンドでdir /on /b /adとしてディレクトリ名だけ予め抽出し、得られた各ディレクトリをfcコマンドのパラメータにしたバッチファイルを作成し、その実行結果をリダイレクトしたファイルを正規表現で加工して差分を探すという手作業を行いました。
結果的にLinux環境で、"Input/output error"が発生していたファイル以外は、全て完全一致することが確認できました。
障害が発生したDISKの論理/物理障害切り分け
先にルータのdmesgに"Run chkdsk"の出力があったことから、Windows環境でchkdsk /fを実行した後(ルーターではない)Linuxマシンでマウントを試みたところ、事態は悪化しマウントすらできなくなりました。
$ sudo mount /dev/sdd1 /mnt/usb $MFTMirr does not match $MFT (record 24). Failed to mount '/dev/sdd1': Input/output error NTFS is either inconsistent, or there is a hardware fault, or it's a SoftRAID/FakeRAID hardware. In the first case run chkdsk /f on Windows then reboot into Windows twice. The usage of the /f parameter is very important! If the device is a SoftRAID/FakeRAID then first activate it and mount a different device under the /dev/mapper/ directory, (e.g. /dev/mapper/nvidia_eahaabcc1). Please see the 'dmraid' documentation for more details.
単にファイルシステムが損傷しているだけの論理障害なのか、HDDのH/W自体に異常をきたしている物理障害なのかを識別するため、まずはSMART情報を確認してみました。
Windows環境でCrystal Disk Infoで確認してみたところ、確認できる値に特に異常は見られませんでした。
また、このDISKは先述の通りIO DATA製ですが、中身のHDDはSamsung製でした。
SamsungのHDD事業はSeagateに買収されていますので、SeatoolsでHDDの検査が出来るのではないかと思ったのですが、できませんでした。
既に読み出せるデータは退避済なので、全領域にデータが記録できれば問題無かろうという思想で、Windows標準のdiskpartユーティリティのclean allコマンド(いわゆる0フィル)を実行したところ正常に完了しました。
これらのことから、H/Wには問題無さそうで物理障害ではない、すなわち論理障害だろうと判断しました。
論理障害であるならWindows環境で使用する訳でもないのに、わざわざNTFSを使う必要は無いのでext4でフォーマットし直して、再利用しようと思い立ちます。
ext4が使えない
ルーターのWeb管理画面からUSBストレージのフォーマットができるのですが、フォーマットタイプの選択肢にはNTFS/FAT/HFSしかありません。
とは言え、SSHログインしてルーターのLinuxバージョンを確認してみると以下の通りでした。
# uname -srm
Linux 2.6.36.4brcmarm armv7l
だいぶ古いカーネルながら、このバージョンならext4サポートしてるはずです。
と言うわけで、(ルーターではない)Linuxマシンでパーティション作成及びext4でファイルシステム作成後、ルータに接続してみたのですがマウントされません(普通は接続したら自動でマウントされる)。
dmesgを確認してみると以下の出力がありました。
EXT4-fs (sdc1): couldn't mount RDWR because of unsupported optional features (400) EXT3-fs (sdc1): error: couldn't mount because of unsupported optional features (2c0) EXT2-fs (sdc1): error: couldn't mount because of unsupported optional features (2c0)
サポートしてないオプション機能を使っているからext4でもext3でもext2でもマウントできないと言っているようです。
今度はSSHコンソールから手動でマウントを試みます。が、マウントできません。
# mount /dev/sdc1 /tmp/mnt/sdc1
mount: mounting /dev/sdc1 on /tmp/mnt/sdc1 failed: Invalid argument
この時も先と同様のログがdmesgに出力されていました。
EXT3-fs (sdc1): error: couldn't mount because of unsupported optional features (2c0) EXT4-fs (sdc1): couldn't mount RDWR because of unsupported optional features (400) EXT2-fs (sdc1): error: couldn't mount because of unsupported optional features (2c0) tfat: fail_safe is enabled tntfs info (device sdc1, pid 12995): ntfs_fill_super(): fail_safe is enabled
ext3, ext4, ext2, tfat, tntfsいずれでもマウントできないと言っているようです。
改めて、明示的にext4を指定してマウントを試みます。
# mount -t ext4 /dev/sdc1 /tmp/mnt/sdc1
mount: mounting /dev/sdc1 on /tmp/mnt/sdc1 failed: Invalid argument
が、やはりマウントできませんでした。今度はdmesgにext4でマウントできなかった旨だけ出力されていました。
EXT4-fs (sdc1): couldn't mount RDWR because of unsupported optional features (400)
他のマシン(Ubuntu 18.04環境)で普通にext4でファイルシステム作成しただけなので"unsupported optional features"と言われる意味が解りませんが、ルータ内の古い組み込みLinuxではサポートしていない何かが使われているのでしょう。
ならば、ルーター自体でext4のファイルシステムを作成すれば問題無かろうと思いました。
ところが、ルータでmkfsやmkfs.ext4を叩いてみるも、コマンドが無い。それでもWeb管理画面からNTFS/FAT/HFSでフォーマットできるのだから、何らかのコマンドはあるはずです。
困ったときのbusyboxを確認してみると、
# busybox BusyBox v1.17.4 (2018-05-27 16:22:58 CST) multi-call binary. Copyright (C) 1998-2009 Erik Andersen, Rob Landley, Denys Vlasenko and others. Licensed under GPLv2. See source distribution for full notice. Usage: busybox [function] [arguments]... or: function [arguments]... BusyBox is a multi-call binary that combines many common Unix utilities into a single executable. Most people will create a link to busybox for each function they wish to use and BusyBox will act like whatever it was invoked as. Currently defined functions: [, [[, arp, ash, awk, basename, blkid, cat, chmod, chown, chpasswd, clear, cmp, cp, crond, cut, date, dd, devmem, df, dirname, dmesg, du, e2fsck, echo, egrep, env, ether-wake, expr, fdisk, fgrep, find, flock, free, fsck, fsck.ext2, fsck.ext3, fsck.minix, fsync, grep, gunzip, gzip, head, ifconfig, insmod, ionice, kill, killall, klogd, less, ln, logger, login, ls, lsmod, lsusb, md5sum, mdev, mkdir, mke2fs, mkfs.ext2, mkfs.ext3, mknod, mkswap, modprobe, more, mount, mv, netstat, nice, nohup, nslookup, pidof, ping, ping6, printf, ps, pwd, readlink, renice, rm, rmdir, rmmod, route, sed, setconsole, sh, sleep, sort, strings, swapoff, swapon, sync, syslogd, tail, tar, telnetd, test, top, touch, tr, traceroute, traceroute6, true, tune2fs, udhcpc, umount, uname, unzip, uptime, usleep, vconfig, vi, watch, wc, which, zcat, zcip
ありました。mke2fs, mkfs.ext2, mkfs.ext3 って、ext4がない!
別マシンで作ったext4が扱えず、ルーター内でext4を作ることもできないなら、ext3でもいいか。と、妥協することにしました。
ext3でファイルシステム作成
まずは、既存の認識できないext4パーティション(ここではsdc1)を削除します。
# ls -l /dev/sdc* brw-r--r-- 1 admin root 8, 32 Nov 13 21:17 /dev/sdc brw-r--r-- 1 admin root 8, 33 Nov 13 21:17 /dev/sdc1 # fdisk /dev/sdc The number of cylinders for this disk is set to 382818. There is nothing wrong with that, but this is larger than 1024, and could in certain setups cause problems with: 1) software that runs at boot time (e.g., old versions of LILO) 2) booting and partitioning software from other OSs (e.g., DOS FDISK, OS/2 FDISK) Command (m for help): p Disk /dev/sdc: 1000.2 GB, 1000204886016 bytes 81 heads, 63 sectors/track, 382818 cylinders Units = cylinders of 5103 * 512 = 2612736 bytes Device Boot Start End Blocks Id System /dev/sdc1 1 382819 976761560 83 Linux Command (m for help): d Selected partition 1 Command (m for help): p Disk /dev/sdc: 1000.2 GB, 1000204886016 bytes 81 heads, 63 sectors/track, 382818 cylinders Units = cylinders of 5103 * 512 = 2612736 bytes Device Boot Start End Blocks Id System Command (m for help): w The partition table has been altered! Calling ioctl() to re-read partition table # ls -l /dev/sdc* brw-r--r-- 1 admin root 8, 32 Nov 13 21:41 /dev/sdc
改めてパーティション作成します。
# fdisk /dev/sdc The number of cylinders for this disk is set to 121601. There is nothing wrong with that, but this is larger than 1024, and could in certain setups cause problems with: 1) software that runs at boot time (e.g., old versions of LILO) 2) booting and partitioning software from other OSs (e.g., DOS FDISK, OS/2 FDISK) Command (m for help): n Command action e extended p primary partition (1-4) Partition number (1-4): 1 First cylinder (1-121601, default 1): Using default value 1 Last cylinder or +size or +sizeM or +sizeK (1-121601, default 121601): Using default value 121601 Command (m for help): p Disk /dev/sdc: 1000.2 GB, 1000204886016 bytes 255 heads, 63 sectors/track, 121601 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Device Boot Start End Blocks Id System /dev/sdc1 1 121601 976760001 83 Linux Command (m for help): w The partition table has been altered! Calling ioctl() to re-read partition table # ls /dev/sdc* /dev/sdc /dev/sdc1
まっさらのsdc1パーティションが出来たので、ここにext3でファイルシステムを作成します。
その前に、busyboxに実装されたmkfs.ext3のパラメータを確認しておくと以下の通り。
# mkfs.ext3 --help BusyBox v1.17.4 (2018-05-27 16:22:58 CST) multi-call binary. Usage: mkfs.ext3 [-c|-l filename] [-b block-size] [-f fragment-size] [-g blocks-per-group] [-i bytes-per-inode] [-j] [-J journal-options] [-N number-of-inodes] [-n] [-m reserved-blocks-percentage] [-o creator-os] [-O feature[,...]] [-q] [r fs-revision-level] [-E extended-options] [-v] [-F] [-L volume-label] [-M last-mounted-directory] [-S] [-T filesystem-type] device [blocks-count] -b size Block size in bytes -c Check for bad blocks before creating -E opts Set extended options -f size Fragment size in bytes -F Force (ignore sanity checks) -g num Number of blocks in a block group -i ratio The bytes/inode ratio -j Create a journal (ext3) -J opts Set journal options (size/device) -l file Read bad blocks list from file -L lbl Set the volume label -m percent Percent of fs blocks to reserve for admin -M dir Set last mounted directory -n Do not actually create anything -N num Number of inodes to create -o os Set the 'creator os' field -O features Dir_index/filetype/has_journal/journal_dev/sparse_super -q Quiet -r rev Set filesystem revision -S Write superblock and group descriptors only -T fs-type Set usage type (news/largefile/largefile4) -v Verbose
今回は特に拘りはないので単に対象パーティション名を指定するだけにします。が、"Could not set up superblock"というエラーが発生し、ファイルシステムが作成できません。
# mkfs.ext3 /dev/sdc1 mke2fs 1.38 (30-Jun-2005) Could not set up superblock
検索してみるとメモリが足りないとこのエラーが発生することがあるようです。
現状の空メモリを確認します。
# free total used free shared buffers Mem: 125960 69048 56912 0 632 Swap: 0 0 0 Total: 125960 69048 56912
128MB程度のメモリを搭載していますが約56MBの空では足りないということになります。ので、とりあえずスワップ領域を追加してやり過ごそうと思います。
# dd if=/dev/zero of=/tmp/mnt/sdb1/swap bs=1M count=128 128+0 records in 128+0 records out # mkswap /tmp/mnt/sdb1/swap Setting up swapspace version 1, size = 134213632 bytes UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx # swapon /tmp/mnt/sdb1/swap # free total used free shared buffers Mem: 125960 95616 30344 0 360 Swap: 131068 0 131068 Total: 257028 95616 161412
161MB程度の空き領域が確保できましたので、再度mkfs.ext3を実行します。
が、30分以上たっても完了せず… 固まった …
そもそもこの環境、ルーターなんですけど、ネットワーク内の機器と通信できなくなったり、インターネット接続もできない状態に陥っていることに気付きました。
待ってればいつかは終わるのかもしれませんが、弊害が大きすぎるので強制的に電源を落として再起動させました。
といった有様なのでルータ自体でext3のファイルシステムを作成することは諦めました。
ext4でファイルシステムを作成した時と同様に、Ubuntu 18.04の別のLinuxマシンでext3のファイルシステムを作成しました(mkfs -t ext3 /dev/sdc1)。PCならすぐ終わります。
ext3のマウント
Ubuntu 18.04のマシンから取り外して、ルーターに接続しただけで自動マウントされました!この際、dmesgには以下の出力が確認できます。
EXT3-fs: barriers not enabled kjournald starting. Commit interval 5 seconds EXT3-fs (sdd1): using internal journal EXT3-fs (sdd1): mounted filesystem with ordered data mode
パーミッション周り
NTFSではないので、所有者の概念に注意する必要があります。
自動でマウントされたDISKは管理者のユーザ・グループとなっていますので、Samba経由でアクセスするユーザが管理者では無ければ、当然アクセスできません。
かと言って、管理者ユーザでsambaアクセスさせるのも望ましくないでしょうから、以下のように当該パーティション配下を根こそぎsambaユーザにchownしてしまうのが手っ取り早いと思います。
# chown -R user:user /tmp/mnt/sdd1
また、Samba経由でファイルを作成すると、ファイルパーミッションがrwxrwxrwx(777)となります。
これは、以下のようにsmb.confでforce create modeが0777指定されているためだと考えられますが、smb.confはWeb管理画面の操作で自動生成・更新されるため、このファイルを直接手で編集するのはお勧めできません。
# grep mode /etc/smb.conf force directory mode = 0777 force create mode = 0777 dos filemode = yes