Raspberry Pi 4でUSB3.0接続のSSDがとても遅い

iowait slow ssd
Raspberry Pi 4 Model Bの4GBモデルをクラウドストレージとして動かしています。メモリーキャッシュのおかげでSDメモリーカードでもそこそこ動くのですが、より速くしようとUSB3.0でSSDをつなぎました。
ところがSSDのアクセスがとてつもなく遅いのです。


Raspberry Pi 4 Model Bの4GBモデルをクラウドストレージとして動かしています。メモリーが4GBあるのでキャッシュが効きSDカードメモリーでもそこそこ動いてくれます。ですが数ギガバイトのビデオファイルを扱うと流石に遅いです。キャッシュからSDメモリーカードへの書き込みに時間がかかります。

そこでUSB3.0に接続したSSDを使うことにしました。SSDからのブートはまだラズパイ4Bでは対応していません。プログラムのデータ用として使ってみました。
1GB未満の小さなファイルを扱っている時は気づかなかったのですが、大きなファイルを扱うとSSDがフリーズしたのかと思うくらい遅くなりました。

この時NetdataでCPUの負荷を見てみました。
関連記事:Raspberry Piの負荷や温度をモニタするにはNetdataが便利です

CPU負荷 IO wait
紫色のiowaitというのがCPU負荷の大部分を占めていました。iowaitで100%近く使い応答しなくなる事もあります。
また、64bitのUbuntuで大量のファイルをコピーするとIO ErrorでSSDが停まってしまうことがありました。

どうやらドライバが怪しいようです。検索すると次のフォーラムがすぐに見つかりました。
STICKY: If you have a Raspberry Pi 4 and are getting bad speeds transferring data to/from USB3.0 SSDs, read this | Raspberry Pi Forums
・・・
Typically, these devices will just stop responding when issued UAS commands that they don't like, or may in rare cases throw write data away which can cause filesystem corruption.
・・・
USB3.0ではUASPというプロトコルを使うと転送速度が上がります。しかしLinuxのドライバはまだこの規格を完全に実装できていいないようです。使用するUSBアダプタに依って相性問題が発生するようです。
この相性問題を解消するにはUASPを使わなければよいそうです。その代わり転送速度は少し落ちます。UASPを使わないようにするにはUSBアダプタをブラックリストへ登録すれば良いそうです。
ラズパイの場合はbootパーティションにあるカーネルコマンドラインにquirksを追加します。

カーネルコマンドラインにquirksを追加する

USB SSDのVIDとPIDを見つける

USBアダプタを特定するため、VIDとPIDを調べます。USB3.0ポートへUSB SSDをつないだ状態で次のコマンドを入れます。
lsusb
すると例えば次のように表示されます。
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 002: ID 152d:0578 JMicron Technology Corp. / JMicron USA Technology Corp. JMS567 SATA 6Gb/s bridge
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
私の場合はBUS 002、Device 002がUSB SSDのアダプタでした。JMicronの変換チップを使ったUSBアダプタだったようです。これの黄色で表した部分の番号をメモしておきます。

quirksをカーネルコマンドラインに追加する

カーネルコマンドラインはRaspbianの場合、/boot/cmdline.txt で指定します。/boot/cmdline.txtをテキストエディタで開きます。
例えば
sudo nano /boot/cmdline.txt
先頭に次の文字列を追加します。
usb-storage.quirks=152d:0578:u 
コマンドの区切りにスペースを入れます。cmdline.txtは改行してはいけません。
usb-storage.quirks=152d:0578:u dwc_otg.lpm_enable=・・・ 
保存して再起動します。
これで指定したUSBアダプタのUASが無効化されて動きます。

USBドライバのUASが無効になっているか確認する

UASで動いているのかどうか確認するにはどうするのでしょうか?
次のコマンドを入れます。
lsusb -t
例えばこんな風に表示が出ます。
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=dwc_otg/1p, 480M
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
    |__ Port 1: Dev 2, If 0, Class=Mass Storage, Driver=uas, 5000M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
上の黄色の部分に"uas"とあるので、このUSBドライバはUASで動きます。5000Mとあるので速度5GbpsのUSB3.0接続ができている事がわかります。
この表示があってもUASで正しく動くとは限りません。動かない場合に前節の設定を行います。
UASが無効になると次のように表示されます。
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=dwc_otg/1p, 480M
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
    |__ Port 1: Dev 2, If 0, Class=Mass Storage, Driver=usb-storage, 5000M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
"uas"ではなく"usb-storage"となります。

Ubuntuの場合

ラズパイ4BでUbuntuを使っている場合のカーネルコマンドラインは次のファイルです。
/boot/firmware/nobtcmd.txt
bluetoothを使う設定変更をした方は
/boot/firmware/btcmd.txt
【2020/05/10追記: Ubuntu 20.04ではcmdline.txtファイルになりました】

まとめ

ラズパイ4BはUSB3.0ポートが搭載され高速なSSDが有効に使えるようになりました。しかしドライバは不完全で相性問題があり十分な速度が出なかったりIO Errorになる事があります。
その時は/boot/cmdline.txtにquirksを追加しUSBアダプタがUASモードで動かないようにします。

ラズパイ4BのUSB端子は電流供給能力が低いらしくSSDによっては動かないものがありました。セルフパワーのハブを通すと動きました。





コメント

最近のコメント

Threaded Recent Comments will be here.