]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: fix and skip submitting invalid osd request 49048/head
authorXiubo Li <xiubli@redhat.com>
Thu, 12 Jan 2023 01:11:02 +0000 (09:11 +0800)
committerXiubo Li <xiubli@redhat.com>
Thu, 12 Jan 2023 01:11:02 +0000 (09:11 +0800)
When the first dentry have enough metadata and the size is larger
than max_write_size, it may submitting one invalid osd request to
Rados, which will cause the cephfs to be readonly.

Fixes: https://tracker.ceph.com/issues/58082
Signed-off-by: Xiubo Li <xiubli@redhat.com>
src/mds/CDir.cc

index d7c5afd83dfc09f8efda17544f3960e8e8573450..e6844cb7a4bdcbe33bd85af5210ffc830e93c073 100644 (file)
@@ -2421,6 +2421,13 @@ void CDir::_omap_commit_ops(int r, int op_prio, int64_t metapool, version_t vers
   auto commit_one = [&](bool header=false) {
     ObjectOperation op;
 
+    /*
+     * Shouldn't submit empty op to Rados, which could cause
+     * the cephfs to become readonly.
+     */
+    ceph_assert(header || !_set.empty() || !_rm.empty());
+
+
     // don't create new dirfrag blindly
     if (!_new)
       op.stat(nullptr, nullptr, nullptr);
@@ -2456,7 +2463,7 @@ void CDir::_omap_commit_ops(int r, int op_prio, int64_t metapool, version_t vers
   int count = 0;
   for (auto &key : stales) {
     unsigned size = key.length() + sizeof(__u32);
-    if (write_size + size > max_write_size)
+    if (write_size > 0 && write_size + size > max_write_size)
       commit_one();
 
     write_size += size;
@@ -2468,7 +2475,7 @@ void CDir::_omap_commit_ops(int r, int op_prio, int64_t metapool, version_t vers
 
   for (auto &key : to_remove) {
     unsigned size = key.length() + sizeof(__u32);
-    if (write_size + size > max_write_size)
+    if (write_size > 0 && write_size + size > max_write_size)
       commit_one();
 
     write_size += size;
@@ -2496,7 +2503,7 @@ 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 + size > max_write_size)
+    if (write_size > 0 && write_size + size > max_write_size)
       commit_one();
 
     write_size += size;