mirror of
https://github.com/ceph/ceph
synced 2024-12-29 15:03:33 +00:00
mds: pop projected snaprealm before inode's parent changes
When creating new snaprealm, we need to split its parent snaprealm's inodes_with_caps. If new snaprealm is newly created during rename, inode's original snaprealm's inodes_with_caps should be split. So in rename/rmdir cases, we should pop projectd snaprealm before inode's parent changes Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
This commit is contained in:
parent
2d60956c8b
commit
7b8c844c3b
@ -408,7 +408,7 @@ void CInode::pop_and_dirty_projected_inode(LogSegment *ls)
|
||||
}
|
||||
|
||||
if (projected_nodes.front().snapnode != projected_inode::UNDEF_SRNODE) {
|
||||
pop_projected_snaprealm(projected_nodes.front().snapnode);
|
||||
pop_projected_snaprealm(projected_nodes.front().snapnode, false);
|
||||
--num_projected_srnodes;
|
||||
}
|
||||
|
||||
@ -486,11 +486,21 @@ void CInode::record_snaprealm_past_parent(sr_t *new_snap, SnapRealm *newparent)
|
||||
}
|
||||
}
|
||||
|
||||
void CInode::pop_projected_snaprealm(sr_t *next_snaprealm)
|
||||
void CInode::early_pop_projected_snaprealm()
|
||||
{
|
||||
assert(!projected_nodes.empty());
|
||||
if (projected_nodes.front().snapnode != projected_inode::UNDEF_SRNODE) {
|
||||
pop_projected_snaprealm(projected_nodes.front().snapnode, true);
|
||||
projected_nodes.front().snapnode = projected_inode::UNDEF_SRNODE;
|
||||
--num_projected_srnodes;
|
||||
}
|
||||
}
|
||||
|
||||
void CInode::pop_projected_snaprealm(sr_t *next_snaprealm, bool early)
|
||||
{
|
||||
if (next_snaprealm) {
|
||||
dout(10) << __func__ << " " << next_snaprealm
|
||||
<< " seq" << next_snaprealm->seq << dendl;
|
||||
dout(10) << __func__ << (early ? " (early) " : " ")
|
||||
<< next_snaprealm << " seq " << next_snaprealm->seq << dendl;
|
||||
bool invalidate_cached_snaps = false;
|
||||
if (!snaprealm) {
|
||||
open_snaprealm();
|
||||
@ -516,7 +526,7 @@ void CInode::pop_projected_snaprealm(sr_t *next_snaprealm)
|
||||
if (snaprealm->parent)
|
||||
dout(10) << " realm " << *snaprealm << " parent " << *snaprealm->parent << dendl;
|
||||
} else {
|
||||
dout(10) << __func__ << " null" << dendl;
|
||||
dout(10) << __func__ << (early ? " (early) null" : " null") << dendl;
|
||||
assert(snaprealm);
|
||||
snaprealm->merge_to(NULL);
|
||||
}
|
||||
|
@ -512,9 +512,10 @@ public:
|
||||
}
|
||||
void record_snaprealm_past_parent(sr_t *new_snap, SnapRealm *newparent);
|
||||
void project_snaprealm_past_parent(SnapRealm *newparent);
|
||||
void early_pop_projected_snaprealm();
|
||||
|
||||
private:
|
||||
void pop_projected_snaprealm(sr_t *next_snaprealm);
|
||||
void pop_projected_snaprealm(sr_t *next_snaprealm, bool early);
|
||||
|
||||
public:
|
||||
mempool_old_inode& cow_old_inode(snapid_t follows, bool cow_head);
|
||||
|
@ -6108,7 +6108,6 @@ void Server::_unlink_local(MDRequestRef& mdr, CDentry *dn, CDentry *straydn, sna
|
||||
dn->make_path_string(t, true);
|
||||
pi.inode.stray_prior_path = std::move(t);
|
||||
}
|
||||
mdr->add_projected_inode(in); // do this _after_ my dn->pre_dirty().. we apply that one manually.
|
||||
pi.inode.version = in->pre_dirty();
|
||||
pi.inode.ctime = mdr->get_op_stamp();
|
||||
pi.inode.change_attr++;
|
||||
@ -6116,9 +6115,10 @@ void Server::_unlink_local(MDRequestRef& mdr, CDentry *dn, CDentry *straydn, sna
|
||||
if (pi.inode.nlink == 0)
|
||||
in->state_set(CInode::STATE_ORPHAN);
|
||||
|
||||
if (dnl->is_primary()) {
|
||||
if (straydn) {
|
||||
// will manually pop projected inode
|
||||
|
||||
// primary link. add stray dentry.
|
||||
assert(straydn);
|
||||
mdcache->predirty_journal_parents(mdr, &le->metablob, in, dn->get_dir(), PREDIRTY_PRIMARY|PREDIRTY_DIR, -1);
|
||||
mdcache->predirty_journal_parents(mdr, &le->metablob, in, straydn->get_dir(), PREDIRTY_PRIMARY|PREDIRTY_DIR, 1);
|
||||
|
||||
@ -6134,6 +6134,7 @@ void Server::_unlink_local(MDRequestRef& mdr, CDentry *dn, CDentry *straydn, sna
|
||||
pi.inode.update_backtrace();
|
||||
le->metablob.add_primary_dentry(straydn, in, true, true);
|
||||
} else {
|
||||
mdr->add_projected_inode(in);
|
||||
// remote link. update remote inode.
|
||||
mdcache->predirty_journal_parents(mdr, &le->metablob, in, dn->get_dir(), PREDIRTY_DIR, -1);
|
||||
mdcache->predirty_journal_parents(mdr, &le->metablob, in, 0, PREDIRTY_PRIMARY);
|
||||
@ -6174,19 +6175,26 @@ void Server::_unlink_local_finish(MDRequestRef& mdr,
|
||||
if (!mdr->more()->witnessed.empty())
|
||||
mdcache->logged_master_update(mdr->reqid);
|
||||
|
||||
CInode *strayin = NULL;
|
||||
bool hadrealm = false;
|
||||
if (straydn) {
|
||||
// if there is newly created snaprealm, need to split old snaprealm's
|
||||
// inodes_with_caps. So pop snaprealm before linkage changes.
|
||||
strayin = dn->get_linkage()->get_inode();
|
||||
hadrealm = strayin->snaprealm ? true : false;
|
||||
strayin->early_pop_projected_snaprealm();
|
||||
}
|
||||
|
||||
// unlink main dentry
|
||||
dn->get_dir()->unlink_inode(dn);
|
||||
dn->pop_projected_linkage();
|
||||
|
||||
// relink as stray? (i.e. was primary link?)
|
||||
CInode *strayin = NULL;
|
||||
bool hadrealm = false;
|
||||
if (straydn) {
|
||||
dout(20) << " straydn is " << *straydn << dendl;
|
||||
CDentry::linkage_t *straydnl = straydn->pop_projected_linkage();
|
||||
strayin = straydnl->get_inode();
|
||||
straydn->pop_projected_linkage();
|
||||
|
||||
hadrealm = strayin->snaprealm ? true : false;
|
||||
strayin->pop_and_dirty_projected_inode(mdr->ls);
|
||||
|
||||
mdcache->touch_dentry_bottom(straydn);
|
||||
}
|
||||
@ -6355,24 +6363,28 @@ void Server::handle_slave_rmdir_prep(MDRequestRef& mdr)
|
||||
void Server::_logged_slave_rmdir(MDRequestRef& mdr, CDentry *dn, CDentry *straydn)
|
||||
{
|
||||
dout(10) << "_logged_slave_rmdir " << *mdr << " on " << *dn << dendl;
|
||||
CInode *in = dn->get_linkage()->get_inode();
|
||||
|
||||
bool new_realm;
|
||||
if (mdr->slave_request->desti_snapbl.length()) {
|
||||
new_realm = !in->snaprealm;
|
||||
in->decode_snap_blob(mdr->slave_request->desti_snapbl);
|
||||
assert(in->snaprealm);
|
||||
assert(in->snaprealm->have_past_parents_open());
|
||||
} else {
|
||||
new_realm = false;
|
||||
}
|
||||
|
||||
// update our cache now, so we are consistent with what is in the journal
|
||||
// when we journal a subtree map
|
||||
CInode *in = dn->get_linkage()->get_inode();
|
||||
dn->get_dir()->unlink_inode(dn);
|
||||
straydn->pop_projected_linkage();
|
||||
dn->pop_projected_linkage();
|
||||
|
||||
mdcache->adjust_subtree_after_rename(in, dn->get_dir(), mdr->more()->slave_update_journaled);
|
||||
|
||||
if (mdr->slave_request->desti_snapbl.length()) {
|
||||
bool hadrealm = (in->snaprealm ? true : false);
|
||||
in->decode_snap_blob(mdr->slave_request->desti_snapbl);
|
||||
assert(in->snaprealm);
|
||||
assert(in->snaprealm->have_past_parents_open());
|
||||
if (!hadrealm)
|
||||
if (new_realm)
|
||||
mdcache->do_realm_invalidate_and_update_notify(in, CEPH_SNAP_OP_SPLIT, false);
|
||||
}
|
||||
|
||||
// done.
|
||||
mdr->slave_request->put();
|
||||
@ -7557,18 +7569,12 @@ void Server::_rename_apply(MDRequestRef& mdr, CDentry *srcdn, CDentry *destdn, C
|
||||
if (destdnl->is_primary()) {
|
||||
assert(straydn);
|
||||
dout(10) << "straydn is " << *straydn << dendl;
|
||||
destdn->get_dir()->unlink_inode(destdn, false);
|
||||
|
||||
straydn->pop_projected_linkage();
|
||||
if (mdr->is_slave() && !mdr->more()->slave_update_journaled)
|
||||
assert(!straydn->is_projected()); // no other projected
|
||||
|
||||
mdcache->touch_dentry_bottom(straydn); // drop dn as quickly as possible.
|
||||
|
||||
// nlink-- targeti
|
||||
// if there is newly created snaprealm, need to split old snaprealm's
|
||||
// inodes_with_caps. So pop snaprealm before linkage changes.
|
||||
if (destdn->is_auth()) {
|
||||
bool hadrealm = (oldin->snaprealm ? true : false);
|
||||
oldin->pop_and_dirty_projected_inode(mdr->ls);
|
||||
oldin->early_pop_projected_snaprealm();
|
||||
new_oldin_snaprealm = (oldin->snaprealm && !hadrealm);
|
||||
} else {
|
||||
assert(mdr->slave_request);
|
||||
@ -7579,6 +7585,18 @@ void Server::_rename_apply(MDRequestRef& mdr, CDentry *srcdn, CDentry *destdn, C
|
||||
assert(oldin->snaprealm->have_past_parents_open());
|
||||
}
|
||||
}
|
||||
|
||||
destdn->get_dir()->unlink_inode(destdn, false);
|
||||
|
||||
straydn->pop_projected_linkage();
|
||||
if (mdr->is_slave() && !mdr->more()->slave_update_journaled)
|
||||
assert(!straydn->is_projected()); // no other projected
|
||||
|
||||
// nlink-- targeti
|
||||
if (destdn->is_auth())
|
||||
oldin->pop_and_dirty_projected_inode(mdr->ls);
|
||||
|
||||
mdcache->touch_dentry_bottom(straydn); // drop dn as quickly as possible.
|
||||
} else if (destdnl->is_remote()) {
|
||||
destdn->get_dir()->unlink_inode(destdn, false);
|
||||
if (oldin->is_auth())
|
||||
@ -7591,6 +7609,24 @@ void Server::_rename_apply(MDRequestRef& mdr, CDentry *srcdn, CDentry *destdn, C
|
||||
assert(in);
|
||||
|
||||
bool srcdn_was_remote = srcdnl->is_remote();
|
||||
if (!srcdn_was_remote) {
|
||||
// if there is newly created snaprealm, need to split old snaprealm's
|
||||
// inodes_with_caps. So pop snaprealm before linkage changes.
|
||||
if (destdn->is_auth()) {
|
||||
bool hadrealm = (in->snaprealm ? true : false);
|
||||
in->early_pop_projected_snaprealm();
|
||||
new_in_snaprealm = (in->snaprealm && !hadrealm);
|
||||
} else {
|
||||
assert(mdr->slave_request);
|
||||
if (mdr->slave_request->srci_snapbl.length()) {
|
||||
new_in_snaprealm = !in->snaprealm;
|
||||
in->decode_snap_blob(mdr->slave_request->srci_snapbl);
|
||||
assert(in->snaprealm);
|
||||
assert(in->snaprealm->have_past_parents_open());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
srcdn->get_dir()->unlink_inode(srcdn);
|
||||
|
||||
// dest
|
||||
@ -7654,19 +7690,8 @@ void Server::_rename_apply(MDRequestRef& mdr, CDentry *srcdn, CDentry *destdn, C
|
||||
mdr->clear_ambiguous_auth();
|
||||
}
|
||||
|
||||
if (destdn->is_auth()) {
|
||||
bool hadrealm = (in->snaprealm ? true : false);
|
||||
if (destdn->is_auth())
|
||||
in->pop_and_dirty_projected_inode(mdr->ls);
|
||||
new_in_snaprealm = (in->snaprealm && !hadrealm);
|
||||
} else {
|
||||
assert(mdr->slave_request);
|
||||
if (mdr->slave_request->srci_snapbl.length()) {
|
||||
new_in_snaprealm = !in->snaprealm;
|
||||
in->decode_snap_blob(mdr->slave_request->srci_snapbl);
|
||||
assert(in->snaprealm);
|
||||
assert(in->snaprealm->have_past_parents_open());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// src
|
||||
|
Loading…
Reference in New Issue
Block a user