@@ -299,6 +299,19 @@ static inline int is_granted_or_cancelled(struct ldlm_lock *lock)
return ret;
}
+static inline bool is_bl_done(struct ldlm_lock *lock)
+{
+ bool bl_done = true;
+
+ if (!ldlm_is_bl_done(lock)) {
+ lock_res_and_lock(lock);
+ bl_done = ldlm_is_bl_done(lock);
+ unlock_res_and_lock(lock);
+ }
+
+ return bl_done;
+}
+
typedef void (*ldlm_policy_wire_to_local_t)(const union ldlm_wire_policy_data *,
union ldlm_policy_data *);
@@ -1832,19 +1832,6 @@ int ldlm_run_ast_work(struct ldlm_namespace *ns, struct list_head *rpc_list,
return rc;
}
-static bool is_bl_done(struct ldlm_lock *lock)
-{
- bool bl_done = true;
-
- if (!ldlm_is_bl_done(lock)) {
- lock_res_and_lock(lock);
- bl_done = ldlm_is_bl_done(lock);
- unlock_res_and_lock(lock);
- }
-
- return bl_done;
-}
-
/**
* Helper function to call blocking AST for LDLM lock \a lock in a
* "cancelling" mode.
@@ -1026,8 +1026,12 @@ int ldlm_cli_cancel(const struct lustre_handle *lockh,
lock_res_and_lock(lock);
/* Lock is being canceled and the caller doesn't want to wait */
- if (ldlm_is_canceling(lock) && (cancel_flags & LCF_ASYNC)) {
+ if (ldlm_is_canceling(lock)) {
unlock_res_and_lock(lock);
+
+ if (!(cancel_flags & LCF_ASYNC))
+ wait_event_idle(lock->l_waitq, is_bl_done(lock));
+
LDLM_LOCK_RELEASE(lock);
return 0;
}