]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
client: make Inode to inherit from RefCountedObject 41052/head
authorXiubo Li <xiubli@redhat.com>
Mon, 1 Mar 2021 02:05:05 +0000 (10:05 +0800)
committerXiubo Li <xiubli@redhat.com>
Wed, 28 Apr 2021 02:48:59 +0000 (10:48 +0800)
This is also mainly one preparation for the inode lock feature, the
InodeRef is useful in the case during the client_lock's unlock/lock
gap, to make sure the Inode is not released.

Fixes: https://tracker.ceph.com/issues/49536
Signed-off-by: Xiubo Li <xiubli@redhat.com>
src/client/Client.cc
src/client/Client.h
src/client/Inode.cc
src/client/Inode.h

index a94876881abda1f2aa04e1f55328f0c39d471066..8132a0d15875056ae7be8a11d6779104fd9b9a15 100644 (file)
@@ -391,13 +391,7 @@ void Client::tear_down_cache()
   // close root ino
   ceph_assert(inode_map.size() <= 1 + root_parents.size());
   if (root && inode_map.size() == 1 + root_parents.size()) {
-    delete root;
-    root = 0;
-    root_ancestor = 0;
-    while (!root_parents.empty())
-      root_parents.erase(root_parents.begin());
-    inode_map.clear();
-    _reset_faked_inos();
+    root.reset();
   }
 
   ceph_assert(inode_map.empty());
@@ -416,7 +410,7 @@ Inode *Client::get_root()
 {
   std::scoped_lock l(client_lock);
   root->ll_get();
-  return root;
+  return root.get();
 }
 
 
@@ -430,7 +424,7 @@ void Client::dump_inode(Formatter *f, Inode *in, set<Inode*>& did, bool disconne
                << (disconnected ? "DISCONNECTED ":"")
                << "inode " << in->ino
                << " " << path
-               << " ref " << in->get_num_ref()
+               << " ref " << in->get_nref()
                << " " << *in << dendl;
 
   if (f) {
@@ -470,7 +464,7 @@ void Client::dump_cache(Formatter *f)
     f->open_array_section("cache");
 
   if (root)
-    dump_inode(f, root, did, true);
+    dump_inode(f, root.get(), did, true);
 
   // make a second pass to catch anything disconnected
   for (ceph::unordered_map<vinodeno_t, Inode*>::iterator it = inode_map.begin();
@@ -705,15 +699,9 @@ void Client::trim_cache(bool trim_kernel_dcache)
     _invalidate_kernel_dcache();
 
   // hose root?
-  if (lru.lru_get_size() == 0 && root && root->get_num_ref() == 0 && inode_map.size() == 1 + root_parents.size()) {
+  if (lru.lru_get_size() == 0 && root && root->get_nref() == 1 && inode_map.size() == 1 + root_parents.size()) {
     ldout(cct, 15) << "trim_cache trimmed root " << root << dendl;
-    delete root;
-    root = 0;
-    root_ancestor = 0;
-    while (!root_parents.empty())
-      root_parents.erase(root_parents.begin());
-    inode_map.clear();
-    _reset_faked_inos();
+    root.reset();
   }
 }
 
@@ -892,7 +880,7 @@ Inode * Client::add_update_inode(InodeStat *st, utime_t from,
     if (!root) {
       root = in;
       if (use_faked_inos())
-        _assign_faked_root(root);
+        _assign_faked_root(root.get());
       root_ancestor = in;
       cwd = root;
     } else if (is_mounting()) {
@@ -3168,8 +3156,11 @@ void Client::_put_inode(Inode *in, int n)
 {
   ldout(cct, 10) << __func__ << " on " << *in << " n = " << n << dendl;
 
-  int left = in->_put(n);
-  if (left == 0) {
+  int left = in->get_nref();
+  ceph_assert(left >= n + 1);
+  in->iput(n);
+  left -= n;
+  if (left == 1) { // the last one will be held by the inode_map
     // release any caps
     remove_all_caps(in);
 
@@ -3180,14 +3171,13 @@ void Client::_put_inode(Inode *in, int n)
     if (use_faked_inos())
       _release_faked_ino(in);
 
-    if (in == root) {
-      root = 0;
+    if (root == nullptr) {
       root_ancestor = 0;
       while (!root_parents.empty())
         root_parents.erase(root_parents.begin());
     }
 
-    delete in;
+    in->iput();
   }
 }
 
@@ -3338,12 +3328,12 @@ void Client::get_cap_ref(Inode *in, int cap)
   if ((cap & CEPH_CAP_FILE_BUFFER) &&
       in->cap_refs[CEPH_CAP_FILE_BUFFER] == 0) {
     ldout(cct, 5) << __func__ << " got first FILE_BUFFER ref on " << *in << dendl;
-    in->get();
+    in->iget();
   }
   if ((cap & CEPH_CAP_FILE_CACHE) &&
       in->cap_refs[CEPH_CAP_FILE_CACHE] == 0) {
     ldout(cct, 5) << __func__ << " got first FILE_CACHE ref on " << *in << dendl;
-    in->get();
+    in->iget();
   }
   in->get_cap_ref(cap);
 }
@@ -5386,7 +5376,7 @@ void Client::_schedule_invalidate_dentry_callback(Dentry *dn, bool del)
 
 void Client::_try_to_trim_inode(Inode *in, bool sched_inval)
 {
-  int ref = in->get_num_ref();
+  int ref = in->get_nref();
   ldout(cct, 5) << __func__ << " in " << *in <<dendl;
 
   if (in->dir && !in->dir->dentries.empty()) {
@@ -5410,13 +5400,13 @@ void Client::_try_to_trim_inode(Inode *in, bool sched_inval)
     }
   }
 
-  if (ref > 0 && (in->flags & I_SNAPDIR_OPEN)) {
+  if (ref > 1 && (in->flags & I_SNAPDIR_OPEN)) {
     InodeRef snapdir = open_snapdir(in);
     _try_to_trim_inode(snapdir.get(), false);
     --ref;
   }
 
-  if (ref > 0) {
+  if (ref > 1) {
     auto q = in->dentries.begin();
     while (q != in->dentries.end()) {
       Dentry *dn = *q;
@@ -6224,7 +6214,7 @@ int Client::mount(const std::string &mount_root, const UserPerm& perms,
   }
 
   ceph_assert(root);
-  _ll_get(root);
+  _ll_get(root.get());
 
   // trace?
   if (!cct->_conf->client_trace.empty()) {
@@ -6385,6 +6375,7 @@ void Client::_unmount(bool abort)
   });
 
   cwd.reset();
+  root.reset();
 
   // clean up any unclosed files
   while (!fd_map.empty()) {
@@ -10551,7 +10542,7 @@ void Client::_getcwd(string& dir, const UserPerm& perms)
   ldout(cct, 10) << __func__ << " " << *cwd << dendl;
 
   Inode *in = cwd.get();
-  while (in != root) {
+  while (in != root.get()) {
     ceph_assert(in->dentries.size() < 2); // dirs can't be hard-linked
 
     // A cwd or ancester is unlinked
@@ -10654,7 +10645,7 @@ int Client::statfs(const char *path, struct statvfs *stbuf,
   // quota but we can see a parent of it that does have a quota, we'll
   // respect that one instead.
   ceph_assert(root != nullptr);
-  Inode *quota_root = root->quota.is_enable() ? root : get_quota_root(root, perms);
+  InodeRef quota_root = root->quota.is_enable() ? root : get_quota_root(root.get(), perms);
 
   // get_quota_root should always give us something
   // because client quotas are always enabled
@@ -11527,7 +11518,7 @@ int Client::ll_walk(const char* name, Inode **out, struct ceph_statx *stx,
 void Client::_ll_get(Inode *in)
 {
   if (in->ll_ref == 0) {
-    in->get();
+    in->iget();
     if (in->is_dir() && !in->dentries.empty()) {
       ceph_assert(in->dentries.size() == 1); // dirs can't be hard-linked
       in->get_first_parent()->get(); // pin dentry
@@ -15364,7 +15355,7 @@ void Client::handle_conf_change(const ConfigProxy& conf,
 
 void intrusive_ptr_add_ref(Inode *in)
 {
-  in->get();
+  in->iget();
 }
 
 void intrusive_ptr_release(Inode *in)
index 011ff1ad07b9a3bcbb638c1cc80c59f2b5fc48c4..629a3c863589ecd95c6537c3ecc06fdbea9934e1 100644 (file)
@@ -1056,7 +1056,7 @@ protected:
 
   std::map<snapid_t, int> ll_snap_ref;
 
-  Inode*                 root = nullptr;
+  InodeRef               root = nullptr;
   map<Inode*, InodeRef>  root_parents;
   Inode*                 root_ancestor = nullptr;
   LRU                    lru;    // lru list of Dentry's in our local metadata cache.
index 69ca873d276572fea494fc6b97cf903bfc20623b..5762759d00a473d41b654cd061baf65ba242ba4a 100644 (file)
@@ -40,7 +40,7 @@ ostream& operator<<(ostream &out, const Inode &in)
 {
   out << in.vino() << "("
       << "faked_ino=" << in.faked_ino
-      << " ref=" << in._ref
+      << " nref=" << in.get_nref()
       << " ll_ref=" << in.ll_ref
       << " cap_refs=" << in.cap_refs
       << " open=" << in.open_by_mode
@@ -379,7 +379,7 @@ Dir *Inode::open_dir()
     ceph_assert(dentries.size() < 2); // dirs can't be hard-linked
     if (!dentries.empty())
       get_first_parent()->get();      // pin dentry
-    get();                  // pin inode
+    iget();                  // pin inode
   }
   return dir;
 }
@@ -397,22 +397,6 @@ bool Inode::check_mode(const UserPerm& perms, unsigned want)
   return (mode & want) == want;
 }
 
-void Inode::get() {
-  _ref++;
-  lsubdout(client->cct, client, 15) << "inode.get on " << this << " " <<  ino << '.' << snapid
-                                   << " now " << _ref << dendl;
-}
-
-//private method to put a reference; see Client::put_inode()
-int Inode::_put(int n) {
-  _ref -= n;
-  lsubdout(client->cct, client, 15) << "inode.put on " << this << " " << ino << '.' << snapid
-                                   << " now " << _ref << dendl;
-  ceph_assert(_ref >= 0);
-  return _ref;
-}
-
-
 void Inode::dump(Formatter *f) const
 {
   f->dump_stream("ino") << ino;
@@ -558,7 +542,7 @@ void Inode::dump(Formatter *f) const
   if (requested_max_size != max_size)
     f->dump_unsigned("requested_max_size", requested_max_size);
 
-  f->dump_int("ref", _ref);
+  f->dump_int("nref", get_nref());
   f->dump_int("ll_ref", ll_ref);
 
   if (!dentries.empty()) {
@@ -790,7 +774,7 @@ void Inode::mark_caps_dirty(int caps)
   lsubdout(client->cct, client, 10) << __func__ << " " << *this << " " << ccap_string(dirty_caps) << " -> "
            << ccap_string(dirty_caps | caps) << dendl;
   if (caps && !caps_dirty())
-    get();
+    iget();
   dirty_caps |= caps;
   client->get_dirty_list().push_back(&dirty_cap_item);
 }
index 22930eb8b9a3e7bad2231c90477b96e09f37bc8f..4144cfa25c9d5d9e5d77d60dbee545737af34596 100644 (file)
@@ -114,7 +114,7 @@ struct CapSnap {
 #define I_CAP_DROPPED          (1 << 4)
 #define I_ERROR_FILELOCK       (1 << 5)
 
-struct Inode {
+struct Inode : RefCountedObject {
   Client *client;
 
   // -- the actual inode --
@@ -229,7 +229,6 @@ struct Inode {
   uint64_t wanted_max_size = 0;
   uint64_t requested_max_size = 0;
 
-  int       _ref = 0;      // ref count. 1 for each dentry, fh that links to me.
   uint64_t  ll_ref = 0;   // separate ref count for ll client
   xlist<Dentry *> dentries; // if i'm linked to a dentry.
   string    symlink;  // symlink content, if it's a symlink
@@ -250,12 +249,10 @@ struct Inode {
   void make_short_path(filepath& p);
   void make_nosnap_relative_path(filepath& p);
 
-  void get();
-  int _put(int n=1);
-
-  int get_num_ref() {
-    return _ref;
-  }
+  // The ref count. 1 for each dentry, fh, inode_map,
+  // cwd that links to me.
+  void iget() { get(); }
+  void iput(int n=1) { ceph_assert(n >= 0); while (n--) put(); }
 
   void ll_get() {
     ll_ref++;