/** * Core of osc_dlm_blocking_ast() logic. */ static void osc_lock_blocking(const struct lu_env *env, struct ldlm_lock *dlmlock, struct osc_lock *olck, int blocking) { struct cl_lock *lock = olck->ols_cl.cls_lock; LASSERT(olck->ols_lock == dlmlock); CLASSERT(OLS_BLOCKED < OLS_CANCELLED); LASSERT(!osc_lock_is_lockless(olck)); /* * Lock might be still addref-ed here, if e.g., blocking ast * is sent for a failed lock. */ osc_lock_unhold(olck); if (blocking && olck->ols_state < OLS_BLOCKED) /* * Move osc_lock into OLS_BLOCKED before canceling the lock, * because it recursively re-enters osc_lock_blocking(), with * the state set to OLS_CANCELLED. */ olck->ols_state = OLS_BLOCKED; /* * cancel and destroy lock at least once no matter how blocking ast is * entered (see comment above osc_ldlm_blocking_ast() for use * cases). cl_lock_cancel() and cl_lock_delete() are idempotent. */ cl_lock_cancel(env, lock); cl_lock_delete(env, lock); }
/** * Invariant that has to be true all of the time. */ static int osc_lock_invariant(struct osc_lock *ols) { struct ldlm_lock *lock = osc_handle_ptr(&ols->ols_handle); struct ldlm_lock *olock = ols->ols_lock; int handle_used = lustre_handle_is_used(&ols->ols_handle); return ergo(osc_lock_is_lockless(ols), ols->ols_locklessable && ols->ols_lock == NULL) || (ergo(olock != NULL, handle_used) && ergo(olock != NULL, olock->l_handle.h_cookie == ols->ols_handle.cookie) && /* * Check that ->ols_handle and ->ols_lock are consistent, but * take into account that they are set at the different time. */ ergo(handle_used, ergo(lock != NULL && olock != NULL, lock == olock) && ergo(lock == NULL, olock == NULL)) && ergo(ols->ols_state == OLS_CANCELLED, olock == NULL && !handle_used) && /* * DLM lock is destroyed only after we have seen cancellation * ast. */ ergo(olock != NULL && ols->ols_state < OLS_CANCELLED, !olock->l_destroyed) && ergo(ols->ols_state == OLS_GRANTED, olock != NULL && olock->l_req_mode == olock->l_granted_mode && ols->ols_hold)); }
/** * Invariant that has to be true all of the time. */ static int osc_lock_invariant(struct osc_lock *ols) { struct ldlm_lock *lock = osc_handle_ptr(&ols->ols_handle); struct ldlm_lock *olock = ols->ols_lock; int handle_used = lustre_handle_is_used(&ols->ols_handle); if (ergo(osc_lock_is_lockless(ols), ols->ols_locklessable && ols->ols_lock == NULL)) return 1; /* * If all the following "ergo"s are true, return 1, otherwise 0 */ if (!ergo(olock != NULL, handle_used)) return 0; if (!ergo(olock != NULL, olock->l_handle.h_cookie == ols->ols_handle.cookie)) return 0; if (!ergo(handle_used, ergo(lock != NULL && olock != NULL, lock == olock) && ergo(lock == NULL, olock == NULL))) return 0; /* * Check that ->ols_handle and ->ols_lock are consistent, but * take into account that they are set at the different time. */ if (!ergo(ols->ols_state == OLS_CANCELLED, olock == NULL && !handle_used)) return 0; /* * DLM lock is destroyed only after we have seen cancellation * ast. */ if (!ergo(olock != NULL && ols->ols_state < OLS_CANCELLED, ((olock->l_flags & LDLM_FL_DESTROYED) == 0))) return 0; if (!ergo(ols->ols_state == OLS_GRANTED, olock != NULL && olock->l_req_mode == olock->l_granted_mode && ols->ols_hold)) return 0; return 1; }