シリーズ目次(Qua Station を mainline Linux で動かす連載・全 7 本)
- (1) 6.18クロスビルド・Ubuntu 26.04起動・シリアルレス診断手法
- (2) SATA・PCIe・Wi-Fi・LEDのハードウェア復活
- (3) rootfsをSSDへ移行
- (4) ext4破損インシデントとUSB2.0/PCIe診断ログ洪水の解決 ← 本記事
- (5) 番外編: 作ったのに使えなかったBluetooth SPP非常口コンソールの話
- (6) 配布イメージを作って GitHub で公開する
- (7) Linux 7.2→7.3 移植編 — Wi-Fi の無言死は上流の 1 行、翌日出た 7.3 は 2 行で一発起動
(1)〜(3)でmainline Linuxへの移植とSSD起動までを終えました。本編は毛色が変わって、実際に本番稼働中に起きたファイルシステム破損インシデントの復旧記録と、その対応中に見つけた副産物2件を扱う「復旧編」です。移植作業そのものではなく障害対応の実録ですが、同じように本番機を運用している人には参考になると思います。
/mnt/data(sdb3) ext4破損インシデントと本番復旧
SSD起動でハードウェア面が一段落した後、実際に本番稼働中にファイルシステム破損という障害が発生し、その対応にあたりました。ADS-B(航空機追跡)関連のデータを置いている821GBのパーティションが対象です。
発端と、初動の判断ミス
Wi-Fiの疎通が不安定になる事象が先に起きており、その対応(PCIe割り込みストームが疑わしいと考え、NetworkManagerの接続自動化を止める目的でActivationPolicy=downを設定するなど)に気を取られていたところ、/mnt/data(sdb3)が突然マウントできなくなっていることに気づきました。
ここで最初の判断ミスをしています。USB-SATA変換ブリッジ経由でfsck.ext4 -p(preen、危険を伴わない範囲だけ自動修正するモード)を実行してしまいました。このブリッジは実際のディスク容量を2セクタ少なくOSに報告する個体で、fsckが最終ブロック(215354549)へ書き込もうとした際に
Error writing block 215354549 (short write)
というエラーで書き込みが中断されました。この書き込み失敗によってfsckの処理そのものが途中で終わり、結果としてファイルシステムのスーパーブロックのチェックサムが不整合な状態のまま残されたと考えています(末尾ブロックの書き込み失敗と主スーパーブロックの整合性は直接の物理的な関係ではなく、処理の中断による副次的な結果と理解しています。正確な内部順序までは未検証です)。状態はclean with errors + invalid superblock checksum。さらに追い打ちで、SSHセッションに直接紐付けたまま長時間コマンド(timeout 180 ssh 'e2fsck ...')を実行してSSH側が先に切れてしまい、e2fsckプロセスがゾンビとして残るという二次被害も発生しています。
復旧に向けた判断の分岐点
ここから先は、慎重に手順を踏んでいます。
-
まずSMART値を確認:
Reallocated_Sector_Ct=0・Current_Pending_Sector=0・Offline_Uncorrectable=0と全てゼロ。少なくとも代替・保留セクタ系の異常は無く、ハードウェア故障ではなくファイルシステム側の問題である可能性が高いと判定できました -
読み取り専用での被害範囲確認:
e2fsck -fn -b 32768 -B 4096 /dev/sdb3(-b 32768でバックアップスーパーブロックを明示指定。主スーパーブロックのチェックサムが壊れているため) -
絶対にやらないと決めたこと:
tune2fs -f -O ^needs_recoveryでジャーナルを丸ごと捨てて逃げる方法(データ損失に直結)と、事故のきっかけになった-p(preen)モードでの再実行を明確に禁止 -
本修復の前に二重の保険を用意:
-
e2image -raでメタデータイメージを退避(保険その1) -
-z <undoファイル>で、e2fsckが触ったブロックを丸ごと元に戻せるようにする(保険その2。undoファイルは修復対象と同じファイルシステム上には置けない仕様で、今回試したCIFS共有では使えず、ローカルディスク上に置く必要がありました)
-
-
本修復コマンド:
失敗した場合のロールバックは
sudo /usr/sbin/e2fsck -fy -C 0 -z /var/tmp/sdb3-undo.e2undo /dev/sdb3sudo e2undo /var/tmp/sdb3-undo.e2undo /dev/sdb3 - 実行環境も見直しました。前述のゾンビプロセス化の反省から、リモートでの長時間処理はSSHセッションに直接紐付けず、
systemd-runやログファイル併用のnohupで切り離して実行する方式に変更しています
修復対象はチェックサム不一致12,770件・孤児inode 15件で、いずれもe2fsck -fyの通常の守備範囲内でした。
朝に
fsck -pで壊した主スーパーブロックのチェックサムは、完全に元に戻った。データ損失ゼロ。
コンテナの復帰
docker/のデータルート(141,132エントリ・5.73GiB)は無事で、コンテナの再構築は不要でした。ただし、Dockerのrestart: unless-stoppedは「手動で止めたコンテナは自動復帰しない」という仕様のため、平常時13本のコンテナのうち9本は自動で復帰しましたが、残り4本(bus-tracker・uptime-kuma・adsb-dashboard・ttyd-viewadsb)は手動での起動が必要でした。
この障害からの教訓
- 🔴 USB-SATA変換ブリッジ経由でfsckを実行するときは、必ず先に
blockdev --getszでブリッジが正しい容量を報告しているか確認する。今回の根本原因は、ブリッジが実容量を2セクタ少なく見せていたことでした - 🔴 末尾パーティションへの書き込みを伴う操作は、ブリッジ越しに行わない(容量の丸め誤差が最後のブロックで効いてくる)
- 🔴 リモートでの長時間処理はSSHセッションに直接紐付けない(
systemd-runやnohup+ログファイルで切り離す) - 🔴 復旧作業の前には必ず二重の保険(読み取り専用のメタデータイメージ+undoファイル)を用意する。
-p(preen)モードや、ジャーナルを捨てる方法(tune2fs -O ^needs_recovery)は使わない - SMART値の確認を最初に行うことで、「ハードウェア故障」と「ファイルシステム破損」を早期に切り分けられました
本体USB2.0ポート復活とPCIe診断ログ洪水の解決
前項の障害対応中、副産物として2つの問題を同時に解決しています。
PCIe診断ログがdmesgを埋め尽くしていた
障害対応中に「起動時のUSBログすらdmesgから消えている」ことに気づき調べたところ、直近1分間のカーネルログ1230行のうち1115行(91%)がPCIe関連の診断ログで埋め尽くされていました。
原因は、mainlineの標準コードには無い、このプロジェクト独自に追加していた診断用ログ出力(dev_info_ratelimited())でした。関数名に反して実質的にレートリミットが効かない形で呼ばれており、割り込みハンドラが呼ばれるたびにほぼ出力され続けていたことが分かりました。該当のログ4行だけを削除し(背後の処理ロジック自体は無害と確認済みのため残置)、dmesgのノイズを91%から0%まで削減しています。
本体USB2.0ポートが一度も認識されなかった謎
同じ調査の流れで、本体のUSB2.0専用ソケットが一度も機器を認識しないという別の問題も解決しました。5つの仮説を順番に検証し、すべて棄却しながら真因にたどり着いています。
| 仮説 | 結果 |
|---|---|
| VBUS用GPIOが上がっていない | ❌棄却(実機で両極性を試したが変化なし) |
| クロックが供給されていない | ❌棄却(そもそもこのUSB2.0コントローラ向けのクロック制御ノード自体がSoCに定義されておらず、クロックのオン/オフという仕組みでは説明が付かなかった) |
| リセットが解除されていない | ❌棄却(別用途のノードがついでに解除していた) |
| PHYの初期化書き込みが必要 | ❌棄却(PHY設定無しでも列挙自体は動いた) |
| ソケットの物理故障 | ❌棄却(後で実際に動いた) |
真因は、6.18のDevice TreeにEHCI/OHCIのノードが1つも存在しなかったことでした。USB2.0専用ソケットはこれらのコントローラにぶら下がっているため、電源(VBUS)をいくら上げても受け止める側のコントローラ自体が定義されていなかったのです。
当初は「カーネルの再ビルドが要る」と判断していましたが、アドバイザーの提案で対象ドライバを**モジュール化(=m)**することでリスクを大幅に下げる方針に転換しました。モジュールならmodprobeで挿抜試験ができ、失敗しても起動そのものへの影響がほぼゼロになります。最終的には手元のカーネルツリーと実機に配置していたビルドが完全に一致していたため、カーネルImage自体は1バイトも変更せず、DTBとモジュール2本の追加だけで機能追加が完了しました。
一番の収穫は手法の方かもしれない。「カーネル本体を作り直さずに機能を足す」という手順が確立できたので、次回以降のハードウェア追加のリスクが大幅に下がった。
ビルド成果物の公開
同じ機種で試したい方向けに、ここまでの全修正(SSD移行・SATA/PCIe/Wi-Fi/LED・USB2.0/PCIe診断ログ対応)を含む最終版のカーネルソース・Image・DTBをGitHubで公開しました。ソースは(2)で触れた通りGPL-2.0の派生物としてsymops/monarch-6.18をフォークする形で公開し、コンパイル済みのバイナリもReleaseとして添付しています。rootfs側については公開していませんが、公開の基準を満たせる状態になればこちらも公開しようと考えています。それまでは(1)(3)に書いた手順(公式Ubuntu Baseからの構築)で各自作成していただければと思います。
-
リポジトリ(
qua-stationブランチ): https://github.com/okura1234/monarch-6.18/tree/qua-station - Release(uImage・DTB添付): https://github.com/okura1234/monarch-6.18/releases/tag/qua-run41
- ボード固有のREADME: https://github.com/okura1234/monarch-6.18/blob/qua-station/README-quastation.md
公開ファイルのハッシュ値(実機の稼働中BOOTパーティションから直接取得した、現在動いているビルドそのものです):
30f74fe861f129ce4b8cf7e25dc6fd33ea5d22cd0738a436256f20c38583c19b uImage (17,166,848 bytes)
e0a71d92fd98f5fcaa2b331e8e94b4b24d23dfe038b4150c27df56e8ce88984f QuaStation.dtb (33,639 bytes)
Releaseに添付したファイルのハッシュと一致することを確認しています。
おわりに
一連の移植作業を終えて「動いて終わり」ではなく、実際に本番運用中に障害が起きたことで、復旧作業自体も含めて運用のリアルな姿を記録することになりました。特にext4破損からの復旧は、判断を一歩間違えれば損失に直結する場面の連続で、SMART確認・読み取り専用での被害把握・二重の保険という手順を踏んだことが功を奏しました。次回(5・番外編)では、実はこの一連の作業の裏で仕込んでいた「もう一つの非常口」の顛末を、少し力を抜いた話として書きます。
参考文献(シリーズ共通)
今回の移植は先人の資産の上に成り立っています。ベースにしたもの・参照したものを、実機(Qua Station)に近い国内発の情報源、同じSoCの海外コミュニティ情報源、および各種公式ドキュメントに分けて挙げます。
国内(Qua Station実機ベース)
- tsukumijima/QuaStation-Kernel-BPi — Qua Station向けLinuxカーネル(RTD1295, Kernel 4.9.119)。今回移植元にした「元のベンダーカーネル」そのもの
- tsukumijima/QuaStation-Ubuntu — Qua Station向けUbuntuビルド自動化スクリプト
- はるろいどの冒険日記「Qua Stationを汎用サーバーにしてみる」
- AsamaNews「Qua stationでLinuxを動かす(eMMCに導入)」
- noriokun4649「Qua Station で起動できる Ubuntu Base 22.04 LTS の rootfs を作る」 — Ubuntu Base の rootfs を chroot で構築し U-Boot から起動する手順。着手前のベンダー4.9系カーネルでの Ubuntu 導入時に参考にした
- 「【Qua station】シリアル接続して、u-bootのコンソールに入る」(お部屋でモバイル) — シリアルコンソール用ピンの位置・配線を紹介
海外(同じRTD1295系SoCのコミュニティ資産)
- symops/monarch-6.18 — WD My Cloud Home(RTD1295)向けLinux 6.18.52。クロック・SATA・GMAC・SMP起動の実装が先行しており、今回の主な参照ツリー
- symops/pelican-6.18 — 同じくRTD1296向け6.18.52
- afaerber/linux (rtd1295-next branch) — RTD1295のmainline化パッチ群。PCIeホストドライバを新規実装する際のベースにした
- jjm2473/rtd1295-next — RTD1295/RTD1296向けLinux 5.9系(eMMC対応)
- Lötzimmer「Debian on WD My Cloud Home single-bay (MCH) - part 1 / part 2」
Wi-Fiファームウェアのライセンス
- linux-firmware WHENCE — RTL8192EE/RTL8812AEファームウェアの配布元・ライセンス種別の記載元
- LICENCE.rtlwifi_firmware.txt — Realtek Semiconductor Corporation, 2010。無改変バイナリの再配布許諾条件
Bluetooth / D-Bus
-
BlueZ Profile API (profile-api.txt) —
org.bluez.ProfileManager1.RegisterProfileの正式な仕様
ファイルシステム復旧(e2fsprogs)
-
e2fsck(8) 公式マニュアル —
-z(undoファイル)・-b(バックアップスーパーブロック)オプションの仕様 - e2undo(8) — undoファイルからのロールバック手順