]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
client: re-use free snap tag 20336/head
authorYan, Zheng <zyan@redhat.com>
Tue, 6 Feb 2018 11:14:08 +0000 (19:14 +0800)
committerYan, Zheng <zyan@redhat.com>
Tue, 6 Feb 2018 11:26:42 +0000 (19:26 +0800)
Fixes: https://tracker.ceph.com/issues/22829
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
src/client/Client.cc
src/client/Client.h
src/client/fuse_ll.cc

index 4265fa79b604e6a3b01592023458a96dbd1f9a23..0cc8bb7b07d06ec0c22bf39808abaa3770bd1eb6 100644 (file)
@@ -10342,6 +10342,8 @@ void Client::_ll_get(Inode *in)
       assert(in->dentries.size() == 1); // dirs can't be hard-linked
       in->get_first_parent()->get(); // pin dentry
     }
+    if (in->snapid != CEPH_NOSNAP)
+      ll_snap_ref[in->snapid]++;
   }
   in->ll_get();
   ldout(cct, 20) << __func__ << " " << in << " " << in->ino << " -> " << in->ll_ref << dendl;
@@ -10356,6 +10358,13 @@ int Client::_ll_put(Inode *in, int num)
       assert(in->dentries.size() == 1); // dirs can't be hard-linked
       in->get_first_parent()->put(); // unpin dentry
     }
+    if (in->snapid != CEPH_NOSNAP) {
+      auto p = ll_snap_ref.find(in->snapid);
+      assert(p != ll_snap_ref.end());
+      assert(p->second > 0);
+      if (--p->second == 0)
+       ll_snap_ref.erase(p);
+    }
     put_inode(in);
     return 0;
   } else {
@@ -10414,6 +10423,15 @@ bool Client::ll_put(Inode *in)
   return ll_forget(in, 1);
 }
 
+int Client::ll_get_snap_ref(snapid_t snap)
+{
+  Mutex::Locker lock(client_lock);
+  auto p = ll_snap_ref.find(snap);
+  if (p != ll_snap_ref.end())
+    return p->second;
+  return 0;
+}
+
 snapid_t Client::ll_get_snapid(Inode *in)
 {
   Mutex::Locker lock(client_lock);
index 2f1f66a1184cd0b4b69bf4ca430ad23809967fbe..cd0506ee4c4663dc5b829242529ac455682c3c94 100644 (file)
@@ -423,6 +423,8 @@ protected:
   void _reset_faked_inos();
   vinodeno_t _map_faked_ino(ino_t ino);
 
+  std::map<snapid_t, int> ll_snap_ref;
+
   Inode*                 root;
   map<Inode*, InodeRef>  root_parents;
   Inode*                 root_ancestor;
@@ -1146,6 +1148,8 @@ public:
                        const UserPerm& perms);
   bool ll_forget(Inode *in, int count);
   bool ll_put(Inode *in);
+  int ll_get_snap_ref(snapid_t snap);
+
   int ll_getattr(Inode *in, struct stat *st, const UserPerm& perms);
   int ll_getattrx(Inode *in, struct ceph_statx *stx, unsigned int want,
                  unsigned int flags, const UserPerm& perms);
index 127e0ea9cee8461ca9fade277c144cea3cf412ef..947c8a4bca9bf2fa94cd66a8b68f4d83cfa42147 100644 (file)
@@ -43,7 +43,8 @@
 
 #define FINO_INO(x) ((x) & ((1ull<<48)-1ull))
 #define FINO_STAG(x) ((x) >> 48)
-#define MAKE_FINO(i,s) ((i) | ((s) << 48))
+#define MAKE_FINO(i,s) ((i) | ((int64_t)(s) << 48))
+#define STAG_MASK 0xffff
 
 #define MINORBITS      20
 #define MINORMASK      ((1U << MINORBITS) - 1)
@@ -1225,13 +1226,35 @@ uint64_t CephFuse::Handle::make_fake_ino(inodeno_t ino, snapid_t snapid)
       return FUSE_ROOT_ID;
 
     Mutex::Locker l(stag_lock);
-    uint64_t stag;
-    if (snap_stag_map.count(snapid) == 0) {
-      stag = ++last_stag;
-      snap_stag_map[snapid] = stag;
-      stag_snap_map[stag] = snapid;
-    } else
-      stag = snap_stag_map[snapid];
+    auto p = snap_stag_map.find(snapid);
+    if (p != snap_stag_map.end()) {
+      inodeno_t fino = MAKE_FINO(ino, p->second);
+      return fino;
+    }
+
+    int first = last_stag & STAG_MASK;
+    int stag =  (++last_stag) & STAG_MASK;
+    for (; stag != first; stag = (++last_stag) & STAG_MASK) {
+      if (stag == 0)
+       continue;
+
+      auto p = stag_snap_map.find(stag);
+      if (p == stag_snap_map.end()) {
+       snap_stag_map[snapid] = stag;
+       stag_snap_map[stag] = snapid;
+       break;
+      }
+
+      if (!client->ll_get_snap_ref(p->second)) {
+       snap_stag_map.erase(p->second);
+       snap_stag_map[snapid] = stag;
+       p->second = snapid;
+       break;
+      }
+    }
+    if (stag == first)
+      assert(0 == "run out of stag");
+
     inodeno_t fino = MAKE_FINO(ino, stag);
     //cout << "make_fake_ino " << ino << "." << snapid << " -> " << fino << std::endl;
     return fino;