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;
}
}
-void CInode::put_scatter_pin(list<Context*>& 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()
nestlock(this, &nestlock_type),
flocklock(this, &flocklock_type),
policylock(this, &policylock_type),
- scatter_pins(0),
loner_cap(-1), want_loner_cap(-1)
{
g_num_ino++;
SimpleLock flocklock;
SimpleLock policylock;
- int scatter_pins;
-
SimpleLock* get_lock(int type) {
switch (type) {
case CEPH_LOCK_IFILE: return &filelock;
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<Context*>& ls);
-
// -- snap --
void open_snaprealm(bool no_split=false);
void close_snaprealm(bool no_join=false);
(IS_TRUE_AND_LT_AUTH(lock->get_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)) &&
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();
{
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)
dout(7) << "export_dir couldn't pin path, failing." << dendl;
return;
}
- // pin parent scatterlocks?
- CInode *diri = dir->inode;
- if (!diri->can_scatter_pin()) {
- dout(7) << "export_dir couldn't pin parent inode scatterlocks, failing. " << *diri << dendl;
-
- // XXX we should make some effort to move lock(s) to a state where we _can_ export!
-
- return;
- }
// ok.
assert(export_state.count(dir) == 0);
cache->make_trace(trace, dir->inode);
CInode *diri = dir->inode;
- if (!mds->locker->dentry_can_rdlock_trace(trace) ||
- !diri->can_scatter_pin()) {
+ if (!mds->locker->dentry_can_rdlock_trace(trace)) {
dout(7) << "export_dir couldn't rdlock path or rd|wrlock parent inode file+nest+dftlock, failing. "
<< *diri << dendl;
// rdlock path
mds->locker->dentry_anon_rdlock_trace_start(trace);
- // pin scatterlocks
- diri->get_scatter_pin();
- dout(10) << " dir inode now scatter pinned " << *diri << dendl;
-
-
cache->show_subtrees();
// note the bounds.
mds->locker->dentry_anon_rdlock_trace_finish(trace);
list<Context*> ls;
- dir->inode->put_scatter_pin(ls);
mds->queue_waiters(ls);
}
// freeze.
dir->_freeze_tree();
- // pin parent scatterlocks (sloppily!)
- dir->inode->get_scatter_pin();
-
// ok!
dout(7) << " sending export_prep_ack on " << *dir << dendl;
mds->send_message(new MExportDirPrepAck(dir->dirfrag()), m->get_connection());
dout(7) << "import_reverse_unfreeze " << *dir << dendl;
dir->unfreeze_tree();
list<Context*> ls;
- dir->inode->put_scatter_pin(ls);
mds->queue_waiters(ls);
cache->discard_delayed_expire(dir);
import_reverse_final(dir);
//audit(); // this fails, bc we munge up the subtree map during handle_import_map (resolve phase)
list<Context*> ls;
- dir->inode->put_scatter_pin(ls);
mds->queue_waiters(ls);
// re-eval imported caps