CVE-2026-98538: writeback: bound cleanup_offline_cgwb() rescans by rotating scanned inodes
In the Linux kernel, the following vulnerability has been resolved:
writeback: bound cleanupofflinecgwb() rescans by rotating scanned inodes
cleanupofflinecgwb() prepares at most WBMAXINODESPERISW inodes per call and is called again until the dying wb is drained, but every call walks wb->battached and then wb->bdirtytime from the same end. Inodes already prepared (they stay on the list with IWBSWITCH set until the switch worker runs) and inodes that cannot be switched (IFREEING, IWILLFREE, !SBACTIVE, DAX, already on the target wb) stay where they are, so each pass rescans a growing run of them under wb->listlock and a full drain is quadratic in the number of inodes on the list. With ~17M inodes attached to one dying cgwb we saw this end in soft lockups, with CPUs reported stuck for 21-48s.
Walk both lists from the oldest end and move every scanned inode to the newest end, so the next pass starts where the previous one stopped and the drain becomes linear. battached is unordered, so nobody sees the reorder there. bdirtytime is ordered by dirtiedwhen, but the oldest unscanned inode stays at the end moveexpiredinodes() picks from, sync takes the whole list regardless of order, and prepared inodes leave the list as soon as the switch work runs and get a new dirtiedtimewhen on the new wb anyway, so the only inodes left out of order are the ones that can never switch (DAX), and only on the dying wb.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade to a fixed release to a version that resolves this vulnerability.
Fixed in 6.6.159.1-1 - Upgrade
Upgrade
azurelinux/kernelto a version that resolves this vulnerability.Fixed in 6.6.159.1-1 - Upgrade
Upgrade
ubuntu/linux-hwe-7.0to a version that resolves this vulnerability.Fixed in 7.0.0-42.42~24.04.1 - Upgrade
Upgrade
ubuntu/linux-riscv-7.0to a version that resolves this vulnerability.Fixed in 7.0.0-42.42.1~24.04.1 - Upgrade
Upgrade
ubuntu/linuxto a version that resolves this vulnerability.Fixed in 7.0.0-42.42 - Upgrade
Upgrade
ubuntu/linux-awsto a version that resolves this vulnerability.Fixed in 7.0.0-1016.17 - Upgrade
Upgrade
ubuntu/linux-gcpto a version that resolves this vulnerability.Fixed in 7.0.0-1016.18 - Upgrade
Upgrade
ubuntu/linux-ibmto a version that resolves this vulnerability.Fixed in 7.0.0-1017.17 - Upgrade
Upgrade
ubuntu/linux-oem-7.0to a version that resolves this vulnerability.Fixed in 7.0.0-1017.17 - Upgrade
Upgrade
ubuntu/linux-oracleto a version that resolves this vulnerability.Fixed in 7.0.0-1015.16 - Upgrade
Upgrade
ubuntu/linux-riscvto a version that resolves this vulnerability.Fixed in 7.0.0-42.42.1
Event History
Frequently Asked Questions
What conditions are needed to trigger the performance problem?
A dying cgroup writeback (cgwb) instance must have a very large number of attached inodes. The reported soft lockups occurred with approximately 17 million inodes attached to one dying cgwb during cleanup.
What is the practical impact before the fix?
Cleanup repeatedly rescans inodes that were already prepared or cannot be switched, making the drain time quadratic in the number of inodes. This can hold the writeback list lock long enough to cause soft lockups, with CPUs reported stuck for 21 to 48 seconds.
How does the fix mitigate the issue?
The fix scans both inode lists from the oldest end and moves every scanned inode to the newest end. Subsequent cleanup passes then continue from where the preceding pass stopped, making the drain linear rather than quadratic.