diff options
author | Bart Van Assche <bvanassche@acm.org> | 2013-08-17 22:34:43 +0200 |
---|---|---|
committer | Robert Love <robert.w.love@intel.com> | 2013-09-04 22:45:22 +0200 |
commit | 7030fd626129ec4d616784516a462d317c251d39 (patch) | |
tree | cd9a65fa2d45e6397ba1620846dc4c9359638df4 /include/scsi | |
parent | libfc: Reduce exchange lock contention in fc_exch_recv_abts() (diff) | |
download | linux-7030fd626129ec4d616784516a462d317c251d39.tar.xz linux-7030fd626129ec4d616784516a462d317c251d39.zip |
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>
Diffstat (limited to 'include/scsi')
-rw-r--r-- | include/scsi/libfc.h | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index e1379b4e8faf..52beadf9a29b 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -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 *); |