OpenWrt で外部 USB ストレージを使う

(公式ガイド:👉 Using storage devices

外部 USB ストレージ用のドライバーのインストール


opkg update
opkg install kmod-usb-storage
opkg install usbutils
  • ドライバーは kmod-usb-storage のみ
  • usbutils はコマンド lsusb -t を使って USB メモリーが接続されているかどうかを調べるためのもの(オプショナル)

lsusb -t
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ohci-platform/2p, 12M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci-platform/2p, 480M
    |__ Port 1: Dev 2, If 0, Class=, Driver=usb-storage, 480M

「Port 1: Dev 5, If 0, Class=Mass Storage, Driver=usb-storage, 480M」の行が表示されていることにより、外部 USB ストレージ(USB メモリースティック)が挿されているのが確認できる。

外部ドライブとして認識されていることの確認

lsusb コマンドによる確認は、USB デバイスが認識されているかどうかのものである。最終的に、OpenWrt の Linux OS 側が、外部ドライブとして認識しているかどうかは、/dev/sd* としてアタッチされているかで確認できる:


ls -l /dev/sd*
brw-------    1 root     root        8,   0 Nov 16 16:42 /dev/sda
brw-------    1 root     root        8,   1 Nov 16 16:42 /dev/sda1

今回の例では、/dev/sda が存在することにより、認識されていることが確認できていることになる。

外部ドライブのパーティションが適切に認識されているかの確認

上で外部ドライブが認識されていることが確認できたが、さらに、/dev/sda の論理的なパーティション(上の例では /dev/sda1)が適切に認識されているかどうかという確認には block ツールを利用する。


opkg install block-mount

次の block コマンドでは、info の出力を grep で /dev/sd* に絞り込んでいる:


block info | grep "/dev/sd"
/dev/sda1: UUID="f2926d1b-b52d-4145-9184-ced547443e55" LABEL="extroot" VERSION="1.16" TYPE="f2fs"

この出力例では /dev/sda1 が f2fs 形式でフォーマットされたパーティションであると認識されていることがわかる(パーティションが非フォーマットの場合は表示されない)。

もし、不良セクターの検査(後述)をしたければ、この段階でやっておくこと。破壊的検査になるので、mkfs.f2fs でフォーマットしたファイルシステムも消えてしまう。

以上で、外部 USB ストレージの動作・設定は問題ないことが確認できたので、以降は、パーティションの作成・フォーマットに入る。


パーティションの作成

基本的には gdisk で対話形式でパーティショニング作業を行う。


opkg install gdisk

gdisk 自体は、OpenWrt 特有の話ではなく、Linux 一般の話となるので、僕が今回の例で行った作業については、後述する。


フォーマット

パーティションを用意したら、適当な形式でフォーマットする。僕の場合、USB フラッシュメモリーに向いていそうな、f2fs を使うことにした:


opkg install f2fs-tools
opkg install kmod-fs-f2fs

おそらくドライバー本体は kmod-fs-f2fs だが、フォーマット操作などのコマンド実行には f2fs-tools が必要なはずである。フォーマットは以下のように mkfs.f2fs コマンド(f2fs-tools に含まれている)で行う。


mkfs.f2fs /dev/sda1

	F2FS-tools: mkfs.f2fs Ver: 1.14.0 (2020-08-24)

Info: Disable heap-based policy
Info: Debug level = 0
Info: Trim is enabled
Info: [/dev/sda1] Disk Model: Storage Media   
Info: Segments per section = 1
Info: Sections per zone = 1
Info: sector size = 512
Info: total sectors = 3911680 (1910 MB)
Info: zone aligned segment0 blkaddr: 512
Info: format version with
  "Linux version 5.10.176 (builder@buildhost) (mips-openwrt-linux-musl-gcc (OpenWrt GCC 11.2.0 r20134-5f15225c1e) 11.2.0, GNU ld (GNU Binutils) 2.37) #0 Thu Apr 27 20:28:15 2023"
Info: [/dev/sda1] Discarding device
Info: This device doesn't support BLKSECDISCARD
Info: This device doesn't support BLKDISCARD
Info: Overprovision ratio = 4.630%
Info: Overprovision segments = 92 (GC reserved = 51)
Info: format successful

通常の fsck をする場合、f2fs-tool のインストールによって f2fs 用の fsck.f2fs が含まれているのでそれを使う:


fsck.f2fs -f /dev/sda1
Info: Force to fix corruption
Info: [/dev/sda1] Disk Model: Storage Media   
Info: Segments per section = 1
Info: Sections per zone = 1
Info: sector size = 512
Info: total sectors = 3911680 (1910 MB)
Info: MKFS version
  "Linux version 5.10.176 (builder@buildhost) (mips-openwrt-linux-musl-gcc (OpenWrt GCC 11.2.0 r20134-5f15225c1e) 11.2.0, GNU ld (GNU Binutils) 2.37) #0 Thu Apr 27 20:28:15 2023"
Info: FSCK version
  from "Linux version 5.10.176 (builder@buildhost) (mips-openwrt-linux-musl-gcc (OpenWrt GCC 11.2.0 r20134-5f15225c1e) 11.2.0, GNU ld (GNU Binutils) 2.37) #0 Thu Apr 27 20:28:15 2023"
    to "Linux version 5.10.176 (builder@buildhost) (mips-openwrt-linux-musl-gcc (OpenWrt GCC 11.2.0 r20134-5f15225c1e) 11.2.0, GNU ld (GNU Binutils) 2.37) #0 Thu Apr 27 20:28:15 2023"
Info: superblock features = 0 : 
Info: superblock encrypt level = 0, salt = 00000000000000000000000000000000
Info: total FS sectors = 3911680 (1910 MB)
Info: CKPT version = 6c0b4c6d
Info: Corrupted valid nat_bits in checkpoint
Info: Write valid nat_bits in checkpoint
Info: checkpoint state = 185 :  trimmed nat_bits compacted_summary unmount

[FSCK] Unreachable nat entries                        [Ok..] [0x0]
[FSCK] SIT valid block bitmap checking                [Ok..]
[FSCK] Hard link checking for regular file            [Ok..] [0x0]
[FSCK] valid_block_count matching with CP             [Ok..] [0x2]
[FSCK] valid_node_count matching with CP (de lookup)  [Ok..] [0x1]
[FSCK] valid_node_count matching with CP (nat lookup) [Ok..] [0x1]
[FSCK] valid_inode_count matched with CP              [Ok..] [0x1]
[FSCK] free segment_count matched with CP             [Ok..] [0x3a8]
[FSCK] next block offset is free                      [Ok..]
[FSCK] fixing SIT types
[FSCK] other corrupted bugs                           [Ok..]
[ASSERT] (check_seg_range:1977) segno <= end_segno

ちなみにフラッシュメモリーの各メモリーセルの不良セクターの検査をしたければ、badblocks を使う方法(後述)もある。fsck との違いは、badblocks の場合、パーティションに対するものではなく、USB ドライブ全体に対するものであり、どちらかというと Memtest86 のように、読み書きを行って物理的なローレベルの動作不良を検査するもののようである。つまり、既存のデータが(ファイルシステムを含めて)破壊されるので、初期の段階でしか badblocks は使いにくい。fsck の場合は、そのような心配はなく、使用開始後でも問題なく行える(非破壊検査)、ただのファイルシステムの不整合を検査するだけのものだからである。


外部ストレージのマウント設定

Linux(UNIX 系 OS)特有の考え方だが、UNIX では、あらゆるファイルを論理的に /(ルート)の配下に置いて統一的に扱うという優れた思想設計のため、「マウント」することでようやくファイルの読み書きが可能になる(Microsoft Windows では、そのまま C ドライブや D ドライブといった形で分けて扱うのと対象的である)。一応、デバイスとしては /dev/sda1 として認識しているものの、それをファイルの読み書きできる通常のディレクトリとして扱うには、論理的ないずれかのディレクトリ(/mnt/data 等)に割り付ける、マウント操作が必要である。

OS 起動時の自動マウント設定には、いくつかのやり方があるが、最近の OpenWrt ではかなり便利になっており、設定ファイルを自分で書き換えなくとも(もちろん書き換えてもよい)、LuCI の設定メニューから設定操作が行えるようになっている。パーティションのフォーマットまでが完了した段階で、OpenWrt をリブートすると、外部ストレージの存在を認識して LuCI に System > Mount Points メニューが登場するので、そこから操作を行えばよい。Swap に関する設定項目もこの中に存在する。

上のスクリーンショットでは今回の作業でフォーマットした USB ストレージが認識されているのが確認できる。現状ではまだ有効化(マウント)されていないので、Edit してマウント先(デフォルトでは /mnt/sda1 とされているもの)を自分の希望するもの(例えば /mnt/data)に変更したりして設定・有効化したりする。


不良セクターの検査(オプショナル)

念のために USB フラッシュドライブ(パーティションではない)の不良セクターを調べておきたい場合には、badblocks コマンドを(インストールして)使う。この検査をする場合は、ファイルシステムを破壊してしまうため、フォーマット作業を行う前にやっておくこと。


opkg install badblocks

badblocks コマンド自体は例えば次のような感じ(badblocks -wsv /dev/sda)で使う(書き込みを伴う破壊的検査):


badblocks -wsv /dev/sda
Checking for bad blocks in read-write mode
From block 0 to 1957887
Testing with pattern 0xaa: done                                                 
Reading and comparing: done                                                 
Testing with pattern 0x55: done                                                 
Reading and comparing: done                                                 
Testing with pattern 0xff: done                                                 
Reading and comparing: done                                                 
Testing with pattern 0x00: done                                                 
Reading and comparing: done                                                 
Pass completed, 0 bad blocks found. (0/0/0 errors)

10101010、01010101、11111111、00000000 の 4 パターンについてそれぞれ書き込み・読み出しでチェックする。Memtest86 の場合のように比較的時間がかかる検査(8GB のメモリースティックでは 2 時間 17 分もかかった)。


gdisk によるパーティション操作

今回は 2GB の USB フラッシュドライブを使い、そのうち 256MB を swap パーティションに、残り 1.6GB をデータ用パーティションにした。

gdisk コマンドでデバイス(/dev/sd*)を指定して実行すれば、あとは対話形式でパーティションデザインを行う形となる。


Disk /dev/sda: 3915776 sectors, 1.9 GiB
Model: Storage Media   
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): 257F8D9E-B548-49DA-AC35-DF64271AA16E
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 3915742
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
1  2048  526335   256.0 MiB   8200  Linux swap
2  526336  3915742   1.6 GiB     8300  Linux filesystem

各パーティションのフォーマットとマウント操作

swap パーティションは mkswap コマンドでフォーマット、データ用パーティションは mkfs.f2fs コマンドで F2FS でフォーマットした。


ls -l /dev/sd*
brw-------    1 root     root        8,   0 Aug  2 16:57 /dev/sda
brw-------    1 root     root        8,   1 Aug  2 16:57 /dev/sda1
brw-------    1 root     root        8,   2 Aug  2 16:57 /dev/sda2
mkswap -L swap /dev/sda1
Setting up swapspace version 1, size = 268431360 bytes

mkfs.f2fs /dev/sda2

 F2FS-tools: mkfs.f2fs Ver: 1.12.0 (2018-11-12)

Info: Disable heap-based policy
Info: Debug level = 0
Info: Label = data
Info: Trim is enabled
Info: [/dev/sda2] Disk Model: Storage Media   
Info: Segments per section = 1
Info: Sections per zone = 1
Info: sector size = 512
Info: total sectors = 3389407 (1654 MB)
Info: zone aligned segment0 blkaddr: 512
Info: format version with
  "Linux version 4.14.180 (builder@buildhost) (gcc version 7.5.0 (OpenWrt GCC 7.5.0 r11063-85e04e9f46)) #0 Sat May 16 18:32:20 2020"
Info: [/dev/sda2] Discarding device
Info: This device doesn't support BLKSECDISCARD
Info: This device doesn't support BLKDISCARD
Info: Overprovision ratio = 4.980%
Info: Overprovision segments = 86 (GC reserved = 48)
Info: format successful

フォーマットを終えてからルーターを再起動すると、LuCI の System > Mount Points メニューが現れる。ここでは /mnt/data に /dev/sda2 を、SWAP に /dev/sda1 を設定した。

swap が有効となり、Status > Overview に Swap free の表示項目が現れたのがわかる。

スワップパーティションではなく、スワップファイルを使いたい場合(推奨)

Linux のスワップ方式としてはあまり一般的ではないが、USB フラッシュドライブで読み書きされるブロックの分散を図るために F2FS を選ぶわけだから、スワップパーティションにしてしまうと、そのパーティションについては利用頻度に偏りが生じてしまう。これを回避するには、パーティションを分割せずに全部を F2FS のパーティション一つにし、スワップファイルでスワップメモリーを実現した方が良い。

(参考:👉 OpenWrt Forum

まずはマウントした /dev/sda すなわち /mnt/data にスワップ容量と同じサイズの空ファイルを作成(0 で埋めた 256MB のファイル)し、パーミッションを適切に設定し、スワップファイルにする。


dd if=/dev/zero of=/mnt/data/swapfile bs=1M count=256
chmod 600 /mnt/data/swapfile
mkswap /mnt/data/swapfile

/etc/config/fstab に必要な設定を加える(uci コマンドを使っても ok)。

/etc/config/fstab

config global
        option anon_mount '0'
        option auto_mount '1'
        option delay_root '5'
        option check_fs '0'
+       option anon_swap '1'
+       option auto_swap '1'

config mount
        option enabled '1'
        option target '/mnt/data'
        option uuid 'd20da465-8ad8-41ba-b327-2d71645b3d20'

+ config swap
+       option enabled '1'
+       option device '/mnt/data/swapfile'

reboot する。


あとがき

  • USB フラッシュドライブに swap パーティションを作成するのはあまり気乗りはしないのだが、今回の例では WordPress をインストールしてデータベースに MariaDB を使うという背景の下で行っており、メモリーが逼迫する状況が十分に考えられるため、the last resort として swap パーティションも用意しておくことにした。本来は HDD か SSD がある場合に用いるべきではないかと思う。
  • OpenWrt ルーターの WWW サーバー化にあたっては、USB 接続の外部記憶領域が必要になってくると思う。USB の外付け HDD でも構わないだろうが、NAS は別に存在し、NAS 兼 WWW サーバー化したいというわけでもない。だとしたら単に WWW サーバーの記憶領域として HDD を用意するのは本来の「省電力な自家用 WWW サーバー」という主旨に反し、自己矛盾した愚策な気もするので、USB フラッシュドライブを使うのが妥当だろう。
  • swap を 256MB にしたのは、今回の例で使用している WZR-HP-AG300H の RAM の 128MB の 2 倍のサイズを目安にした(👉 What's the right amount of swap space for a modern Linux system?)。

コメント

このブログの人気の投稿

清水俊史『上座部仏教における聖典論の研究』

シークエンスパパともの先見の明

シークエンスパパとも 本物の霊能力