From: Sage Weil Date: Wed, 22 Sep 2010 22:41:24 +0000 (-0700) Subject: mds: add scatterpins X-Git-Tag: v0.22~129 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=961e186d4752d811760c8364d9fd810eea408927;p=ceph.git mds: add scatterpins --- diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index f8799cf61222..cea9981f38c4 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -152,6 +152,9 @@ ostream& operator<<(ostream& out, CInode& in) out << " need_snapflush=" << in.client_need_snapflush; + if (in.scatter_pins > 0) + out << " scatter_pins=" << in.scatter_pins; + // locks if (!in.authlock.is_sync_and_unlocked()) out << " " << in.authlock; @@ -1511,6 +1514,20 @@ void CInode::finish_scatter_gather_update_accounted(int type, Mutation *mut, EMe } } +void CInode::put_scatter_pin(list& ls) +{ + assert(scatter_pins > 0); + scatter_pins--; + if (scatter_pins == 0) { + dirfragtreelock.take_waiting(SimpleLock::WAIT_ALL, ls); + filelock.take_waiting(SimpleLock::WAIT_ALL, ls); + nestlock.take_waiting(SimpleLock::WAIT_ALL, ls); + ls.push_back(new Locker::C_EvalScatterGathers(mdcache->mds->locker, this)); + } +} + + + // waiting bool CInode::is_frozen() diff --git a/src/mds/CInode.h b/src/mds/CInode.h index cacd9a6a13de..98c36748aa9e 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -400,6 +400,7 @@ private: snaplock(this, &snaplock_type), nestlock(this, &nestlock_type), flocklock(this, &flocklock_type), + scatter_pins(0), loner_cap(-1), want_loner_cap(-1) { g_num_ino++; @@ -584,6 +585,8 @@ public: ScatterLock nestlock; SimpleLock flocklock; + int scatter_pins; + SimpleLock* get_lock(int type) { switch (type) { case CEPH_LOCK_IFILE: return &filelock; @@ -608,6 +611,21 @@ public: void finish_scatter_gather_update(int type); void finish_scatter_gather_update_accounted(int type, Mutation *mut, EMetaBlob *metablob); + // scatter pins prevent either a scatter or unscatter on _any_ + // scatterlock for this inode. + bool is_scatter_pinned() { + return scatter_pins > 0; + } + bool can_scatter_pin() { + return + dirfragtreelock.can_scatter_pin(get_loner()) && + filelock.can_scatter_pin(get_loner()) && + nestlock.can_scatter_pin(get_loner()); + } + void get_scatter_pin() { + scatter_pins++; + } + void put_scatter_pin(list& ls); // -- snap -- void open_snaprealm(bool no_split=false); diff --git a/src/mds/Locker.cc b/src/mds/Locker.cc index 4a7da21e4394..4203aefc50a9 100644 --- a/src/mds/Locker.cc +++ b/src/mds/Locker.cc @@ -452,6 +452,7 @@ void Locker::eval_gather(SimpleLock *lock, bool first, bool *pneed_issue, listget_sm()->states[next].can_wrlock, auth) || !lock->is_wrlocked()) && (IS_TRUE_AND_LT_AUTH(lock->get_sm()->states[next].can_xlock, auth) || !lock->is_xlocked()) && (IS_TRUE_AND_LT_AUTH(lock->get_sm()->states[next].can_lease, auth) || !lock->is_leased()) && + (!in || !in->is_scatter_pinned() || !lock->is_scatterlock()) && (!caps || ((~lock->gcaps_allowed(CAP_ANY, next) & other_issued) == 0 && (~lock->gcaps_allowed(CAP_LONER, next) & loner_issued) == 0 && (~lock->gcaps_allowed(CAP_XLOCKER, next) & xlocker_issued) == 0)) && @@ -705,6 +706,27 @@ void Locker::eval_cap_gather(CInode *in) finish_contexts(finishers); } +void Locker::eval_scatter_gathers(CInode *in) +{ + bool need_issue = false; + list finishers; + + dout(10) << "eval_scatter_gathers " << *in << dendl; + + // kick locks now + if (!in->filelock.is_stable()) + eval_gather(&in->filelock, false, &need_issue, &finishers); + if (!in->nestlock.is_stable()) + eval_gather(&in->nestlock, false, &need_issue, &finishers); + if (!in->dirfragtreelock.is_stable()) + eval_gather(&in->dirfragtreelock, false, &need_issue, &finishers); + + if (need_issue && in->is_head()) + issue_caps(in); + + finish_contexts(finishers); +} + void Locker::eval(SimpleLock *lock, bool *need_issue) { switch (lock->get_type()) { @@ -3125,6 +3147,8 @@ void Locker::scatter_writebehind(ScatterLock *lock) CInode *in = (CInode*)lock->get_parent(); dout(10) << "scatter_writebehind " << in->inode.mtime << " on " << *lock << " on " << *in << dendl; + assert(!in->is_scatter_pinned()); + // journal Mutation *mut = new Mutation; mut->ls = mds->mdlog->get_current_segment(); @@ -3233,6 +3257,15 @@ void Locker::scatter_nudge(ScatterLock *lock, Context *c, bool forcelockchange) { CInode *p = (CInode *)lock->get_parent(); + if (p->is_scatter_pinned()) { + dout(10) << "scatter_nudge waiting for scatter pin release on " << *p << dendl; + if (c) + p->filelock.add_waiter(SimpleLock::WAIT_RD, c); + else + // just requeue. not ideal.. starvation prone.. + updated_scatterlocks.push_back(lock->get_updated_item()); + return; + } if (p->is_frozen() || p->is_freezing()) { dout(10) << "scatter_nudge waiting for unfreeze on " << *p << dendl; if (c) diff --git a/src/mds/Locker.h b/src/mds/Locker.h index 7bf36b358d7f..63a4628ce902 100644 --- a/src/mds/Locker.h +++ b/src/mds/Locker.h @@ -99,6 +99,20 @@ public: eval(lock, need_issue); } + class C_EvalScatterGathers : public Context { + Locker *locker; + CInode *in; + public: + C_EvalScatterGathers(Locker *l, CInode *i) : locker(l), in(i) { + in->get(CInode::PIN_PTRWAITER); + } + void finish(int r) { + in->put(CInode::PIN_PTRWAITER); + locker->eval_scatter_gathers(in); + } + }; + void eval_scatter_gathers(CInode *in); + void eval_cap_gather(CInode *in); bool eval(CInode *in, int mask); diff --git a/src/mds/ScatterLock.h b/src/mds/ScatterLock.h index ea593e41eb99..ad1c0aa96b8a 100644 --- a/src/mds/ScatterLock.h +++ b/src/mds/ScatterLock.h @@ -64,6 +64,10 @@ public: } } + bool is_scatterlock() const { + return true; + } + bool is_sync_and_unlocked() const { return SimpleLock::is_sync_and_unlocked() && @@ -71,6 +75,9 @@ public: !is_flushing(); } + bool can_scatter_pin(client_t loner) { + return can_rdlock(-1) || can_wrlock(loner); + } xlist::item *get_updated_item() { return &more()->item_updated; } utime_t get_update_stamp() { return more()->update_stamp; } diff --git a/src/mds/SimpleLock.h b/src/mds/SimpleLock.h index 2e06b279d733..a5c2390153cb 100644 --- a/src/mds/SimpleLock.h +++ b/src/mds/SimpleLock.h @@ -220,6 +220,10 @@ public: delete _unstable; } + virtual bool is_scatterlock() const { + return false; + } + // parent MDSCacheObject *get_parent() { return parent; } int get_type() { return type->type; }