Skip to content

Commit b1ea37c

Browse files
committed
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 <[email protected]>
1 parent 472cc2b commit b1ea37c

File tree

1 file changed

+12
-1
lines changed

1 file changed

+12
-1
lines changed

src/mds/Server.cc

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4085,6 +4085,7 @@ CDir* Server::try_open_auth_dirfrag(CInode *diri, frag_t fg, const MDRequestRef&
40854085
void Server::handle_client_getattr(const MDRequestRef& mdr, bool is_lookup)
40864086
{
40874087
const cref_t<MClientRequest> &req = mdr->client_request;
4088+
client_t client = mdr->get_client();
40884089

40894090
if (req->get_filepath().depth() == 0 && is_lookup) {
40904091
// refpath can't be empty for lookup but it can for
@@ -4106,6 +4107,17 @@ void Server::handle_client_getattr(const MDRequestRef& mdr, bool is_lookup)
41064107
if (r > 0)
41074108
return; // delayed
41084109

4110+
// Do not batch if any xlock is held
4111+
if (!r) {
4112+
CInode *in = mdr->in[0];
4113+
if (((mask & CEPH_CAP_LINK_SHARED) && (in->linklock.is_xlocked_by_client(client))) ||
4114+
((mask & CEPH_CAP_AUTH_SHARED) && (in->authlock.is_xlocked_by_client(client))) ||
4115+
((mask & CEPH_CAP_XATTR_SHARED) && (in->xattrlock.is_xlocked_by_client(client))) ||
4116+
((mask & CEPH_CAP_FILE_SHARED) && (in->filelock.is_xlocked_by_client(client)))) {
4117+
r = -1;
4118+
}
4119+
}
4120+
41094121
if (r < 0) {
41104122
// fall-thru. let rdlock_path_pin_ref() check again.
41114123
} else if (is_lookup) {
@@ -4147,7 +4159,6 @@ void Server::handle_client_getattr(const MDRequestRef& mdr, bool is_lookup)
41474159
* handling this case here is easier than weakening rdlock
41484160
* semantics... that would cause problems elsewhere.
41494161
*/
4150-
client_t client = mdr->get_client();
41514162
int issued = 0;
41524163
Capability *cap = ref->get_client_cap(client);
41534164
if (cap && (mdr->snapid == CEPH_NOSNAP ||

0 commit comments

Comments
 (0)