]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: Add full caps to avoid osd full check
authorKotresh HR <khiremat@redhat.com>
Mon, 8 Mar 2021 12:08:26 +0000 (17:38 +0530)
committerKotresh HR <khiremat@redhat.com>
Fri, 4 Jun 2021 07:09:50 +0000 (12:39 +0530)
Fixes: https://tracker.ceph.com/issues/50532
Signed-off-by: Kotresh HR <khiremat@redhat.com>
(cherry picked from commit 6db81d8479b539d3ca6b98dc244c525e71a36437)

src/mds/MDSAuthCaps.cc
src/mds/MDSAuthCaps.h
src/mds/Server.cc

index dbf96ff30329590989d78f427de82c7c5d34c680..b78ebd6615b792f8ec9be0d99893e7d10f03df3c 100644 (file)
@@ -85,18 +85,26 @@ struct MDSCapParser : qi::grammar<Iterator, MDSAuthCaps()>
              (fs_name)[_val = phoenix::construct<MDSCapMatch>(std::string(),
                                                              _1)]);
 
-    // capspec = * | r[w][p][s]
+    // capspec = * | r[w][f][p][s]
     capspec = spaces >> (
         lit("*")[_val = MDSCapSpec(MDSCapSpec::ALL)]
         |
         lit("all")[_val = MDSCapSpec(MDSCapSpec::ALL)]
         |
+        (lit("rwfps"))[_val = MDSCapSpec(MDSCapSpec::RWFPS)]
+        |
         (lit("rwps"))[_val = MDSCapSpec(MDSCapSpec::RWPS)]
         |
+        (lit("rwfp"))[_val = MDSCapSpec(MDSCapSpec::RWFP)]
+        |
+        (lit("rwfs"))[_val = MDSCapSpec(MDSCapSpec::RWFS)]
+        |
         (lit("rwp"))[_val = MDSCapSpec(MDSCapSpec::RWP)]
         |
         (lit("rws"))[_val = MDSCapSpec(MDSCapSpec::RWS)]
         |
+        (lit("rwf"))[_val = MDSCapSpec(MDSCapSpec::RWF)]
+        |
         (lit("rw"))[_val = MDSCapSpec(MDSCapSpec::RW)]
         |
         (lit("r"))[_val = MDSCapSpec(MDSCapSpec::READ)]
@@ -271,6 +279,12 @@ bool MDSAuthCaps::is_capable(std::string_view inode_path,
         }
       }
 
+      if (mask & MAY_FULL) {
+        if (!grant.spec.allow_full()) {
+          continue;
+        }
+      }
+
       // check unix permissions?
       if (grant.match.uid == MDSCapMatch::MDS_AUTH_UID_ANY) {
         return true;
@@ -412,6 +426,9 @@ ostream &operator<<(ostream &out, const MDSCapSpec &spec)
     if (spec.allow_write()) {
       out << "w";
     }
+    if (spec.allow_full()) {
+      out << "f";
+    }
     if (spec.allow_set_vxattr()) {
       out << "p";
     }
index fee779a7fa762b24f91d6cf983b9c691ae433c69..395c921fd5fe25f1dc0ab33afc51067d747892a2 100644 (file)
@@ -34,6 +34,7 @@ enum {
   MAY_CHGRP    = (1 << 5),
   MAY_SET_VXATTR = (1 << 6),
   MAY_SNAPSHOT = (1 << 7),
+  MAY_FULL     = (1 << 8),
 };
 
 // what we can do
@@ -45,16 +46,22 @@ struct MDSCapSpec {
   static const unsigned SET_VXATTR     = (1 << 3);
   // if the capability permits mksnap/rmsnap
   static const unsigned SNAPSHOT       = (1 << 4);
+  // if the capability permits to bypass osd full check
+  static const unsigned FULL           = (1 << 5);
 
   static const unsigned RW             = (READ|WRITE);
+  static const unsigned RWF            = (READ|WRITE|FULL);
   static const unsigned RWP            = (READ|WRITE|SET_VXATTR);
   static const unsigned RWS            = (READ|WRITE|SNAPSHOT);
+  static const unsigned RWFP           = (READ|WRITE|FULL|SET_VXATTR);
+  static const unsigned RWFS           = (READ|WRITE|FULL|SNAPSHOT);
   static const unsigned RWPS           = (READ|WRITE|SET_VXATTR|SNAPSHOT);
+  static const unsigned RWFPS          = (READ|WRITE|FULL|SET_VXATTR|SNAPSHOT);
 
   MDSCapSpec() = default;
   MDSCapSpec(unsigned _caps) : caps(_caps) {
     if (caps & ALL)
-      caps |= RWPS;
+      caps |= RWFPS;
   }
 
   bool allow_all() const {
@@ -83,6 +90,9 @@ struct MDSCapSpec {
   bool allow_set_vxattr() const {
     return (caps & SET_VXATTR);
   }
+  bool allow_full() const {
+    return (caps & FULL);
+  }
 private:
   unsigned caps = 0;
 };
index 4869ff2472c43675c4887aaadd11957a0a6d0831..8f3831cb02b1672bb6fbe265446b2630699dbead 100644 (file)
@@ -2511,6 +2511,11 @@ void Server::dispatch_client_request(MDRequestRef& mdr)
   }
   
   if (is_full) {
+    CInode *cur = try_get_auth_inode(mdr, req->get_filepath().get_ino());
+    if (!cur) {
+      respond_to_request(mdr, -EINVAL);
+      return;
+    }
     if (req->get_op() == CEPH_MDS_OP_SETLAYOUT ||
         req->get_op() == CEPH_MDS_OP_SETDIRLAYOUT ||
         req->get_op() == CEPH_MDS_OP_SETLAYOUT ||
@@ -2524,9 +2529,13 @@ void Server::dispatch_client_request(MDRequestRef& mdr)
         (!mdr->has_more() || mdr->more()->witnessed.empty())) // haven't started peer request
        ) {
 
-      dout(20) << __func__ << ": full, responding CEPHFS_ENOSPC to op " << ceph_mds_op_name(req->get_op()) << dendl;
-      respond_to_request(mdr, -CEPHFS_ENOSPC);
-      return;
+      if (check_access(mdr, cur, MAY_FULL)) {
+        dout(20) << __func__ << ": full, has FULL caps, permitting op " << ceph_mds_op_name(req->get_op()) << dendl;
+      } else {
+        dout(20) << __func__ << ": full, responding CEPHFS_ENOSPC to op " << ceph_mds_op_name(req->get_op()) << dendl;
+        respond_to_request(mdr, -CEPHFS_ENOSPC);
+        return;
+      }
     } else {
       dout(20) << __func__ << ": full, permitting op " << ceph_mds_op_name(req->get_op()) << dendl;
     }