From c6ce4c1f379fddb2ae3bdadb0bbc0b3dccace6a3 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Mon, 11 Mar 2024 13:09:14 +0800 Subject: [PATCH] mds: always make getattr wait for xlock to be released by the previous client When the previous client's setattr request is still holding the xlock for the linklock/authlock/xattrlock/filelock locks, if the same client send a getattr request it will use the projected inode to fill the reply, while for other clients the getattr requests will use the non-projected inode to fill replies. This causes inconsistent file mode across multiple clients. This will just skip batching the ops when any of the xlock is held. Fixes: https://tracker.ceph.com/issues/63906 Signed-off-by: Xiubo Li (cherry picked from commit b1ea37c5a6cc7b2dad417128990a6403de9cb170) --- src/mds/Server.cc | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/mds/Server.cc b/src/mds/Server.cc index bd8e1f11b1c..dc52b56ec46 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -4083,6 +4083,7 @@ CDir* Server::try_open_auth_dirfrag(CInode *diri, frag_t fg, const MDRequestRef& void Server::handle_client_getattr(const MDRequestRef& mdr, bool is_lookup) { const cref_t &req = mdr->client_request; + client_t client = mdr->get_client(); if (req->get_filepath().depth() == 0 && is_lookup) { // refpath can't be empty for lookup but it can for @@ -4104,6 +4105,17 @@ void Server::handle_client_getattr(const MDRequestRef& mdr, bool is_lookup) if (r > 0) return; // delayed + // Do not batch if any xlock is held + if (!r) { + CInode *in = mdr->in[0]; + if (((mask & CEPH_CAP_LINK_SHARED) && (in->linklock.is_xlocked_by_client(client))) || + ((mask & CEPH_CAP_AUTH_SHARED) && (in->authlock.is_xlocked_by_client(client))) || + ((mask & CEPH_CAP_XATTR_SHARED) && (in->xattrlock.is_xlocked_by_client(client))) || + ((mask & CEPH_CAP_FILE_SHARED) && (in->filelock.is_xlocked_by_client(client)))) { + r = -1; + } + } + if (r < 0) { // fall-thru. let rdlock_path_pin_ref() check again. } else if (is_lookup) { @@ -4145,7 +4157,6 @@ void Server::handle_client_getattr(const MDRequestRef& mdr, bool is_lookup) * handling this case here is easier than weakening rdlock * semantics... that would cause problems elsewhere. */ - client_t client = mdr->get_client(); int issued = 0; Capability *cap = ref->get_client_cap(client); if (cap && (mdr->snapid == CEPH_NOSNAP || -- 2.39.5