aboutsummaryrefslogtreecommitdiff
path: root/include/scsi
diff options
context:
space:
mode:
authorBart Van Assche <bvanassche@acm.org>2013-08-17 20:34:43 +0000
committerRobert Love <robert.w.love@intel.com>2013-09-04 13:45:22 -0700
commit7030fd626129ec4d616784516a462d317c251d39 (patch)
treecd9a65fa2d45e6397ba1620846dc4c9359638df4 /include/scsi
parentf95b35cfcacadac16dbc5477fd22b0786256a3d1 (diff)
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.h9
1 files changed, 9 insertions, 0 deletions
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index e1379b4e8fa..52beadf9a29 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 *);