]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: fix and skip submitting invalid osd request 49941/head
authorXiubo Li <xiubli@redhat.com>
Thu, 12 Jan 2023 01:11:02 +0000 (09:11 +0800)
committerXiubo Li <xiubli@redhat.com>
Tue, 31 Jan 2023 05:45:34 +0000 (13:45 +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>
(cherry picked from commit e268728014700fde6dec1bdf8df3fb0ce226ede4)

src/mds/CDir.cc

index e9b9c38d2558cfd9b47d49c4b76eb17fc80925a7..b5b020f988095852b4278a84171c20dc01a04538 100644 (file)
@@ -2294,6 +2294,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);
@@ -2329,7 +2336,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;
@@ -2341,7 +2348,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;
@@ -2371,7 +2378,7 @@ void CDir::_omap_commit_ops(int r, int op_prio, int64_t metapool, version_t vers
     off += item.dft_len;
 
     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;