From: Venky Shankar Date: Thu, 7 May 2026 09:47:38 +0000 (+0530) Subject: mds: prevent CDir omap commit with empty updates/removals/header X-Git-Tag: v21.0.1~35^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=068fab674c3bff757ea5fef86be82769ff813c29;p=ceph.git mds: prevent CDir omap commit with empty updates/removals/header 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 --- diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc index 14f2465d72c..8d8e268a921 100644 --- a/src/mds/CDir.cc +++ b/src/mds/CDir.cc @@ -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);