news 2026/6/10 4:55:42

一次XFS死锁问题分析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一次XFS死锁问题分析

现象

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

#1 schedule_timeout

#2 down (信号量/互斥等待)

#3 down

#4 xfs_buf_lock [xfs]

#5 xfs_buf_find [xfs]

#6 xfs_buf_get_map [xfs]

#7 xfs_trans_read_buf_map [xfs]

#8 xfs_trans_read_buf_map [xfs] (封装层)

#9 xfs_read_agf / xfs_alloc_read_agf [xfs] ← 正在尝试拿 AGF buf

#10 xfs_agf_* / xfs_read_agf_* [xfs]

#11 xfs_trans_read_buf [xfs]

#12 xfs_alloc_read_agf [xfs]

#13 xfs_btree_update / xfs_btree_del* [xfs]

#14 xfs_inodegc_* / xfs_ifree_cluster [xfs]

#15 xfs_inactive_ifree [xfs]

#16 xfs_destroy_inode [xfs]

#17 xfs_fs_destroy_inode [xfs] ← 释放 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

#1 schedule_timeout

#2 xfs_iget [xfs] ← iget 等待(可能循环)

#3 xfs_ilock [xfs]

#4 xfs_iunlock [xfs]

#5 xfs_dir_ialloc [xfs]

#6 xfs_ialloc [xfs] (第1次/第2次分配)

#7 xfs_create [xfs]

#8 xfs_generic_create [xfs]

#9 path_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 专用块搞乱)。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 7:11:10

Springboot文化艺术发展有限公司4rl42(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表项目功能:用户,日程动态,明星影音,fans俱乐部,练习生报名,商务合作,简历投递开题报告内容一、选题背景与意义行业现状与痛点随着全球文化产业的蓬勃发展,文化艺术领域正迎来前所未有的发展机遇。然而,传统的文化艺术管理方式…

作者头像 李华
网站建设 2026/6/10 7:53:25

Spring Boot 接口全链路测试全攻略:从单元到生产级验证

Spring Boot 接口全链路测试全攻略:从单元到生产级验证 在分布式微服务系统中,接口稳定性直接决定了用户体验和业务连续性。 本文将系统性介绍 8 种核心测试方法,并额外补充 7 个进阶策略,帮助你从开发到生产,构建一个全面的测试体系,让 Spring Boot 接口稳定性提升 100…

作者头像 李华
网站建设 2026/6/10 11:42:54

前端动画性能优化

先说说为啥动画性能这么要命。现在用户可没耐心等你页面慢慢加载,动画一卡顿,轻则体验打折,重则流失用户。更别提搜索引擎现在把页面交互流畅度也算进排名因素了,你要敢让动画掉帧,SEO排名分分钟往下掉。而且移动端设备…

作者头像 李华
网站建设 2026/6/10 12:32:04

计算机Java毕设实战-基于Springboot网上蛋糕售卖店管理系统的设计与实现基于springboot的云与糖蛋糕购物平台系统的设计与实现【完整源码+LW+部署说明+演示视频,全bao一条龙等】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/6/10 3:18:01

Java毕设选题推荐:基于Springboot的网上蛋糕售卖店管理系统设计基于springboot的云与糖蛋糕购物平台系统的设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/6/10 12:32:08

用MATLAB实现眼球检测与注视跟踪:从人脸到瞳孔的探索之旅

使用 MATLAB 通过人脸检测、眼睛区域检测、瞳孔检测和眼睛跟踪进行眼球检测和眼睛注视跟踪。 通过摄像头捕捉人脸,主要使用Viola-Jones人脸检测器检测人脸,然后再检测人眼,通过霍夫圆检测选择眼球,并判断眼球在眼睛中的位置。 在计…

作者头像 李华