libfc: Do not invoke the response handler after fc_exch_done()

While the FCoE initiator driver invokes fc_exch_done() from inside
the libfc response handler, FCoE target drivers typically invoke
fc_exch_done() from outside the libfc response handler. The object
fc_exch.arg points at may disappear as soon as fc_exch_done() has
finished. So it's important not to invoke the response handler
function after fc_exch_done() has finished. Modify libfc such that
this guarantee is provided if fc_exch_done() is invoked from
outside a response handler. This patch fixes a sporadic crash in
FCoE target implementations after a command has been aborted.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Cc: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
This commit is contained in:
Bart Van Assche
2013-08-17 20:34:43 +00:00
committed by Robert Love
parent f95b35cfca
commit 7030fd6261
2 changed files with 101 additions and 39 deletions

View File

@@ -410,6 +410,12 @@ struct fc_seq {
* @fh_type: The frame type
* @class: The class of service
* @seq: The sequence in use on this exchange
* @resp_active: Number of tasks that are concurrently executing @resp().
* @resp_task: If @resp_active > 0, either the task executing @resp(), the
* task that has been interrupted to execute the soft-IRQ
* executing @resp() or NULL if more than one task is executing
* @resp concurrently.
* @resp_wq: Waitqueue for the tasks waiting on @resp_active.
* @resp: Callback for responses on this exchange
* @destructor: Called when destroying the exchange
* @arg: Passed as a void pointer to the resp() callback
@@ -441,6 +447,9 @@ struct fc_exch {
u32 r_a_tov;
u32 f_ctl;
struct fc_seq seq;
int resp_active;
struct task_struct *resp_task;
wait_queue_head_t resp_wq;
void (*resp)(struct fc_seq *, struct fc_frame *, void *);
void *arg;
void (*destructor)(struct fc_seq *, void *);