Merge pull request #8180 from ukernel/jewel-15167

Be more careful about directory fragmentation and scrubbing

Reviewed-by: John Spray <john.spray@redhat.com>
Reviewed-by: Greg Farnum <gfarnum@redhat.com>
This commit is contained in:
Gregory Farnum 2016-03-24 17:44:53 -07:00
commit 0831e5944c
4 changed files with 20 additions and 9 deletions

View File

@ -4173,12 +4173,10 @@ void CInode::scrub_initialize(CDentry *scrub_parent,
MDSInternalContextBase *f)
{
dout(20) << __func__ << " with scrub_version " << get_version() << dendl;
assert(!scrub_infop || !scrub_infop->scrub_in_progress);
assert(!scrub_is_in_progress());
scrub_info();
if (!scrub_infop)
scrub_infop = new scrub_info_t();
else
assert(!scrub_infop->scrub_in_progress);
if (get_projected_inode()->is_dir()) {
// fill in dirfrag_stamps with initial state
@ -4210,7 +4208,7 @@ void CInode::scrub_initialize(CDentry *scrub_parent,
int CInode::scrub_dirfrag_next(frag_t* out_dirfrag)
{
dout(20) << __func__ << dendl;
assert(scrub_infop && scrub_infop->scrub_in_progress);
assert(scrub_is_in_progress());
if (!is_dir()) {
return -ENOTDIR;
@ -4258,7 +4256,7 @@ void CInode::scrub_dirfrags_scrubbing(list<frag_t>* out_dirfrags)
void CInode::scrub_dirfrag_finished(frag_t dirfrag)
{
dout(20) << __func__ << " on frag " << dirfrag << dendl;
assert(scrub_infop && scrub_infop->scrub_in_progress);
assert(scrub_is_in_progress());
std::map<frag_t, scrub_stamp_info_t>::iterator i =
scrub_infop->dirfrag_stamps.find(dirfrag);
@ -4271,7 +4269,7 @@ void CInode::scrub_dirfrag_finished(frag_t dirfrag)
void CInode::scrub_finished(MDSInternalContextBase **c) {
dout(20) << __func__ << dendl;
assert(scrub_info()->scrub_in_progress);
assert(scrub_is_in_progress());
for (std::map<frag_t, scrub_stamp_info_t>::iterator i =
scrub_infop->dirfrag_stamps.begin();
i != scrub_infop->dirfrag_stamps.end();

View File

@ -288,6 +288,10 @@ public:
scrub_info_create();
return scrub_infop;
}
bool scrub_is_in_progress() const {
return (scrub_infop && scrub_infop->scrub_in_progress);
}
/**
* Start scrubbing on this inode. That could be very short if it's
* a file, or take a long time if we're recursively scrubbing a directory.

View File

@ -10569,6 +10569,11 @@ bool MDCache::can_fragment(CInode *diri, list<CDir*>& dirs)
return false;
}
if (diri->scrub_is_in_progress()) {
dout(7) << "can_fragment: scrub in progress" << dendl;
return false;
}
for (list<CDir*>::iterator p = dirs.begin(); p != dirs.end(); ++p) {
CDir *dir = *p;
if (dir->state_test(CDir::STATE_FRAGMENTING)) {

View File

@ -146,11 +146,15 @@ void ScrubStack::scrub_dir_inode(CInode *in,
++i) {
// turn frags into CDir *
CDir *dir = in->get_dirfrag(*i);
scrubbing_cdirs.push_back(dir);
dout(25) << __func__ << " got CDir " << *dir << " presently scrubbing" << dendl;
if (dir) {
scrubbing_cdirs.push_back(dir);
dout(25) << __func__ << " got CDir " << *dir << " presently scrubbing" << dendl;
} else {
in->scrub_dirfrag_finished(*i);
dout(25) << __func__ << " missing dirfrag " << *i << " skip scrubbing" << dendl;
}
}
dout(20) << __func__ << " consuming from " << scrubbing_cdirs.size()
<< " scrubbing cdirs" << dendl;