- anchor_destroy needs to xlock linklock.. which means it needs a Mutation wrapper?
- ... when it gets a caller.. someday..
-- fix rm -r vs mds exports
- - use new dir size values in dirstat
-
- replay of dir fragmentation (dont want dir frozen, pins, etc.?)
- rename slave in-memory rollback on failure
}
}
- if (actual.nsubdirs != expect.nsubdirs ||
- actual.nfiles != expect.nfiles) {
+ if (dir != "" &&
+ (actual.nsubdirs != expect.nsubdirs ||
+ actual.nfiles != expect.nfiles)) {
dout(0) << dir << ": expected " << expect << dendl;
dout(0) << dir << ": got " << actual << dendl;
}
if (time_to_stop()) return 0;
+ srand(0);
if (1) {
for (int k=0; k<n; k++) {
inode->adjust_nested_anchors(by);
}
+void CDir::verify_fragstat()
+{
+ assert(is_complete());
+ if (inode->is_stray())
+ return;
+
+ frag_info_t c;
+ memset(&c, 0, sizeof(c));
+
+ for (map_t::iterator it = items.begin();
+ it != items.end();
+ it++) {
+ CDentry *dn = it->second;
+ if (dn->is_null())
+ continue;
+
+ dout(10) << " " << *dn << dendl;
+ if (dn->is_primary())
+ dout(10) << " " << *dn->inode << dendl;
+
+ if (dn->is_primary()) {
+ if (dn->inode->is_dir())
+ c.nsubdirs++;
+ else
+ c.nfiles++;
+ }
+ if (dn->is_remote()) {
+ if (dn->get_remote_d_type() == (S_IFDIR >> 12))
+ c.nsubdirs++;
+ else
+ c.nfiles++;
+ }
+ }
+
+ if (c.nsubdirs != fnode.fragstat.nsubdirs ||
+ c.nfiles != fnode.fragstat.nfiles) {
+ dout(0) << "verify_fragstat failed " << fnode.fragstat << " on " << *this << dendl;
+ dout(0) << " i count " << c << dendl;
+ assert(0);
+ } else {
+ dout(0) << "verify_fragstat ok " << fnode.fragstat << " on " << *this << dendl;
+ }
+}
/*****************************************************************************
* FREEZING
int get_nested_auth_pins() { return nested_auth_pins; }
void auth_pin();
void auth_unpin();
+
void adjust_nested_auth_pins(int inc);
+ void verify_fragstat();
int get_nested_anchors() { return nested_anchors; }
void adjust_nested_anchors(int by);
EMetaBlob *rollback)
{
bool primary_dn = flags & PREDIRTY_PRIMARY;
- bool do_parent = flags & PREDIRTY_DIR;
+ bool do_parent_mtime = flags & PREDIRTY_DIR;
dout(10) << "predirty_nested"
- << (do_parent ? " do_parent_mtime":"")
+ << (do_parent_mtime ? " do_parent_mtime":"")
<< " linkunlink=" << linkunlink
<< (primary_dn ? " primary_dn":" remote_dn")
<< " " << *in << dendl;
parent = in->get_projected_parent_dn()->get_dir();
}
- if (flags == 0) {
- dout(10) << " no flags, just adding dir context to blob(s)" << dendl;
+ if (flags == 0 && linkunlink == 0) {
+ dout(10) << " no flags/linkunlink, just adding dir context to blob(s)" << dendl;
blob->add_dir_context(parent);
if (rollback)
rollback->add_dir_context(parent);
// opportunistically adjust parent dirfrag
CInode *pin = parent->get_inode();
- if (do_parent) {
- assert(mut->wrlocks.count(&pin->dirlock));
+ if (do_parent_mtime || linkunlink) {
+ assert(mut->wrlocks.count(&pin->dirlock) ||
+ mut->is_slave()); // we are slave. master will have wrlocked the dir.
}
// inode -> dirfrag
fnode_t *pf = parent->project_fnode();
pf->version = parent->pre_dirty();
- if (do_parent) {
- dout(10) << "predirty_nested updating mtime/size on " << *parent << dendl;
+ if (do_parent_mtime) {
+ dout(10) << "predirty_nested updating mtime on " << *parent << dendl;
pf->fragstat.mtime = mut->now;
if (mut->now > pf->fragstat.rctime)
pf->fragstat.rctime = mut->now;
- if (linkunlink) {
- if (in->is_dir())
- pf->fragstat.nsubdirs += linkunlink;
- else
- pf->fragstat.nfiles += linkunlink;
- }
+ }
+ if (linkunlink) {
+ dout(10) << "predirty_nested updating size on " << *parent << dendl;
+ if (in->is_dir())
+ pf->fragstat.nsubdirs += linkunlink;
+ else
+ pf->fragstat.nfiles += linkunlink;
}
if (primary_dn) {
if (linkunlink == 0) {
curi = pi;
parent = cur->get_projected_parent_dn()->get_dir();
linkunlink = 0;
- do_parent = false;
+ do_parent_mtime = false;
primary_dn = true;
}
mut->wrlocks.erase(lock);
mut->locks.erase(lock);
}
-
- scatter_eval_gather(lock);
+
+ if (!lock->is_wrlocked())
+ scatter_eval_gather(lock);
}
break; // do it.
case LOCK_SCATTER:
- // lock first. this is the slow way, incidentally.
- if (lock->get_parent()->is_replicated()) {
- send_lock_message(lock, LOCK_AC_LOCK);
- lock->init_gather();
- } else {
- if (!lock->is_wrlocked()) {
- break; // do it now, we're fine
- }
- }
+ if (!lock->get_parent()->is_replicated() &&
+ !lock->is_wrlocked())
+ break; // do it now
+
lock->set_state(LOCK_GLOCKC);
lock->get_parent()->auth_pin();
+
+ if (lock->get_parent()->is_replicated()) {
+ lock->init_gather();
+ send_lock_message(lock, LOCK_AC_LOCK);
+ }
return;
default:
break; // do it.
}
+ lock->set_state(LOCK_GTEMPSYNCC);
+ lock->get_parent()->auth_pin();
+
if (lock->get_parent()->is_replicated()) {
- send_lock_message(lock, LOCK_AC_LOCK);
lock->init_gather();
+ send_lock_message(lock, LOCK_AC_LOCK);
}
- lock->set_state(LOCK_GTEMPSYNCC);
- lock->get_parent()->auth_pin();
+
return;
case LOCK_TEMPSYNC:
}
assert(curdir);
+ // HACK
+ if (curdir->is_complete())
+ curdir->verify_fragstat();
+
// frozen?
/*
if (curdir->is_frozen()) {
LogSegment *ls; // the log segment i'm committing to
utime_t now;
+ // flag mutation as slave
+ int slave_to_mds; // this is a slave request if >= 0.
+
// -- my pins and locks --
// cache pins (so things don't expire)
set< MDSCacheObject* > pins;
Mutation() : ls(0),
done_locking(false), committing(false), aborted(false) {}
- Mutation(metareqid_t ri) : reqid(ri),
- ls(0),
- done_locking(false), committing(false), aborted(false) {}
+ Mutation(metareqid_t ri, int slave_to=-1) :
+ reqid(ri),
+ ls(0),
+ slave_to_mds(slave_to),
+ done_locking(false), committing(false), aborted(false) {}
virtual ~Mutation() {}
+ bool is_master() { return slave_to_mds < 0; }
+ bool is_slave() { return slave_to_mds >= 0; }
+
// pin items in cache
void pin(MDSCacheObject *o) {
if (pins.count(o) == 0) {
// -- 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
// ---------------------------------------------------
MDRequest() :
session(0), client_request(0), ref(0),
- slave_request(0), slave_to_mds(-1),
+ slave_request(0),
_more(0) {}
MDRequest(metareqid_t ri, MClientRequest *req) :
Mutation(ri),
session(0), client_request(req), ref(0),
- slave_request(0), slave_to_mds(-1),
+ slave_request(0),
_more(0) {}
MDRequest(metareqid_t ri, int by) :
- Mutation(ri),
+ Mutation(ri, by),
session(0), client_request(0), ref(0),
- slave_request(0), slave_to_mds(by),
+ slave_request(0),
_more(0) {}
~MDRequest() {
delete _more;
}
- bool is_master() { return slave_to_mds < 0; }
- bool is_slave() { return slave_to_mds >= 0; }
-
More* more() {
if (!_more) _more = new More();
return _more;
assert(dir->get_projected_version() == dir->get_version());
+ if (dir->is_complete())
+ dir->verify_fragstat();
+
// dir
dirfrag_t df = dir->dirfrag();
::encode(df, exportbl);
le->metablob.add_dentry(dn, dn->is_dirty());
}
+ if (dir->is_complete())
+ dir->verify_fragstat();
+
dout(7) << "decode_import_dir done " << *dir << dendl;
return num_imported;
}
dout(20) << " trace added " << lmask << " " << *dn << dendl;
// dir
+ if (dn->get_dir()->is_complete())
+ dn->get_dir()->verify_fragstat();
DirStat::encode(bl, dn->get_dir(), whoami);
dout(20) << " trace added " << *dn->get_dir() << dendl;
return;
}
+ dir->verify_fragstat();
+
mdr->now = g_clock.real_now();
// build dir contents
dout(10) << " destdn " << *destdn << dendl;
+ bool linkmerge = (srcdn->inode == destdn->inode &&
+ (srcdn->is_primary() || destdn->is_primary()));
+ if (linkmerge)
+ dout(10) << " this is a link merge" << dendl;
+
+ // -- create stray dentry? --
+ CDentry *straydn = 0;
+ if (destdn->is_primary() && !linkmerge) {
+ straydn = mdcache->get_or_create_stray_dentry(destdn->inode);
+ mdr->pin(straydn);
+ dout(10) << "straydn is " << *straydn << dendl;
+ }
+
// -- locks --
set<SimpleLock*> rdlocks, wrlocks, xlocks;
+ // straydn?
+ if (straydn)
+ wrlocks.insert(&straydn->dir->inode->dirlock);
+
// rdlock sourcedir path, xlock src dentry
for (int i=0; i<(int)srctrace.size()-1; i++)
rdlocks.insert(&srctrace[i]->lock);
xlocks.insert(&srcdn->lock);
wrlocks.insert(&srcdn->dir->inode->dirlock);
- /*
- * no, this causes problems if the dftlock is scattered...
- * and what was i thinking anyway?
- * rdlocks.insert(&srcdn->dir->inode->dirfragtreelock); // rd lock on srci dirfragtree.
- */
-
// rdlock destdir path, xlock dest dentry
for (int i=0; i<(int)desttrace.size(); i++)
rdlocks.insert(&desttrace[i]->lock);
if (mdr->now == utime_t())
mdr->now = g_clock.real_now();
- bool linkmerge = (srcdn->inode == destdn->inode &&
- (srcdn->is_primary() || destdn->is_primary()));
-
- // -- create stray dentry? --
- CDentry *straydn = 0;
- if (destdn->is_primary() && !linkmerge) {
- straydn = mdcache->get_or_create_stray_dentry(destdn->inode);
- mdr->pin(straydn);
- dout(10) << "straydn is " << *straydn << dendl;
- }
-
// -- prepare witnesses --
/*
* NOTE: we use _all_ replicas as witnesses.
}
// prepare nesting, mtime updates
- if (mdr->is_master()) {
- int predirty_dir = silent ? 0:PREDIRTY_DIR;
-
- // sub off target
- if (!destdn->is_null())
- mds->locker->predirty_nested(mdr, metablob, destdn->inode, destdn->dir,
- (destdn->is_primary() ? PREDIRTY_PRIMARY:0)|predirty_dir, -1,
- rollback);
-
- // move srcdn
- int predirty_primary = (srcdn->is_primary() && srcdn->dir != destdn->dir) ? PREDIRTY_PRIMARY:0;
- int flags = predirty_dir | predirty_primary;
- if (srcdn->is_auth())
- mds->locker->predirty_nested(mdr, metablob, srcdn->inode, srcdn->dir, flags, -1, rollback);
+ int predirty_dir = silent ? 0:PREDIRTY_DIR;
+
+ // sub off target
+ if (destdn->is_auth() && !destdn->is_null())
+ mds->locker->predirty_nested(mdr, metablob, destdn->inode, destdn->dir,
+ (destdn->is_primary() ? PREDIRTY_PRIMARY:0)|predirty_dir, -1,
+ rollback);
+
+ // move srcdn
+ int predirty_primary = (srcdn->is_primary() && srcdn->dir != destdn->dir) ? PREDIRTY_PRIMARY:0;
+ int flags = predirty_dir | predirty_primary;
+ if (srcdn->is_auth())
+ mds->locker->predirty_nested(mdr, metablob, srcdn->inode, srcdn->dir, flags, -1, rollback);
+ if (destdn->is_auth())
mds->locker->predirty_nested(mdr, metablob, srcdn->inode, destdn->dir, flags, 1, rollback);
- }
// add it all to the metablob
// target inode