From: Patrick Donnelly Date: Mon, 14 Apr 2025 18:02:01 +0000 (-0400) Subject: mds: check for snapshots on parent snaprealms X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=571e86f49b0667a117bd251872ddb5d01a516195;p=ceph.git mds: check for snapshots on parent snaprealms The code was incorrectly only looking at snapshots in the current snaprealm. Fixes: https://tracker.ceph.com/issues/70912 Signed-off-by: Patrick Donnelly (cherry picked from commit b8fd8e79ae757619b7d6011134dc2ed2ce17d8e4) --- diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 874b8c45d1d0..576ee3d5cabb 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -6497,11 +6497,7 @@ void Server::handle_client_setvxattr(const MDRequestRef& mdr, CInode *cur) if (!xlock_policylock(mdr, cur, false, false, std::move(lov))) return; - if (_dir_is_nonempty(mdr, cur)) { - respond_to_request(mdr, -ENOTEMPTY); - return; - } - if (cur->snaprealm && cur->snaprealm->srnode.snaps.size()) { + if (_dir_is_nonempty(mdr, cur) || _dir_has_snaps(mdr, cur)) { respond_to_request(mdr, -ENOTEMPTY); return; } @@ -6529,11 +6525,7 @@ void Server::handle_client_setvxattr(const MDRequestRef& mdr, CInode *cur) if (!xlock_policylock(mdr, cur, false, false, std::move(lov))) return; - if (_dir_is_nonempty(mdr, cur)) { - respond_to_request(mdr, -ENOTEMPTY); - return; - } - if (cur->snaprealm && cur->snaprealm->srnode.snaps.size()) { + if (_dir_is_nonempty(mdr, cur) || _dir_has_snaps(mdr, cur)) { respond_to_request(mdr, -ENOTEMPTY); return; } @@ -6566,11 +6558,7 @@ void Server::handle_client_setvxattr(const MDRequestRef& mdr, CInode *cur) if (!xlock_policylock(mdr, cur, false, false, std::move(lov))) return; - if (_dir_is_nonempty(mdr, cur)) { - respond_to_request(mdr, -ENOTEMPTY); - return; - } - if (cur->snaprealm && cur->snaprealm->srnode.snaps.size()) { + if (_dir_is_nonempty(mdr, cur) || _dir_has_snaps(mdr, cur)) { respond_to_request(mdr, -ENOTEMPTY); return; } @@ -6594,11 +6582,7 @@ void Server::handle_client_setvxattr(const MDRequestRef& mdr, CInode *cur) if (!xlock_policylock(mdr, cur, false, false, std::move(lov))) return; - if (_dir_is_nonempty(mdr, cur)) { - respond_to_request(mdr, -ENOTEMPTY); - return; - } - if (cur->snaprealm && cur->snaprealm->srnode.snaps.size()) { + if (_dir_is_nonempty(mdr, cur) || _dir_has_snaps(mdr, cur)) { respond_to_request(mdr, -ENOTEMPTY); return; } @@ -8902,6 +8886,16 @@ bool Server::_dir_is_nonempty_unlocked(const MDRequestRef& mdr, CInode *in) return false; } +bool Server::_dir_has_snaps(const MDRequestRef& mdr, CInode *diri) +{ + dout(10) << __func__ << ": " << *diri << dendl; + ceph_assert(diri->is_auth()); + ceph_assert(diri->snaplock.can_read(mdr->get_client())); + + SnapRealm *realm = diri->find_snaprealm(); + return !realm->get_snaps().empty(); +} + bool Server::_dir_is_nonempty(const MDRequestRef& mdr, CInode *in) { dout(10) << "dir_is_nonempty " << *in << dendl; diff --git a/src/mds/Server.h b/src/mds/Server.h index e7aca9e18e16..730da85c36c4 100644 --- a/src/mds/Server.h +++ b/src/mds/Server.h @@ -279,6 +279,7 @@ public: void handle_client_unlink(const MDRequestRef& mdr); bool _dir_is_nonempty_unlocked(const MDRequestRef& mdr, CInode *rmdiri); bool _dir_is_nonempty(const MDRequestRef& mdr, CInode *rmdiri); + bool _dir_has_snaps(const MDRequestRef& mdr, CInode *diri); void _unlink_local(const MDRequestRef& mdr, CDentry *dn, CDentry *straydn); void _unlink_local_finish(const MDRequestRef& mdr, CDentry *dn, CDentry *straydn,