Merge PR #18538 into master

* refs/pull/18538/head:
	mds: clean up clog damage message when repairing
	mds: flush after scrub repairs
	mds: don't report repaired backtraces in damagetable
	mds: cleaner scrub complete log msg

Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
This commit is contained in:
Patrick Donnelly 2017-11-03 14:37:26 -07:00
commit 1eb9766d86
No known key found for this signature in database
GPG Key ID: 3A2A7E25BEA8AADB
6 changed files with 106 additions and 28 deletions

View File

@ -3958,6 +3958,12 @@ next:
<< "(" << path << "), rewriting it";
in->_mark_dirty_parent(in->mdcache->mds->mdlog->get_current_segment(),
false);
// Flag that we repaired this BT so that it won't go into damagetable
results->backtrace.repaired = true;
// Flag that we did some repair work so that our repair operation
// can be flushed at end of scrub
in->scrub_infop->header->set_repaired();
}
// If the inode's number was free in the InoTable, fix that
@ -4096,6 +4102,7 @@ next:
dir->scrub_infop->pending_scrub_error) {
dir->scrub_infop->pending_scrub_error = false;
if (dir->scrub_infop->header->get_repair()) {
results->raw_stats.repaired = true;
results->raw_stats.error_str
<< "dirfrag(" << p->first << ") has bad stats (will be fixed); ";
} else {
@ -4114,6 +4121,7 @@ next:
results->raw_stats.error_str
<< "freshly-calculated rstats don't match existing ones (will be fixed)";
in->mdcache->repair_inode_stats(in);
results->raw_stats.repaired = true;
} else {
results->raw_stats.error_str
<< "freshly-calculated rstats don't match existing ones";
@ -4188,6 +4196,18 @@ void CInode::validated_data::dump(Formatter *f) const
f->close_section(); // results
}
bool CInode::validated_data::all_damage_repaired() const
{
bool unrepaired =
(raw_stats.checked && !raw_stats.passed && !raw_stats.repaired)
||
(backtrace.checked && !backtrace.passed && !backtrace.repaired)
||
(inode.checked && !inode.passed && !inode.repaired);
return !unrepaired;
}
void CInode::dump(Formatter *f) const
{
InodeStoreBase::dump(f);
@ -4323,7 +4343,7 @@ void CInode::scrub_maybe_delete_info()
}
void CInode::scrub_initialize(CDentry *scrub_parent,
const ScrubHeaderRefConst& header,
ScrubHeaderRef& header,
MDSInternalContextBase *f)
{
dout(20) << __func__ << " with scrub_version " << get_version() << dendl;
@ -4453,7 +4473,12 @@ void CInode::scrub_finished(MDSInternalContextBase **c) {
if (scrub_infop->header->get_origin() == this) {
// We are at the point that a tagging scrub was initiated
LogChannelRef clog = mdcache->mds->clog;
clog->info() << "scrub complete with tag '" << scrub_infop->header->get_tag() << "'";
if (scrub_infop->header->get_tag().empty()) {
clog->info() << "scrub complete";
} else {
clog->info() << "scrub complete with tag '"
<< scrub_infop->header->get_tag() << "'";
}
}
}

View File

@ -273,7 +273,7 @@ class CInode : public MDSCacheObject, public InodeStoreBase, public Counter<CIno
/// my own (temporary) stamps and versions for each dirfrag we have
std::map<frag_t, scrub_stamp_info_t> dirfrag_stamps;
ScrubHeaderRefConst header;
ScrubHeaderRef header;
scrub_info_t() : scrub_stamp_info_t(),
scrub_parent(NULL), on_finish(NULL),
@ -287,6 +287,14 @@ class CInode : public MDSCacheObject, public InodeStoreBase, public Counter<CIno
return scrub_infop;
}
ScrubHeaderRef get_scrub_header() {
if (scrub_infop == nullptr) {
return nullptr;
} else {
return scrub_infop->header;
}
}
bool scrub_is_in_progress() const {
return (scrub_infop && scrub_infop->scrub_in_progress);
}
@ -299,7 +307,7 @@ class CInode : public MDSCacheObject, public InodeStoreBase, public Counter<CIno
* directory's get_projected_version())
*/
void scrub_initialize(CDentry *scrub_parent,
const ScrubHeaderRefConst& header,
ScrubHeaderRef& header,
MDSInternalContextBase *f);
/**
* Get the next dirfrag to scrub. Gives you a frag_t in output param which
@ -1108,14 +1116,13 @@ public:
*/
struct validated_data {
template<typename T>struct member_status {
bool checked;
bool passed;
int ondisk_read_retval;
bool checked = false;
bool passed = false;
bool repaired = false;
int ondisk_read_retval = 0;
T ondisk_value;
T memory_value;
std::stringstream error_str;
member_status() : checked(false), passed(false),
ondisk_read_retval(0) {}
};
bool performed_validation;
@ -1134,6 +1141,8 @@ public:
passed_validation(false) {}
void dump(Formatter *f) const;
bool all_damage_repaired() const;
};
/**

View File

@ -12112,14 +12112,45 @@ void MDCache::enqueue_scrub_work(MDRequestRef& mdr)
header->set_origin(in);
// only set completion context for non-recursive scrub, because we don't
// want to block asok caller on long running scrub
Context *fin = nullptr;
if (!header->get_recursive()) {
cs->take_finisher();
}
// If the scrub did some repair, then flush the journal at the end of
// the scrub. Otherwise in the case of e.g. rewriting a backtrace
// the on disk state will still look damaged.
auto expiry_fin = new FunctionContext([this, header, fin](int r){
if (header->get_repaired()) {
dout(4) << "Flushing journal because scrub did some repairs" << dendl;
mds->mdlog->start_new_segment();
mds->mdlog->trim_all();
if (fin) {
MDSGatherBuilder expiry_gather(g_ceph_context);
const std::set<LogSegment*> &expiring_segments = mds->mdlog->get_expiring_segments();
for (std::set<LogSegment*>::const_iterator i = expiring_segments.begin();
i != expiring_segments.end(); ++i) {
(*i)->wait_for_expiry(expiry_gather.new_sub());
}
expiry_gather.set_finisher(new MDSInternalContextWrapper(mds, fin));
expiry_gather.activate();
}
} else {
if (fin) {
fin->complete(r);
}
}
});
if (!header->get_recursive()) {
Context *fin = cs->take_finisher();
mds->scrubstack->enqueue_inode_top(in, header,
new MDSInternalContextWrapper(mds, fin));
} else
mds->scrubstack->enqueue_inode_bottom(in, header, NULL);
new MDSInternalContextWrapper(mds,
expiry_fin));
} else {
mds->scrubstack->enqueue_inode_bottom(in, header,
new MDSInternalContextWrapper(mds,
expiry_fin));
}
mds->server->respond_to_request(mdr, 0);
return;

View File

@ -43,6 +43,9 @@ public:
const std::string &get_tag() const { return tag; }
Formatter &get_formatter() const { return *formatter; }
bool get_repaired() const { return repaired; }
void set_repaired() { repaired = true; }
protected:
const std::string tag;
const bool force;
@ -50,6 +53,8 @@ protected:
const bool repair;
Formatter * const formatter;
CInode *origin;
bool repaired = false; // May be set during scrub if repairs happened
};
typedef ceph::shared_ptr<ScrubHeader> ScrubHeaderRef;

View File

@ -59,7 +59,7 @@ void ScrubStack::pop_inode(CInode *in)
}
void ScrubStack::_enqueue_inode(CInode *in, CDentry *parent,
const ScrubHeaderRefConst& header,
ScrubHeaderRef& header,
MDSInternalContextBase *on_finish, bool top)
{
dout(10) << __func__ << " with {" << *in << "}"
@ -72,7 +72,7 @@ void ScrubStack::_enqueue_inode(CInode *in, CDentry *parent,
push_inode_bottom(in);
}
void ScrubStack::enqueue_inode(CInode *in, const ScrubHeaderRefConst& header,
void ScrubStack::enqueue_inode(CInode *in, ScrubHeaderRef& header,
MDSInternalContextBase *on_finish, bool top)
{
_enqueue_inode(in, NULL, header, on_finish, top);
@ -134,7 +134,8 @@ void ScrubStack::scrub_dir_inode(CInode *in,
bool all_frags_terminal = true;
bool all_frags_done = true;
const ScrubHeaderRefConst& header = in->scrub_info()->header;
ScrubHeaderRef header = in->get_scrub_header();
assert(header != nullptr);
if (header->get_recursive()) {
list<frag_t> scrubbing_frags;
@ -289,7 +290,7 @@ void ScrubStack::scrub_dir_inode_final(CInode *in)
}
void ScrubStack::scrub_dirfrag(CDir *dir,
const ScrubHeaderRefConst& header,
ScrubHeaderRef& header,
bool *added_children, bool *is_terminal,
bool *done)
{
@ -376,7 +377,9 @@ void ScrubStack::_validate_inode_done(CInode *in, int r,
in->make_path_string(path, true);
}
if (result.backtrace.checked && !result.backtrace.passed) {
if (result.backtrace.checked && !result.backtrace.passed
&& !result.backtrace.repaired)
{
// Record backtrace fails as remote linkage damage, as
// we may not be able to resolve hard links to this inode
mdcache->mds->damage_table.notify_remote_damaged(in->inode.ino, path);
@ -393,9 +396,14 @@ void ScrubStack::_validate_inode_done(CInode *in, int r,
// Inform the cluster log if we found an error
if (!result.passed_validation) {
clog->warn() << "Scrub error on inode " << in->ino()
<< " (" << path << ") see " << g_conf->name
<< " log and `damage ls` output for details";
if (result.all_damage_repaired()) {
clog->info() << "Scrub repaired inode " << in->ino()
<< " (" << path << ")";
} else {
clog->warn() << "Scrub error on inode " << in->ino()
<< " (" << path << ") see " << g_conf->name
<< " log and `damage ls` output for details";
}
// Put the verbose JSON output into the MDS log for later inspection
JSONFormatter f;

View File

@ -73,14 +73,14 @@ public:
* @param header The ScrubHeader propagated from whereever this scrub
* was initiated
*/
void enqueue_inode_top(CInode *in, const ScrubHeaderRefConst& header,
void enqueue_inode_top(CInode *in, ScrubHeaderRef& header,
MDSInternalContextBase *on_finish) {
enqueue_inode(in, header, on_finish, true);
}
/** Like enqueue_inode_top, but we wait for all pending scrubs before
* starting this one.
*/
void enqueue_inode_bottom(CInode *in, const ScrubHeaderRefConst& header,
void enqueue_inode_bottom(CInode *in, ScrubHeaderRef& header,
MDSInternalContextBase *on_finish) {
enqueue_inode(in, header, on_finish, false);
}
@ -90,9 +90,9 @@ private:
* Put the inode at either the top or bottom of the stack, with
* the given scrub params, and then try and kick off more scrubbing.
*/
void enqueue_inode(CInode *in, const ScrubHeaderRefConst& header,
void enqueue_inode(CInode *in, ScrubHeaderRef& header,
MDSInternalContextBase *on_finish, bool top);
void _enqueue_inode(CInode *in, CDentry *parent, const ScrubHeaderRefConst& header,
void _enqueue_inode(CInode *in, CDentry *parent, ScrubHeaderRef& header,
MDSInternalContextBase *on_finish, bool top);
/**
* Kick off as many scrubs as are appropriate, based on the current
@ -164,7 +164,7 @@ private:
* progress. Try again later.
*
*/
void scrub_dirfrag(CDir *dir, const ScrubHeaderRefConst& header,
void scrub_dirfrag(CDir *dir, ScrubHeaderRef& header,
bool *added_children, bool *is_terminal, bool *done);
/**
* Scrub a directory-representing dentry.