{"id":21569,"date":"2026-09-12T04:31:21","date_gmt":"2026-09-11T20:31:21","guid":{"rendered":"https:\/\/www.54iter.cn\/?vuln=cve-2026-89647"},"modified":"2026-09-12T04:31:21","modified_gmt":"2026-09-11T20:31:21","slug":"cve-2026-89647","status":"publish","type":"vuln","link":"https:\/\/www.54iter.cn\/?vuln=cve-2026-89647","title":{"rendered":"CVE-2026-89647 &#8211; In the Linux kernel, the following vulnerability has been resolved:\n\nceph: do not repeat c"},"content":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>ceph: do not repeat ceph_trim_dentries() if no progress possible<\/p>\n<p>ceph_cap_reclaim_work() re-queues itself for as long as<br \/>\nceph_trim_dentries() returns -EAGAIN, which happens whenever a lease<br \/>\nwalk exhausts its `nr_to_scan` budget.  This creates a busy loop that<br \/>\nconsumes CPU without making any progress when there is nothing to<br \/>\nreclaim: with no cap pressure (`count==0`) and every scanned lease<br \/>\nstill valid, each pass runs the full scan budget down to zero and<br \/>\nreturns `-EAGAIN`, only to be queued again immediately.<\/p>\n<p>The dir-lease walk made this worse.  When `expire_dir_lease` is<br \/>\n`false` (i.e. we have no intention of reclaiming dir leases),<br \/>\n__dir_lease_check() returned `TOUCH` for every valid lease.  `TOUCH`<br \/>\nmoves the dentry to the tail of the list and resets `di-&gt;time` via<br \/>\n__dentry_dir_lease_touch(), so a walk over N valid leases pointlessly<br \/>\nrewrote the list, refreshed the timestamps (preventing them from ever<br \/>\naging out) and always drained `nr_to_scan`, guaranteeing the `-EAGAIN`<br \/>\nrequeue.<\/p>\n<p>Fix this in three steps:<\/p>\n<p> &#8211; Return `KEEP` instead of `TOUCH` when `expire_dir_lease` is<br \/>\n   `false`.  If we are not going to reclaim the lease, leave it in<br \/>\n   place instead of churning the list and resetting its timestamp; the<br \/>\n   walk then terminates naturally (or via `STOP` at the first fresh<br \/>\n   lease).<\/p>\n<p> &#8211; Only return `-EAGAIN` from the first (dentry-lease) walk when something<br \/>\n   was actually freed.  A full batch that frees nothing means retrying<br \/>\n   the same list immediately is futile; fall through to the dir-lease<br \/>\n   walk instead.<\/p>\n<p> &#8211; After both walks, bail out with success (0) when nothing was freed<br \/>\n   and there is no cap pressure (`count==0`).  There is no reason to<br \/>\n   keep retrying when we are not over the cap limit and made no<br \/>\n   progress.<\/p>\n<p>Under real cap pressure (`count&gt;0`) the reclaim path is unchanged and<br \/>\nstill retries via `-EAGAIN`.<\/p>\n<p>Without this patch, I saw 500 ceph_trim_dentries() calls per second on<br \/>\nour web servers.  This is very visible in `\/proc\/lock_stat` (5 minute<br \/>\ncapture):<\/p>\n<p>              class name    con-bounces    contentions   waittime-min   waittime-max waittime-total   waittime-avg    acq-bounces   acquisitions   holdtime-min   holdtime-max holdtime-total   holdtime-avg<\/p>\n<p> &amp;mdsc-&gt;dentry_list_lock:        126180         128218           0.04        8063.44    15986965.20         124.69        1573354        5296812           0.04        8291.28    74164526.48          14.00<br \/>\n &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br \/>\n &amp;mdsc-&gt;dentry_list_lock         111736          [] __ceph_dentry_dir_lease_touch+0x7c\/0xa8<br \/>\n &amp;mdsc-&gt;dentry_list_lock           2631          [] __dentry_leases_walk+0x64\/0x2c8<br \/>\n &amp;mdsc-&gt;dentry_list_lock           3878          [] __ceph_dentry_lease_touch+0x5c\/0xa8<br \/>\n &amp;mdsc-&gt;dentry_list_lock           9973          [] __dentry_lease_unlist+0x50\/0xa0<br \/>\n &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br \/>\n &amp;mdsc-&gt;dentry_list_lock         123621          [] __dentry_leases_walk+0x64\/0x2c8<br \/>\n &amp;mdsc-&gt;dentry_list_lock           1822          [] __ceph_dentry_dir_lease_touch+0x7c\/0xa8<br \/>\n &amp;mdsc-&gt;dentry_list_lock           2720          [] __dentry_lease_unlist+0x50\/0xa0<br \/>\n &amp;mdsc-&gt;dentry_list_lock             55          [] __ceph_dentry_lease_touch+0x5c\/0xa8<\/p>\n<p>With this patch:<\/p>\n<p>              class name    con-bounces    contentions   waittime-min   waittime-max waittime-total   waittime-avg    acq-bounces   acquisitions   holdtime-min   holdtime-max holdtime-total   holdtime-avg<\/p>\n<p> &amp;mdsc-&gt;dentry_list_lock:          1203           1215           0.16         408.88       33082.88          27.23        4320501        7357389           0.04         500.64     1961578.00           0.27<br \/>\n &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br \/>\n &amp;mdsc-&gt;dentry_list_lock           1029          [] __ceph_dentry_dir_lease_touch+0x7c\/0xa8<br \/>\n &amp;mdsc-&gt;dentry_list_lock            1<br \/>\n&#8212;truncated&#8212;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the Linux kernel, the following vulnerability has been resolved:<\/p>\n<p>ceph: do not repeat ceph_trim_dentries() if no progress possible<\/p>\n<p>ceph_cap_reclaim_work() re-queues itself for as long as<br \/>\nceph_trim<\/p>\n","protected":false},"template":"","meta":[],"categories":[],"tags":[],"class_list":["post-21569","vuln","type-vuln","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln\/21569","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/vuln"}],"about":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=\/wp\/v2\/types\/vuln"}],"wp:attachment":[{"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=21569"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=21569"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.54iter.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=21569"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}