]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: provide mechanism to authpin while freezing
authorPatrick Donnelly <pdonnell@redhat.com>
Tue, 13 Feb 2024 16:07:26 +0000 (11:07 -0500)
committerPatrick Donnelly <pdonnell@redhat.com>
Wed, 20 Mar 2024 14:56:54 +0000 (10:56 -0400)
When a subtree is freezing, it's no longer possible to acquire new authpins.
This is a problem when a compound request like quiescing a subtree is trying to
acquire authpins for each sub-op. This creates a situation where some quiesce
sub-ops complete with authpins (thereby preventing the tree from becoming
"frozen") and new sub-ops cannot acquire authpins (because the tree is
"freezing"). To circumvent this, allow some authpin requests to proceed if
FLAG_BYPASSFREEZING is set.

Signed-off-by: Patrick Donnelly <pdonnell@redhat.com>
src/mds/CDentry.cc
src/mds/CDentry.h
src/mds/CDir.cc
src/mds/CDir.h
src/mds/CInode.cc
src/mds/CInode.h
src/mds/MDSCacheObject.h
src/mds/Mutation.cc
src/mds/Mutation.h
src/mds/Server.cc
src/messages/MMDSPeerRequest.h

index 8694dfc72a2e6f8145e8b803a6e81d23e24696e6..9f5f1a49f55ec64977285bb2ab55965b512f2993 100644 (file)
@@ -368,10 +368,10 @@ int CDentry::get_num_dir_auth_pins() const
   return auth_pins;
 }
 
-bool CDentry::can_auth_pin(int *err_ret) const
+bool CDentry::can_auth_pin(int *err_ret, bool bypassfreezing) const
 {
   ceph_assert(dir);
-  return dir->can_auth_pin(err_ret);
+  return dir->can_auth_pin(err_ret, bypassfreezing);
 }
 
 void CDentry::auth_pin(void *by)
index 2566395d185617bec6c4e0bbeb6719b2e6cdcdf0..837ce2b8818d83409b6b107b4b21c77b091816af 100644 (file)
@@ -222,7 +222,7 @@ public:
   void _put() override;
 
   // auth pins
-  bool can_auth_pin(int *err_ret=nullptr) const override;
+  bool can_auth_pin(int *err_ret=nullptr, bool bypassfreezing=false) const override;
   void auth_pin(void *by) override;
   void auth_unpin(void *by) override;
   void adjust_nested_auth_pins(int diradj, void *by);
index a8aaf11c0512c2eef9b33108ee5236a92319aab0..c65dee271fc8e67b3ed267e12cb7effb6d240b2f 100644 (file)
@@ -3445,16 +3445,25 @@ void CDir::adjust_freeze_after_rename(CDir *dir)
   mdcache->mds->queue_waiters(unfreeze_waiters);
 }
 
-bool CDir::can_auth_pin(int *err_ret) const
+bool CDir::can_auth_pin(int *err_ret, bool bypassfreezing) const
 {
   int err;
   if (!is_auth()) {
     err = ERR_NOT_AUTH;
-  } else if (is_freezing_dir() || is_frozen_dir()) {
+  } else if (is_freezing_dir()) {
+    if (bypassfreezing) {
+      dout(20) << "allowing authpin with freezing" << dendl;
+      err = 0;
+    } else {
+      err = ERR_FRAGMENTING_DIR;
+    }
+  } else if (is_frozen_dir()) {
     err = ERR_FRAGMENTING_DIR;
   } else {
     auto p = is_freezing_or_frozen_tree();
-    if (p.first || p.second) {
+    if (p.first && !bypassfreezing) {
+      err = ERR_EXPORTING_TREE;
+    } else if (p.second) {
       err = ERR_EXPORTING_TREE;
     } else {
       err = 0;
index 7cc4dc7ffcf8379104f061d19bc12572e2f076a4..234da01b10c9b941236b8367cb3977ece95e1802 100644 (file)
@@ -526,7 +526,7 @@ public:
   void abort_import();
 
   // -- auth pins --
-  bool can_auth_pin(int *err_ret=nullptr) const override;
+  bool can_auth_pin(int *err_ret=nullptr, bool bypassfreezing=false) const override;
   int get_auth_pins() const { return auth_pins; }
   int get_dir_auth_pins() const { return dir_auth_pins; }
   void auth_pin(void *who) override;
index 7e9185ff5cc66ee02e9308af552983382f4a48ad..6d15908e545520ed7acb5b4f5a089e20fc65a6d6 100644 (file)
@@ -2929,11 +2929,18 @@ void CInode::clear_ambiguous_auth()
 }
 
 // auth_pins
-bool CInode::can_auth_pin(int *err_ret) const {
+bool CInode::can_auth_pin(int *err_ret, bool bypassfreezing) const {
   int err;
   if (!is_auth()) {
     err = ERR_NOT_AUTH;
-  } else if (is_freezing_inode() || is_frozen_inode() || is_frozen_auth_pin()) {
+  } else if (is_freezing_inode()) {
+    if (bypassfreezing) {
+      dout(20) << "allowing authpin with freezing" << dendl;
+      err = 0;
+    } else {
+      err = ERR_EXPORTING_INODE;
+    }
+  } else if (is_frozen_inode() || is_frozen_auth_pin()) {
     err = ERR_EXPORTING_INODE;
   } else {
     if (parent)
index 242288d5ec330a9451cdf11f4540df40f6de35bd..7d91becb97b9b8a4612a637a27496d8215fdf010 100644 (file)
@@ -926,7 +926,7 @@ class CInode : public MDSCacheObject, public InodeStoreBase, public Counter<CIno
   mds_authority_t authority() const override;
 
   // -- auth pins --
-  bool can_auth_pin(int *err_ret=nullptr) const override;
+  bool can_auth_pin(int *err_ret=nullptr, bool bypassfreezing=false) const override;
   void auth_pin(void *by) override;
   void auth_unpin(void *by) override;
 
index 7da2a67c3a273400097a341b4ddb957c60964813..8a319b4404d902c6e028787e57c65bdb81146b19 100644 (file)
@@ -210,7 +210,7 @@ class MDSCacheObject {
     ERR_FRAGMENTING_DIR,
     ERR_EXPORTING_INODE,
   };
-  virtual bool can_auth_pin(int *err_code=nullptr) const = 0;
+  virtual bool can_auth_pin(int *err_code=nullptr, bool bypassfreezing=false) const = 0;
   virtual void auth_pin(void *who) = 0;
   virtual void auth_unpin(void *who) = 0;
   virtual bool is_frozen() const = 0;
index f866f663359c6f66ece9047f178819a0c5203bc2..ecc455de08db64ce3575e3390d84d761ae93ecad 100644 (file)
@@ -364,9 +364,9 @@ void MDRequestImpl::clear_ambiguous_auth()
   more()->is_ambiguous_auth = false;
 }
 
-bool MDRequestImpl::can_auth_pin(MDSCacheObject *object)
+bool MDRequestImpl::can_auth_pin(MDSCacheObject *object, bool bypassfreezing)
 {
-  return object->can_auth_pin() ||
+  return object->can_auth_pin(nullptr, bypassfreezing) ||
          (is_auth_pinned(object) && has_more() &&
          more()->is_freeze_authpin &&
          more()->rename_inode == object);
index ded6271f99ee3920ce14d8b1b42c9f2070584bbf..fcb0b5a21ad8b7297e6307b2a11e857527faa4f5 100644 (file)
@@ -399,7 +399,7 @@ struct MDRequestImpl : public MutationImpl {
   bool freeze_auth_pin(CInode *inode);
   void unfreeze_auth_pin(bool clear_inode=false);
   void set_remote_frozen_auth_pin(CInode *inode);
-  bool can_auth_pin(MDSCacheObject *object);
+  bool can_auth_pin(MDSCacheObject *object, bool bypassfreezing=false);
   void drop_local_auth_pins();
   void set_ambiguous_auth(CInode *inode);
   void clear_ambiguous_auth();
index b27cd2bdbc2445c59a450f8f27693ec4815e9b0a..5749bfa7f263d9546dc080097cf4bc4075e13e9e 100644 (file)
@@ -3149,9 +3149,13 @@ void Server::handle_peer_auth_pin(const MDRequestRef& mdr)
   list<MDSCacheObject*> objects;
   CInode *auth_pin_freeze = NULL;
   bool nonblocking = mdr->peer_request->is_nonblocking();
+  bool bypassfreezing = mdr->peer_request->is_bypassfreezing();
   bool fail = false, wouldblock = false, readonly = false;
   ref_t<MMDSPeerRequest> reply;
 
+  dout(15) << " nonblocking=" << nonblocking
+           << " bypassfreezing=" << bypassfreezing << dendl;
+
   if (mdcache->is_readonly()) {
     dout(10) << " read-only FS" << dendl;
     readonly = true;
@@ -3183,7 +3187,7 @@ void Server::handle_peer_auth_pin(const MDRequestRef& mdr)
       }
       if (mdr->is_auth_pinned(obj))
        continue;
-      if (!mdr->can_auth_pin(obj)) {
+      if (!mdr->can_auth_pin(obj, bypassfreezing)) {
        if (nonblocking) {
          dout(10) << " can't auth_pin (freezing?) " << *obj << " nonblocking" << dendl;
          fail = true;
index 1799ab361a11587cac19e4d0c2c4bb40a06d1bb6..1a007364d4abbc9df0cb9cf2664c054bc43b072c 100644 (file)
@@ -106,6 +106,7 @@ public:
   static constexpr unsigned FLAG_INTERRUPTED   = 1<<5;
   static constexpr unsigned FLAG_NOTIFYBLOCKING        = 1<<6;
   static constexpr unsigned FLAG_REQBLOCKED    = 1<<7;
+  static constexpr unsigned FLAG_BYPASSFREEZING = 1<<8;
 
   // for locking
   __u16 lock_type;  // lock object type
@@ -160,6 +161,8 @@ public:
   void clear_notify_blocking() const { flags &= ~FLAG_NOTIFYBLOCKING; }
   bool is_req_blocked() const { return (flags & FLAG_REQBLOCKED); }
   void mark_req_blocked() { flags |= FLAG_REQBLOCKED; }
+  bool is_bypassfreezing() const { return (flags & FLAG_BYPASSFREEZING); }
+  void mark_bypassfreezing() { flags |= FLAG_BYPASSFREEZING; }
 
   void set_lock_type(int t) { lock_type = t; }
   const ceph::buffer::list& get_lock_data() const { return inode_export; }