scst: Switch to thread context before executing a reservation command

Persistent reservation commands need thread context because
scst_pr_is_cmd_allowed() locks the PR mutex. Reservation commands
either need BH or thread context. Hence switch from atomic to
thread context before processing such commands.

Reported-by: Shahar Salzman <shahar.salzman@kaminario.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>


git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@5963 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Bart Van Assche
2015-01-13 08:42:28 +00:00
parent 6cff234ab4
commit 87fb2237c0

View File

@@ -1594,12 +1594,44 @@ void scst_rx_data(struct scst_cmd *cmd, int status,
}
EXPORT_SYMBOL(scst_rx_data);
/*
* Whether a command must be executed in thread context. Persistent reservation
* commands need thread context because of dev_pr_mutex. Traditional reserve
* and release commands need thread context because e.g. queueing a unit
* attention needs either BH or thread context.
*/
static inline bool scst_needs_thread_context(struct scst_cmd *cmd)
{
switch (cmd->cdb[0]) {
case PERSISTENT_RESERVE_IN:
case PERSISTENT_RESERVE_OUT:
case RESERVE:
case RESERVE_10:
case RELEASE:
case RELEASE_10:
return true;
}
return false;
}
static int scst_tgt_pre_exec(struct scst_cmd *cmd)
{
int res = SCST_CMD_STATE_RES_CONT_SAME, rc;
TRACE_ENTRY();
/* Switch to thread context before executing a reservation command. */
if (unlikely(scst_cmd_atomic(cmd) &&
((cmd->dev && cmd->dev->pr_is_set) ||
scst_needs_thread_context(cmd)))) {
TRACE_DBG("Atomic context and %s, rescheduling (cmd %p)",
cmd->dev && cmd->dev->pr_is_set ?
"dev->pr_is_set" : "reservation command", cmd);
res = SCST_CMD_STATE_RES_NEED_THREAD;
goto out;
}
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
if (unlikely(trace_flag & TRACE_DATA_RECEIVED) &&
(cmd->data_direction & SCST_DATA_WRITE)) {