From a56953a6b43e9e441a7e84ef3c1117b64f8d84cc Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 27 May 2008 12:39:31 -0700 Subject: [PATCH] mds: make cache track nested anchors --- src/mds/CDentry.cc | 8 ++++++++ src/mds/CDentry.h | 8 +++++--- src/mds/CDir.cc | 18 ++++++++++++++++++ src/mds/CDir.h | 5 +++++ src/mds/CInode.cc | 19 +++++++++++++++++-- src/mds/CInode.h | 8 +++++++- src/mds/MDCache.cc | 22 ++++++++++++++++++++-- 7 files changed, 80 insertions(+), 8 deletions(-) diff --git a/src/mds/CDentry.cc b/src/mds/CDentry.cc index 7be4c032915f9..ab8002af9c7c5 100644 --- a/src/mds/CDentry.cc +++ b/src/mds/CDentry.cc @@ -326,6 +326,14 @@ bool CDentry::is_frozen() } +void CDentry::adjust_nested_anchors(int by) +{ + nested_anchors += by; + dout(20) << "adjust_nested_anchors by " << by << " -> " << nested_anchors << dendl; + assert(nested_anchors >= 0); + dir->adjust_nested_anchors(by); +} + // ---------------------------- // locking diff --git a/src/mds/CDentry.h b/src/mds/CDentry.h index 6805330e1fe51..55f2a49c11723 100644 --- a/src/mds/CDentry.h +++ b/src/mds/CDentry.h @@ -92,6 +92,7 @@ class CDentry : public MDSCacheObject, public LRUObject { off_t dir_offset; int auth_pins, nested_auth_pins; + int nested_anchors; friend class Migrator; friend class Locker; @@ -117,7 +118,7 @@ public: version(0), projected_version(0), xlist_dirty(this), dir_offset(0), - auth_pins(0), nested_auth_pins(0), + auth_pins(0), nested_auth_pins(0), nested_anchors(0), lock(this, CEPH_LOCK_DN, WAIT_LOCK_OFFSET) { } CDentry(const string& n, CInode *in) : name(n), @@ -126,7 +127,7 @@ public: version(0), projected_version(0), xlist_dirty(this), dir_offset(0), - auth_pins(0), nested_auth_pins(0), + auth_pins(0), nested_auth_pins(0), nested_anchors(0), lock(this, CEPH_LOCK_DN, WAIT_LOCK_OFFSET) { } CDentry(const string& n, inodeno_t ino, unsigned char dt, CInode *in=0) : name(n), @@ -135,7 +136,7 @@ public: version(0), projected_version(0), xlist_dirty(this), dir_offset(0), - auth_pins(0), nested_auth_pins(0), + auth_pins(0), nested_auth_pins(0), nested_anchors(0), lock(this, CEPH_LOCK_DN, WAIT_LOCK_OFFSET) { } CInode *get_inode() const { return inode; } @@ -169,6 +170,7 @@ public: void adjust_nested_auth_pins(int by); bool is_frozen(); + void adjust_nested_anchors(int by); // dentry type is primary || remote || null // inode ptr is required for primary, optional for remote, undefined for null diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc index 16b8b9b0ef180..f8f72e8a830b8 100644 --- a/src/mds/CDir.cc +++ b/src/mds/CDir.cc @@ -75,6 +75,8 @@ ostream& operator<<(ostream& out, CDir& dir) if (dir.get_cum_auth_pins()) out << " ap=" << dir.get_auth_pins() << "+" << dir.get_nested_auth_pins(); + if (dir.get_nested_anchors()) + out << " na=" << dir.get_nested_anchors(); out << " state=" << dir.get_state(); if (dir.state_test(CDir::STATE_COMPLETE)) out << "|complete"; @@ -157,6 +159,8 @@ CDir::CDir(CInode *in, frag_t fg, MDCache *mdcache, bool auth) : nested_auth_pins = 0; request_pins = 0; + nested_anchors = 0; + //hack_num_accessed = -1; dir_rep = REP_NONE; @@ -359,6 +363,9 @@ void CDir::link_inode_work( CDentry *dn, CInode *in) // adjust auth pin count if (in->auth_pins + in->nested_auth_pins) dn->adjust_nested_auth_pins(in->auth_pins + in->nested_auth_pins); + + if (in->inode.anchored + in->nested_anchors) + dn->adjust_nested_anchors(in->nested_anchors + in->inode.anchored); } void CDir::unlink_inode( CDentry *dn ) @@ -442,6 +449,9 @@ void CDir::unlink_inode_work( CDentry *dn ) if (in->auth_pins + in->nested_auth_pins) dn->adjust_nested_auth_pins(0 - (in->auth_pins + in->nested_auth_pins)); + if (in->inode.anchored + in->nested_anchors) + dn->adjust_nested_anchors(0 - (in->nested_anchors + in->inode.anchored)); + // detach inode in->remove_primary_parent(dn); dn->inode = 0; @@ -514,6 +524,7 @@ void CDir::steal_dentry(CDentry *dn) } nested_auth_pins += dn->auth_pins + dn->nested_auth_pins; + nested_anchors += dn->nested_anchors; if (dn->is_dirty()) num_dirty++; @@ -1564,6 +1575,13 @@ void CDir::adjust_nested_auth_pins(int inc) inode->adjust_nested_auth_pins(inc); } +void CDir::adjust_nested_anchors(int by) +{ + nested_anchors += by; + dout(20) << "adjust_nested_anchors by " << by << " -> " << nested_anchors << dendl; + assert(nested_anchors >= 0); + inode->adjust_nested_anchors(by); +} /***************************************************************************** diff --git a/src/mds/CDir.h b/src/mds/CDir.h index 386cf50ae4f0a..5e87f83af261d 100644 --- a/src/mds/CDir.h +++ b/src/mds/CDir.h @@ -214,6 +214,8 @@ protected: int nested_auth_pins; int request_pins; + int nested_anchors; + // cache control (defined for authority; hints for replicas) int dir_rep; set dir_rep_by; // if dir_rep == REP_LIST @@ -446,6 +448,9 @@ public: void auth_unpin(); void adjust_nested_auth_pins(int inc); + int get_nested_anchors() { return nested_anchors; } + void adjust_nested_anchors(int by); + // -- freezing -- bool freeze_tree(); void _freeze_tree(); diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 026e164adbb1a..897e6aabc58f3 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -576,7 +576,12 @@ void CInode::decode_lock_state(int type, bufferlist& bl) ::decode(tm, p); if (inode.ctime < tm) inode.ctime = tm; ::decode(inode.nlink, p); - ::decode(inode.anchored, p); + { + bool was_anchored = inode.anchored; + ::decode(inode.anchored, p); + if (was_anchored != inode.anchored) + parent->adjust_nested_anchors((int)inode.anchored - (int)was_anchored); + } break; case CEPH_LOCK_IDFT: @@ -826,7 +831,14 @@ void CInode::adjust_nested_auth_pins(int a) parent->adjust_nested_auth_pins(a); } - +void CInode::adjust_nested_anchors(int by) +{ + nested_anchors += by; + dout(20) << "adjust_nested_anchors by " << by << " -> " << nested_anchors << dendl; + assert(nested_anchors >= 0); + if (parent) + parent->adjust_nested_anchors(by); +} // authority @@ -898,7 +910,10 @@ void CInode::decode_import(bufferlist::iterator& p, LogSegment *ls) { utime_t old_mtime = inode.mtime; + bool was_anchored = inode.anchored; ::decode(inode, p); + if (was_anchored != inode.anchored) + parent->adjust_nested_anchors((int)inode.anchored - (int)was_anchored); if (old_mtime > inode.mtime) { assert(dirlock.is_updated()); inode.mtime = old_mtime; // preserve our mtime, if it is larger diff --git a/src/mds/CInode.h b/src/mds/CInode.h index 0f5673b714db7..cd766104e41de 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -116,7 +116,6 @@ class CInode : public MDSCacheObject { static const int WAIT_DIRLOCK_OFFSET = 4 + 3*SimpleLock::WAIT_BITS; // same static const int WAIT_VERSIONLOCK_OFFSET = 4 + 4*SimpleLock::WAIT_BITS; static const int WAIT_XATTRLOCK_OFFSET = 4 + 5*SimpleLock::WAIT_BITS; - static const int WAIT_NESTEDLOCK_OFFSET = 4 + 6*SimpleLock::WAIT_BITS; static const int WAIT_ANY_MASK = (0xffffffff); @@ -229,6 +228,9 @@ private: public: int auth_pin_freeze_allowance; +private: + int nested_anchors; // _NOT_ including me! + public: inode_load_vec_t pop; @@ -255,6 +257,7 @@ public: xlist_dirty_dirfrag_dir(this), xlist_purging_inode(this), auth_pins(0), nested_auth_pins(0), + nested_anchors(0), versionlock(this, CEPH_LOCK_IVERSION, WAIT_VERSIONLOCK_OFFSET), authlock(this, CEPH_LOCK_IAUTH, WAIT_AUTHLOCK_OFFSET), linklock(this, CEPH_LOCK_ILINK, WAIT_LINKLOCK_OFFSET), @@ -501,6 +504,7 @@ public: void auth_pin(); void auth_unpin(); + void adjust_nested_anchors(int by); // -- freeze -- bool is_freezing_inode() { return state_test(STATE_FREEZING); } @@ -614,6 +618,8 @@ class CInodeDiscover { int get_replica_nonce() { return replica_nonce; } void update_inode(CInode *in) { + if (in->parent && inode.anchored != in->inode.anchored) + in->parent->adjust_nested_anchors((int)inode.anchored - (int)in->inode.anchored); in->inode = inode; in->symlink = symlink; in->dirfragtree = dirfragtree; diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 1826b07fdf122..93899951077f8 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -4777,6 +4777,21 @@ void MDCache::anchor_create(MDRequest *mdr, CInode *in, Context *onfinish) return; } + // rdlock path + set rdlocks = mdr->rdlocks; + set wrlocks = mdr->wrlocks; + set xlocks = mdr->xlocks; + + CDentry *dn = in->get_parent_dn(); + while (dn) { + rdlocks.insert(&dn->lock); + dn = dn->get_dir()->get_inode()->get_parent_dn(); + } + if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks)) { + dout(7) << "anchor_create waiting for locks " << *in << dendl; + return; + } + // wait in->add_waiter(CInode::WAIT_ANCHORED, onfinish); @@ -4851,17 +4866,20 @@ public: void MDCache::_anchor_prepared(CInode *in, version_t atid, bool add) { - dout(10) << "_anchor_create_prepared " << *in << " atid " << atid << dendl; - assert(in->inode.anchored == false); + dout(10) << "_anchor_prepared " << *in << " atid " << atid + << " " << (add ? "create":"destroy") << dendl; + assert(in->inode.anchored == !add); // update the logged inode copy inode_t *pi = in->project_inode(); if (add) { pi->anchored = true; pi->dirstat.ranchors++; + in->parent->adjust_nested_anchors(1); } else { pi->anchored = false; pi->dirstat.ranchors--; + in->parent->adjust_nested_anchors(-1); } pi->version = in->pre_dirty(); -- 2.39.5