Merge PR #20468 into master

* refs/pull/20468/head:
	mds: fix check of underwater dentries

Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
This commit is contained in:
Patrick Donnelly 2018-02-27 02:22:31 -08:00
commit e016a6bc57
No known key found for this signature in database
GPG Key ID: 3A2A7E25BEA8AADB
2 changed files with 50 additions and 45 deletions

View File

@ -1658,8 +1658,7 @@ CDentry *CDir::_load_dentry(
bufferlist &bl,
const int pos,
const std::set<snapid_t> *snaps,
bool *force_dirty,
list<CInode*> *undef_inodes)
bool *force_dirty)
{
bufferlist::iterator q = bl.begin();
@ -1711,10 +1710,16 @@ CDentry *CDir::_load_dentry(
}
if (dn) {
if (dn->get_linkage()->get_inode() == 0) {
dout(12) << "_fetched had NEG dentry " << *dn << dendl;
} else {
dout(12) << "_fetched had dentry " << *dn << dendl;
CDentry::linkage_t *dnl = dn->get_linkage();
dout(12) << "_fetched had " << (dnl->is_null() ? "NEG" : "") << " dentry " << *dn << dendl;
if (committed_version == 0 &&
dnl->is_remote() &&
dn->is_dirty() &&
ino == dnl->get_remote_ino() &&
d_type == dnl->get_remote_d_type()) {
// see comment below
dout(10) << "_fetched had underwater dentry " << *dn << ", marking clean" << dendl;
dn->mark_clean();
}
} else {
// (remote) link
@ -1747,15 +1752,35 @@ CDentry *CDir::_load_dentry(
bool undef_inode = false;
if (dn) {
CInode *in = dn->get_linkage()->get_inode();
if (in) {
dout(12) << "_fetched had dentry " << *dn << dendl;
if (in->state_test(CInode::STATE_REJOINUNDEF)) {
undef_inodes->push_back(in);
undef_inode = true;
}
} else
dout(12) << "_fetched had NEG dentry " << *dn << dendl;
CDentry::linkage_t *dnl = dn->get_linkage();
dout(12) << "_fetched had " << (dnl->is_null() ? "NEG" : "") << " dentry " << *dn << dendl;
if (dnl->is_primary()) {
CInode *in = dnl->get_inode();
if (in->state_test(CInode::STATE_REJOINUNDEF)) {
undef_inode = true;
} else if (committed_version == 0 &&
dn->is_dirty() &&
inode_data.inode.ino == in->ino() &&
inode_data.inode.version == in->get_version()) {
/* clean underwater item?
* Underwater item is something that is dirty in our cache from
* journal replay, but was previously flushed to disk before the
* mds failed.
*
* We only do this is committed_version == 0. that implies either
* - this is a fetch after from a clean/empty CDir is created
* (and has no effect, since the dn won't exist); or
* - this is a fetch after _recovery_, which is what we're worried
* about. Items that are marked dirty from the journal should be
* marked clean if they appear on disk.
*/
dout(10) << "_fetched had underwater dentry " << *dn << ", marking clean" << dendl;
dn->mark_clean();
dout(10) << "_fetched had underwater inode " << *dnl->get_inode() << ", marking clean" << dendl;
in->mark_clean();
}
}
}
if (!dn || undef_inode) {
@ -1917,7 +1942,7 @@ void CDir::_omap_fetched(bufferlist& hdrbl, map<string, bufferlist>& omap,
try {
dn = _load_dentry(
p->first, dname, last, p->second, pos, snaps,
&force_dirty, &undef_inodes);
&force_dirty);
} catch (const buffer::error &err) {
cache->mds->clog->warn() << "Corrupt dentry '" << dname << "' in "
"dir frag " << dirfrag() << ": "
@ -1936,36 +1961,17 @@ void CDir::_omap_fetched(bufferlist& hdrbl, map<string, bufferlist>& omap,
continue;
}
if (dn && (wanted_items.count(mempool::mds_co::string(dname)) > 0 || !complete)) {
if (!dn)
continue;
CDentry::linkage_t *dnl = dn->get_linkage();
if (dnl->is_primary() && dnl->get_inode()->state_test(CInode::STATE_REJOINUNDEF))
undef_inodes.push_back(dnl->get_inode());
if (wanted_items.count(mempool::mds_co::string(dname)) > 0 || !complete) {
dout(10) << " touching wanted dn " << *dn << dendl;
inode->mdcache->touch_dentry(dn);
}
/** clean underwater item?
* Underwater item is something that is dirty in our cache from
* journal replay, but was previously flushed to disk before the
* mds failed.
*
* We only do this is committed_version == 0. that implies either
* - this is a fetch after from a clean/empty CDir is created
* (and has no effect, since the dn won't exist); or
* - this is a fetch after _recovery_, which is what we're worried
* about. Items that are marked dirty from the journal should be
* marked clean if they appear on disk.
*/
if (committed_version == 0 &&
dn &&
dn->get_version() <= got_fnode.version &&
dn->is_dirty()) {
dout(10) << "_fetched had underwater dentry " << *dn << ", marking clean" << dendl;
dn->mark_clean();
if (dn->get_linkage()->is_primary()) {
assert(dn->get_linkage()->get_inode()->get_version() <= got_fnode.version);
dout(10) << "_fetched had underwater inode " << *dn->get_linkage()->get_inode() << ", marking clean" << dendl;
dn->get_linkage()->get_inode()->mark_clean();
}
}
}
//cache->mds->logger->inc("newin", num_new_inodes_loaded);

View File

@ -605,8 +605,7 @@ protected:
bufferlist &bl,
int pos,
const std::set<snapid_t> *snaps,
bool *force_dirty,
std::list<CInode*> *undef_inodes);
bool *force_dirty);
/**
* Mark this fragment as BADFRAG (common part of go_bad and go_bad_dentry)