]> 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>
Tue, 25 Aug 2020 00:39:55 +0000 (08:39 +0800)
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
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 5fa858b6af7926deca3e9b2c1d3a42130b1126df..02213a701739e0cfdc016293674ae38e8cc49872 100644 (file)
@@ -3364,17 +3364,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)
 {
@@ -3656,6 +3645,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);
+  }
+}
 
 // =============================================
 
@@ -3771,23 +3792,9 @@ int CInode::encode_inodestat(bufferlist& bl, Session *session,
   }
 
   // max_size is min of projected, actual
-  uint64_t max_size;
-  {
-    auto it = oi->client_ranges.find(client);
-    if (it == oi->client_ranges.end()) {
-      max_size = 0;
-    } else {
-      max_size = it->second.range.last;
-      if (oi != pi) {
-       it = pi->client_ranges.find(client);
-       if (it == pi->client_ranges.end()) {
-         max_size = 0;
-       } else {
-         max_size = std::min(max_size, it->second.range.last);
-       }
-      }
-    }
-  }
+  uint64_t max_size =
+    std::min(oi->get_client_range(client),
+            pi->get_client_range(client));
 
   // inline data
   version_t inline_version = 0;
@@ -4139,24 +4146,9 @@ void CInode::encode_cap_message(const ref_t<MClientCaps> &m, Capability *cap)
   }
 
   // max_size is min of projected, actual.
-  {
-    uint64_t max_size;
-    auto it = oi->client_ranges.find(client);
-    if (it == oi->client_ranges.end()) {
-      max_size = 0;
-    } else {
-      max_size = it->second.range.last;
-      if (oi != pi) {
-       it = pi->client_ranges.find(client);
-       if (it == pi->client_ranges.end()) {
-         max_size = 0;
-       } else {
-         max_size = std::min(max_size, it->second.range.last);
-       }
-      }
-    }
-    m->max_size = max_size;
-  }
+  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;
   m->head.mode = i->mode;
index 781bcf7f72606fe42c617f36b29a3220de75ff56..600307b5724d565f63361748d2f3f7f96f2d4c68 100644 (file)
@@ -358,6 +358,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;
 
@@ -932,6 +934,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 dc41004a67d23eb6820ae03c63a7cc96fb28d8c9..47dd38bad3cc6d1d7a9d93b6245b81f5b2a5777a 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;
 }
 
@@ -3733,11 +3739,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;
-  {
-    auto it = latest->client_ranges.find(client);
-    old_max = it != latest->client_ranges.end() ? it->second.range.last: 0;
-  }
+  uint64_t old_max = latest->get_client_range(client);
   uint64_t new_max = old_max;
   
   if (in->is_file()) {
@@ -3854,10 +3856,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 f88337562270cf3dc859b8cd638b6f31c7880dfd..920e141f9a4607df7cd70989a049016fe2cd8e32 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))
@@ -6399,14 +6401,18 @@ void MDCache::identify_files_to_recover()
     }
     
     bool recover = false;
-    for (auto& p : in->get_inode()->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;
+    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 6703cba1b187b6a3a2080196e242b79901b56cb7..9a6d90bf9bdf6a32c8a8e150b6da85fbe0069368 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->get_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 4eb759afd0f0aee132a53f95fdca9aeee674ee62..7c5d7db52d5aed44d5b438011e310b1a829814df 100644 (file)
@@ -4395,6 +4395,7 @@ void Server::handle_client_openc(MDRequestRef& mdr)
     _inode->client_ranges[client].range.first = 0;
     _inode->client_ranges[client].range.last = _inode->layout.stripe_unit;
     _inode->client_ranges[client].follows = follows;
+    newi->mark_clientwriteable();
     cap->mark_clientwriteable();
   }
   
@@ -5058,6 +5059,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();
   }
   
@@ -6030,6 +6032,7 @@ void Server::handle_client_mknod(MDRequestRef& mdr)
       _inode->client_ranges[client].range.first = 0;
       _inode->client_ranges[client].range.last = _inode->layout.stripe_unit;
       _inode->client_ranges[client].follows = follows;
+      newi->mark_clientwriteable();
       cap->mark_clientwriteable();
     }
   }
index ee2a99e30635a525210d342506b569ac7e9f3610..2ff639e18d22d96a6969ee26d27032242fe5bb15 100644 (file)
@@ -188,6 +188,8 @@ void StrayManager::_purge_stray_purged(
     pi.inode->truncate_size = 0;
     pi.inode->truncate_from = 0;
     pi.inode->version = in->pre_dirty();
+    pi.inode->client_ranges.clear();
+    in->clear_clientwriteable();
 
     CDir *dir = dn->get_dir();
     auto pf = dir->project_fnode(mut);
index 78d8405ac9d4390bea7359e78950faf8c32c4e44..de38ef79de85901696f2c882706e09447208dddc 100644 (file)
@@ -494,6 +494,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();