From: Patrick Donnelly Date: Mon, 14 Apr 2025 18:02:01 +0000 (-0400) Subject: mds: check for snapshots on parent snaprealms X-Git-Tag: v20.3.0~2^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=b8fd8e79ae757619b7d6011134dc2ed2ce17d8e4;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 --- diff --git a/src/mds/Server.cc b/src/mds/Server.cc index e78b43a82ffe..8885931ee6eb 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -6595,11 +6595,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; } @@ -6627,11 +6623,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; } @@ -6664,11 +6656,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; } @@ -6692,11 +6680,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; } @@ -9225,6 +9209,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 460618a319c7..b8b78b2dff62 100644 --- a/src/mds/Server.h +++ b/src/mds/Server.h @@ -302,6 +302,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,