From: Yan, Zheng Date: Wed, 5 Aug 2020 09:31:57 +0000 (+0800) Subject: mds: don't move inode with nlink > 1 to global snaprealm if it's in subvolume X-Git-Tag: wip-pdonnell-testing-20200918.022351~305^2~1 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=63da28d6a8be20183a294744892a41f47e8ba24b;p=ceph-ci.git mds: don't move inode with nlink > 1 to global snaprealm if it's in subvolume Fixes: https://tracker.ceph.com/issues/46074 Signed-off-by: "Yan, Zheng" --- diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 69cd3bdab01..e55698738e8 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -605,18 +605,20 @@ void CInode::record_snaprealm_past_parent(sr_t *new_snap, SnapRealm *newparent) } } -void CInode::record_snaprealm_parent_dentry(sr_t *new_snap, SnapRealm *newparent, +void CInode::record_snaprealm_parent_dentry(sr_t *new_snap, SnapRealm *oldparent, CDentry *dn, bool primary_dn) { ceph_assert(new_snap->is_parent_global()); - SnapRealm *oldparent = dn->get_dir()->inode->find_snaprealm(); + + if (!oldparent) + oldparent = dn->get_dir()->inode->find_snaprealm(); auto& snaps = oldparent->get_snaps(); if (!primary_dn) { auto p = snaps.lower_bound(dn->first); if (p != snaps.end()) new_snap->past_parent_snaps.insert(p, snaps.end()); - } else if (newparent != oldparent) { + } else { // 'last_destroyed' is used as 'current_parent_since' auto p = snaps.lower_bound(new_snap->last_destroyed); if (p != snaps.end()) diff --git a/src/mds/Server.cc b/src/mds/Server.cc index cd2319e3eb8..d560f1c7371 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -6351,7 +6351,7 @@ void Server::handle_client_link(MDRequestRef& mdr) // local or remote? if (targeti->is_auth()) - _link_local(mdr, destdn, targeti); + _link_local(mdr, destdn, targeti, target_realm); else _link_remote(mdr, true, destdn, targeti); mds->balancer->maybe_fragment(dir, false); @@ -6376,7 +6376,7 @@ public: }; -void Server::_link_local(MDRequestRef& mdr, CDentry *dn, CInode *targeti) +void Server::_link_local(MDRequestRef& mdr, CDentry *dn, CInode *targeti, SnapRealm *target_realm) { dout(10) << "_link_local " << *dn << " to " << *targeti << dendl; @@ -6396,10 +6396,10 @@ void Server::_link_local(MDRequestRef& mdr, CDentry *dn, CInode *targeti) pi.inode->version = tipv; bool adjust_realm = false; - if (!targeti->is_projected_snaprealm_global()) { + if (!target_realm->get_subvolume_ino() && !targeti->is_projected_snaprealm_global()) { sr_t *newsnap = targeti->project_snaprealm(); targeti->mark_snaprealm_global(newsnap); - targeti->record_snaprealm_parent_dentry(newsnap, NULL, targeti->get_projected_parent_dn(), true); + targeti->record_snaprealm_parent_dentry(newsnap, target_realm, targeti->get_projected_parent_dn(), true); adjust_realm = true; } @@ -6651,10 +6651,13 @@ void Server::handle_peer_link_prep(MDRequestRef& mdr) if (mdr->peer_request->get_op() == MMDSPeerRequest::OP_LINKPREP) { inc = true; pi.inode->nlink++; - if (!targeti->is_projected_snaprealm_global()) { + + CDentry *target_pdn = targeti->get_projected_parent_dn(); + SnapRealm *target_realm = target_pdn->get_dir()->inode->find_snaprealm(); + if (!target_realm->get_subvolume_ino() && !targeti->is_projected_snaprealm_global()) { sr_t *newsnap = targeti->project_snaprealm(); targeti->mark_snaprealm_global(newsnap); - targeti->record_snaprealm_parent_dentry(newsnap, NULL, targeti->get_projected_parent_dn(), true); + targeti->record_snaprealm_parent_dentry(newsnap, target_realm, target_pdn, true); adjust_realm = true; realm_projected = true; } @@ -7034,7 +7037,7 @@ void Server::handle_client_unlink(MDRequestRef& mdr) if (!mdr->more()->desti_srnode) { if (in->is_projected_snaprealm_global()) { sr_t *new_srnode = in->prepare_new_srnode(0); - in->record_snaprealm_parent_dentry(new_srnode, NULL, dn, dnl->is_primary()); + in->record_snaprealm_parent_dentry(new_srnode, nullptr, dn, dnl->is_primary()); // dropping the last linkage or dropping the last remote linkage, // detch the inode from global snaprealm auto nlink = in->get_projected_inode()->nlink; @@ -7933,7 +7936,7 @@ void Server::handle_client_rename(MDRequestRef& mdr) srci->get_projected_inode()->nlink == 1 && srci->is_projected_snaprealm_global()) { sr_t *new_srnode = srci->prepare_new_srnode(0); - srci->record_snaprealm_parent_dentry(new_srnode, NULL, destdn, false); + srci->record_snaprealm_parent_dentry(new_srnode, nullptr, destdn, false); srci->clear_snaprealm_global(new_srnode); mdr->more()->srci_srnode = new_srnode; @@ -7942,7 +7945,7 @@ void Server::handle_client_rename(MDRequestRef& mdr) if (oldin && !mdr->more()->desti_srnode) { if (oldin->is_projected_snaprealm_global()) { sr_t *new_srnode = oldin->prepare_new_srnode(0); - oldin->record_snaprealm_parent_dentry(new_srnode, NULL, destdn, destdnl->is_primary()); + oldin->record_snaprealm_parent_dentry(new_srnode, dest_realm, destdn, destdnl->is_primary()); // dropping the last linkage or dropping the last remote linkage, // detch the inode from global snaprealm auto nlink = oldin->get_projected_inode()->nlink; @@ -7963,7 +7966,7 @@ void Server::handle_client_rename(MDRequestRef& mdr) if (!mdr->more()->srci_srnode) { if (srci->is_projected_snaprealm_global()) { sr_t *new_srnode = srci->prepare_new_srnode(0); - srci->record_snaprealm_parent_dentry(new_srnode, dest_realm, srcdn, srcdnl->is_primary()); + srci->record_snaprealm_parent_dentry(new_srnode, src_realm, srcdn, srcdnl->is_primary()); mdr->more()->srci_srnode = new_srnode; } else if (srcdnl->is_primary()) { snapid_t follows = src_realm->get_newest_seq(); diff --git a/src/mds/Server.h b/src/mds/Server.h index 301725f5aa7..ee7443145e3 100644 --- a/src/mds/Server.h +++ b/src/mds/Server.h @@ -234,7 +234,7 @@ public: // link void handle_client_link(MDRequestRef& mdr); - void _link_local(MDRequestRef& mdr, CDentry *dn, CInode *targeti); + void _link_local(MDRequestRef& mdr, CDentry *dn, CInode *targeti, SnapRealm *target_realm); void _link_local_finish(MDRequestRef& mdr, CDentry *dn, CInode *targeti, version_t, version_t, bool);