里豳朝 发表于 2025-10-20 23:45:14

一次XFS死锁问题分析

kernel version: 5.1.0
现象

XFS 文件系统出现挂起(hung),业务进程大量处于 D 状态;多处堆栈显示卡在 xfs_iget 与 xfs_fs_destroy_inode 路径上。
诊断过程

关键堆栈1(最早D住的进程,释放inode卡住)


[*]进程:postgres
[*]PID:202276
[*]症状:在 xfs_fs_destroy_inode 路径上等待,向下追溯可见正在尝试读取/获取 AGF 缓冲(xfs buf),而该锁被其他事务持有。AGF保存了空闲块的信息。
#0__schedule
#1schedule_timeout
#2down                      (信号量/互斥等待)
#3down
#4xfs_buf_lock            
#5xfs_buf_find            
#6xfs_buf_get_map         
#7xfs_trans_read_buf_map   
#8xfs_trans_read_buf_map       (封装层)
#9xfs_read_agf / xfs_alloc_read_agf← 正在尝试拿 AGF buf
#10 xfs_agf_* / xfs_read_agf_*         
#11 xfs_trans_read_buf               
#12 xfs_alloc_read_agf               
#13 xfs_btree_update / xfs_btree_del*
#14 xfs_inodegc_* / xfs_ifree_cluster
#15 xfs_inactive_ifree               
#16 xfs_destroy_inode                  
#17 xfs_fs_destroy_inode                  ← 释放 inode 主路径
#18 destroy_inode                      (VFS)
#19 evict                              (VFS)
#20 dentry_kill                        (VFS)
#21 dput                               (VFS)
#22 renameat2 / unlinkat               (syscall)
#23 __x64_sys_*                        (syscall)
#24 do_syscall_64
#25 entry_SYSCALL_64_after_hwframe解析xfs_buf地址,顺着 xfs_buf → xfs_trans → xlog_ticket → task_struct.pid 反查,锁持有者落到下一条堆栈(关键堆栈2)。
关键堆栈2(锁的持有者,创建/iget 路径卡住)


[*]进程:postgres
[*]PID:1894063
[*]症状:在 xfs_create / xfs_iget 路径;该事务已持有 AGF/AGI 相关日志项(从日志 item 链可见),同时在 iget 上等待 inode 资源,构成与 #1 的 ABBA 互等。
#0__schedule
#1schedule_timeout
#2xfs_iget                        ← iget 等待(可能循环)
#3xfs_ilock                  
#4xfs_iunlock                  
#5xfs_dir_ialloc               
#6xfs_ialloc                      (第1次/第2次分配)
#7xfs_create                  
#8xfs_generic_create         
#9path_openat / do_open      (VFS)
#10 do_filp_open               (VFS)
#11 do_sys_openat2
#12 do_sys_open
#13 __x64_sys_openat
#14 do_syscall_64
#15 entry_SYSCALL_64_after_hwframe关联关系:堆栈2 持有 AGF → 堆栈1 需要 AGF;堆栈1 持有 inode/inode-bp → 堆栈2 需要 inode-bp;互相等待形成系统级挂起(xfs hung + iget 死循环)。
根因

两个进程:

[*]进程 1(销毁文件):正在删除文件、回收 inode;
[*]进程 2(创建文件):正在分配新的 inode。
两个进程都要去改 XFS 的元数据结构,尤其是:
[*]AGF(空闲块信息)
[*]AGI(inode 信息)
[*]inode cluster buffer(一组 inode 的缓存块)
这几个结构之间是要上锁的。如果 A 拿着 inode 的锁再去要 AGF 的锁,而 B 拿着 AGF 的锁再去要 inode 的锁,就会变成 “你等我,我等你” —— 这就是典型的死锁(deadlock)。
于是,整个 XFS 文件系统“挂死”(hung),看到的就是:
[*]postgres 进程全在 D 状态;
[*]xfs_iget 死循环;
修复

补丁:xfs: use deferred frees for btree block freeing(commit b742d7b4f0e03...)
核心思想:把“立刻释放”改为“延迟释放”。
技术上怎么实现的:

[*]把原来直接调用的
xfs_free_extent()改成了xfs_free_extent_later()。
意思是:“我先把要释放的块记录到一个待办列表(deferred list)里,等当前事务快提交时再一起处理。”
[*]提交阶段,这些“待释放块”会被系统安全地处理:

[*]如果空间紧张,可以分多次提交;
[*]不会在持有其他锁时再去改 AGF;
[*]因此避免了死锁的条件。

[*]同时引入了一个 xefi_agresv 参数,
确保延迟释放的块仍然走正确的空闲空间管理逻辑(防止把 AG 专用块搞乱)。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

神泱 发表于 2025-12-11 14:31:00

不错,里面软件多更新就更好了

梢疠 发表于 2025-12-18 06:14:05

喜欢鼓捣这些软件,现在用得少,谢谢分享!

靳夏萱 发表于 2025-12-22 15:05:10

鼓励转贴优秀软件安全工具和文档!

度阡舅 发表于 2026-1-15 03:57:10

很好很强大我过来先占个楼 待编辑

事值 发表于 2026-1-21 10:07:30

感谢分享

左丘纨 发表于 2026-1-21 10:16:13

分享、互助 让互联网精神温暖你我

诈知 发表于 2026-1-21 16:43:00

感谢分享,下载保存了,貌似很强大

饮邺谲 发表于 2026-1-21 22:31:43

不错,里面软件多更新就更好了

贼瘁 发表于 2026-1-23 17:19:44

喜欢鼓捣这些软件,现在用得少,谢谢分享!

峰襞副 发表于 2026-1-26 20:23:33

懂技术并乐意极积无私分享的人越来越少。珍惜

恿榫 发表于 2026-1-27 01:59:58

懂技术并乐意极积无私分享的人越来越少。珍惜

上官泰 发表于 2026-1-27 03:00:12

谢谢分享,辛苦了

姚望舒 发表于 2026-1-27 08:04:56

很好很强大我过来先占个楼 待编辑

稿辏付 发表于 2026-1-27 19:52:08

喜欢鼓捣这些软件,现在用得少,谢谢分享!

梦霉 发表于 2026-1-30 07:04:37

感谢分享,学习下。

阮蓄 发表于 2026-2-2 02:38:41

谢谢分享,试用一下

喳谍 发表于 2026-2-3 04:46:53

不错,里面软件多更新就更好了

都淑贞 发表于 2026-2-4 03:11:03

用心讨论,共获提升!

幽淆 发表于 2026-2-5 17:27:19

东西不错很实用谢谢分享
页: [1] 2
查看完整版本: 一次XFS死锁问题分析