这里介绍使用 vscode(gdb) + qemu 调试 Lustre文件系统,前置操作需要确定使用的 Linux 内核版本源代码,并能成功编译 Lustre. 具体可以参考 Ubuntu 下编译安装 Lustre
以下内容以 ubuntu 5.19.0-41.42 源代码为例
一、获取源代码
1. 获取 Linux 内核源代码
这里同样以 ubuntu 5.19.0-41.42 源代码(linux kernel 5.19.17)为例
sudo apt install linux-source-5.19.0=5.19.0-41.42\~22.04.1
下载的源码会在/usr/src目录下,解压获得 linux
tar jxvf /usr/src/linux-source-5.19.0.tar.bz2
2. 获取 Lustre 源代码
将 lustre 源代码放到 linux 源码 fs 目录下
cd fs
git clone git://git.whamcloud.com/fs/lustre-release.git
二、调试 Linux 内核
调试 lustre 方法主要是将 lustre 作为可加载的内核模块同 linux 内核一同调试,首先是先实现 linux 内核的调试
1. 配置内核编译选项
为了方便安装后续使用 lustre 所需要的相关依赖,需要支持debian在线软件包的根文件系统,我这里采用runninglinuxkernel制作的根文件系统。
runninglinuxkernel的内核版本是5.0。首先从中获取几个需要用到的文件,用于编译调试上一步获得的内核源代码:
1. 配置文件 .config
2. 脚本 run_debian_x86_64.sh
3. 半成品的根文件系统分片 rootfs_debian_x86_64.part00/01
将上面的几个文件放到内核代码根目录上
make menuconfig
修改下面两个选项:
│ Symbol: VERSION_SIGNATURE [=]
│ Type : string
│ Defined at init/Kconfig:360
│ Prompt: Arbitrary version signature
│ Location:
│ Main menu
│ (1) -> General setup
│ Symbol: GDB_SCRIPTS [=y]
│ Type : bool
│ Defined at lib/Kconfig.debug:383
│ Prompt: Provide GDB scripts for kernel debugging
│ Depends on: DEBUG_INFO [=y]
│ Location:
│ Main menu
│ -> Kernel hacking
│ (1) -> Compile-time checks and compiler options
- 将
Arbitrary version signature
修改为Ubuntu
(我这的源代码是 Ubuntu ),目的是后续 lustre 进行configure
时能检测出发行版是Ubuntu
- 包含
Provide GDB scripts for kernel debugging
生成vmlinux-gdb.py
脚本
2. 编译内核
make -j$(nproc)
3. 制作根文件系统
sudo ./run_debian_x86_64.sh build_rootfs
运行成功后会得到一个 rootfs_debian_x86_64.ext4
的文件,这个是制作得到的根文件系统。
注:runninglinuxkernel里面的
rootfs_debian_x86_64.part
是基于 debian10,其中一些 lustre 依赖的软件包过旧无法满足较新版本的 lustre. 所以后面启动后可以将debian10 升级到 debian12. 可以参考从Debian10升级到Debian12
打开 run_debian_x86_64.sh
文件,删除下面两行内容
--fsdev local,id=kmod_dev,path=./kmodules,security_model=none \
-device virtio-9p-pci,fsdev=kmod_dev,mount_tag=kmod_mount\
4. 运行和调试
使用 run
或 run debug
来运行或调试内核
./run_debian_x86_64.sh run
./run_debian_x86_64.sh run debug
调试时,运行 run debug
后即可用 vscode 或 gdb 远程连接 :1234 调试
vscode调试launch
的configurations
可以配置为以下内容,其它的可以根据自己需求配置。
{
"name": "kernel-debug",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/vmlinux",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"miDebuggerServerAddress": "127.0.0.1:1234",
"miDebuggerPath": "/usr/bin/gdb",
"MIMode": "gdb",
"logging": {
"engineLogging": false
},
}
三、单步调试 Lustre
1. 配置 Lustre
将 lustre 的源代码放到 linux 源代码的 fs
目录下
sh autogen.sh
./configure --with-linux=[linux-source-dir] --enable-client --enable-server --without-o2ib --disable-strict-errors --disable-tests
linux-source-dir
是上一步的 Linux 代码目录
2. 获取 ldiskfs 源代码
进入ldiskfs
目录,应用补丁
cd ldiskfs
make
3. 在Linux中启用Lustre文件系统支持
在 lustre 目录下创建 Kconfig 文件,写入以下内容(其他内容可根据需要自定义)
config LUSTRE_FS
tristate "Lustre filesystem support"
help
Lustre file system.
在 linux 目录的 fs/Kconfig 文件中添加
source "fs/lustre/Kconfig"
在 linux 目录的 fs/Makefile 文件中添加
obj-$(CONFIG_LUSTRE_FS) += lustre/
接着在 linux 目录下配置
make menuconfig
然后将 File systems -> Lustre filesystem support
选择为<M>内核模块方式编译
理论上也可以使用<Y>指定将 lustre 编译链接到内核中,但需要对 lustre 进行较大的修改。比如,ldiskfs是有ext4应用补丁得到,可能会存在相同的变量或函数定义,编译链接到内核中可能会导致重定义等问题。
4. 编译安装 Lustre 内核模块
linux 目录下编译内核
make -j$(nproc)
接着将 lustre 的内核模块安装到根文件系统中
sudo ./run_debian_x86_64.sh update_rootfs
5. 安装 lustre 工具包
以上步骤只是安装了 lustre 的内核模块,还需要安装以可执行文件方式存在的工具包(mkfs, mount, lfs…)
可以用以下两种方式安装
- lustre 目录下使用
make debs
制作deb安装包,然后复制**-utils-**.deb
到根文件系统,qemu 启动系统后安装这个deb软件包 - 将编译好的 utils 目录下的可执行文件复制到根文件系统中使用
6. 调试
这里需要用到vmlinux-gdb.py脚本, Ubuntu 可能会将脚本的自动加载限制在已知的安全目录中。 如果gdb报告拒绝加载vmlinux-gdb.py,可修改.gdbinit使用add-auto-load-safe-path
添加安全目录。
启动调试的时候,可以在 init/main.c
中的 start_kernel
打一个断点,触发断点后执行命令lx-symbols
,lx-symbols
包含在 vmlinux-gdb.py
脚本中,用于加载 Linux 内核和模块的符号表,方便调试内核与加载的模块。
使用 lx-symbols
后,当加载了内核模块后,会自动加载内核和已加载模块的符号信息,如
-exec lx-symbols
loading vmlinux
scanning for modules in …
loading @0xffffffffa0000000: … fs/lustre/libcfs/libcfs/libcfs.ko
loading @0xffffffffa0021000: … fs/lustre/lnet/lnet/lnet.ko
…
fs/lustre/lustre/llite/super25.c
文件的 lustre_fill_super
函数是挂载 lustre 的入口点,可在该函数打断点后执行挂载操作判断调试配置时候成功。
当修改了源代码,重新编译内核后更新根文件系统,使用 update_rootfs
即可安装新的模块到根文件系统
make -j$(nproc)
sudo ./run_debian_x86_64.sh update_rootfs
附:使用 vscode 单步调试示例
- 在终端中运行
./run_debian_x86_64.sh run debug
- 在
start_kernel
处设置断点,vscode启动调试连接 :1234 - 触发断点后在调试控制台执行命令
lx-symbols
自动加载调试符号信息
- 在 vscode 中设置 lustre 代码断点,在qemu guest中执行 lustre 相关操作。
可以在调试控制台中看到,模块的调试信息会被自动加载