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;
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 {
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);
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;
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);
#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)
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;