mirror of
https://github.com/ceph/ceph
synced 2025-04-01 00:26:47 +00:00
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:
commit
e016a6bc57
@ -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);
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user