]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: prevent CDir omap commit with empty updates/removals/header 68793/head
authorVenky Shankar <vshankar@redhat.com>
Thu, 7 May 2026 09:47:38 +0000 (15:17 +0530)
committerVenky Shankar <vshankar@redhat.com>
Thu, 21 May 2026 06:46:11 +0000 (12:16 +0530)
Empty `stales` and `to_remove` causes `size` to be initialized with
sizeof(fnode_t). If the encoded inode size (plus fnode_t size) exceeds
max_dir_commit_size, commit_one() is called as a non-header update
with empty `_set` and `_rm` sets causing the MDS to assert.

While this patch prevents the assert, it is unknown at this point as
to why the encoded inode size is so large. We have seen it before
once, but there is lack of debug information to dig into. This fix
will prevent the assert, however, the MDS would go read-only due to
the large rados operation size, but at least we will have a live
system to debug at that point.

Fixes: http://tracker.ceph.com/issues/76455
Signed-off-by: Venky Shankar <vshankar@redhat.com>
src/mds/CDir.cc

index 14f2465d72c5cdfbefcc447b493edcd3640dd011..8d8e268a921111b7689ea7e1cdf37fcf59afd841 100644 (file)
@@ -2528,8 +2528,14 @@ void CDir::_omap_commit_ops(int r, int op_prio, int64_t metapool, version_t vers
     }
 
     unsigned size = item.key.length() + bl.length() + 2 * sizeof(__u32);
-    if (write_size > 0 && write_size + size > max_write_size)
-      commit_one();
+    if (write_size > 0 && write_size + size > max_write_size) {
+      if (!_set.empty() || !_rm.empty()) {
+        commit_one();
+      } else {
+        dout(1) << "skipping empty commit, inode size exceeded max_dir_commit_size ("
+                << size << " vs. " << max_write_size << ")" << dendl;
+      }
+    }
 
     write_size += size;
     _set[std::move(item.key)] = std::move(bl);