]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: explicitly track files with client writeable ranges
authorYan, Zheng <zyan@redhat.com>
Fri, 10 Jul 2020 09:56:19 +0000 (17:56 +0800)
committerYan, Zheng <zyan@redhat.com>
Fri, 9 Oct 2020 16:02:44 +0000 (00:02 +0800)
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
(cherry picked from commit 44f67be02b8e8aa8fc69283bf12107c2df3f8277)

 Conflicts:
src/mds/CInode.cc
src/mds/Locker.cc
src/mds/MDCache.cc
src/mds/Server.cc
src/mds/StrayManager.cc

src/mds/CInode.cc
src/mds/CInode.h
src/mds/Locker.cc
src/mds/MDCache.cc
src/mds/Migrator.cc
src/mds/Server.cc
src/mds/StrayManager.cc
src/mds/mdstypes.h

index 7055e0e49d21b7db09387db1851c2129671f36c0..78263f7fb515a15c34077d1800b0fefe2554a626 100644 (file)
@@ -3281,17 +3281,6 @@ void CInode::set_mds_caps_wanted(mds_rank_t mds, int32_t wanted)
   }
 }
 
-void CInode::adjust_num_caps_notable(int d)
-{
-  if (!num_caps_notable && d > 0)
-    mdcache->open_file_table.add_inode(this);
-  else if (num_caps_notable > 0 && num_caps_notable == -d)
-    mdcache->open_file_table.remove_inode(this);
-
-  num_caps_notable +=d;
-  ceph_assert(num_caps_notable >= 0);
-}
-
 Capability *CInode::add_client_cap(client_t client, Session *session,
                                   SnapRealm *conrealm, bool new_inode)
 {
@@ -3573,6 +3562,38 @@ bool CInode::issued_caps_need_gather(SimpleLock *lock)
   return false;
 }
 
+void CInode::adjust_num_caps_notable(int d)
+{
+  if (!is_clientwriteable()) {
+    if (!num_caps_notable && d > 0)
+      mdcache->open_file_table.add_inode(this);
+    else if (num_caps_notable > 0 && num_caps_notable == -d)
+      mdcache->open_file_table.remove_inode(this);
+  }
+
+  num_caps_notable +=d;
+  ceph_assert(num_caps_notable >= 0);
+}
+
+void CInode::mark_clientwriteable()
+{
+  if (last != CEPH_NOSNAP)
+    return;
+  if (!state_test(STATE_CLIENTWRITEABLE)) {
+    if (num_caps_notable == 0)
+      mdcache->open_file_table.add_inode(this);
+    state_set(STATE_CLIENTWRITEABLE);
+  }
+}
+
+void CInode::clear_clientwriteable()
+{
+  if (state_test(STATE_CLIENTWRITEABLE)) {
+    if (num_caps_notable == 0)
+      mdcache->open_file_table.remove_inode(this);
+    state_clear(STATE_CLIENTWRITEABLE);
+  }
+}
 
 // =============================================
 
@@ -3690,10 +3711,8 @@ int CInode::encode_inodestat(bufferlist& bl, Session *session,
 
   // max_size is min of projected, actual
   uint64_t max_size =
-    std::min(oi->client_ranges.count(client) ?
-       oi->client_ranges[client].range.last : 0,
-       pi->client_ranges.count(client) ?
-       pi->client_ranges[client].range.last : 0);
+    std::min(oi->get_client_range(client),
+            pi->get_client_range(client));
 
   // inline data
   version_t inline_version = 0;
@@ -4045,8 +4064,8 @@ void CInode::encode_cap_message(const ref_t<MClientCaps> &m, Capability *cap)
   }
 
   // max_size is min of projected, actual.
-  uint64_t oldms = oi->client_ranges.count(client) ? oi->client_ranges[client].range.last : 0;
-  uint64_t newms = pi->client_ranges.count(client) ? pi->client_ranges[client].range.last : 0;
+  uint64_t oldms = oi->get_client_range(client);
+  uint64_t newms = pi->get_client_range(client);
   m->max_size = std::min(oldms, newms);
 
   i = pauth ? pi:oi;
index a416a9060a3822ac1524a65853c4e56fea669abf..4bf81fd248b51a25d9f54d47b5e398c5b49837d4 100644 (file)
@@ -323,6 +323,8 @@ class CInode : public MDSCacheObject, public InodeStoreBase, public Counter<CIno
   static const int STATE_DELAYEDEXPORTPIN      = (1<<19);
   static const int STATE_DISTEPHEMERALPIN       = (1<<20);
   static const int STATE_RANDEPHEMERALPIN       = (1<<21);
+  static const int STATE_CLIENTWRITEABLE       = (1<<22);
+
   // orphan inode needs notification of releasing reference
   static const int STATE_ORPHAN =      STATE_NOTIFYREF;
 
@@ -842,6 +844,11 @@ class CInode : public MDSCacheObject, public InodeStoreBase, public Counter<CIno
   int get_caps_wanted(int *ploner = 0, int *pother = 0, int shift = 0, int mask = -1) const;
   bool issued_caps_need_gather(SimpleLock *lock);
 
+  // client writeable
+  bool is_clientwriteable() const { return state & STATE_CLIENTWRITEABLE; }
+  void mark_clientwriteable();
+  void clear_clientwriteable();
+
   // -- authority --
   mds_authority_t authority() const override;
 
index bbaf7054d1e2df3048c8a66835fd6d3da0ed0f2e..2a587659afdef348ebc7706e899ceafc2136b4c6 100644 (file)
@@ -2763,6 +2763,12 @@ bool Locker::calc_new_client_ranges(CInode *in, uint64_t size, bool *max_increas
     it = pi->client_ranges.erase(it);
     updated = true;
   }
+  if (updated) {
+    if (pi->client_ranges.empty())
+      in->clear_clientwriteable();
+    else
+      in->mark_clientwriteable();
+  }
   return updated;
 }
 
@@ -3725,7 +3731,7 @@ bool Locker::_do_cap_update(CInode *in, Capability *cap,
   // increase or zero max_size?
   uint64_t size = m->get_size();
   bool change_max = false;
-  uint64_t old_max = latest->client_ranges.count(client) ? latest->client_ranges[client].range.last : 0;
+  uint64_t old_max = latest->get_client_range(client);
   uint64_t new_max = old_max;
   
   if (in->is_file()) {
@@ -3842,10 +3848,13 @@ bool Locker::_do_cap_update(CInode *in, Capability *cap,
       cr.range.first = 0;
       cr.range.last = new_max;
       cr.follows = in->first - 1;
+      in->mark_clientwriteable();
       if (cap)
        cap->mark_clientwriteable();
     } else {
       pi.inode.client_ranges.erase(client);
+      if (pi.inode.client_ranges.empty())
+       in->clear_clientwriteable();
       if (cap)
        cap->clear_clientwriteable();
     }
index 869cde4bf4e2fd6c07936080856949ff7cf5b356..788d7e8c02c1644d015522eca83e8a4281e8be78 100644 (file)
@@ -353,6 +353,8 @@ void MDCache::remove_inode(CInode *o)
 
   o->clear_scatter_dirty();
 
+  o->clear_clientwriteable();
+
   o->item_open_file.remove_myself();
 
   if (o->state_test(CInode::STATE_QUEUEDEXPORTPIN))
@@ -6378,16 +6380,18 @@ void MDCache::identify_files_to_recover()
     }
     
     bool recover = false;
-    for (map<client_t,client_writeable_range_t>::iterator p = in->inode.client_ranges.begin();
-        p != in->inode.client_ranges.end();
-        ++p) {
-      Capability *cap = in->get_client_cap(p->first);
-      if (cap) {
-       cap->mark_clientwriteable();
-      } else {
-       dout(10) << " client." << p->first << " has range " << p->second << " but no cap on " << *in << dendl;
-       recover = true;
-       break;
+    const auto& client_ranges = in->get_projected_inode()->client_ranges;
+    if (!client_ranges.empty()) {
+      in->mark_clientwriteable();
+      for (auto& p : client_ranges) {
+       Capability *cap = in->get_client_cap(p.first);
+       if (cap) {
+         cap->mark_clientwriteable();
+       } else {
+         dout(10) << " client." << p.first << " has range " << p.second << " but no cap on " << *in << dendl;
+         recover = true;
+         break;
+       }
       }
     }
 
index 1efb72d5f11e9065c503778b73b7879ccefa0220..875e6baf38239bc7a89240df8d255670f0c4eec1 100644 (file)
@@ -1726,6 +1726,8 @@ void Migrator::finish_export_inode(CInode *in, mds_rank_t peer,
 
   in->clear_dirty_parent();
 
+  in->clear_clientwriteable();
+
   in->clear_file_locks();
 
   // waiters
@@ -2868,6 +2870,7 @@ void Migrator::import_reverse(CDir *dir)
 
        in->clear_dirty_parent();
 
+       in->clear_clientwriteable();
        in->state_clear(CInode::STATE_NEEDSRECOVER);
 
        in->authlock.clear_gather();
@@ -3228,6 +3231,9 @@ void Migrator::decode_import_inode(CDentry *dn, bufferlist::const_iterator& blp,
 
   if (in->inode.is_dirty_rstat())
     in->mark_dirty_rstat();
+
+  if (!in->get_inode().client_ranges.empty())
+    in->mark_clientwriteable();
   
   // clear if dirtyscattered, since we're going to journal this
   //  but not until we _actually_ finish the import...
index 8c24a195d6be91535b2eef6ec38128e33705167f..e9dfa58c9b26bb631f487447d9e66947f563bcd3 100644 (file)
@@ -4391,6 +4391,7 @@ void Server::handle_client_openc(MDRequestRef& mdr)
     in->inode.client_ranges[client].range.first = 0;
     in->inode.client_ranges[client].range.last = in->inode.layout.stripe_unit;
     in->inode.client_ranges[client].follows = follows;
+    in->mark_clientwriteable();
     cap->mark_clientwriteable();
   }
   
@@ -5055,6 +5056,7 @@ void Server::do_open_truncate(MDRequestRef& mdr, int cmode)
     pi.inode.client_ranges[client].range.last = pi.inode.get_layout_size_increment();
     pi.inode.client_ranges[client].follows = realm->get_newest_seq();
     changed_ranges = true;
+    in->mark_clientwriteable();
     cap->mark_clientwriteable();
   }
   
@@ -6055,6 +6057,7 @@ void Server::handle_client_mknod(MDRequestRef& mdr)
       newi->inode.client_ranges[client].range.first = 0;
       newi->inode.client_ranges[client].range.last = newi->inode.layout.stripe_unit;
       newi->inode.client_ranges[client].follows = follows;
+      newi->mark_clientwriteable();
       cap->mark_clientwriteable();
     }
   }
index a093dd73fb004fe338a976a5ee16ce3eba9b1d7e..6f821c0a1f6e30ca6362ede5984b4590d9dee732 100644 (file)
@@ -185,10 +185,11 @@ void StrayManager::_purge_stray_purged(
     auto &pi = in->project_inode();
     pi.inode.size = 0;
     pi.inode.max_size_ever = 0;
-    pi.inode.client_ranges.clear();
     pi.inode.truncate_size = 0;
     pi.inode.truncate_from = 0;
     pi.inode.version = in->pre_dirty();
+    pi.inode.client_ranges.clear();
+    in->clear_clientwriteable();
 
     le->metablob.add_dir_context(dn->dir);
     le->metablob.add_primary_dentry(dn, in, true);
index cd829b86698f08545bd9c0749ed2caa151ba0882..3f0b05a095284122fa04c9022a1f47a651ac4b2b 100644 (file)
@@ -482,6 +482,11 @@ struct inode_t {
 
   bool is_dirty_rstat() const { return !(rstat == accounted_rstat); }
 
+  uint64_t get_client_range(client_t client) const {
+    auto it = client_ranges.find(client);
+    return it != client_ranges.end() ? it->second.range.last : 0;
+  }
+
   uint64_t get_max_size() const {
     uint64_t max = 0;
       for (std::map<client_t,client_writeable_range_t>::const_iterator p = client_ranges.begin();