}
-void Locker::drop_locks(MDRequest *mdr)
+void Locker::drop_locks(Mutation *mut)
{
// leftover locks
- while (!mdr->xlocks.empty())
- xlock_finish(*mdr->xlocks.begin(), mdr);
- while (!mdr->rdlocks.empty())
- rdlock_finish(*mdr->rdlocks.begin(), mdr);
- while (!mdr->wrlocks.empty())
- wrlock_finish(*mdr->wrlocks.begin(), mdr);
+ while (!mut->xlocks.empty())
+ xlock_finish(*mut->xlocks.begin(), mut);
+ while (!mut->rdlocks.empty())
+ rdlock_finish(*mut->rdlocks.begin(), mut);
+ while (!mut->wrlocks.empty())
+ wrlock_finish(*mut->wrlocks.begin(), mut);
}
}
}
-bool Locker::rdlock_start(SimpleLock *lock, MDRequest *mdr)
+bool Locker::rdlock_start(SimpleLock *lock, MDRequest *mut)
{
switch (lock->get_type()) {
case CEPH_LOCK_IFILE:
- return file_rdlock_start((FileLock*)lock, mdr);
+ return file_rdlock_start((FileLock*)lock, mut);
case CEPH_LOCK_IDFT:
case CEPH_LOCK_IDIR:
case CEPH_LOCK_INESTED:
- return scatter_rdlock_start((ScatterLock*)lock, mdr);
+ return scatter_rdlock_start((ScatterLock*)lock, mut);
default:
- return simple_rdlock_start(lock, mdr);
+ return simple_rdlock_start(lock, mut);
}
}
-void Locker::rdlock_finish(SimpleLock *lock, MDRequest *mdr)
+void Locker::rdlock_finish(SimpleLock *lock, Mutation *mut)
{
switch (lock->get_type()) {
case CEPH_LOCK_IFILE:
- return file_rdlock_finish((FileLock*)lock, mdr);
+ return file_rdlock_finish((FileLock*)lock, mut);
case CEPH_LOCK_IDFT:
case CEPH_LOCK_IDIR:
case CEPH_LOCK_INESTED:
- return scatter_rdlock_finish((ScatterLock*)lock, mdr);
+ return scatter_rdlock_finish((ScatterLock*)lock, mut);
default:
- return simple_rdlock_finish(lock, mdr);
+ return simple_rdlock_finish(lock, mut);
}
}
-bool Locker::wrlock_start(SimpleLock *lock, MDRequest *mdr)
+bool Locker::wrlock_start(SimpleLock *lock, MDRequest *mut)
{
switch (lock->get_type()) {
case CEPH_LOCK_IDFT:
case CEPH_LOCK_IDIR:
case CEPH_LOCK_INESTED:
- return scatter_wrlock_start((ScatterLock*)lock, mdr);
+ return scatter_wrlock_start((ScatterLock*)lock, mut);
case CEPH_LOCK_IVERSION:
- return local_wrlock_start((LocalLock*)lock, mdr);
+ return local_wrlock_start((LocalLock*)lock, mut);
//case CEPH_LOCK_IFILE:
- //return file_wrlock_start((ScatterLock*)lock, mdr);
+ //return file_wrlock_start((ScatterLock*)lock, mut);
default:
assert(0);
return false;
}
}
-void Locker::wrlock_finish(SimpleLock *lock, MDRequest *mdr)
+void Locker::wrlock_finish(SimpleLock *lock, Mutation *mut)
{
switch (lock->get_type()) {
case CEPH_LOCK_IDFT:
case CEPH_LOCK_IDIR:
case CEPH_LOCK_INESTED:
- return scatter_wrlock_finish((ScatterLock*)lock, mdr);
+ return scatter_wrlock_finish((ScatterLock*)lock, mut);
case CEPH_LOCK_IVERSION:
- return local_wrlock_finish((LocalLock*)lock, mdr);
+ return local_wrlock_finish((LocalLock*)lock, mut);
default:
assert(0);
}
}
-bool Locker::xlock_start(SimpleLock *lock, MDRequest *mdr)
+bool Locker::xlock_start(SimpleLock *lock, MDRequest *mut)
{
switch (lock->get_type()) {
case CEPH_LOCK_IFILE:
- return file_xlock_start((FileLock*)lock, mdr);
+ return file_xlock_start((FileLock*)lock, mut);
case CEPH_LOCK_IVERSION:
- return local_xlock_start((LocalLock*)lock, mdr);
+ return local_xlock_start((LocalLock*)lock, mut);
case CEPH_LOCK_IDFT:
case CEPH_LOCK_IDIR:
case CEPH_LOCK_INESTED:
assert(0);
default:
- return simple_xlock_start(lock, mdr);
+ return simple_xlock_start(lock, mut);
}
}
-void Locker::xlock_finish(SimpleLock *lock, MDRequest *mdr)
+void Locker::xlock_finish(SimpleLock *lock, Mutation *mut)
{
switch (lock->get_type()) {
case CEPH_LOCK_IFILE:
- return file_xlock_finish((FileLock*)lock, mdr);
+ return file_xlock_finish((FileLock*)lock, mut);
case CEPH_LOCK_IVERSION:
- return local_xlock_finish((LocalLock*)lock, mdr);
+ return local_xlock_finish((LocalLock*)lock, mut);
case CEPH_LOCK_IDFT:
case CEPH_LOCK_IDIR:
case CEPH_LOCK_INESTED:
assert(0);
default:
- return simple_xlock_finish(lock, mdr);
+ return simple_xlock_finish(lock, mut);
}
}
struct C_Locker_FileUpdate_finish : public Context {
Locker *locker;
CInode *in;
- list<CInode*> nest_updates;
- LogSegment *ls;
+ Mutation *mut;
bool share;
- C_Locker_FileUpdate_finish(Locker *l, CInode *i, LogSegment *s, list<CInode*> &ls, bool e=false) :
- locker(l), in(i), ls(s), share(e) {
- nest_updates.swap(ls);
+ C_Locker_FileUpdate_finish(Locker *l, CInode *i, Mutation *m, bool e=false) :
+ locker(l), in(i), mut(m), share(e) {
in->get(CInode::PIN_PTRWAITER);
}
void finish(int r) {
- locker->file_update_finish(in, ls, nest_updates, share);
+ locker->file_update_finish(in, mut, share);
}
};
-void Locker::file_update_finish(CInode *in, LogSegment *ls, list<CInode*> &nest_updates, bool share)
+void Locker::file_update_finish(CInode *in, Mutation *mut, bool share)
{
dout(10) << "file_update_finish on " << *in << dendl;
- in->pop_and_dirty_projected_inode(ls);
+ in->pop_and_dirty_projected_inode(mut->ls);
in->put(CInode::PIN_PTRWAITER);
- for (list<CInode*>::iterator p = nest_updates.begin();
- p != nest_updates.end();
- p++) {
- (*p)->pop_and_dirty_projected_inode(ls);
- scatter_wrlock_finish(&(*p)->dirlock, 0);
- }
-
- file_wrlock_finish(&in->filelock);
+ mut->pop_and_dirty_projected_inodes();
+ mut->pop_and_dirty_projected_fnodes();
+ drop_locks(mut);
+
if (share && in->is_auth() && in->filelock.is_stable())
share_inode_max_size(in);
}
dout(10) << "check_inode_max_size " << latest->max_size << " -> " << new_max
<< " on " << *in << dendl;
+
+ Mutation *mut = new Mutation;
+ mut->ls = mds->mdlog->get_current_segment();
inode_t *pi = in->project_inode();
pi->version = in->pre_dirty();
pi->max_size = new_max;
EOpen *le = new EOpen(mds->mdlog);
+ predirty_nested(mut, &le->metablob, in);
le->metablob.add_dir_context(in->get_parent_dir());
- list<CInode*> nest_updates;
- predirty_nested(&le->metablob, in, nest_updates);
le->metablob.add_primary_dentry(in->parent, true, 0, pi);
- LogSegment *ls = mds->mdlog->get_current_segment();
le->add_ino(in->ino());
- ls->open_files.push_back(&in->xlist_open_file);
- mds->mdlog->submit_entry(le, new C_Locker_FileUpdate_finish(this, in, ls, nest_updates, true));
- file_wrlock_start(&in->filelock, forcewrlock); // wrlock for duration of journal
+ mut->ls->open_files.push_back(&in->xlist_open_file);
+ mds->mdlog->submit_entry(le, new C_Locker_FileUpdate_finish(this, in, mut, true));
+ file_wrlock_start(&in->filelock, mut, forcewrlock); // wrlock for duration of journal
return true;
}
<< " for " << *in << dendl;
pi->time_warp_seq = m->get_time_warp_seq();
}
+ Mutation *mut = new Mutation;
+ mut->ls = mds->mdlog->get_current_segment();
+ file_wrlock_start(&in->filelock, mut); // wrlock for duration of journal
+ predirty_nested(mut, &le->metablob, in);
le->metablob.add_dir_context(in->get_parent_dir());
- list<CInode*> nest_updates;
- predirty_nested(&le->metablob, in, nest_updates);
le->metablob.add_primary_dentry(in->parent, true, 0, pi);
- LogSegment *ls = mds->mdlog->get_current_segment();
- mds->mdlog->submit_entry(le, new C_Locker_FileUpdate_finish(this, in, ls, nest_updates, change_max));
- file_wrlock_start(&in->filelock); // wrlock for duration of journal
+ mds->mdlog->submit_entry(le, new C_Locker_FileUpdate_finish(this, in, mut, change_max));
}
// reevaluate, waiters
// nested ---------------------------------------------------------------
-void Locker::predirty_nested(EMetaBlob *blob, CInode *in, list<CInode*> &ls)
+void Locker::predirty_nested(Mutation *mut, EMetaBlob *blob, CInode *in)
{
- assert(ls.empty());
-
CDir *parent = in->get_projected_parent_dn()->get_dir();
- blob->add_dir_context(parent);
// initial diff from *in
inode_t *curi = in->get_projected_inode();
dout(10) << "predirty_nested delta " << drbytes << " bytes / " << drfiles << " files from " << *in << dendl;
// build list of inodes to wrlock, dirty, and update
+ list<CInode*> lsi;
CInode *cur = in;
while (parent) {
assert(cur->is_auth());
if (pin->is_base())
break;
- if (!scatter_wrlock_try(&pin->dirlock)) {
+ if (mut->wrlocks.count(&pin->dirlock) == 0 &&
+ !scatter_wrlock_try(&pin->dirlock, mut)) {
dout(10) << "predirty_nested can't wrlock " << pin->dirlock << " on " << *pin << dendl;
break;
}
- ls.push_back(pin);
+ // inode -> dirfrag
+ mut->add_projected_fnode(parent);
+
+ fnode_t *pf = parent->project_fnode();
+ pf->version = parent->pre_dirty();
+ pf->nested.rbytes += drbytes;
+ pf->nested.rfiles += drfiles;
+ pf->nested.rctime = rctime;
+
+ curi->accounted_nested.rbytes += drbytes;
+ curi->accounted_nested.rfiles += drfiles;
+ curi->accounted_nested.rctime = rctime;
// FIXME
if (!pin->is_auth()) {
break;
}
- // project update
+ // dirfrag -> diri
+ mut->add_projected_inode(pin);
+ lsi.push_back(pin);
+
version_t ppv = pin->pre_dirty();
inode_t *pi = pin->project_inode();
pi->version = ppv;
pi->nested.rfiles += drfiles;
pi->nested.rctime = rctime;
- frag_t fg = parent->dirfrag().frag;
- pin->dirfrag_nested[fg].rbytes += drbytes;
- pin->dirfrag_nested[fg].rfiles += drfiles;
- pin->dirfrag_nested[fg].rctime = rctime;
-
- curi->accounted_nested.rbytes += drbytes;
- curi->accounted_nested.rfiles += drfiles;
- curi->accounted_nested.rctime = rctime;
-
cur = pin;
curi = pi;
parent = cur->get_projected_parent_dn()->get_dir();
}
// now, stick it in the blob
- for (list<CInode*>::iterator p = ls.begin();
- p != ls.end();
+ blob->add_dir_context(parent);
+ for (list<CInode*>::iterator p = lsi.begin();
+ p != lsi.end();
p++) {
CInode *cur = *p;
inode_t *pi = cur->get_projected_inode();
return false;
}
-bool Locker::simple_rdlock_start(SimpleLock *lock, MDRequest *mdr)
+bool Locker::simple_rdlock_start(SimpleLock *lock, MDRequest *mut)
{
dout(7) << "simple_rdlock_start on " << *lock << " on " << *lock->get_parent() << dendl;
// can read? grab ref.
- if (lock->can_rdlock(mdr)) {
+ if (lock->can_rdlock(mut)) {
lock->get_rdlock();
- mdr->rdlocks.insert(lock);
- mdr->locks.insert(lock);
+ mut->rdlocks.insert(lock);
+ mut->locks.insert(lock);
return true;
}
// wait!
dout(7) << "simple_rdlock_start waiting on " << *lock << " on " << *lock->get_parent() << dendl;
- lock->add_waiter(SimpleLock::WAIT_RD, new C_MDS_RetryRequest(mdcache, mdr));
+ lock->add_waiter(SimpleLock::WAIT_RD, new C_MDS_RetryRequest(mdcache, mut));
return false;
}
-void Locker::simple_rdlock_finish(SimpleLock *lock, MDRequest *mdr)
+void Locker::simple_rdlock_finish(SimpleLock *lock, Mutation *mut)
{
// drop ref
lock->put_rdlock();
- if (mdr) {
- mdr->rdlocks.erase(lock);
- mdr->locks.erase(lock);
+ if (mut) {
+ mut->rdlocks.erase(lock);
+ mut->locks.erase(lock);
}
dout(7) << "simple_rdlock_finish on " << *lock << " on " << *lock->get_parent() << dendl;
simple_eval_gather(lock);
}
-bool Locker::simple_xlock_start(SimpleLock *lock, MDRequest *mdr)
+bool Locker::simple_xlock_start(SimpleLock *lock, MDRequest *mut)
{
dout(7) << "simple_xlock_start on " << *lock << " on " << *lock->get_parent() << dendl;
// xlock by me?
if (lock->is_xlocked() &&
- lock->get_xlocked_by() == mdr)
+ lock->get_xlocked_by() == mut)
return true;
// auth?
if (lock->get_state() == LOCK_LOCK) {
if (lock->is_xlocked()) {
// by someone else.
- lock->add_waiter(SimpleLock::WAIT_WR, new C_MDS_RetryRequest(mdcache, mdr));
+ lock->add_waiter(SimpleLock::WAIT_WR, new C_MDS_RetryRequest(mdcache, mut));
return false;
}
// xlock.
- lock->get_xlock(mdr);
- mdr->xlocks.insert(lock);
- mdr->locks.insert(lock);
+ lock->get_xlock(mut);
+ mut->xlocks.insert(lock);
+ mut->locks.insert(lock);
return true;
} else {
// wait for lock
- lock->add_waiter(SimpleLock::WAIT_STABLE, new C_MDS_RetryRequest(mdcache, mdr));
+ lock->add_waiter(SimpleLock::WAIT_STABLE, new C_MDS_RetryRequest(mdcache, mut));
return false;
}
} else {
// replica
// this had better not be a remote xlock attempt!
- assert(!mdr->slave_request);
+ assert(!mut->slave_request);
// wait for single auth
if (lock->get_parent()->is_ambiguous_auth()) {
lock->get_parent()->add_waiter(MDSCacheObject::WAIT_SINGLEAUTH,
- new C_MDS_RetryRequest(mdcache, mdr));
+ new C_MDS_RetryRequest(mdcache, mut));
return false;
}
// send lock request
int auth = lock->get_parent()->authority().first;
- mdr->more()->slaves.insert(auth);
- MMDSSlaveRequest *r = new MMDSSlaveRequest(mdr->reqid, MMDSSlaveRequest::OP_XLOCK);
+ mut->more()->slaves.insert(auth);
+ MMDSSlaveRequest *r = new MMDSSlaveRequest(mut->reqid, MMDSSlaveRequest::OP_XLOCK);
r->set_lock_type(lock->get_type());
lock->get_parent()->set_object_info(r->get_object_info());
mds->send_message_mds(r, auth);
// wait
- lock->add_waiter(SimpleLock::WAIT_REMOTEXLOCK, new C_MDS_RetryRequest(mdcache, mdr));
+ lock->add_waiter(SimpleLock::WAIT_REMOTEXLOCK, new C_MDS_RetryRequest(mdcache, mut));
return false;
}
}
-void Locker::simple_xlock_finish(SimpleLock *lock, MDRequest *mdr)
+void Locker::simple_xlock_finish(SimpleLock *lock, Mutation *mut)
{
dout(7) << "simple_xlock_finish on " << *lock << " on " << *lock->get_parent() << dendl;
// drop ref
- assert(lock->can_xlock(mdr));
+ assert(lock->can_xlock(mut));
lock->put_xlock();
- assert(mdr);
- mdr->xlocks.erase(lock);
- mdr->locks.erase(lock);
+ assert(mut);
+ mut->xlocks.erase(lock);
+ mut->locks.erase(lock);
// remote xlock?
if (!lock->get_parent()->is_auth()) {
dout(7) << "simple_xlock_finish releasing remote xlock on " << *lock->get_parent() << dendl;
int auth = lock->get_parent()->authority().first;
if (mds->mdsmap->get_state(auth) >= MDSMap::STATE_REJOIN) {
- MMDSSlaveRequest *slavereq = new MMDSSlaveRequest(mdr->reqid, MMDSSlaveRequest::OP_UNXLOCK);
+ MMDSSlaveRequest *slavereq = new MMDSSlaveRequest(mut->reqid, MMDSSlaveRequest::OP_UNXLOCK);
slavereq->set_lock_type(lock->get_type());
lock->get_parent()->set_object_info(slavereq->get_object_info());
mds->send_message_mds(slavereq, auth);
// ==========================================================================
// scatter lock
-bool Locker::scatter_rdlock_start(ScatterLock *lock, MDRequest *mdr)
+bool Locker::scatter_rdlock_start(ScatterLock *lock, MDRequest *mut)
{
dout(7) << "scatter_rdlock_start on " << *lock
<< " on " << *lock->get_parent() << dendl;
if (lock->get_state() == LOCK_SCATTER &&
!lock->get_parent()->is_auth()) {
dout(7) << "scatter_rdlock_start scatterlock read on a stable scattered replica, fw to auth" << dendl;
- mdcache->request_forward(mdr, lock->get_parent()->authority().first);
+ mdcache->request_forward(mut, lock->get_parent()->authority().first);
return false;
}
scatter_sync(lock);
// can rdlock?
- if (lock->can_rdlock(mdr)) {
+ if (lock->can_rdlock(mut)) {
lock->get_rdlock();
- mdr->rdlocks.insert(lock);
- mdr->locks.insert(lock);
+ mut->rdlocks.insert(lock);
+ mut->locks.insert(lock);
return true;
}
// wait for read.
- lock->add_waiter(SimpleLock::WAIT_RD|SimpleLock::WAIT_STABLE, new C_MDS_RetryRequest(mdcache, mdr));
+ lock->add_waiter(SimpleLock::WAIT_RD|SimpleLock::WAIT_STABLE, new C_MDS_RetryRequest(mdcache, mut));
// initiate sync or tempsync?
if (lock->is_stable() &&
return false;
}
-void Locker::scatter_rdlock_finish(ScatterLock *lock, MDRequest *mdr)
+void Locker::scatter_rdlock_finish(ScatterLock *lock, MDRequest *mut)
{
dout(7) << "scatter_rdlock_finish on " << *lock
<< " on " << *lock->get_parent() << dendl;
lock->put_rdlock();
- if (mdr) {
- mdr->rdlocks.erase(lock);
- mdr->locks.erase(lock);
+ if (mut) {
+ mut->rdlocks.erase(lock);
+ mut->locks.erase(lock);
}
scatter_eval_gather(lock);
}
-bool Locker::scatter_wrlock_try(ScatterLock *lock)
+bool Locker::scatter_wrlock_try(ScatterLock *lock, Mutation *mut)
{
// pre-twiddle?
if (lock->get_parent()->is_auth() &&
// can wrlock?
if (lock->can_wrlock()) {
lock->get_wrlock();
+ mut->wrlocks.insert(lock);
+ mut->locks.insert(lock);
return true;
}
return false;
}
-bool Locker::scatter_wrlock_start(ScatterLock *lock, MDRequest *mdr)
+bool Locker::scatter_wrlock_start(ScatterLock *lock, MDRequest *mut)
{
dout(7) << "scatter_wrlock_start on " << *lock
<< " on " << *lock->get_parent() << dendl;
- if (scatter_wrlock_try(lock)) {
- mdr->wrlocks.insert(lock);
- mdr->locks.insert(lock);
+ if (scatter_wrlock_try(lock, mut))
return true;
- }
// wait for write.
lock->add_waiter(SimpleLock::WAIT_WR|SimpleLock::WAIT_STABLE,
- new C_MDS_RetryRequest(mdcache, mdr));
+ new C_MDS_RetryRequest(mdcache, mut));
// initiate scatter or lock?
if (lock->is_stable()) {
return false;
}
-void Locker::scatter_wrlock_finish(ScatterLock *lock, MDRequest *mdr)
+void Locker::scatter_wrlock_finish(ScatterLock *lock, Mutation *mut)
{
dout(7) << "scatter_wrlock_finish on " << *lock
<< " on " << *lock->get_parent() << dendl;
lock->put_wrlock();
- if (mdr) {
- mdr->wrlocks.erase(lock);
- mdr->locks.erase(lock);
+ if (mut) {
+ mut->wrlocks.erase(lock);
+ mut->locks.erase(lock);
}
scatter_eval_gather(lock);
// local lock
-bool Locker::local_wrlock_start(LocalLock *lock, MDRequest *mdr)
+bool Locker::local_wrlock_start(LocalLock *lock, MDRequest *mut)
{
dout(7) << "local_wrlock_start on " << *lock
<< " on " << *lock->get_parent() << dendl;
if (lock->can_wrlock()) {
lock->get_wrlock();
- mdr->wrlocks.insert(lock);
- mdr->locks.insert(lock);
+ mut->wrlocks.insert(lock);
+ mut->locks.insert(lock);
return true;
} else {
- lock->add_waiter(SimpleLock::WAIT_WR|SimpleLock::WAIT_STABLE, new C_MDS_RetryRequest(mdcache, mdr));
+ lock->add_waiter(SimpleLock::WAIT_WR|SimpleLock::WAIT_STABLE, new C_MDS_RetryRequest(mdcache, mut));
return false;
}
}
-void Locker::local_wrlock_finish(LocalLock *lock, MDRequest *mdr)
+void Locker::local_wrlock_finish(LocalLock *lock, MDRequest *mut)
{
dout(7) << "local_wrlock_finish on " << *lock
<< " on " << *lock->get_parent() << dendl;
lock->put_wrlock();
- mdr->wrlocks.erase(lock);
- mdr->locks.erase(lock);
+ mut->wrlocks.erase(lock);
+ mut->locks.erase(lock);
}
-bool Locker::local_xlock_start(LocalLock *lock, MDRequest *mdr)
+bool Locker::local_xlock_start(LocalLock *lock, MDRequest *mut)
{
dout(7) << "local_xlock_start on " << *lock
<< " on " << *lock->get_parent() << dendl;
- if (lock->is_xlocked_by_other(mdr)) {
- lock->add_waiter(SimpleLock::WAIT_WR|SimpleLock::WAIT_STABLE, new C_MDS_RetryRequest(mdcache, mdr));
+ if (lock->is_xlocked_by_other(mut)) {
+ lock->add_waiter(SimpleLock::WAIT_WR|SimpleLock::WAIT_STABLE, new C_MDS_RetryRequest(mdcache, mut));
return false;
}
- lock->get_xlock(mdr);
- mdr->xlocks.insert(lock);
- mdr->locks.insert(lock);
+ lock->get_xlock(mut);
+ mut->xlocks.insert(lock);
+ mut->locks.insert(lock);
return true;
}
-void Locker::local_xlock_finish(LocalLock *lock, MDRequest *mdr)
+void Locker::local_xlock_finish(LocalLock *lock, MDRequest *mut)
{
dout(7) << "local_xlock_finish on " << *lock
<< " on " << *lock->get_parent() << dendl;
lock->put_xlock();
- mdr->xlocks.erase(lock);
- mdr->locks.erase(lock);
+ mut->xlocks.erase(lock);
+ mut->locks.erase(lock);
lock->finish_waiters(SimpleLock::WAIT_STABLE |
SimpleLock::WAIT_WR |
// file lock
-bool Locker::file_rdlock_start(FileLock *lock, MDRequest *mdr)
+bool Locker::file_rdlock_start(FileLock *lock, MDRequest *mut)
{
dout(7) << "file_rdlock_start " << *lock << " on " << *lock->get_parent() << dendl;
// can read? grab ref.
- if (lock->can_rdlock(mdr)) {
+ if (lock->can_rdlock(mut)) {
lock->get_rdlock();
- mdr->rdlocks.insert(lock);
- mdr->locks.insert(lock);
+ mut->rdlocks.insert(lock);
+ mut->locks.insert(lock);
return true;
}
if (lock->is_stable()) {
file_lock(lock); // lock, bc easiest to back off ... FIXME
- if (lock->can_rdlock(mdr)) {
+ if (lock->can_rdlock(mut)) {
lock->get_rdlock();
- mdr->rdlocks.insert(lock);
- mdr->locks.insert(lock);
+ mut->rdlocks.insert(lock);
+ mut->locks.insert(lock);
lock->finish_waiters(SimpleLock::WAIT_STABLE);
return true;
}
} else {
dout(7) << "file_rdlock_start waiting until stable on " << *lock << " on " << *lock->get_parent() << dendl;
- lock->add_waiter(SimpleLock::WAIT_STABLE, new C_MDS_RetryRequest(mdcache, mdr));
+ lock->add_waiter(SimpleLock::WAIT_STABLE, new C_MDS_RetryRequest(mdcache, mut));
return false;
}
} else {
int auth = in->authority().first;
dout(7) << "file_rdlock_start " << *lock << " on " << *lock->get_parent() << " on replica and async, fw to auth " << auth << dendl;
assert(auth != mds->get_nodeid());
- mdcache->request_forward(mdr, auth);
+ mdcache->request_forward(mut, auth);
return false;
} else {
// wait until stable
dout(7) << "inode_file_rdlock_start waiting until stable on " << *lock << " on " << *lock->get_parent() << dendl;
- lock->add_waiter(SimpleLock::WAIT_STABLE, new C_MDS_RetryRequest(mdcache, mdr));
+ lock->add_waiter(SimpleLock::WAIT_STABLE, new C_MDS_RetryRequest(mdcache, mut));
return false;
}
}
// wait
dout(7) << "file_rdlock_start waiting on " << *lock << " on " << *lock->get_parent() << dendl;
- lock->add_waiter(SimpleLock::WAIT_RD, new C_MDS_RetryRequest(mdcache, mdr));
+ lock->add_waiter(SimpleLock::WAIT_RD, new C_MDS_RetryRequest(mdcache, mut));
return false;
}
-void Locker::file_rdlock_finish(FileLock *lock, MDRequest *mdr)
+void Locker::file_rdlock_finish(FileLock *lock, MDRequest *mut)
{
dout(7) << "rdlock_finish on " << *lock << " on " << *lock->get_parent() << dendl;
// drop ref
lock->put_rdlock();
- mdr->rdlocks.erase(lock);
- mdr->locks.erase(lock);
+ mut->rdlocks.erase(lock);
+ mut->locks.erase(lock);
if (!lock->is_rdlocked()) {
if (!lock->is_stable())
}
}
-bool Locker::file_wrlock_start(FileLock *lock, bool force)
+bool Locker::file_wrlock_start(FileLock *lock, MDRequest *mut, bool force)
{
dout(7) << "file_wrlock_start on " << *lock
<< " on " << *lock->get_parent() << dendl;
assert(force || lock->can_wrlock());
lock->get_wrlock();
+ mut->wrlocks.insert(lock);
+ mut->locks.insert(lock);
return true;
/*
if (lock->can_wrlock()) {
lock->get_wrlock();
- mdr->wrlocks.insert(lock);
- mdr->locks.insert(lock);
+ mut->wrlocks.insert(lock);
+ mut->locks.insert(lock);
return true;
} else {
- lock->add_waiter(SimpleLock::WAIT_WR|SimpleLock::WAIT_STABLE, new C_MDS_RetryRequest(mdcache, mdr));
+ lock->add_waiter(SimpleLock::WAIT_WR|SimpleLock::WAIT_STABLE, new C_MDS_RetryRequest(mdcache, mut));
return false;
}*/
}
-void Locker::file_wrlock_finish(FileLock *lock)
+void Locker::file_wrlock_finish(FileLock *lock, Mutation *mut)
{
dout(7) << "wrlock_finish on " << *lock << " on " << *lock->get_parent() << dendl;
lock->put_wrlock();
-
+ if (mut) {
+ mut->wrlocks.erase(lock);
+ mut->locks.erase(lock);
+ }
+
if (!lock->is_wrlocked())
file_eval_gather(lock);
}
-bool Locker::file_xlock_start(FileLock *lock, MDRequest *mdr)
+bool Locker::file_xlock_start(FileLock *lock, MDRequest *mut)
{
dout(7) << "file_xlock_start on " << *lock << " on " << *lock->get_parent() << dendl;
assert(lock->get_parent()->is_auth()); // remote file xlock not implemented
// already xlocked by me?
- if (lock->get_xlocked_by() == mdr)
+ if (lock->get_xlocked_by() == mut)
return true;
// can't write?
- if (!lock->can_xlock(mdr)) {
+ if (!lock->can_xlock(mut)) {
// auth
if (!lock->can_xlock_soon()) {
if (!lock->is_stable()) {
dout(7) << "file_xlock_start on auth, waiting for stable on " << *lock << " on " << *lock->get_parent() << dendl;
- lock->add_waiter(SimpleLock::WAIT_STABLE, new C_MDS_RetryRequest(mdcache, mdr));
+ lock->add_waiter(SimpleLock::WAIT_STABLE, new C_MDS_RetryRequest(mdcache, mut));
return false;
}
}
// check again
- if (lock->can_xlock(mdr)) {
+ if (lock->can_xlock(mut)) {
assert(lock->get_parent()->is_auth());
- lock->get_xlock(mdr);
- mdr->locks.insert(lock);
- mdr->xlocks.insert(lock);
+ lock->get_xlock(mut);
+ mut->locks.insert(lock);
+ mut->xlocks.insert(lock);
return true;
} else {
dout(7) << "file_xlock_start on auth, waiting for write on " << *lock << " on " << *lock->get_parent() << dendl;
- lock->add_waiter(SimpleLock::WAIT_WR, new C_MDS_RetryRequest(mdcache, mdr));
+ lock->add_waiter(SimpleLock::WAIT_WR, new C_MDS_RetryRequest(mdcache, mut));
return false;
}
}
-void Locker::file_xlock_finish(FileLock *lock, MDRequest *mdr)
+void Locker::file_xlock_finish(FileLock *lock, MDRequest *mut)
{
dout(7) << "file_xlock_finish on " << *lock << " on " << *lock->get_parent() << dendl;
// drop ref
- assert(lock->can_xlock(mdr));
+ assert(lock->can_xlock(mut));
lock->put_xlock();
- mdr->locks.erase(lock);
- mdr->xlocks.erase(lock);
+ mut->locks.erase(lock);
+ mut->xlocks.erase(lock);
assert(lock->get_parent()->is_auth()); // or implement remote xlocks
class CDir;
class CInode;
class CDentry;
+class Mutation;
+class MDRequest;
+class EMetaBlob;
class Message;
set<SimpleLock*> &wrlocks,
set<SimpleLock*> &xlocks);
- void drop_locks(MDRequest *mdr);
+ void drop_locks(Mutation *mut);
void eval_gather(SimpleLock *lock);
protected:
- bool rdlock_start(SimpleLock *lock, MDRequest *mdr);
- void rdlock_finish(SimpleLock *lock, MDRequest *mdr);
- bool xlock_start(SimpleLock *lock, MDRequest *mdr);
+ bool rdlock_start(SimpleLock *lock, MDRequest *mut);
+ void rdlock_finish(SimpleLock *lock, Mutation *mut);
+ bool xlock_start(SimpleLock *lock, MDRequest *mut);
public:
- void xlock_finish(SimpleLock *lock, MDRequest *mdr); // public for Server's slave UNXLOCK
+ void xlock_finish(SimpleLock *lock, Mutation *mut); // public for Server's slave UNXLOCK
protected:
- bool wrlock_start(SimpleLock *lock, MDRequest *mdr);
- void wrlock_finish(SimpleLock *lock, MDRequest *mdr);
+ bool wrlock_start(SimpleLock *lock, MDRequest *mut);
+ void wrlock_finish(SimpleLock *lock, Mutation *mut);
public:
void rejoin_set_state(SimpleLock *lock, int s, list<Context*>& waiters);
void handle_simple_lock(SimpleLock *lock, MLock *m);
void simple_sync(SimpleLock *lock);
void simple_lock(SimpleLock *lock);
- bool simple_rdlock_start(SimpleLock *lock, MDRequest *mdr);
- void simple_rdlock_finish(SimpleLock *lock, MDRequest *mdr);
- bool simple_xlock_start(SimpleLock *lock, MDRequest *mdr);
- void simple_xlock_finish(SimpleLock *lock, MDRequest *mdr);
+ bool simple_rdlock_start(SimpleLock *lock, MDRequest *mut);
+ void simple_rdlock_finish(SimpleLock *lock, Mutation *mut);
+ bool simple_xlock_start(SimpleLock *lock, MDRequest *mut);
+ void simple_xlock_finish(SimpleLock *lock, Mutation *mut);
public:
bool dentry_can_rdlock_trace(vector<CDentry*>& trace);
void scatter_sync(ScatterLock *lock);
void scatter_scatter(ScatterLock *lock);
void scatter_tempsync(ScatterLock *lock);
- bool scatter_rdlock_start(ScatterLock *lock, MDRequest *mdr);
- void scatter_rdlock_finish(ScatterLock *lock, MDRequest *mdr);
- bool scatter_wrlock_try(ScatterLock *lock);
- bool scatter_wrlock_start(ScatterLock *lock, MDRequest *mdr);
- void scatter_wrlock_finish(ScatterLock *lock, MDRequest *mdr);
+ bool scatter_rdlock_start(ScatterLock *lock, MDRequest *mut);
+ void scatter_rdlock_finish(ScatterLock *lock, Mutation *mut);
+ bool scatter_wrlock_try(ScatterLock *lock, Mutation *mut);
+ bool scatter_wrlock_start(ScatterLock *lock, MDRequest *mut);
+ void scatter_wrlock_finish(ScatterLock *lock, Mutation *mut);
void scatter_writebehind(ScatterLock *lock);
class C_Locker_ScatterWB : public Context {
void scatter_writebehind_finish(ScatterLock *lock, LogSegment *ls);
public:
- void predirty_nested(class EMetaBlob *blob, CInode *in, list<CInode*> &ls);
+ void predirty_nested(Mutation *mut, EMetaBlob *blob, CInode *in);
// local
protected:
- bool local_wrlock_start(LocalLock *lock, MDRequest *mdr);
- void local_wrlock_finish(LocalLock *lock, MDRequest *mdr);
- bool local_xlock_start(LocalLock *lock, MDRequest *mdr);
- void local_xlock_finish(LocalLock *lock, MDRequest *mdr);
+ bool local_wrlock_start(LocalLock *lock, MDRequest *mut);
+ void local_wrlock_finish(LocalLock *lock, Mutation *mut);
+ bool local_xlock_start(LocalLock *lock, MDRequest *mut);
+ void local_xlock_finish(LocalLock *lock, Mutation *mut);
// file
void file_mixed(FileLock *lock);
void file_loner(FileLock *lock);
bool file_rdlock_try(FileLock *lock, Context *con);
- bool file_rdlock_start(FileLock *lock, MDRequest *mdr);
- void file_rdlock_finish(FileLock *lock, MDRequest *mdr);
- bool file_wrlock_start(FileLock *lock, bool force=false);
+ bool file_rdlock_start(FileLock *lock, MDRequest *mut);
+ void file_rdlock_finish(FileLock *lock, Mutation *mut);
+ bool file_wrlock_start(FileLock *lock, MDRequest *mut, bool force=false);
void file_wrlock_finish(FileLock *lock);
- bool file_xlock_start(FileLock *lock, MDRequest *mdr);
- void file_xlock_finish(FileLock *lock, MDRequest *mdr);
+ bool file_xlock_start(FileLock *lock, MDRequest *mut);
+ void file_xlock_finish(FileLock *lock, Mutation *mut);
void request_inode_file_caps(CInode *in);
void handle_inode_file_caps(class MInodeFileCaps *m);
- void file_update_finish(CInode *in, LogSegment *ls, list<CInode*> &nest_updates, bool share);
+ void file_update_finish(CInode *in, Mutation *mut, bool share);
public:
bool check_inode_max_size(CInode *in, bool forcewrlock=false);
private:
}
};
-/** active_request_t
- * state we track for requests we are currently processing.
- * mostly information about locks held, so that we can drop them all
- * the request is finished or forwarded. see request_*().
- */
-struct MDRequest {
- metareqid_t reqid;
- Session *session;
-
- // -- i am a client (master) request
- MClientRequest *client_request; // client request (if any)
-
- vector<CDentry*> trace; // original path traversal.
- CInode *ref; // reference inode. if there is only one, and its path is pinned.
-
- // -- i am a slave request
- MMDSSlaveRequest *slave_request; // slave request (if one is pending; implies slave == true)
- int slave_to_mds; // this is a slave request if >= 0.
-
- // -- misc --
+struct Mutation {
LogSegment *ls; // the log segment i'm committing to
utime_t now;
// for applying projected inode changes
list<CInode*> projected_inodes;
+ list<CDir*> projected_fnodes;
+
+ Mutation() : ls(0),
+ done_locking(false), committing(false), aborted(false)
+ {}
+
+ // pin items in cache
+ void pin(MDSCacheObject *o) {
+ if (pins.count(o) == 0) {
+ o->get(MDSCacheObject::PIN_REQUEST);
+ pins.insert(o);
+ }
+ }
+ void set_stickydirs(CInode *in) {
+ if (stickydirs.count(in) == 0) {
+ in->get_stickydirs();
+ stickydirs.insert(in);
+ }
+ }
+
+ // auth pins
+ bool is_auth_pinned(MDSCacheObject *object) {
+ return auth_pins.count(object) || remote_auth_pins.count(object);
+ }
+ void auth_pin(MDSCacheObject *object) {
+ if (!is_auth_pinned(object)) {
+ object->auth_pin();
+ auth_pins.insert(object);
+ }
+ }
+ void auth_unpin(MDSCacheObject *object) {
+ assert(is_auth_pinned(object));
+ object->auth_unpin();
+ auth_pins.erase(object);
+ }
+ void drop_local_auth_pins() {
+ for (set<MDSCacheObject*>::iterator it = auth_pins.begin();
+ it != auth_pins.end();
+ it++) {
+ assert((*it)->is_auth());
+ (*it)->auth_unpin();
+ }
+ auth_pins.clear();
+ }
+
+ void add_projected_inode(CInode *in) {
+ projected_inodes.push_back(in);
+ }
+ void pop_and_dirty_projected_inodes() {
+ while (!projected_inodes.empty()) {
+ CInode *in = projected_inodes.front();
+ projected_inodes.pop_front();
+ in->pop_and_dirty_projected_inode(ls);
+ }
+ }
+
+ void add_projected_fnode(CDir *dir) {
+ projected_fnodes.push_back(dir);
+ }
+ void pop_and_dirty_projected_fnodes() {
+ while (!projected_fnodes.empty()) {
+ CDir *dir = projected_fnodes.front();
+ projected_fnodes.pop_front();
+ dir->pop_and_dirty_projected_fnode(ls);
+ }
+ }
+
+ virtual void print(ostream &out) {
+ out << "mutation(" << this << ")";
+ }
+};
+
+inline ostream& operator<<(ostream& out, Mutation &mut)
+{
+ mut.print(out);
+ return out;
+}
+
+
+/** active_request_t
+ * state we track for requests we are currently processing.
+ * mostly information about locks held, so that we can drop them all
+ * the request is finished or forwarded. see request_*().
+ */
+struct MDRequest : public Mutation {
+ metareqid_t reqid;
+ Session *session;
+
+ // -- i am a client (master) request
+ MClientRequest *client_request; // client request (if any)
+
+ vector<CDentry*> trace; // original path traversal.
+ CInode *ref; // reference inode. if there is only one, and its path is pinned.
+
+ // -- i am a slave request
+ MMDSSlaveRequest *slave_request; // slave request (if one is pending; implies slave == true)
+ int slave_to_mds; // this is a slave request if >= 0.
+
// break rarely-used fields into a separately allocated structure
// to save memory for most ops
MDRequest() :
session(0), client_request(0), ref(0),
slave_request(0), slave_to_mds(-1),
- ls(0),
- done_locking(false), committing(false), aborted(false),
_more(0) {}
MDRequest(metareqid_t ri, MClientRequest *req) :
reqid(ri), session(0), client_request(req), ref(0),
slave_request(0), slave_to_mds(-1),
- ls(0),
- done_locking(false), committing(false), aborted(false),
_more(0) {}
MDRequest(metareqid_t ri, int by) :
reqid(ri), session(0), client_request(0), ref(0),
slave_request(0), slave_to_mds(by),
- ls(0),
- done_locking(false), committing(false), aborted(false),
_more(0) {}
~MDRequest() {
delete _more;
bool slave_did_prepare() { return more()->slave_commit; }
- // pin items in cache
- void pin(MDSCacheObject *o) {
- if (pins.count(o) == 0) {
- o->get(MDSCacheObject::PIN_REQUEST);
- pins.insert(o);
- }
- }
- void set_stickydirs(CInode *in) {
- if (stickydirs.count(in) == 0) {
- in->get_stickydirs();
- stickydirs.insert(in);
- }
- }
-
- // auth pins
- bool is_auth_pinned(MDSCacheObject *object) {
- return auth_pins.count(object) || remote_auth_pins.count(object);
- }
- void auth_pin(MDSCacheObject *object) {
- if (!is_auth_pinned(object)) {
- object->auth_pin();
- auth_pins.insert(object);
- }
- }
- void auth_unpin(MDSCacheObject *object) {
- assert(is_auth_pinned(object));
- object->auth_unpin();
- auth_pins.erase(object);
- }
- void drop_local_auth_pins() {
- for (set<MDSCacheObject*>::iterator it = auth_pins.begin();
- it != auth_pins.end();
- it++) {
- assert((*it)->is_auth());
- (*it)->auth_unpin();
- }
- auth_pins.clear();
- }
-
- void add_projected_inode(CInode *in) {
- projected_inodes.push_back(in);
- }
- void pop_and_dirty_projected_inodes() {
- while (!projected_inodes.empty()) {
- CInode *in = projected_inodes.front();
- projected_inodes.pop_front();
- in->pop_and_dirty_projected_inode(ls);
- }
+ void print(ostream &out) {
+ out << "request(" << reqid;
+ //if (request) out << " " << *request;
+ if (is_slave()) out << " slave_to mds" << slave_to_mds;
+ if (client_request) out << " cr=" << client_request;
+ if (slave_request) out << " sr=" << slave_request;
+ out << ")";
}
};
-inline ostream& operator<<(ostream& out, MDRequest &mdr)
-{
- out << "request(" << mdr.reqid;
- //if (mdr.request) out << " " << *mdr.request;
- if (mdr.is_slave()) out << " slave_to mds" << mdr.slave_to_mds;
- if (mdr.client_request) out << " cr=" << mdr.client_request;
- if (mdr.slave_request) out << " sr=" << mdr.slave_request;
- out << ")";
- return out;
-}
struct MDSlaveUpdate {
EMetaBlob commit;