return dir->can_auth_pin();
}
-void CDentry::auth_pin()
+void CDentry::auth_pin(void *by)
{
if (auth_pins == 0)
get(PIN_AUTHPIN);
auth_pins++;
- dout(10) << "auth_pin on " << *this
+#ifdef MDS_AUTHPIN_SET
+ auth_pin_set.insert(by);
+#endif
+
+ dout(10) << "auth_pin by " << by << " on " << *this
<< " now " << auth_pins << "+" << nested_auth_pins
<< dendl;
dir->adjust_nested_auth_pins(1, 1);
}
-void CDentry::auth_unpin()
+void CDentry::auth_unpin(void *by)
{
auth_pins--;
+
+#ifdef MDS_AUTHPIN_SET
+ assert(auth_pin_set.count(by));
+ auth_pin_set.erase(auth_pin_set.find(by));
+#endif
+
if (auth_pins == 0)
put(PIN_AUTHPIN);
- dout(10) << "auth_unpin on " << *this
+ dout(10) << "auth_unpin by " << by << " on " << *this
<< " now " << auth_pins << "+" << nested_auth_pins
<< dendl;
assert(auth_pins >= 0);
off_t dir_offset;
int auth_pins, nested_auth_pins;
+#ifdef MDS_AUTHPIN_SET
+ multiset<void*> auth_pin_set;
+#endif
int nested_anchors;
friend class Migrator;
// auth pins
bool can_auth_pin();
- void auth_pin();
- void auth_unpin();
+ void auth_pin(void *by);
+ void auth_unpin(void *by);
void adjust_nested_auth_pins(int by, int dirby);
bool is_frozen();
return;
}
- auth_pin();
+ auth_pin(this);
state_set(CDir::STATE_FETCHING);
if (cache->mds->logger) cache->mds->logger->inc("dir_f");
// mark complete, !fetching
state_set(STATE_COMPLETE);
state_clear(STATE_FETCHING);
- auth_unpin();
+ auth_unpin(this);
// kick waiters
finish_waiting(WAIT_COMPLETE, 0);
// auth_pin on first waiter
if (waiting_for_commit.empty())
- auth_pin();
+ auth_pin(this);
waiting_for_commit[want].push_back(c);
// ok.
// unpin if we kicked the last waiter.
if (were_waiters &&
waiting_for_commit.empty())
- auth_unpin();
+ auth_unpin(this);
}
// unpin parent of frozen dir/tree?
if (inode->is_auth() && (is_frozen_tree_root() || is_frozen_dir()))
- inode->auth_unpin();
+ inode->auth_unpin(this);
}
if (was_subtree && !is_subtree_root()) {
dout(10) << " old subtree root, adjusting auth_pins" << dendl;
// pin parent of frozen dir/tree?
if (inode->is_auth() && (is_frozen_tree_root() || is_frozen_dir()))
- inode->auth_pin();
+ inode->auth_pin(this);
}
// newly single auth?
*
*/
-void CDir::auth_pin()
+void CDir::auth_pin(void *by)
{
if (auth_pins == 0)
get(PIN_AUTHPIN);
auth_pins++;
- dout(10) << "auth_pin on " << *this << " count now " << auth_pins << " + " << nested_auth_pins << dendl;
+#ifdef MDS_AUTHPIN_SET
+ auth_pin_set.insert(by);
+#endif
+
+ dout(10) << "auth_pin by " << by
+ << " on " << *this
+ << " count now " << auth_pins << " + " << nested_auth_pins << dendl;
// nest pins?
if (is_subtree_root()) return; // no.
inode->adjust_nested_auth_pins(1);
}
-void CDir::auth_unpin()
+void CDir::auth_unpin(void *by)
{
auth_pins--;
+
+#ifdef MDS_AUTHPIN_SET
+ assert(auth_pin_set.count(by));
+ auth_pin_set.erase(auth_pin_set.find(by));
+#endif
if (auth_pins == 0)
put(PIN_AUTHPIN);
- dout(10) << "auth_unpin on " << *this << " count now " << auth_pins << " + " << nested_auth_pins << dendl;
+ dout(10) << "auth_unpin by " << by
+ << " on " << *this
+ << " count now " << auth_pins << " + " << nested_auth_pins << dendl;
assert(auth_pins >= 0);
maybe_finish_freeze(); // pending freeze?
assert(!is_frozen());
assert(!is_freezing());
- auth_pin();
+ auth_pin(this);
if (is_freezeable(true)) {
_freeze_tree();
- auth_unpin();
+ auth_unpin(this);
return true;
} else {
state_set(STATE_FREEZINGTREE);
// auth_pin inode for duration of freeze, if we are not a subtree root.
if (is_auth() && !is_subtree_root())
- inode->auth_pin();
+ inode->auth_pin(this);
}
void CDir::unfreeze_tree()
// unpin (may => FREEZEABLE) FIXME: is this order good?
if (is_auth() && !is_subtree_root())
- inode->auth_unpin();
+ inode->auth_unpin(this);
// waiters?
finish_waiting(WAIT_UNFREEZE);
// freezing. stop it.
assert(state_test(STATE_FREEZINGTREE));
state_clear(STATE_FREEZINGTREE);
- auth_unpin();
+ auth_unpin(this);
finish_waiting(WAIT_UNFREEZE);
}
assert(!is_frozen());
assert(!is_freezing());
- auth_pin();
+ auth_pin(this);
if (is_freezeable_dir(true)) {
_freeze_dir();
- auth_unpin();
+ auth_unpin(this);
return true;
} else {
state_set(STATE_FREEZINGDIR);
get(PIN_FROZEN);
if (is_auth() && !is_subtree_root())
- inode->auth_pin(); // auth_pin for duration of freeze
+ inode->auth_pin(this); // auth_pin for duration of freeze
}
// unpin (may => FREEZEABLE) FIXME: is this order good?
if (is_auth() && !is_subtree_root())
- inode->auth_unpin();
+ inode->auth_unpin(this);
finish_waiting(WAIT_UNFREEZE);
} else {
// still freezing. stop.
assert(state_test(STATE_FREEZINGDIR));
state_clear(STATE_FREEZINGDIR);
- auth_unpin();
+ auth_unpin(this);
finish_waiting(WAIT_UNFREEZE);
}
// lock nesting, freeze
int auth_pins;
+#ifdef MDS_AUTHPIN_SET
+ multiset<void*> auth_pin_set;
+#endif
int nested_auth_pins, dir_auth_pins;
int request_pins;
int get_auth_pins() { return auth_pins; }
int get_nested_auth_pins() { return nested_auth_pins; }
int get_dir_auth_pins() { return dir_auth_pins; }
- void auth_pin();
- void auth_unpin();
+ void auth_pin(void *who);
+ void auth_unpin(void *who);
void adjust_nested_auth_pins(int inc, int dirinc);
void verify_fragstat();
// we can freeze the _dir_ even with nested pins...
if (state_test(STATE_FREEZINGDIR)) {
_freeze_dir();
- auth_unpin();
+ auth_unpin(this);
finish_waiting(WAIT_FROZEN);
}
if (nested_auth_pins != 0)
return;
if (state_test(STATE_FREEZINGTREE)) {
_freeze_tree();
- auth_unpin();
+ auth_unpin(this);
finish_waiting(WAIT_FROZEN);
}
}
out << " v" << in.get_version();
- if (in.is_auth_pinned())
+ if (in.is_auth_pinned()) {
out << " ap=" << in.get_num_auth_pins();
+#ifdef MDS_AUTHPIN_SET
+ out << "(" << in.auth_pin_set << ")";
+#endif
+ }
if (in.state_test(CInode::STATE_AMBIGUOUSAUTH)) out << " AMBIGAUTH";
if (in.state_test(CInode::STATE_NEEDSRECOVER)) out << " needsrecover";
return true;
}
-void CInode::auth_pin()
+void CInode::auth_pin(void *by)
{
if (auth_pins == 0)
get(PIN_AUTHPIN);
auth_pins++;
- dout(10) << "auth_pin on " << *this
+#ifdef MDS_AUTHPIN_SET
+ auth_pin_set.insert(by);
+#endif
+
+ dout(10) << "auth_pin by " << by << " on " << *this
<< " now " << auth_pins << "+" << nested_auth_pins
<< dendl;
parent->adjust_nested_auth_pins(1, 1);
}
-void CInode::auth_unpin()
+void CInode::auth_unpin(void *by)
{
auth_pins--;
+
+#ifdef MDS_AUTHPIN_SET
+ assert(auth_pin_set.count(by));
+ auth_pin_set.erase(auth_pin_set.find(by));
+#endif
+
if (auth_pins == 0)
put(PIN_AUTHPIN);
- dout(10) << "auth_unpin on " << *this
+ dout(10) << "auth_unpin by " << by << " on " << *this
<< " now " << auth_pins << "+" << nested_auth_pins
<< dendl;
int auth_pins;
int nested_auth_pins;
public:
+#ifdef MDS_AUTHPIN_SET
+ multiset<void*> auth_pin_set;
+#endif
int auth_pin_freeze_allowance;
private:
int get_num_auth_pins() { return auth_pins; }
void adjust_nested_auth_pins(int a);
bool can_auth_pin();
- void auth_pin();
- void auth_unpin();
+ void auth_pin(void *by);
+ void auth_unpin(void *by);
void adjust_nested_anchors(int by);
int get_nested_anchors() { return nested_anchors; }
// -- reference counting --
void bad_put(int by) {
- generic_dout(7) << " bad put " << *this << " by " << by << " " << pin_name(by) << " was " << ref << " (" << ref_set << ")" << dendl;
+ generic_dout(0) << " bad put " << *this << " by " << by << " " << pin_name(by) << " was " << ref
+#ifdef MDS_REF_SET
+ << " (" << ref_set << ")"
+#endif
+ << dendl;
#ifdef MDS_REF_SET
assert(ref_set.count(by) == 1);
#endif
assert(ref > 0);
}
void bad_get(int by) {
- generic_dout(7) << " bad get " << *this << " by " << by << " " << pin_name(by) << " was " << ref << " (" << ref_set << ")" << dendl;
+ generic_dout(0) << " bad get " << *this << " by " << by << " " << pin_name(by) << " was " << ref
+#ifdef MDS_REF_SET
+ << " (" << ref_set << ")"
+#endif
+ << dendl;
#ifdef MDS_REF_SET
assert(ref_set.count(by) == 0);
#endif
{
if (!lock->is_stable()) {
lock->set_state(s);
- lock->get_parent()->auth_unpin();
+ lock->get_parent()->auth_unpin(lock);
} else {
lock->set_state(s);
}
mut->apply();
drop_locks(mut);
mut->drop_local_auth_pins();
-
delete mut;
if (share && in->is_auth() && in->filelock.is_stable())
lock->finish_waiters(SimpleLock::WAIT_STABLE|SimpleLock::WAIT_WR);
if (lock->get_parent()->is_auth()) {
- lock->get_parent()->auth_unpin();
+ lock->get_parent()->auth_unpin(lock);
// re-eval?
simple_eval(lock);
// change lock
lock->set_state(LOCK_GLOCKR);
lock->init_gather();
- lock->get_parent()->auth_pin();
+ lock->get_parent()->auth_pin(lock);
} else {
lock->set_state(LOCK_LOCK);
}
<< " on " << *lock->get_parent() << dendl;
lock->set_state(LOCK_LOCK);
lock->finish_waiters(ScatterLock::WAIT_XLOCK|ScatterLock::WAIT_STABLE);
- lock->get_parent()->auth_unpin();
+ lock->get_parent()->auth_unpin(lock);
}
}
<< " on " << *lock->get_parent() << dendl;
lock->set_state(LOCK_LOCK);
lock->finish_waiters(ScatterLock::WAIT_XLOCK|ScatterLock::WAIT_STABLE);
- lock->get_parent()->auth_unpin();
+ lock->get_parent()->auth_unpin(lock);
}
}
}
lock->set_state(LOCK_SYNC);
lock->finish_waiters(ScatterLock::WAIT_RD|ScatterLock::WAIT_STABLE);
- lock->get_parent()->auth_unpin();
+ lock->get_parent()->auth_unpin(lock);
}
// gscattert|gscatters -> scatter?
}
lock->set_state(LOCK_SCATTER);
lock->finish_waiters(ScatterLock::WAIT_WR|ScatterLock::WAIT_STABLE);
- lock->get_parent()->auth_unpin();
+ lock->get_parent()->auth_unpin(lock);
}
// gTempsyncC|gTempsyncL -> tempsync
<< " on " << *lock->get_parent() << dendl;
lock->set_state(LOCK_TEMPSYNC);
lock->finish_waiters(ScatterLock::WAIT_RD|ScatterLock::WAIT_STABLE);
- lock->get_parent()->auth_unpin();
+ lock->get_parent()->auth_unpin(lock);
}
}
CInode *in = (CInode*)lock->get_parent();
dout(10) << "scatter_writebehind_finish on " << *lock << " on " << *in << dendl;
in->pop_and_dirty_projected_inode(mut->ls);
+
mut->apply();
drop_locks(mut);
+ mut->drop_local_auth_pins();
+ delete mut;
+
//scatter_eval_gather(lock);
}
case LOCK_LOCK:
if (lock->is_wrlocked() || lock->is_xlocked()) {
lock->set_state(LOCK_GSYNCL);
- lock->get_parent()->auth_pin();
+ lock->get_parent()->auth_pin(lock);
return;
}
break; // do it.
break; // do it now
lock->set_state(LOCK_GLOCKC);
- lock->get_parent()->auth_pin();
+ lock->get_parent()->auth_pin(lock);
if (lock->get_parent()->is_replicated()) {
lock->init_gather();
default: assert(0);
}
- lock->get_parent()->auth_pin();
+ lock->get_parent()->auth_pin(lock);
if (lock->get_parent()->is_replicated()) {
send_lock_message(lock, LOCK_AC_LOCK);
default: assert(0);
}
- lock->get_parent()->auth_pin();
+ lock->get_parent()->auth_pin(lock);
if (lock->get_parent()->is_replicated()) {
send_lock_message(lock, LOCK_AC_LOCK);
if (lock->is_wrlocked() ||
lock->is_xlocked()) {
lock->set_state(LOCK_GTEMPSYNCL);
- lock->get_parent()->auth_pin();
+ lock->get_parent()->auth_pin(lock);
return;
}
break; // do it.
}
lock->set_state(LOCK_GTEMPSYNCC);
- lock->get_parent()->auth_pin();
+ lock->get_parent()->auth_pin(lock);
if (lock->get_parent()->is_replicated()) {
lock->init_gather();
void Locker::local_wrlock_grab(LocalLock *lock, Mutation *mut)
{
- dout(7) << "local_wrlock_try on " << *lock
+ dout(7) << "local_wrlock_grab on " << *lock
<< " on " << *lock->get_parent() << dendl;
assert(lock->can_wrlock());
lock->get_rdlock();
lock->finish_waiters(SimpleLock::WAIT_STABLE|SimpleLock::WAIT_WR|SimpleLock::WAIT_RD);
lock->put_rdlock();
- lock->get_parent()->auth_unpin();
+ lock->get_parent()->auth_unpin(lock);
break;
// to mixed
case LOCK_GMIXEDR:
lock->set_state(LOCK_MIXED);
lock->finish_waiters(SimpleLock::WAIT_STABLE);
- lock->get_parent()->auth_unpin();
+ lock->get_parent()->auth_unpin(lock);
break;
case LOCK_GMIXEDL:
}
lock->finish_waiters(SimpleLock::WAIT_STABLE);
- lock->get_parent()->auth_unpin();
+ lock->get_parent()->auth_unpin(lock);
break;
// to loner
case LOCK_GLONERR:
lock->set_state(LOCK_LONER);
lock->finish_waiters(SimpleLock::WAIT_STABLE);
- lock->get_parent()->auth_unpin();
+ lock->get_parent()->auth_unpin(lock);
break;
case LOCK_GLONERM:
lock->set_state(LOCK_LONER);
lock->finish_waiters(SimpleLock::WAIT_STABLE);
- lock->get_parent()->auth_unpin();
+ lock->get_parent()->auth_unpin(lock);
break;
// to sync
lock->get_rdlock();
lock->finish_waiters(SimpleLock::WAIT_RD|SimpleLock::WAIT_STABLE);
lock->put_rdlock();
- lock->get_parent()->auth_unpin();
+ lock->get_parent()->auth_unpin(lock);
break;
default:
}
if (gather) {
- lock->get_parent()->auth_pin();
+ lock->get_parent()->auth_pin(lock);
return false;
}
}
}
if (gather)
- lock->get_parent()->auth_pin();
+ lock->get_parent()->auth_pin(lock);
else
lock->set_state(LOCK_LOCK);
}
}
if (gather)
- lock->get_parent()->auth_pin();
+ lock->get_parent()->auth_pin(lock);
else {
lock->set_state(LOCK_MIXED);
issue_caps(in);
}
if (gather) {
- lock->get_parent()->auth_pin();
+ lock->get_parent()->auth_pin(lock);
return;
}
}
CInode *in = dir->inode;
dout(10) << "try_subtree_merge_at journaling merged bound " << *in << dendl;
- in->auth_pin();
+ in->auth_pin(this);
// journal write-behind.
inode_t *pi = in->project_inode();
{
dout(10) << "subtree_merge_writebehind_finish on " << in << dendl;
in->pop_and_dirty_projected_inode(ls);
- in->auth_unpin();
+ in->auth_unpin(this);
}
void MDCache::eval_subtree_root(CDir *dir)
dout(10) << "queue_file_recover " << *in << dendl;
in->state_clear(CInode::STATE_NEEDSRECOVER);
in->state_set(CInode::STATE_RECOVERING);
- in->auth_pin();
+ in->auth_pin(this);
file_recover_queue.insert(in);
}
in->get_projected_inode()->size = in->inode.size;
mds->locker->check_inode_max_size(in, true, in->inode.size);
- in->auth_unpin();
+ in->auth_unpin(this);
do_file_recover();
}
// auth: do it
in->state_set(CInode::STATE_ANCHORING);
in->get(CInode::PIN_ANCHORING);
- in->auth_pin();
+ in->auth_pin(this);
// make trace
vector<Anchor> trace;
// auth: do it
in->state_set(CInode::STATE_UNANCHORING);
in->get(CInode::PIN_UNANCHORING);
- in->auth_pin();
+ in->auth_pin(this);
// do it
C_MDC_AnchorPrepared *fin = new C_MDC_AnchorPrepared(this, in, false);
assert(in->state_test(CInode::STATE_ANCHORING));
in->state_clear(CInode::STATE_ANCHORING);
in->put(CInode::PIN_ANCHORING);
- in->auth_unpin();
+ in->auth_unpin(this);
// apply update to cache
in->pop_and_dirty_projected_inode(mut->ls);
}
void auth_pin(MDSCacheObject *object) {
if (!is_auth_pinned(object)) {
- object->auth_pin();
+ object->auth_pin(this);
auth_pins.insert(object);
}
}
void auth_unpin(MDSCacheObject *object) {
assert(auth_pins.count(object));
- object->auth_unpin();
+ object->auth_unpin(this);
auth_pins.erase(object);
}
void drop_local_auth_pins() {
it != auth_pins.end();
it++) {
assert((*it)->is_auth());
- (*it)->auth_unpin();
+ (*it)->auth_unpin(this);
}
auth_pins.clear();
}
case EXPORT_DISCOVERING:
dout(10) << "export state=discovering : canceling freeze and removing auth_pin" << dendl;
dir->unfreeze_tree(); // cancel the freeze
- dir->auth_unpin();
+ dir->auth_unpin(this);
export_state.erase(dir); // clean up
dir->state_clear(CDir::STATE_EXPORTING);
if (export_peer[dir] != who) // tell them.
mds->send_message_mds(new MExportDirDiscover(dir), dest);
// start the freeze, but hold it up with an auth_pin.
- dir->auth_pin();
+ dir->auth_pin(this);
dir->freeze_tree();
assert(dir->is_freezing_tree());
dir->add_waiter(CDir::WAIT_FROZEN, new C_MDC_ExportFreeze(this, dir));
} else {
// freeze the subtree
export_state[dir] = EXPORT_FREEZING;
- dir->auth_unpin();
+ dir->auth_unpin(this);
}
delete m; // done
#include "include/frag.h"
#include "include/xlist.h"
-#define MDS_REF_SET // define me for improved debug output, sanity checking
+#define MDS_REF_SET // define me for improved debug output, sanity checking
+#define MDS_AUTHPIN_SET // define me for debugging auth pin leaks
//#define MDS_VERIFY_FRAGSTAT // do do (slow) sanity checking on frags
#define MDS_PORT_CACHE 0x200
// --------------------------------------------
// auth pins
virtual bool can_auth_pin() = 0;
- virtual void auth_pin() = 0;
- virtual void auth_unpin() = 0;
+ virtual void auth_pin(void *who) = 0;
+ virtual void auth_unpin(void *who) = 0;
virtual bool is_frozen() = 0;