waypipe 报 Iris kernel too old 排查:被『客户端没有 GPU 节点』带偏的过程

八月 09, 2026 更新: 九月 13, 2026 [Linux 与系统] #waypipe #调试

问题现象

客户端机器通过 waypipe 连到服务器跑图形程序:

waypipe ssh workpc
weston-dnd

结果终端刷出报错:

error: Kernel is too old (4.16+ required) or unusable for Iris.
Check your dmesg logs for loading failures.

偶发还伴随 waypipe 的 dmabuf 报错:

S607565: 60.485827 [src/dmabuf.c:125] Failed to open drm fd for /dev/dri/renderD128: No such file or directory

关键对照:waypipe --no-gpu ssh workpc 后执行 weston-dnd 完全正常。显然问题在 waypipe 的 GPU 通道(dmabuf 直传)。

本文如实记录一次被错误怀疑带偏的排查——错误的焦点反复落在"服务端/客户端到底谁没有 renderD128"上,而真相在另一个层面。

第一轮误判:怀疑服务端(服务器)缺 renderD128

初始推断很自然:报错里有 Failed to open drm fd for /dev/dri/renderD128,dmabuf 直传要求两端都能打开渲染节点,于是先怀疑服务器。

在服务器上查证:

ls /dev/dri/          # card0-4 + renderD128,存在
uname -r              # 7.0.0-28-generic
getfacl /dev/dri/renderD128   # user:peter:rw-, mask rw-

服务器有 renderD128、ACL 正常、python 实测 open() 成功、gbm_create_device() 成功。服务器侧完全正常,排除。

第二轮误判:怀疑客户端没有 GPU 节点

服务器没问题,那按"两端缺一不可"的逻辑,报错应该发生在客户端——客户端 waypipe 进程要打开它自己那台机器的 /dev/dri/renderD128。于是推断"客户端机器有显卡但驱动没加载 render 节点"(比如 NVIDIA 没开 modeset=1、i915 模块被禁用等)。

但用户明确说:客户端是有 GPU 的。

而且注意一个拓扑干扰项:SSH 连接里看到的对端 IP 192.168.4.148 其实是 WireGuard 服务器(中间转发),不是客户端真机——这又增加了"客户端到底在哪"的混乱。实际上真正做 waypipe 客户端的机器是用户面前的物理机。

转向实测:报错到底来自哪一端

靠猜没用,直接实验定位报错来源。把两端 stderr 分开:

waypipe ssh workpc 'weston-dnd 2>/tmp/wp-server-err.log' 2>/tmp/wp-client-err.log

结果:

报错文本来自客户端 waypipe 进程自身,不是服务器,也不是 weston-dnd。第一轮"服务器缺 GPU"彻底排除,且"客户端没有 renderD128"也被推翻了——因为客户端明明有:

ls /dev/dri/    # card0 + renderD128
lspci           # Intel UHD 770 (Raptor Lake-S)

决定性一步:客户端 Mesa 其实全在软渲染

客户端 GPU 节点存在,但 iris 驱动本身可能有问题。用 glxinfo / eglinfo 看客户端 Mesa 实际用的渲染器:

glxinfo -B | grep -i renderer
# OpenGL renderer string: llvmpipe (LLVM 19.1.7, 256 bits)

关键发现:客户端所有 OpenGL 都是 llvmpipe(软件渲染),根本没有用 i915 硬件加速! 连 gnome-shell 桌面都在软渲染。

本地直接测 gbm_create_device() 也能复现那两行 Iris 报错(与 waypipe 无关):

python3 -c "import os,ctypes; ...gbm_create_device(os.open('/dev/dri/renderD128', os.O_RDWR))"
# error: Kernel is too old (4.16+ required) or unusable for Iris.
# gbm_create_device: OK     ← 回退到 llvmpipe 后仍能创建设备

这说明:不是"没有 GPU 节点",而是"iris 驱动加载失败,Mesa 静默回退到 llvmpipe"。waypipe 的 GPU 通道坚持用 iris,失败后就把报错打出来。

真正根因:i915 GuC 固件缺失,GPU wedged

报错提示 "Check your dmesg logs",用 sudo 看内核日志:

sudo dmesg | grep -iE 'i915|xe|drm'
i915 0000:00:02.0: firmware: failed to load i915/tgl_guc_70.1.1.bin (-2)
i915 0000:00:02.0: [drm] *ERROR* GT0: GuC firmware i915/tgl_guc_70.bin: fetch failed -ENOENT
i915 0000:00:02.0: [drm] *ERROR* GT0: GuC initialization failed -ENOENT
i915 0000:00:02.0: [drm] *ERROR* GT0: Failed to initialize GPU, declaring it wedged!

根因锁定:客户端的 i915 驱动因为缺 GuC 固件初始化失败,GPU 被内核标记为 wedged(不可用)。 于是 Mesa 的 iris 驱动初始化失败 → 报 Kernel is too old (4.16+ required) or unusable for Iris → 回退 llvmpipe。

检查固件目录:

ls /lib/firmware/i915/        # 只有 dg2_dmc_ver2_07.bin,无 tgl_guc*
apt-file search tgl_guc       # 属于 firmware-intel-graphics 包
apt-cache policy firmware-intel-graphics   # 未安装

解决:安装固件包 + 重启

sudo apt install firmware-intel-graphics
sudo reboot    # i915 被 Wayland 桌面会话占用,无法热卸载,必须重启

验证固件进入 initramfs(确保重启后能加载):

lsinitramfs /boot/initrd.img-$(uname -r) | grep tgl_guc
# usr/lib/firmware/i915/tgl_guc_70.bin ...

重启后预期:glxinfo -B 渲染器从 llvmpipe 变成 Mesa Intel(R) Raptor Lake-S,waypipe GPU 通道不再报错。

复盘:这次排查为什么被带偏

  1. 报错文本双来源混淆。Failed to open drm fd 是 waypipe 的,Kernel is too old for Iris 是 Mesa 的——两者都指向"GPU 不可用",但一个让人联想到"缺节点/权限",一个让人联想到"内核太旧"。真正原因(GPU wedged)藏在 dmesg 里,不靠日志只看表象必然误判。

  2. "两端缺一不可"的框架太粗糙。渲染节点存在 ≠ 驱动可用。客户端明明有 /dev/dri/renderD128,却因 iris 初始化失败实际不可用——ls /dev/dri 根本看不出 GPU 是好的。判断 GPU 是否可用要看 Mesa 实际用什么渲染器(glxinfo -B)和内核日志(dmesg),而不是只看有没有节点文件。

  3. 网络拓扑干扰。WireGuard 中转让 SSH 对端 IP 显示为 WG 服务器而非客户端真机,一度让人纠结"客户端到底是哪台"。先厘清拓扑,再谈哪一端。

  4. 先分离两端 stderr 再下结论。waypipe ssh host 'cmd 2>server.log' 2>client.log 一次性把"报错来自客户端还是服务端"定死,避免了来回猜。

排查工具速查

想确认什么命令
报错来自哪端waypipe ssh h 'cmd 2>s.log' 2>c.log 分别看两端
GPU 是否真可用glxinfo -B | grep -i renderer(llvmpipe = 软渲染,坏)
内核驱动状态sudo dmesg | grep -iE 'i915|xe|drm'
渲染节点归属readlink /sys/class/drm/renderD128/device/driver
固件是否齐全ls /lib/firmware/i915/、apt-file search tgl_guc
固件是否进 initrdlsinitramfs /boot/initrd.img-$(uname -r) | grep tgl_guc

2026-08-16 复发补充:这次不是没装固件,是没重启 + 两端都要加 render 组

8 月 16 日同款症状再次出现(waypipe ssh huawei-vm yad 报 Iris + dmabuf 报错), 但这次排查方向完全不同,记录两个 08-09 版本没覆盖的坑。

症状

error: Kernel is too old (4.16+ required) or unusable for Iris.
S20933:  0.007984 [src/dmabuf.c:129] Failed to open drm fd for /dev/dri/renderD128: Permission denied
(yad:20929): Gdk-CRITICAL **: ... gdk_x11_window_get_xid: assertion 'GDK_IS_X11_WINDOW (window)' failed

注意 dmabuf 报错从 No such file or directory(08-09)变成了 Permission denied——上一轮修完的机器已无此问题, 本次报错来自另一台机器(waypipe 客户端,192.168.2.100)。照旧先分离两端 stderr 定位来源: waypipe ssh huawei-vm 'yad 2>/tmp/wp-server-err.log' 2>/tmp/wp-client-err.log。

坑一:固件装了 ≠ 生效,wedged 状态只能重启恢复

客户端 dmesg 明明是 8 月 7 日开机时 tgl_guc_70.bin: fetch failed -ENOENT、GPU wedged, 但 firmware-intel-graphics 8 月 9 日已装好、lsinitramfs 也确认 tgl_guc_70.bin 已在 initrd 里——

对比时间线发现:开机(08-07 21:44)→ 装固件 + 重建 initramfs(08-09 22:16)→ 之后一直没重启。 i915 被 Wayland 桌面会话占用无法热卸载,wedged 状态从开机起就固定了,装再多固件也不影响已加载的驱动。 判断 GPU 是否真修好必须看当前会话的 glxinfo -B(llvmpipe = 还是坏的),而不是看 initrd 里有没有固件。

坑二:两端都要有 render 组权限,VM 内也要加

修复 Iris 后 dmabuf 报错仍在(Permission denied),客户端 usermod -aG render peter 后 报错消失一半——剩 Permission denied 转到了服务端 huawei-vm(VM 内 peter 只有 video 组, /dev/dri/renderD128 属组是 render)。VM 内同样要加:

# VM 内(或经 qemu-guest-agent 以 root 执行)
usermod -aG render peter
# 组变更不作用于已登录会话,重新 ssh 即可;客户端侧同理

坑三:yad 的 Gdk-CRITICAL 是 wayland 下的无害断言

gdk_x11_window_get_xid: assertion 'GDK_IS_X11_WINDOW' failed 是 yad(GTK3)内部获取 X11 窗口 ID 的代码路径在 wayland 后端下触发的断言——窗口仍能正常弹出,忽略即可,不属于故障。

本次完整链路小结

Iris 报错(客户端)→ 固件在 initrd 里但没重启 → 重启
dmabuf Permission denied(客户端)→ usermod -aG render
dmabuf Permission denied(服务端 VM)→ VM 内同样 usermod -aG render
Gdk-CRITICAL → 无害,忽略

2026-08-26 复发补充:第三种形态——服务端就是 QXL,永远没有 renderD128

8 月 26 日同款报错再次出现(cat ~/.ssh/id_ed25519.pub | clipcopy 后终端刷出), 但与前两次排雷方向都不同:这一次没任何 GPU 问题是可修的,纯粹是拓扑+参数问题。

症状

blog % cat ~/.ssh/id_ed25519.pub | clipcopy
S45742: 56.574026 [src/dmabuf.c:125] Failed to open drm fd for /dev/dri/renderD128: No such file or directory

和前两次的关键区别:报错文本是 No such file or directory(08-09 同款文本), 而不是 08-16 的 Permission denied——这次不是"有节点但权限不足",而是节点本身不存在。

定位:服务端(目标机)是 QXL 虚拟显卡,无渲染节点

报错来自 waypipe 服务端,即本次 SSH 的目标机(his-host,192.168.2.156 虚拟机)。查:

ls /dev/dri/
# crw-rw---- 1 root video 226,  1 ... card1      ← 只有显示节点
#                                无 renderD128       ← 没有渲染节点
lspci | grep -i vga
# 00:01.0 VGA compatible controller: Red Hat, Inc. QXL paravirtual graphic card

QXL 是纯 2D 的哑虚拟显卡(CPU 描画、无 3D 硬件),内核驱动本来就不注册渲染节点, 与 08-09/08-16 里"客户端机器有 renderD128 但驱动坏了/没权限"完全是两码事——这台机器永远不会有 renderD128, 再怎么装固件、加 render 组都没用(芯片没这功能)。CHANGELOG 里的待办"QXL → virtio-gpu 3D(virgl)" 就是给虚拟显卡模拟 3D 后,renderD128 才会出现。

(2026-09-13 更新:该 VM 已换成 virtio-vga-gl,renderD128 已出现,见文末收尾。)

复发的直接原因:会话没带 --no-gpu

08-09 的修复约定是客户端 waypipe --no-gpu ssh(禁用 GPU 协议、改走共享内存), 只要带了,即使服务端没渲染节点也不报错。但本次的 waypipe server 进程是 8/21 重建的会话, 看进程 cmdline 就知道客户端当时没用 --no-gpu(若带了,server 侧命令会带 -n):

waypipe -c lz4 --login-shell --unlink-socket -s /tmp waypipe-server-...

于是剪贴板复制时服务端照样尝试 dmabuf 直传 → 打开 /dev/dri/renderD128 → No such file。

repo 里两份"入口文档"仍写着不带 --no-gpu 的旧命令,这正是复发温床:

三种形态判别速查

报错文本含义方向
No such file or directory打开 renderD128 时节点不存在该端是 2D-only 卡(QXL/virtio-gpu 2D/bochs),只能 --no-gpu
Permission denied节点存在但用户无权限该端 usermod -aG render(重新 ssh 生效)
Kernel is too old ... for Iris设备存在但驱动初始化失败(GPU wedged)查 dmesg:装固件 + 重启

本次修复

  1. 客户端重连会话,用 waypipe --no-gpu ssh -o controlpath=none peter@192.168.2.156(连着旧会话的窗口重开)
  2. 顺手更新 dotfiles/.cheat/waypipe. 为带 --no-gpu 的新命令
  3. 长期:VM 升级 virgl(virtio-gpu 3D)后 renderD128 出现,届时才可去掉 --no-gpu(2026-09-13 已完成,见下)

2026-09-13 收尾:renderD128 已出现

his-host 已完成 QXL → virtio-vga-gl 迁移(实测过程见 工具链迁移 Wayland 的「根治方案」章节):

ls /dev/dri/                     # card1 + renderD128
dmesg | grep -i virgl
# [drm] features: +virgl +edid -resource_blob -host_visible

本文三种形态至此全部闭环:客户端 Iris(固件/重启)、两端 render 组权限、服务端 QXL 无渲染节点(迁移解决)。本机 waypipe 隧道可以去掉 --no-gpu 了(已建立的隧道要重连才生效)。