case CEPH_LOCK_IDFT:
case CEPH_LOCK_IDIR:
case CEPH_LOCK_INESTED:
- assert(0);
+ return scatter_xlock_start((ScatterLock*)lock, mut);
default:
return simple_xlock_start(lock, mut);
}
case CEPH_LOCK_IDFT:
case CEPH_LOCK_IDIR:
case CEPH_LOCK_INESTED:
- assert(0);
+ return scatter_xlock_finish((ScatterLock*)lock, mut);
default:
return simple_xlock_finish(lock, mut);
}
}
+bool Locker::scatter_xlock_start(ScatterLock *lock, MDRequest *mut)
+{
+ dout(7) << "file_xlock_start on " << *lock << " on " << *lock->get_parent() << dendl;
+
+ assert(lock->get_parent()->is_auth()); // remote scatter xlock not implemented
+
+ // already xlocked by me?
+ if (lock->get_xlocked_by() == mut)
+ return true;
+
+ // can't write?
+ if (!lock->can_xlock(mut)) {
+
+ // auth
+ if (!lock->can_xlock_soon()) {
+ if (!lock->is_stable()) {
+ dout(7) << "scatter_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, mut));
+ return false;
+ }
+
+ // initiate lock
+ scatter_lock(lock);
+
+ // fall-thru to below.
+ }
+ }
+
+ // check again
+ if (lock->can_xlock(mut)) {
+ assert(lock->get_parent()->is_auth());
+ lock->get_xlock(mut);
+ mut->locks.insert(lock);
+ mut->xlocks.insert(lock);
+ return true;
+ } else {
+ dout(7) << "scatter_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, mut));
+ return false;
+ }
+}
+
+void Locker::scatter_xlock_finish(ScatterLock *lock, Mutation *mut)
+{
+ dout(7) << "scatter_xlock_finish on " << *lock << " on " << *lock->get_parent() << dendl;
+
+ // drop ref
+ assert(lock->can_xlock(mut));
+ lock->put_xlock();
+ mut->locks.erase(lock);
+ mut->xlocks.erase(lock);
+
+ assert(lock->get_parent()->is_auth()); // or implement remote xlocks
+
+ // others waiting?
+ lock->finish_waiters(SimpleLock::WAIT_STABLE |
+ SimpleLock::WAIT_WR |
+ SimpleLock::WAIT_RD, 0);
+
+ if (lock->get_parent()->is_auth())
+ scatter_eval(lock);
+}
+
+
class C_Locker_ScatterEval : public Context {
Locker *locker;
ScatterLock *lock;
CDentry *dn;
CInode *targeti;
version_t dpv;
- version_t dirpv;
public:
- C_MDS_link_remote_finish(MDS *m, MDRequest *r, CDentry *d, CInode *ti, version_t dirpv_) :
+ C_MDS_link_remote_finish(MDS *m, MDRequest *r, CDentry *d, CInode *ti) :
mds(m), mdr(r), dn(d), targeti(ti),
- dpv(d->get_projected_version()),
- dirpv(dirpv_) { }
+ dpv(d->get_projected_version()) {}
void finish(int r) {
assert(r == 0);
- mds->server->_link_remote_finish(mdr, dn, targeti, dpv, dirpv);
+ mds->server->_link_remote_finish(mdr, dn, targeti, dpv);
}
};
mdr->ls = mdlog->get_current_segment();
EUpdate *le = new EUpdate(mdlog, "link_remote");
le->metablob.add_client_req(mdr->reqid);
- version_t dirpv = predirty_dn_diri(mdr, dn, &le->metablob); // dir inode's mtime
- le->metablob.add_dir_context(dn->get_dir());
+ mds->locker->predirty_nested(mdr, &le->metablob, targeti, dn->dir, false, true, 1);
le->metablob.add_remote_dentry(dn, true, targeti->ino(),
MODE_TO_DT(targeti->inode.mode)); // new remote
mdr->committing = true;
// log + wait
- mdlog->submit_entry(le, new C_MDS_link_remote_finish(mds, mdr, dn, targeti, dirpv));
+ mdlog->submit_entry(le, new C_MDS_link_remote_finish(mds, mdr, dn, targeti));
}
void Server::_link_remote_finish(MDRequest *mdr, CDentry *dn, CInode *targeti,
- version_t dpv, version_t dirpv)
+ version_t dpv)
{
dout(10) << "_link_remote_finish " << *dn << " to " << *targeti << dendl;
dn->dir->link_remote_inode(dn, targeti);
dn->mark_dirty(dpv, mdr->ls);
- // dir inode's mtime
- dirty_dn_diri(mdr, dn, dirpv);
+ mdr->apply();
// bump target popularity
mds->balancer->hit_inode(mdr->now, targeti, META_POP_IWR);
EUpdate *le = new EUpdate(mdlog, "unlink_local");
le->metablob.add_client_req(mdr->reqid);
- version_t ipv = 0; // dirty inode version
- inode_t *ji = 0; // journaled projected inode
+ if (dn->is_primary())
+ dn->inode->projected_parent = straydn;
+
+ inode_t *pi = dn->inode->project_inode();
+ mdr->add_projected_inode(dn->inode);
+ pi->version = dn->inode->pre_dirty();
+ pi->nlink--;
+ pi->ctime = mdr->now;
+
+ mds->locker->predirty_nested(mdr, &le->metablob, dn->inode, dn->dir,
+ dn->is_primary(), true, -1);
+
if (dn->is_primary()) {
// primary link. add stray dentry.
assert(straydn);
- dn->inode->projected_parent = straydn;
- ipv = dn->inode->pre_dirty();
le->metablob.add_dir_context(straydn->dir);
- ji = le->metablob.add_primary_dentry(straydn, true, dn->inode);
+ le->metablob.add_primary_dentry(straydn, true, dn->inode, pi);
} else {
// remote link. update remote inode.
- ipv = dn->inode->pre_dirty();
le->metablob.add_dir_context(dn->inode->get_parent_dir());
- ji = le->metablob.add_primary_dentry(dn->inode->parent, true, dn->inode);
+ le->metablob.add_primary_dentry(dn->inode->parent, true, dn->inode);
}
-
- // update journaled target inode
- inode_t *pi = dn->inode->project_inode();
- pi->nlink--;
- pi->ctime = mdr->now;
- pi->version = ipv;
- *ji = *pi; // copy into journal
// the unlinked dentry
dn->pre_dirty();
- mds->locker->predirty_nested(mdr, &le->metablob, dn->inode, dn->dir,
- dn->is_primary(), true, -1);
le->metablob.add_null_dentry(dn, true);
if (mdr->more()->dst_reanchor_atid)
straydn->dir->link_primary_inode(straydn, in);
}
- // nlink--, dirty old dentry
- in->pop_and_dirty_projected_inode(mdr->ls);
- dn->mark_dirty(dnpv, mdr->ls);
-
mdr->apply();
+ dn->mark_dirty(dnpv, mdr->ls);
// share unlink news with replicas
for (map<int,int>::iterator it = dn->replicas_begin();