- * The exiting condition is no avail grants and no dirty pages caching,
- * that really means there is no space on the OST. */
- init_waitqueue_head(&ocw.ocw_waitq);
- ocw.ocw_oap = oap;
- ocw.ocw_grant = bytes;
- while (cli->cl_dirty_pages > 0 || cli->cl_w_in_flight > 0) {
- list_add_tail(&ocw.ocw_entry, &cli->cl_cache_waiters);
- ocw.ocw_rc = 0;
- spin_unlock(&cli->cl_loi_list_lock);
-
- osc_io_unplug_async(env, cli, NULL);
-
- CDEBUG(D_CACHE, "%s: sleeping for cache space @ %p for %p\n",
- cli_name(cli), &ocw, oap);
-
- rc = wait_event_idle_timeout(ocw.ocw_waitq,
- ocw_granted(cli, &ocw),
- cfs_time_seconds(AT_OFF ?
- obd_timeout :
- at_max));
-
- spin_lock(&cli->cl_loi_list_lock);
-
- if (rc <= 0) {
- /* l_wait_event is interrupted by signal or timed out */
- list_del_init(&ocw.ocw_entry);
- if (rc == 0)
- rc = -ETIMEDOUT;
- break;
- }
- LASSERT(list_empty(&ocw.ocw_entry));
- rc = ocw.ocw_rc;
-
- if (rc != -EDQUOT)
- break;
- if (osc_enter_cache_try(cli, oap, bytes)) {
- rc = 0;
- break;
- }
- }
-
- switch (rc) {
- case 0:
- OSC_DUMP_GRANT(D_CACHE, cli, "finally got grant space\n");
- break;
- case -ETIMEDOUT:
+ * The exiting condition (other than success) is no avail grants
+ * and no dirty pages caching, that really means there is no space
+ * on the OST.
+ */
+ remain = wait_event_idle_exclusive_timeout_cmd(
+ cli->cl_cache_waiters,
+ (entered = osc_enter_cache_try(cli, oap, bytes)) ||
+ (cli->cl_dirty_pages == 0 && cli->cl_w_in_flight == 0),
+ timeout,
+ cli_unlock_and_unplug(env, cli, oap),
+ cli_lock_after_unplug(cli));
+
+ if (entered) {
+ if (remain == timeout)
+ OSC_DUMP_GRANT(D_CACHE, cli, "granted from cache\n");
+ else
+ OSC_DUMP_GRANT(D_CACHE, cli,
+ "finally got grant space\n");
+ wake_up(&cli->cl_cache_waiters);
+ rc = 0;
+ } else if (remain == 0) {