From 13a817fa3822c8c9b8af033e27129e125efc1896 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 25 Jul 2008 21:26:45 -0700 Subject: [PATCH] mds: open snaprealm parents during path_traverse. once parents are all open, set a flag --- src/TODO | 18 ++++++------- src/mds/CDir.cc | 48 ++++++++++++++++++++++------------- src/mds/MDCache.cc | 6 +++++ src/mds/snap.cc | 63 +++++++++++++++++++++++++++++++++++----------- src/mds/snap.h | 6 +++-- 5 files changed, 97 insertions(+), 44 deletions(-) diff --git a/src/TODO b/src/TODO index 03139d05b527b..12ab9208fe77b 100644 --- a/src/TODO +++ b/src/TODO @@ -25,22 +25,22 @@ snapshots - 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 diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc index 3c5629decb7af..ec4a15d4c52e4 100644 --- a/src/mds/CDir.cc +++ b/src/mds/CDir.cc @@ -1047,16 +1047,19 @@ void CDir::_fetched(bufferlist &bl) 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 *snaps = 0; SnapRealm *realm = inode->find_snaprealm(); - const set& 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; @@ -1079,9 +1082,9 @@ void CDir::_fetched(bufferlist &bl) << dendl; bool stale = false; - if (purge_stale && last != CEPH_NOSNAP) { - set::const_iterator p = snaps.lower_bound(first); - if (p == snaps.end() || *p > last) { + if (snaps && last != CEPH_NOSNAP) { + set::const_iterator p = snaps->lower_bound(first); + if (p == snaps->end() || *p > last) { dout(10) << " skipping stale dentry on [" << first << "," << last << "]" << dendl; stale = true; } @@ -1178,8 +1181,8 @@ void CDir::_fetched(bufferlist &bl) 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 ); @@ -1358,8 +1361,17 @@ void CDir::_commit(version_t want) int32_t n = num_head_items + num_snap_items; ::encode(n, bl); - const set& snaps = inode->find_snaprealm()->get_snaps(); - snapid_t newest_seq = inode->find_snaprealm()->get_newest_seq(); + // snap purge? + const set *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(); @@ -1370,9 +1382,9 @@ void CDir::_commit(version_t want) if (dn->is_null()) continue; // skip negative entries - if (dn->last != CEPH_NOSNAP) { - set::const_iterator p = snaps.lower_bound(dn->first); - if (p == snaps.end() || *p > dn->last) { + if (snaps && dn->last != CEPH_NOSNAP) { + set::const_iterator p = snaps->lower_bound(dn->first); + if (p == snaps->end() || *p > dn->last) { dout(10) << " purging " << *dn << dendl; remove_dentry(dn); continue; @@ -1420,8 +1432,8 @@ void CDir::_commit(version_t want) 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); } } diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index cd1eb4cdc32fe..8bd428352fe14 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -4837,6 +4837,12 @@ int MDCache::path_traverse(MDRequest *mdr, Message *req, // who } + // 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); diff --git a/src/mds/snap.cc b/src/mds/snap.cc index 50d33ef70c299..79ec9c8ccc3e9 100644 --- a/src/mds/snap.cc +++ b/src/mds/snap.cc @@ -27,33 +27,66 @@ << ".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::iterator p = past_parents.begin(); + assert(past_parents.size() >= open_past_parents.size()); + if (past_parents.size() > open_past_parents.size()) { + for (map::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::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; } diff --git a/src/mds/snap.h b/src/mds/snap.h index 0e1c31821d37e..c29fa93449052 100644 --- a/src/mds/snap.h +++ b/src/mds/snap.h @@ -109,6 +109,7 @@ struct SnapRealm { MDCache *mdcache; CInode *inode; + bool open; // set to true once all past_parents are opened SnapRealm *parent; set open_children; // active children that are currently open map open_past_parents; // these are explicitly pinned. @@ -126,7 +127,7 @@ struct SnapRealm { 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) { @@ -138,7 +139,8 @@ struct SnapRealm { 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& s, -- 2.39.5