From e610179a6a59c463eb3d85e87152ed3268c808ff Mon Sep 17 00:00:00 2001 From: Patrick Donnelly Date: Mon, 17 Jul 2023 16:10:59 -0400 Subject: [PATCH] mds: drop locks and retry when lock set changes An optimization was added to avoid an unnecessary gather on the inode filelock when the client can safely get the file size without also getting issued the requested caps. However, if a retry of getattr is necessary, this conditional inclusion of the inode filelock can cause lock-order violations resulting in deadlock. So, if we've already acquired some of the inode's locks then we must drop locks and retry. Fixes: https://tracker.ceph.com/issues/62052 Fixes: c822b3e2573578c288d170d1031672b74e02dced Signed-off-by: Patrick Donnelly (cherry picked from commit b5719ac32fe6431131842d62ffaf7101c03e9bac) --- src/mds/Server.cc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/mds/Server.cc b/src/mds/Server.cc index bf12cb7e2c8f..ff7e3d8968d5 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -4082,6 +4082,24 @@ void Server::handle_client_getattr(MDRequestRef& mdr, bool is_lookup) } else if (ref->filelock.is_stable() || ref->filelock.get_num_wrlocks() > 0 || !ref->filelock.can_read(mdr->get_client())) { + /* Since we're taking advantage of an optimization here: + * + * We cannot suddenly, due to a changing condition, add this filelock as + * it can cause lock-order deadlocks. In this case, that condition is the + * lock state changes between request retries. If that happens, we need + * to check if we've acquired the other locks in this vector. If we have, + * then we need to drop those locks and retry. + */ + if (mdr->is_rdlocked(&ref->linklock) || + mdr->is_rdlocked(&ref->authlock) || + mdr->is_rdlocked(&ref->xattrlock)) { + /* start over */ + dout(20) << " dropping locks and restarting request because filelock state change" << dendl; + mds->locker->drop_locks(mdr.get()); + mdr->drop_local_auth_pins(); + mds->queue_waiter(new C_MDS_RetryRequest(mdcache, mdr)); + return; + } lov.add_rdlock(&ref->filelock); mdr->locking_state &= ~MutationImpl::ALL_LOCKED; } -- 2.47.3