pi->version = in->pre_dirty();
pi->max_size = new_max;
EOpen *le = new EOpen(mds->mdlog);
- predirty_nested(mut, &le->metablob, in, true, 0, false);
le->metablob.add_dir_context(in->get_parent_dir());
le->metablob.add_primary_dentry(in->parent, true, 0, pi);
le->add_ino(in->ino());
Mutation *mut = new Mutation;
mut->ls = mds->mdlog->get_current_segment();
file_wrlock_force(&in->filelock, mut); // wrlock for duration of journal
- predirty_nested(mut, &le->metablob, in, true, 0, false);
+ predirty_nested(mut, &le->metablob, in, 0, true, false);
le->metablob.add_dir_context(in->get_parent_dir());
le->metablob.add_primary_dentry(in->parent, true, 0, pi);
mds->mdlog->submit_entry(le, new C_Locker_FileUpdate_finish(this, in, mut, change_max));
// nested ---------------------------------------------------------------
void Locker::predirty_nested(Mutation *mut, EMetaBlob *blob,
- CInode *in, bool primary_dn, CDir *parent,
- bool do_parent, int linkunlink)
+ CInode *in, CDir *parent,
+ bool do_nested, bool do_parent, int linkunlink)
{
dout(10) << "predirty_nested "
- << (primary_dn ? "primary_dn ":"remote_dn ")
<< (do_parent ? "do_parent_mtime ":"")
<< "linkunlink=" << linkunlink
+ << (do_nested ? "do_nested ":"")
<< " " << *in << dendl;
if (!parent)
inode_t *curi = in->get_projected_inode();
- __s64 drbytes, drfiles, drsubdirs;
+ __s64 drbytes = 1, drfiles = 0, drsubdirs = 0;
utime_t rctime;
// build list of inodes to wrlock, dirty, and update
if (do_parent) {
assert(mut->wrlocks.count(&pin->dirlock));
assert(mut->wrlocks.count(&pin->nestedlock));
+ assert(do_nested || linkunlink == 0);
}
- if (mut->wrlocks.count(&pin->nestedlock) == 0 &&
+ if (do_nested &&
+ mut->wrlocks.count(&pin->nestedlock) == 0 &&
!scatter_wrlock_try(&pin->nestedlock, mut)) {
dout(10) << "predirty_nested can't wrlock " << pin->nestedlock << " on " << *pin << dendl;
+ do_nested = false;
break;
}
+ if (!do_parent && !do_nested)
+ break;
+
// inode -> dirfrag
mut->add_projected_fnode(parent);
pf->fraginfo.nfiles += linkunlink;
}
}
- if (primary_dn) {
+ if (do_nested) {
if (linkunlink == 0) {
drbytes = curi->nested.rbytes - curi->accounted_nested.rbytes;
drfiles = curi->nested.rfiles - curi->accounted_nested.rfiles;
curi = pi;
parent = cur->get_projected_parent_dn()->get_dir();
linkunlink = 0;
- primary_dn = true;
do_parent = false;
}
le->metablob.add_client_req(req->get_reqid());
le->metablob.add_allocated_ino(newi->ino(), mds->idalloc->get_version());
- mds->locker->predirty_nested(mdr, &le->metablob, newi, true, dn->dir, true, 1);
+ mds->locker->predirty_nested(mdr, &le->metablob, newi, dn->dir, true, true, 1);
le->metablob.add_primary_dentry(dn, true, newi, &newi->inode);
EUpdate *le = new EUpdate(mdlog, "mkdir");
le->metablob.add_client_req(req->get_reqid());
le->metablob.add_allocated_ino(newi->ino(), mds->idalloc->get_version());
- mds->locker->predirty_nested(mdr, &le->metablob, newi, true, dn->dir, true, 1);
+ mds->locker->predirty_nested(mdr, &le->metablob, newi, dn->dir, true, true, 1);
le->metablob.add_primary_dentry(dn, true, newi, &newi->inode);
le->metablob.add_dir(newdir, true, true); // dirty AND complete
EUpdate *le = new EUpdate(mdlog, "symlink");
le->metablob.add_client_req(req->get_reqid());
le->metablob.add_allocated_ino(newi->ino(), mds->idalloc->get_version());
- mds->locker->predirty_nested(mdr, &le->metablob, newi, true, dn->dir, true, 1);
+ mds->locker->predirty_nested(mdr, &le->metablob, newi, dn->dir, true, true, 1);
le->metablob.add_primary_dentry(dn, true, newi, &newi->inode);
// log + wait
// log + wait
EUpdate *le = new EUpdate(mdlog, "link_local");
le->metablob.add_client_req(mdr->reqid);
- mds->locker->predirty_nested(mdr, &le->metablob, targeti, false, dn->dir,
- true, 1);
+ 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
le->metablob.add_dir_context(targeti->get_parent_dir());
// the unlinked dentry
dn->pre_dirty();
- mds->locker->predirty_nested(mdr, &le->metablob, dn->inode, dn->is_primary(), dn->dir,
- true, -1);
+ 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)
xlocks.insert(&srcdn->lock);
wrlocks.insert(&srcdn->dir->inode->dirlock);
wrlocks.insert(&srcdn->dir->inode->nestedlock);
+ if (srcdn->is_primary() && srcdn->inode->is_dir())
+ xlocks.insert(&srcdn->inode->nestedlock);
+
/*
* no, this causes problems if the dftlock is scattered...
* and what was i thinking anyway?
xlocks.insert(&destdn->lock);
wrlocks.insert(&destdn->dir->inode->dirlock);
wrlocks.insert(&destdn->dir->inode->nestedlock);
+ if (destdn->is_primary() && destdn->inode->is_dir())
+ xlocks.insert(&destdn->inode->nestedlock);
// xlock versionlock on srci if remote?
// this ensures it gets safely remotely auth_pinned, avoiding deadlock;
bool linkmerge = (srcdn->inode == destdn->inode &&
(srcdn->is_primary() || destdn->is_primary()));
- if (mdr->is_master()) {
- mdr->more()->pvmap[destdn->dir->inode] = predirty_dn_diri(mdr, destdn, metablob);
- if (destdn->dir != srcdn->dir)
- mdr->more()->pvmap[srcdn->dir->inode] = predirty_dn_diri(mdr, srcdn, metablob);
- }
-
- inode_t *tji = 0; // journaled inode getting nlink--
- version_t tipv = 0; // it's version
- inode_t *sji = 0; // renamed inode, if different that tji
- version_t sipv = 0;
-
+ // prepare
+ inode_t *pi = 0, *ji = 0; // renamed inode
+ inode_t *tpi = 0, *tji = 0; // target/overwritten inode
+
if (linkmerge) {
dout(10) << "will merge remote+primary links" << dendl;
-
+
// destdn -> primary
- metablob->add_dir_context(destdn->dir);
+ tpi = destdn->inode->project_inode();
+ //mdr->add_projected_inode(destdn->inode);
if (destdn->is_auth())
- tipv = mdr->more()->pvmap[destdn] = destdn->pre_dirty(destdn->inode->inode.version);
- tji = metablob->add_primary_dentry(destdn, true, destdn->inode);
+ tpi->version = mdr->more()->pvmap[destdn] = destdn->pre_dirty(destdn->inode->inode.version);
destdn->inode->projected_parent = destdn;
// do src dentry
- metablob->add_dir_context(srcdn->dir);
if (srcdn->is_auth())
mdr->more()->pvmap[srcdn] = srcdn->pre_dirty();
- metablob->add_null_dentry(srcdn, true);
-
} else {
- // move to stray?
+ // target?
if (destdn->is_primary()) {
- // primary. we'll move inode to stray dir.
- assert(straydn);
-
- // link-- inode, move to stray dir.
- metablob->add_dir_context(straydn->dir);
- if (straydn->is_auth())
- tipv = mdr->more()->pvmap[straydn] = straydn->pre_dirty(destdn->inode->inode.version);
- tji = metablob->add_primary_dentry(straydn, true, destdn->inode);
+ assert(straydn); // moving to straydn.
+ // link--, and move.
+ if (destdn->is_auth()) {
+ tpi = destdn->inode->project_inode();
+ //mdr->add_projected_inode(destdn->inode);
+ tpi->version = mdr->more()->pvmap[straydn] = straydn->pre_dirty(tpi->version);
+ }
destdn->inode->projected_parent = straydn;
- }
- else if (destdn->is_remote()) {
- // remote.
+ } else if (destdn->is_remote()) {
// nlink-- targeti
- metablob->add_dir_context(destdn->inode->get_parent_dir());
- if (destdn->inode->is_auth())
- tipv = mdr->more()->pvmap[destdn->inode] = destdn->inode->pre_dirty();
- tji = metablob->add_primary_dentry(destdn->inode->parent, true, destdn->inode); // update primary
- dout(10) << "remote targeti (nlink--) is " << *destdn->inode << dendl;
- }
- else {
+ if (destdn->inode->is_auth()) {
+ tpi = destdn->inode->project_inode();
+ //mdr->add_projected_inode(destdn->inode);
+ tpi->version = mdr->more()->pvmap[destdn->inode] = destdn->inode->pre_dirty();
+ }
+ } else
assert(destdn->is_null());
- }
- // add dest dentry
- metablob->add_dir_context(destdn->dir);
+ // dest
if (srcdn->is_remote()) {
- dout(10) << "src is a remote dentry" << dendl;
if (destdn->is_auth())
mdr->more()->pvmap[destdn] = destdn->pre_dirty();
- metablob->add_remote_dentry(destdn, true, srcdn->get_remote_ino(),
- srcdn->get_remote_d_type());
if (srcdn->inode->is_auth()) {
- sipv = srcdn->inode->pre_dirty();
- sji = metablob->add_primary_dentry(srcdn->inode->get_parent_dn(), true);
+ pi = srcdn->inode->project_inode();
+ //mdr->add_projected_inode(srcdn->inode);
+ pi->version = srcdn->inode->pre_dirty();
}
- } else {
- assert(srcdn->is_primary());
- dout(10) << "src is a primary dentry" << dendl;
+ } else if (srcdn->is_primary()) {
if (destdn->is_auth()) {
+ version_t oldpv;
if (srcdn->is_auth())
- sipv = srcdn->inode->get_projected_version();
+ oldpv = srcdn->inode->get_projected_version();
else {
- sipv = mdr->more()->inode_import_v;
+ oldpv = mdr->more()->inode_import_v;
/* import node */
bufferlist::iterator blp = mdr->more()->inode_import.begin();
srcdn->inode->state_clear(CInode::STATE_AUTH);
srcdn->inode->mark_clean();
}
- sipv = mdr->more()->pvmap[destdn] = destdn->pre_dirty(sipv+1);
+ pi = srcdn->inode->project_inode();
+ //mdr->add_projected_inode(srcdn->inode);
+ pi->version = mdr->more()->pvmap[destdn] = destdn->pre_dirty(oldpv);
}
- sji = metablob->add_primary_dentry(destdn, true, srcdn->inode);
srcdn->inode->projected_parent = destdn;
}
-
- // remove src dentry
- metablob->add_dir_context(srcdn->dir);
+
+ // remove src
if (srcdn->is_auth())
mdr->more()->pvmap[srcdn] = srcdn->pre_dirty();
+ }
+
+ if (pi) {
+ pi->ctime = mdr->now;
+ }
+ if (tpi) {
+ tpi->nlink--;
+ tpi->ctime = mdr->now;
+ }
+
+ // prepare nesting, mtime updates
+ if (mdr->is_master()) {
+ // sub off target
+ if (!linkmerge && destdn->is_primary())
+ mds->locker->predirty_nested(mdr, metablob, destdn->inode, destdn->dir,
+ true, true, -1);
+ if (destdn->dir == srcdn->dir) {
+ // same dir. don't update nested info or adjust counts.
+ mds->locker->predirty_nested(mdr, metablob, srcdn->inode, srcdn->dir,
+ false, true);
+ } else {
+ // different dir. update nested accounting.
+ if (srcdn->is_auth())
+ mds->locker->predirty_nested(mdr, metablob, srcdn->inode, srcdn->dir,
+ srcdn->is_primary(), true, -1);
+ mds->locker->predirty_nested(mdr, metablob, srcdn->inode, destdn->dir,
+ srcdn->is_primary(), true, 1);
+ }
+ }
+
+ // add it all to the metablob
+ if (linkmerge) {
+ metablob->add_primary_dentry(destdn, true, destdn->inode, tpi);
+ metablob->add_null_dentry(srcdn, true);
+ } else {
+ // target inode
+ if (destdn->is_primary())
+ tji = metablob->add_primary_dentry(straydn, true, destdn->inode, tpi);
+ else if (destdn->is_remote()) {
+ metablob->add_dir_context(destdn->inode->get_parent_dir());
+ tji = metablob->add_primary_dentry(destdn->inode->parent, true, destdn->inode, tpi);
+ }
+
+ // dest
+ if (srcdn->is_remote()) {
+ metablob->add_remote_dentry(destdn, true, srcdn->get_remote_ino(),
+ srcdn->get_remote_d_type());
+ if (pi)
+ metablob->add_primary_dentry(srcdn->inode->get_parent_dn(), true, srcdn->inode, pi); // ???
+ } else if (srcdn->is_primary()) {
+ ji = metablob->add_primary_dentry(destdn, true, srcdn->inode, pi);
+ }
+
+ // src
metablob->add_null_dentry(srcdn, true);
// new subtree?
}
}
- if (tipv) {
- // update journaled target/overwritten inode
- inode_t *pi = destdn->inode->project_inode();
- pi->nlink--;
- pi->ctime = mdr->now;
- pi->version = tipv;
- *tji = *pi; // copy into journal
+ // do inode updates in journal, even if we aren't auth (hmm, is this necessary?)
+ if (ji && !pi) {
+ ji->ctime = mdr->now;
}
- if (sji) {
- // update renamed inode
- inode_t *pi = srcdn->inode->project_inode();
- pi->ctime = mdr->now;
- pi->version = sipv;
- *sji = *pi; // copy into journal
+ if (tji && !tpi) {
+ tji->nlink--;
+ tji->ctime = mdr->now;
}
// anchor updates?
bool linkmerge = (srcdn->inode == destdn->inode &&
(srcdn->is_primary() || destdn->is_primary()));
- // dir mtimes
- if (mdr->is_master()) {
- dirty_dn_diri(mdr, destdn, mdr->more()->pvmap[destdn->dir->inode]);
- if (destdn->dir != srcdn->dir)
- dirty_dn_diri(mdr, srcdn, mdr->more()->pvmap[srcdn->dir->inode]);
- }
-
if (linkmerge) {
if (destdn->is_primary()) {
dout(10) << "merging remote onto primary link" << dendl;
// nlink-- in place
if (destdn->inode->is_auth())
destdn->inode->pop_and_dirty_projected_inode(mdr->ls);
-
+
// unlink srcdn
srcdn->dir->unlink_inode(srcdn);
if (srcdn->is_auth())
srcdn->mark_dirty(mdr->more()->pvmap[srcdn], mdr->ls);
} else {
dout(10) << "merging primary onto remote link" << dendl;
- assert(srcdn->is_primary());
-
+
// move inode to dest
srcdn->dir->unlink_inode(srcdn);
destdn->dir->unlink_inode(destdn);
if (srcdn->is_auth())
srcdn->mark_dirty(mdr->more()->pvmap[srcdn], mdr->ls);
}
- }
- else {
+ } else {
// unlink destdn?
if (!destdn->is_null())
destdn->dir->unlink_inode(destdn);
if (straydn) {
dout(10) << "straydn is " << *straydn << dendl;
-
+
// relink oldin to stray dir. destdn was primary.
assert(oldin);
straydn->dir->link_primary_inode(straydn, oldin);
//assert(straypv == ipv);
-
+
// nlink-- in stray dir.
if (oldin->is_auth())
oldin->pop_and_dirty_projected_inode(mdr->ls);
// srcdn was primary.
srcdn->dir->unlink_inode(srcdn);
destdn->dir->link_primary_inode(destdn, in);
-
+
// srcdn inode import?
if (!srcdn->is_auth() && destdn->is_auth()) {
assert(mdr->more()->inode_import.length() > 0);
destdn->inode->state_set(CInode::STATE_AUTH);
}
}
+
if (destdn->inode->is_auth())
destdn->inode->pop_and_dirty_projected_inode(mdr->ls);
srcdn->mark_dirty(mdr->more()->pvmap[srcdn], mdr->ls);
}
+ // apply remaining projected inodes
+ mdr->apply();
+
// update subtree map?
if (destdn->is_primary() && destdn->inode->is_dir())
mdcache->adjust_subtree_after_rename(destdn->inode, srcdn->dir);
le->metablob.add_client_req(req->get_reqid());
le->metablob.add_allocated_ino(in->ino(), mds->idalloc->get_version());
- mds->locker->predirty_nested(mdr, &le->metablob, in, true, dn->dir, true, 1);
+ mds->locker->predirty_nested(mdr, &le->metablob, in, dn->dir, true, true, 1);
le->metablob.add_primary_dentry(dn, true, in, &in->inode);
// log + wait