} 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;
}