title: Linux 6.17でPLEX録画の音飛びを修正する(smsdvbドライバのsysfs_emit_at警告対応)
tags:
- Linux
- Ubuntu
- 録画
- カーネルモジュール
- NHK
はじめに
Ubuntu 24.04 + Linux kernel 6.17 環境でdocker-mirakurun-epgstationを使って録画していたところ、録画ファイルに断続的な音飛びが発生するようになりました。
調査の結果、Linux 6.17で追加されたsysfs_emit_at()の厳格な検証チェックが、USBチューナードライバ(smsdvb)で誤発火し、USBの割り込み処理に遅延が生じてTSパケットがドロップしていたことが原因でした。
本記事では原因の特定から修正・適用までの手順を解説します。
環境
| 項目 | 内容 |
|---|---|
| OS | Ubuntu 24.04 LTS |
| カーネル | Linux 6.17.0-20-generic (HWE) |
| チューナー | PLEX PX-S1UD(Sianoチップ搭載 USBチューナー) |
| 録画ソフト | docker-mirakurun-epgstation |
| チューナーコマンド | dvbv5-zap + arib-b25-stream-test |
症状
- 録画した.tsファイルを再生すると、数分おきに音声が一瞬途切れる
- 映像は乱れないが音だけ飛ぶ
- リアルタイム視聴でも同様の現象が発生
原因調査
dmesgを確認したところ、録画中に以下のWARNINGが繰り返し出力されていました。
[2304623.686375] invalid sysfs_emit_at: buf:000000001fec78bb at:0
[2304623.686384] WARNING: CPU: 0 PID: 0 at fs/sysfs/file.c:795 sysfs_emit_at+0x63/0xd0
...
[2304623.686675] smsdvb_print_isdb_stats_ex+0x42e/0x650 [smsdvb]
[2304623.686682] smsdvb_update_isdbt_stats_ex+0x31/0x6e0 [smsdvb]
[2304623.686694] smsdvb_onresponse+0x2bc/0x660 [smsdvb]
根本原因
sysfs_emit_at()はLinux 6.17でsysfsページバッファ以外から呼ばれた場合にWARN_ONを発火する検証ロジックが追加されました。
drivers/media/common/siano/smsdvb-debugfs.cでは、構造体内のchar stats_data[PAGE_SIZE]バッファ(syfsページではない)に対してsysfs_emit_at()を使って統計情報を書き込んでいます。そのため、チューナーからレスポンスが届くたびにWARN_ONが発火。
WARN_ONはカーネルのスタックトレース出力を伴うため、USB割り込みコンテキストで数msの遅延が生じ、TSパケットのドロップ → 音飛びにつながっていました。
修正方法
sysfs_emit_at(buf, n, fmt, ...) を snprintf(buf + n, PAGE_SIZE - n, fmt, ...) に置き換えます。
対象ファイル:drivers/media/common/siano/smsdvb-debugfs.c(104箇所)
手順
1. カーネルソースを取得
mkdir -p ~/kernel-build && cd ~/kernel-build
apt-get source linux-hwe-6.17
※deb-srcが有効になっている必要があります。確認方法:
grep "deb-src" /etc/apt/sources.list /etc/apt/sources.list.d/*.sources 2>/dev/null | grep -v "^#"
2. 対象ファイルを確認
find ~/kernel-build/linux-hwe-6.17-6.17.0 -name "smsdvb-debugfs.c"
# → ~/kernel-build/linux-hwe-6.17-6.17.0/drivers/media/common/siano/smsdvb-debugfs.c
3. sysfs_emit_at → snprintf に一括置換
sed -i 's/sysfs_emit_at(buf, n, /snprintf(buf + n, PAGE_SIZE - n, /g' \
~/kernel-build/linux-hwe-6.17-6.17.0/drivers/media/common/siano/smsdvb-debugfs.c
置換件数の確認:
grep -c "snprintf" ~/kernel-build/linux-hwe-6.17-6.17.0/drivers/media/common/siano/smsdvb-debugfs.c
# → 104
grep -c "sysfs_emit_at" ~/kernel-build/linux-hwe-6.17-6.17.0/drivers/media/common/siano/smsdvb-debugfs.c
# → 0
4. カーネルヘッダーの確認
dpkg -l linux-headers-$(uname -r)
# ii linux-headers-6.17.0-20-generic ...
インストールされていない場合:
sudo apt install linux-headers-$(uname -r)
5. モジュールのビルド
cd ~/kernel-build/linux-hwe-6.17-6.17.0
make -C /lib/modules/$(uname -r)/build M=$(pwd)/drivers/media/common/siano modules
成功するとsmsdvb.koが生成されます:
CC [M] smsdvb-debugfs.o
LD [M] smsdvb.o
LD [M] smsdvb.ko
6. 既存モジュールをバックアップして差し替え
現在のモジュールはzstd圧縮(.ko.zst)されているので、圧縮してから配置します。
# バックアップ
sudo cp /lib/modules/$(uname -r)/kernel/drivers/media/common/siano/smsdvb.ko.zst \
/lib/modules/$(uname -r)/kernel/drivers/media/common/siano/smsdvb.ko.zst.bak
# 新モジュールを圧縮
zstd -19 ~/kernel-build/linux-hwe-6.17-6.17.0/drivers/media/common/siano/smsdvb.ko \
-o /tmp/smsdvb.ko.zst
# zstdファイルの検証
zstd -t /tmp/smsdvb.ko.zst
# 配置
sudo cp /tmp/smsdvb.ko.zst \
/lib/modules/$(uname -r)/kernel/drivers/media/common/siano/smsdvb.ko.zst
7. モジュールの再読み込み
sudo depmod -a
sudo modprobe -r smsdvb
sudo modprobe smsdvb
8. 確認
sudo dmesg | grep -E "smsdvb|sysfs_emit|WARNING" | tail -20
修正前:
[xxxxxx] invalid sysfs_emit_at: buf:000000001fec78bb at:0
[xxxxxx] WARNING: CPU: 0 PID: 0 at fs/sysfs/file.c:795 sysfs_emit_at+0x63/0xd0
修正後(新モジュールロード後にWARNINGが出なくなる):
[xxxxxx] smsdvb: loading out-of-tree module taints kernel.
[xxxxxx] smsdvb: module verification failed: signature and/or required key missing - tainting kernel
[xxxxxx] smsdvb:smsdvb_hotplug: DVB interface registered.
[xxxxxx] smsdvb:smsdvb_hotplug: DVB interface registered.
[xxxxxx] smsdvb:smsdvb_hotplug: DVB interface registered.
[xxxxxx] smsdvb:smsdvb_hotplug: DVB interface registered.
WARNINGが消え、DVBインターフェースが正常に登録されました。
注意事項
カーネルが"tainted"になる
自前ビルドのモジュールは署名がないため、module verification failedと表示されカーネルがtainted状態になります。動作に支障はありません。
カーネルアップデート時に元に戻る
apt upgradeでカーネルが更新されると、このモジュールは上書きされます。その場合は再度ビルドが必要ですが、ソースは~/kernel-build/に残っているので手順5以降を繰り返すだけで済みます。
まとめ
| 項目 | 内容 |
|---|---|
| 原因 | Linux 6.17のsysfs_emit_at()にsysfsページ検証が追加され、smsdvbドライバで誤発火 |
| 影響 | USB割り込み遅延 → TSパケットドロップ → 音飛び |
| 修正 |
sysfs_emit_at(buf, n, ...) → snprintf(buf + n, PAGE_SIZE - n, ...) に置換(104箇所) |
| 対象ファイル | drivers/media/common/siano/smsdvb-debugfs.c |
同じ環境(PLEX PX-S1UD/PX-Q1UD/VASTDTV VT20など Sianoチップ搭載USBチューナー + Linux 6.17)で録画の音飛びに悩んでいる方の参考になれば幸いです。