@@ -2964,6 +2964,9 @@ static int mdc_precleanup(struct obd_device *obd)
static int mdc_cleanup(struct obd_device *obd)
{
+ struct client_obd *cli = &obd->u.cli;
+
+ LASSERT(cli->cl_mod_rpcs_in_flight == 0);
return osc_cleanup_common(obd);
}
@@ -1487,6 +1487,7 @@ int obd_mod_rpc_stats_seq_show(struct client_obd *cli, struct seq_file *seq)
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,
@@ -1499,10 +1500,9 @@ 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
@@ -1516,6 +1516,7 @@ static int claim_mod_rpc_function(wait_queue_entry_t *wq_entry,
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;
@@ -1543,6 +1544,7 @@ u16 obd_get_mod_rpc_slot(struct client_obd *cli, u32 opc)
struct mod_waiter wait = {
.cli = cli,
.close_req = (opc == MDS_CLOSE),
+ .woken = false,
};
u16 i, max;
@@ -1556,7 +1558,8 @@ u16 obd_get_mod_rpc_slot(struct client_obd *cli, u32 opc)
* 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);