struct mod_waiter {
struct client_obd *cli;
bool close_req;
+ bool woken;
wait_queue_entry_t wqe;
};
static int claim_mod_rpc_function(wait_queue_entry_t *wq_entry,
int ret;
/* As woken_wake_function() doesn't remove us from the wait_queue,
- * we could get called twice for the same thread - take care.
+ * we use own flag to ensure we're called just once.
*/
- if (wq_entry->flags & WQ_FLAG_WOKEN)
- /* Already woke this thread, don't try again */
+ if (w->woken)
return 0;
/* A slot is available if
if (w->close_req)
cli->cl_close_rpcs_in_flight++;
ret = woken_wake_function(wq_entry, mode, flags, key);
+ w->woken = true;
} else if (cli->cl_close_rpcs_in_flight)
/* No other waiter could be woken */
ret = -1;
struct mod_waiter wait = {
.cli = cli,
.close_req = (opc == MDS_CLOSE),
+ .woken = false,
};
__u16 i, max;
* and there will be no need to wait.
*/
wake_up_locked(&cli->cl_mod_rpcs_waitq);
- if (!(wait.wqe.flags & WQ_FLAG_WOKEN)) {
+ /* XXX: handle spurious wakeups (from unknown yet source */
+ while (wait.woken == false) {
spin_unlock_irq(&cli->cl_mod_rpcs_waitq.lock);
wait_woken(&wait.wqe, TASK_UNINTERRUPTIBLE,
MAX_SCHEDULE_TIMEOUT);