From 9bdf337f0c841694a361cdba1b0ab34a409b0080 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Thu, 17 Mar 2016 20:00:36 +0800 Subject: [PATCH 1/2] mds: avoid scrubbing (CDir*)NULL If dirfrags get fragmented in the middle of scrubbing, get_dirfrag() can return NULL. Fixes: #15167 Signed-off-by: Yan, Zheng --- src/mds/ScrubStack.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/mds/ScrubStack.cc b/src/mds/ScrubStack.cc index 1eaddf65fb9..7da1b4bb509 100644 --- a/src/mds/ScrubStack.cc +++ b/src/mds/ScrubStack.cc @@ -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; From 865eb89a67764758ec45152ed81706111971f095 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Fri, 18 Mar 2016 10:16:37 +0800 Subject: [PATCH 2/2] mds: forbid fragmenting dirfrag while scrub in progress Signed-off-by: Yan, Zheng --- src/mds/CInode.cc | 10 ++++------ src/mds/CInode.h | 4 ++++ src/mds/MDCache.cc | 5 +++++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 28a1b1a240e..423be968930 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -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* 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::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::iterator i = scrub_infop->dirfrag_stamps.begin(); i != scrub_infop->dirfrag_stamps.end(); diff --git a/src/mds/CInode.h b/src/mds/CInode.h index 5ff343a013f..c3fe65aaaff 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -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. diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 9eec056905c..d9e59018f61 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -10569,6 +10569,11 @@ bool MDCache::can_fragment(CInode *diri, list& dirs) return false; } + if (diri->scrub_is_in_progress()) { + dout(7) << "can_fragment: scrub in progress" << dendl; + return false; + } + for (list::iterator p = dirs.begin(); p != dirs.end(); ++p) { CDir *dir = *p; if (dir->state_test(CDir::STATE_FRAGMENTING)) {