- snap collections
- garbage collection
+mds
+- migrator import/export of versioned dentries, inodes... drop them on export...
+/- pin/unpin open_past_parents.
+/- call open_parents() where needed.
+ - what about during recovery? e.g. client reconnected caps...
+- resolve/rejoin vs snapshots!
- client reconnect vs snaps
+- mds server ops
+ - link rollback
+ - rename rollback
- hard link backpointers
- anchor source dir
- build snaprealm for any hardlinked file
- include snaps for all (primary+remote) parents
-- migrator import/export of versioned dentries, inodes... drop them on export...
-
-/- pin/unpin open_past_parents.
-- call open_parents() where needed.
-
-- mds server ops
- - link rollback
- - rename rollback
-
userspace client
int32_t n;
::decode(n, p);
-
snapid_t got_newest_seq;
::decode(got_newest_seq, p);
+
+ // purge stale snaps?
+ // * only if we have past_parents open!
+ const set<snapid_t> *snaps = 0;
SnapRealm *realm = inode->find_snaprealm();
- const set<snapid_t>& snaps = realm->get_snaps();
- bool purge_stale = false;
- if (got_newest_seq < realm->get_newest_seq()) {
+ if (!realm->have_past_parents_open()) {
+ dout(10) << " no snap purge, one or more past parents NOT open" << dendl;
+ } else if (got_newest_seq < realm->get_newest_seq()) {
+ snaps = &realm->get_snaps();
dout(10) << " got newest_seq " << got_newest_seq << " < " << realm->get_newest_seq()
- << ", will purge stale entries using snaps " << snaps << dendl;
- purge_stale = true;
+ << ", snap purge based on " << *snaps << dendl;
}
//int num_new_inodes_loaded = 0;
<< dendl;
bool stale = false;
- if (purge_stale && last != CEPH_NOSNAP) {
- set<snapid_t>::const_iterator p = snaps.lower_bound(first);
- if (p == snaps.end() || *p > last) {
+ if (snaps && last != CEPH_NOSNAP) {
+ set<snapid_t>::const_iterator p = snaps->lower_bound(first);
+ if (p == snaps->end() || *p > last) {
dout(10) << " skipping stale dentry on [" << first << "," << last << "]" << dendl;
stale = true;
}
in->xattrs.swap(xattrs);
in->decode_snap_blob(snapbl);
in->old_inodes.swap(old_inodes);
- if (purge_stale)
- in->purge_stale_snap_data(snaps);
+ if (snaps)
+ in->purge_stale_snap_data(*snaps);
// add
cache->add_inode( in );
int32_t n = num_head_items + num_snap_items;
::encode(n, bl);
- const set<snapid_t>& snaps = inode->find_snaprealm()->get_snaps();
- snapid_t newest_seq = inode->find_snaprealm()->get_newest_seq();
+ // snap purge?
+ const set<snapid_t> *snaps = 0;
+ snapid_t newest_seq = 0;
+ SnapRealm *realm = inode->find_snaprealm();
+ if (realm->have_past_parents_open()) {
+ snaps = &realm->get_snaps();
+ newest_seq = realm->get_newest_seq();
+ dout(10) << " snap purge based on " << *snaps << dendl;
+ } else {
+ dout(10) << " no snap purge, one or more past parents NOT open" << dendl;
+ }
::encode(newest_seq, bl);
map_t::iterator p = items.begin();
if (dn->is_null())
continue; // skip negative entries
- if (dn->last != CEPH_NOSNAP) {
- set<snapid_t>::const_iterator p = snaps.lower_bound(dn->first);
- if (p == snaps.end() || *p > dn->last) {
+ if (snaps && dn->last != CEPH_NOSNAP) {
+ set<snapid_t>::const_iterator p = snaps->lower_bound(dn->first);
+ if (p == snaps->end() || *p > dn->last) {
dout(10) << " purging " << *dn << dendl;
remove_dentry(dn);
continue;
in->encode_snap_blob(snapbl);
::encode(snapbl, bl);
- if (in->is_multiversion())
- in->purge_stale_snap_data(snaps);
+ if (in->is_multiversion() && snaps)
+ in->purge_stale_snap_data(*snaps);
::encode(in->old_inodes, bl);
}
}
}
+ // make sure snaprealm parents are open...
+ if (cur->snaprealm && !cur->snaprealm->open && mdr &&
+ !cur->snaprealm->open_parents(mdr))
+ return 1;
+
+
// dentry
CDentry *dn = curdir->lookup(path[depth], snapid);
<< ".cache.snaprealm(" << inode->ino() \
<< " seq " << seq << " " << this << ") "
-bool SnapRealm::open_parents(MDRequest *mdr)
+bool SnapRealm::open_parents(MDRequest *mdr, snapid_t first, snapid_t last)
{
- dout(10) << "open_parents" << dendl;
+ dout(10) << "open_parents [" << first << "," << last << "]" << dendl;
+ if (open)
+ return true;
// make sure my current parents' parents are open...
if (parent) {
- dout(10) << " parent is " << *parent
+ dout(10) << " current parent [" << current_parent_since << ",head] is " << *parent
<< " on " << *parent->inode << dendl;
- if (!parent->open_parents(mdr))
+ if (last >= current_parent_since &&
+ !parent->open_parents(mdr, MAX(first, current_parent_since), last))
return false;
}
// and my past parents too!
- for (map<snapid_t, snaplink_t>::iterator p = past_parents.begin();
+ assert(past_parents.size() >= open_past_parents.size());
+ if (past_parents.size() > open_past_parents.size()) {
+ for (map<snapid_t, snaplink_t>::iterator p = past_parents.begin();
+ p != past_parents.end();
+ p++) {
+ dout(10) << " past_parent [" << p->second.first << "," << p->first << "] is "
+ << p->second.ino << dendl;
+ CInode *parent = mdcache->get_inode(p->second.ino);
+ if (!parent) {
+ mdcache->open_remote_ino(p->second.ino, mdr,
+ new C_MDS_RetryRequest(mdcache, mdr));
+ return false;
+ }
+ assert(parent->snaprealm); // hmm!
+ if (!open_past_parents.count(p->second.ino)) {
+ open_past_parents[p->second.ino] = parent->snaprealm;
+ parent->get(CInode::PIN_PASTSNAPPARENT);
+ }
+ if (!parent->snaprealm->open_parents(mdr, p->second.first, p->first))
+ return false;
+ }
+ }
+
+ open = true;
+ return true;
+}
+
+bool SnapRealm::have_past_parents_open(snapid_t first, snapid_t last)
+{
+ dout(10) << "have_past_parents_open [" << first << "," << last << "]" << dendl;
+ for (map<snapid_t, snaplink_t>::iterator p = past_parents.lower_bound(first);
p != past_parents.end();
- p++) {
- CInode *parent = mdcache->get_inode(p->second.ino);
- if (!parent) {
- mdcache->open_remote_ino(p->second.ino, mdr,
- new C_MDS_RetryRequest(mdcache, mdr));
+ p++) {
+ if (p->second.first > last)
+ break;
+ dout(10) << " past parent [" << p->second.first << "," << p->first << "] was "
+ << p->second.ino << dendl;
+ if (open_past_parents.count(p->second.ino) == 0) {
+ dout(10) << " past parent " << p->second.ino << " is not open" << dendl;
return false;
}
- assert(parent->snaprealm); // hmm!
- if (!open_past_parents.count(p->second.ino)) {
- open_past_parents[p->second.ino] = parent->snaprealm;
- parent->get(CInode::PIN_PASTSNAPPARENT);
- }
+ if (!open_past_parents[p->second.ino]->have_past_parents_open(MAX(first, p->second.first),
+ MIN(last, p->first)))
+ return false;
}
return true;
}
MDCache *mdcache;
CInode *inode;
+ bool open; // set to true once all past_parents are opened
SnapRealm *parent;
set<SnapRealm*> open_children; // active children that are currently open
map<inodeno_t,SnapRealm*> open_past_parents; // these are explicitly pinned.
created(0), last_created(0), seq(0),
current_parent_since(1),
mdcache(c), inode(in),
- parent(0)
+ open(false), parent(0)
{ }
bool exists(const string &name) {
return false;
}
- bool open_parents(MDRequest *mdr);
+ bool open_parents(MDRequest *mdr, snapid_t first=1, snapid_t last=CEPH_NOSNAP);
+ bool have_past_parents_open(snapid_t first=1, snapid_t last=CEPH_NOSNAP);
void close_parents();
void build_snap_set(set<snapid_t>& s,