From 2307cfbc2719d8e22b850393e0695c4079353317 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 25 Jul 2008 15:17:43 -0700 Subject: [PATCH] mds: catrack last_created, clean up caching semantics, use either get_newest_snap() or get_last_create() in callers --- src/mds/CInode.cc | 2 +- src/mds/MDCache.cc | 9 +++---- src/mds/Server.cc | 40 ++++++++++++++++++------------- src/mds/snap.cc | 59 +++++++++++++++++++++++++++++----------------- src/mds/snap.h | 34 +++++++++++++++++++------- 5 files changed, 92 insertions(+), 52 deletions(-) diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 2f2f0d5a7ac17..5c913c107a716 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -1124,7 +1124,7 @@ old_inode_t& CInode::cow_old_inode(snapid_t follows, inode_t *pi) void CInode::pre_cow_old_inode() { - snapid_t follows = find_snaprealm()->get_latest_snap(); + snapid_t follows = find_snaprealm()->get_newest_snap(); if (first <= follows) cow_old_inode(follows, get_projected_inode()); } diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 4838bb4dc18fe..bbe6d16da75cf 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -1046,7 +1046,7 @@ void MDCache::journal_cow_dentry(EMetaBlob *metablob, CDentry *dn, snapid_t foll CInode *in = dn->inode; if (follows == CEPH_NOSNAP || follows == 0) - follows = in->find_snaprealm()->get_latest_snap(); + follows = in->find_snaprealm()->get_newest_snap(); // already cloned? if (follows < in->first) @@ -1066,7 +1066,7 @@ void MDCache::journal_cow_dentry(EMetaBlob *metablob, CDentry *dn, snapid_t foll } } else { if (follows == CEPH_NOSNAP) - follows = dn->dir->inode->find_snaprealm()->get_latest_snap(); + follows = dn->dir->inode->find_snaprealm()->get_newest_snap(); // already cloned? if (follows < dn->first) @@ -1383,7 +1383,7 @@ void MDCache::predirty_journal_parents(Mutation *mut, EMetaBlob *blob, // rstat if (primary_dn) { SnapRealm *prealm = parent->inode->find_snaprealm(); - snapid_t latest = prealm->get_latest_snap(); + snapid_t latest = prealm->get_newest_snap(); snapid_t follows = cfollows; if (follows == CEPH_NOSNAP || follows == 0) @@ -4761,7 +4761,8 @@ int MDCache::path_traverse(MDRequest *mdr, Message *req, // who dout(10) << "traverse: snapdir" << dendl; snapid = CEPH_SNAPDIR; depth++; - assert(psnapdiri); + if (!psnapdiri) + return -EINVAL; *psnapdiri = cur; continue; } diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 28c58136ca3c1..ace8a8cd17978 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -1497,7 +1497,7 @@ CDentry* Server::rdlock_path_xlock_dentry(MDRequest *mdr, bool okexist, bool mus rdlocks.insert(&dn->lock); // existing dn, rdlock wrlocks.insert(&dn->dir->inode->dirlock); // also, wrlock on dir mtime wrlocks.insert(&dn->dir->inode->nestlock); // also, wrlock on dir mtime - mds->locker->include_snap_rdlocks(rdlocks, mdr->ref); + mds->locker->include_snap_rdlocks(rdlocks, dn->dir->inode); if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks)) return 0; @@ -2068,7 +2068,7 @@ void Server::handle_client_mknod(MDRequest *mdr) CDentry *dn = rdlock_path_xlock_dentry(mdr, false, false); if (!dn) return; - snapid_t follows = dn->dir->inode->find_snaprealm()->get_latest_snap(); + snapid_t follows = dn->dir->inode->find_snaprealm()->get_last_created(); mdr->now = g_clock.real_now(); CInode *newi = prepare_new_inode(mdr, dn->dir); @@ -2112,7 +2112,7 @@ void Server::handle_client_mkdir(MDRequest *mdr) if (!dn) return; // new inode - snapid_t follows = dn->dir->inode->find_snaprealm()->get_latest_snap(); + snapid_t follows = dn->dir->inode->find_snaprealm()->get_last_created(); mdr->now = g_clock.real_now(); CInode *newi = prepare_new_inode(mdr, dn->dir); @@ -2160,7 +2160,7 @@ void Server::handle_client_symlink(MDRequest *mdr) if (!dn) return; mdr->now = g_clock.real_now(); - snapid_t follows = dn->dir->inode->find_snaprealm()->get_latest_snap(); + snapid_t follows = dn->dir->inode->find_snaprealm()->get_last_created(); CInode *newi = prepare_new_inode(mdr, dn->dir); assert(newi); @@ -2323,7 +2323,7 @@ void Server::_link_local(MDRequest *mdr, CDentry *dn, CInode *targeti) pi->ctime = mdr->now; pi->version = tipv; - snapid_t follows = dn->dir->inode->find_snaprealm()->get_latest_snap(); + snapid_t follows = dn->dir->inode->find_snaprealm()->get_last_created(); dn->first = follows+1; // log + wait @@ -3663,7 +3663,7 @@ void Server::_rename_prepare(MDRequest *mdr, if (!destdn->is_null()) mdcache->journal_cow_dentry(metablob, destdn); else - destdn->first = destdn->dir->inode->find_snaprealm()->get_latest_snap()+1; + destdn->first = destdn->dir->inode->find_snaprealm()->get_last_created()+1; metablob->add_remote_dentry(destdn, true, srcdn->get_remote_ino(), srcdn->get_remote_d_type()); mdcache->journal_cow_dentry(metablob, srcdn->inode->get_parent_dn()); ji = metablob->add_primary_dentry(srcdn->inode->get_parent_dn(), true, srcdn->inode, pi); @@ -3671,16 +3671,18 @@ void Server::_rename_prepare(MDRequest *mdr, if (!destdn->is_null()) mdcache->journal_cow_dentry(metablob, destdn); else - destdn->first = destdn->dir->inode->find_snaprealm()->get_latest_snap()+1; + destdn->first = destdn->dir->inode->find_snaprealm()->get_last_created()+1; metablob->add_primary_dentry(destdn, true, destdn->inode, pi); } } else if (srcdn->is_primary()) { // project snap parent update? bufferlist snapbl; - if (destdn->is_auth() && srcdn->inode->snaprealm) { + if (!srcdn->inode->snaprealm) + srcdn->inode->open_snaprealm(); + if (destdn->is_auth()) { SnapRealm *realm = srcdn->inode->snaprealm; - snapid_t oldlast = realm->parent->get_latest_snap(); - snapid_t newlast = destdn->dir->inode->find_snaprealm()->get_latest_snap(); + snapid_t oldlast = realm->parent->get_newest_snap(); + snapid_t newlast = destdn->dir->inode->find_snaprealm()->get_last_created(); snapid_t first = realm->current_parent_since; snapid_t old_since = realm->current_parent_since; @@ -3701,7 +3703,7 @@ void Server::_rename_prepare(MDRequest *mdr, if (!destdn->is_null()) mdcache->journal_cow_dentry(metablob, destdn); else - destdn->first = destdn->dir->inode->find_snaprealm()->get_latest_snap()+1; + destdn->first = destdn->dir->inode->find_snaprealm()->get_last_created()+1; ji = metablob->add_primary_dentry(destdn, true, srcdn->inode, pi, 0, &snapbl); } @@ -3808,10 +3810,10 @@ void Server::_rename_apply(MDRequest *mdr, CDentry *srcdn, CDentry *destdn, CDen destdn->inode->pop_and_dirty_projected_inode(mdr->ls); // snap parent update? - if (destdn->is_auth() && destdn->inode->snaprealm) { + if (destdn->inode->is_dir()) { SnapRealm *realm = destdn->inode->snaprealm; - snapid_t oldlast = srcdn->dir->inode->find_snaprealm()->get_latest_snap(); - snapid_t newlast = destdn->dir->inode->find_snaprealm()->get_latest_snap(); + snapid_t oldlast = srcdn->dir->inode->find_snaprealm()->get_newest_snap(); + snapid_t newlast = destdn->dir->inode->find_snaprealm()->get_last_created(); snapid_t first = realm->current_parent_since; if (oldlast >= realm->current_parent_since) { @@ -4768,7 +4770,7 @@ void Server::handle_client_openc(MDRequest *mdr) // create inode. mdr->now = g_clock.real_now(); - snapid_t follows = dn->dir->inode->find_snaprealm()->get_latest_snap(); + snapid_t follows = dn->dir->inode->find_snaprealm()->get_last_created(); CInode *in = prepare_new_inode(mdr, dn->dir); assert(in); @@ -4997,11 +4999,14 @@ void Server::handle_client_mksnap(MDRequest *mdr) // project the snaprealm.. hack! bufferlist snapbl; snapid_t old_seq = diri->snaprealm->seq; + snapid_t old_lc = diri->snaprealm->last_created; diri->snaprealm->snaps[snapid] = info; diri->snaprealm->seq = snapid; + diri->snaprealm->last_created = snapid; diri->encode_snap_blob(snapbl); diri->snaprealm->snaps.erase(snapid); diri->snaprealm->seq = old_seq; + diri->snaprealm->last_created = old_lc; le->metablob.add_primary_dentry(diri->get_projected_parent_dn(), true, 0, pi, 0, &snapbl); mdlog->submit_entry(le, new C_MDS_mksnap_finish(mds, mdr, diri, info)); @@ -5020,6 +5025,7 @@ void Server::_mksnap_finish(MDRequest *mdr, CInode *diri, SnapInfo &info) snapid_t snapid = info.snapid; diri->snaprealm->snaps[snapid] = info; diri->snaprealm->seq = snapid; + diri->snaprealm->last_created = snapid; dout(10) << "snaprealm now " << *diri->snaprealm << dendl; bufferlist snapbl; @@ -5049,8 +5055,10 @@ void Server::_mksnap_finish(MDRequest *mdr, CInode *diri, SnapInfo &info) dout(10) << " " << realm << " open_children are " << realm->open_children << dendl; for (set::iterator p = realm->open_children.begin(); p != realm->open_children.end(); - p++) + p++) { + (*p)->invalidate_cached_snaps(); q.push_back(*p); + } } // send diff --git a/src/mds/snap.cc b/src/mds/snap.cc index 0999b88b72f54..d7f2378884964 100644 --- a/src/mds/snap.cc +++ b/src/mds/snap.cc @@ -57,10 +57,17 @@ bool SnapRealm::open_parents(MDRequest *mdr) * get list of snaps for this realm. we must include parents' snaps * for the intervals during which they were our parent. */ -void SnapRealm::build_snap_set(set &s, snapid_t first, snapid_t last) +void SnapRealm::build_snap_set(set &s, + snapid_t& max_seq, snapid_t& max_last_created, + snapid_t first, snapid_t last) { dout(10) << "build_snap_set [" << first << "," << last << "] on " << *this << dendl; + if (seq > max_seq) + max_seq = seq; + if (last_created > max_last_created) + max_last_created = last_created; + // include my snaps within interval [first,last] for (map::iterator p = snaps.lower_bound(first); // first element >= first p != snaps.end() && p->first <= last; @@ -76,39 +83,47 @@ void SnapRealm::build_snap_set(set &s, snapid_t first, snapid_t last) assert(oldparent->snaprealm); snapid_t thru = MIN(last, p->first); - oldparent->snaprealm->build_snap_set(s, + oldparent->snaprealm->build_snap_set(s, max_seq, max_last_created, MAX(first, p->second.first), thru); } if (current_parent_since <= last && parent) - parent->build_snap_set(s, current_parent_since, last); + parent->build_snap_set(s, max_seq, max_last_created, current_parent_since, last); } /* * build vector in reverse sorted order */ +void SnapRealm::check_cache() +{ + if (cached_seq >= seq) + return; + + cached_snaps.clear(); + cached_snap_vec.clear(); + cached_last_created = last_created; + cached_seq = seq; + build_snap_set(cached_snaps, cached_seq, cached_last_created, 0, CEPH_NOSNAP); + + dout(10) << "check_cache " << cached_snaps + << " seq " << seq + << " cached_seq " << cached_seq + << " cached_last_created " << cached_last_created << ")" + << dendl; +} + const set& SnapRealm::get_snaps() { - if (cached_snaps.empty() || cached_snaps_seq < seq) { - cached_snaps.clear(); - cached_snap_vec.clear(); - build_snap_set(cached_snaps, 0, CEPH_NOSNAP); - - dout(10) << "get_snaps " << cached_snaps - << " (seq " << seq << ")" - << dendl; - } else { - dout(10) << "get_snaps " << cached_snaps - << " (seq " << seq << ")" - << " (cached)" - << dendl; - } + check_cache(); + dout(10) << "get_snaps " << cached_snaps + << " (seq " << seq << " cached_seq " << cached_seq << ")" + << dendl; return cached_snaps; } const vector& SnapRealm::get_snap_vector() { - get_snaps(); + check_cache(); if (cached_snap_vec.empty()) { cached_snap_vec.resize(cached_snaps.size()); @@ -294,21 +309,21 @@ void SnapRealm::build_snap_trace(bufferlist& snapbl) SnapRealmInfo info; info.ino = inode->ino(); info.seq = seq; + info.parent_since = current_parent_since; if (parent) { info.parent = parent->inode->ino(); if (!past_parents.empty()) { snapid_t last = past_parents.rbegin()->first; set past; - build_snap_set(past, 0, last); + snapid_t max_seq, max_last_created; + build_snap_set(past, max_seq, max_last_created, 0, last); info.prior_parent_snaps.reserve(past.size()); for (set::reverse_iterator p = past.rbegin(); p != past.rend(); p++) info.prior_parent_snaps.push_back(*p); - info.parent_since = last+1; dout(10) << "build_snap_trace prior_parent_snaps from [1," << last << "] " << info.prior_parent_snaps << dendl; - } else - info.parent_since = 1; + } } else info.parent = 0; diff --git a/src/mds/snap.h b/src/mds/snap.h index ec116724e2786..5b03358b125a9 100644 --- a/src/mds/snap.h +++ b/src/mds/snap.h @@ -81,13 +81,16 @@ WRITE_CLASS_ENCODER(snaplink_t) struct SnapRealm { // realm state - snapid_t created, seq; + snapid_t created; // when this realm was created. + snapid_t last_created; // last snap created in _this_ realm. + snapid_t seq; // basically, a version/seq # for changes to _this_ realm. snapid_t current_parent_since; map snaps; map past_parents; // key is "last" (or NOSNAP) void encode(bufferlist& bl) const { ::encode(created, bl); + ::encode(last_created, bl); ::encode(seq, bl); ::encode(current_parent_since, bl); ::encode(snaps, bl); @@ -95,6 +98,7 @@ struct SnapRealm { } void decode(bufferlist::iterator& p) { ::decode(created, p); + ::decode(last_created, p); ::decode(seq, p); ::decode(current_parent_since, p); ::decode(snaps, p); @@ -109,8 +113,9 @@ struct SnapRealm { set open_children; // active children that are currently open map open_past_parents; // these are explicitly pinned. - // caches? - snapid_t cached_snaps_seq; + // cache + snapid_t cached_seq; // max seq over self and all past+present parents. + snapid_t cached_last_created; // max last_created over all past+present parents set cached_snaps; vector cached_snap_vec; @@ -118,7 +123,7 @@ struct SnapRealm { map > client_caps; // to identify clients who need snap notifications SnapRealm(MDCache *c, CInode *in) : - created(0), seq(0), + created(0), last_created(0), seq(0), current_parent_since(1), mdcache(c), inode(in), parent(0) @@ -134,7 +139,9 @@ struct SnapRealm { } bool open_parents(MDRequest *mdr); - void build_snap_set(set& s, snapid_t first, snapid_t last); + void build_snap_set(set& s, + snapid_t& max_seq, snapid_t& max_last_created, + snapid_t first, snapid_t last); void get_snap_info(map& infomap, snapid_t first=0, snapid_t last=CEPH_NOSNAP); void build_snap_trace(bufferlist& snapbl); @@ -142,14 +149,22 @@ struct SnapRealm { const string& get_snapname(snapid_t snapid, inodeno_t atino); snapid_t resolve_snapname(const string &name, inodeno_t atino, snapid_t first=0, snapid_t last=CEPH_NOSNAP); + void check_cache(); const set& get_snaps(); const vector& get_snap_vector(); - snapid_t get_latest_snap() { - const set &snaps = get_snaps(); - if (snaps.empty()) + void invalidate_cached_snaps() { + cached_seq = 0; + } + snapid_t get_last_created() { + check_cache(); + return cached_last_created; + } + snapid_t get_newest_snap() { + check_cache(); + if (cached_snaps.empty()) return 0; else - return *snaps.rbegin(); + return *cached_snaps.rbegin(); } void change_open_parent_to(SnapRealm *newp) { @@ -174,6 +189,7 @@ WRITE_CLASS_ENCODER(SnapRealm) inline ostream& operator<<(ostream& out, const SnapRealm &realm) { out << "snaprealm(seq " << realm.seq + << " lc " << realm.last_created << " snaps=" << realm.snaps; if (realm.past_parents.size()) { out << " past_parents=("; -- 2.39.5