aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorBart Van Assche <bvanassche@acm.org>2014-03-14 08:54:11 -0400
committerRoland Dreier <roland@purestorage.com>2014-03-24 13:05:31 -0400
commitb3fe628da2898cf1387105026dfed551ecc25de5 (patch)
tree6df463ae165b00ab3ca3f005e98853f8c97e2565 /drivers/infiniband
parentac72d766a8e44d782bd5480fc953ab6025c82e92 (diff)
IB/srp: Fix a race condition between failing I/O and I/O completion
Avoid that srp_terminate_io() can access req->scmnd after it has been cleared by the I/O completion code. Do this by protecting req->scmnd accesses from srp_terminate_io() via locking Signed-off-by: Bart Van Assche <bvanassche@acm.org> Acked-by: Sagi Grimberg <sagig@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c33
1 files changed, 22 insertions, 11 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index a64e469db116..66a908bf3fb9 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -783,6 +783,7 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
783 * srp_claim_req - Take ownership of the scmnd associated with a request. 783 * srp_claim_req - Take ownership of the scmnd associated with a request.
784 * @target: SRP target port. 784 * @target: SRP target port.
785 * @req: SRP request. 785 * @req: SRP request.
786 * @sdev: If not NULL, only take ownership for this SCSI device.
786 * @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take 787 * @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take
787 * ownership of @req->scmnd if it equals @scmnd. 788 * ownership of @req->scmnd if it equals @scmnd.
788 * 789 *
@@ -791,16 +792,17 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
791 */ 792 */
792static struct scsi_cmnd *srp_claim_req(struct srp_target_port *target, 793static struct scsi_cmnd *srp_claim_req(struct srp_target_port *target,
793 struct srp_request *req, 794 struct srp_request *req,
795 struct scsi_device *sdev,
794 struct scsi_cmnd *scmnd) 796 struct scsi_cmnd *scmnd)
795{ 797{
796 unsigned long flags; 798 unsigned long flags;
797 799
798 spin_lock_irqsave(&target->lock, flags); 800 spin_lock_irqsave(&target->lock, flags);
799 if (!scmnd) { 801 if (req->scmnd &&
802 (!sdev || req->scmnd->device == sdev) &&
803 (!scmnd || req->scmnd == scmnd)) {
800 scmnd = req->scmnd; 804 scmnd = req->scmnd;
801 req->scmnd = NULL; 805 req->scmnd = NULL;
802 } else if (req->scmnd == scmnd) {
803 req->scmnd = NULL;
804 } else { 806 } else {
805 scmnd = NULL; 807 scmnd = NULL;
806 } 808 }
@@ -827,9 +829,10 @@ static void srp_free_req(struct srp_target_port *target,
827} 829}
828 830
829static void srp_finish_req(struct srp_target_port *target, 831static void srp_finish_req(struct srp_target_port *target,
830 struct srp_request *req, int result) 832 struct srp_request *req, struct scsi_device *sdev,
833 int result)
831{ 834{
832 struct scsi_cmnd *scmnd = srp_claim_req(target, req, NULL); 835 struct scsi_cmnd *scmnd = srp_claim_req(target, req, sdev, NULL);
833 836
834 if (scmnd) { 837 if (scmnd) {
835 srp_free_req(target, req, scmnd, 0); 838 srp_free_req(target, req, scmnd, 0);
@@ -841,11 +844,20 @@ static void srp_finish_req(struct srp_target_port *target,
841static void srp_terminate_io(struct srp_rport *rport) 844static void srp_terminate_io(struct srp_rport *rport)
842{ 845{
843 struct srp_target_port *target = rport->lld_data; 846 struct srp_target_port *target = rport->lld_data;
847 struct Scsi_Host *shost = target->scsi_host;
848 struct scsi_device *sdev;
844 int i; 849 int i;
845 850
851 /*
852 * Invoking srp_terminate_io() while srp_queuecommand() is running
853 * is not safe. Hence the warning statement below.
854 */
855 shost_for_each_device(sdev, shost)
856 WARN_ON_ONCE(sdev->request_queue->request_fn_active);
857
846 for (i = 0; i < target->req_ring_size; ++i) { 858 for (i = 0; i < target->req_ring_size; ++i) {
847 struct srp_request *req = &target->req_ring[i]; 859 struct srp_request *req = &target->req_ring[i];
848 srp_finish_req(target, req, DID_TRANSPORT_FAILFAST << 16); 860 srp_finish_req(target, req, NULL, DID_TRANSPORT_FAILFAST << 16);
849 } 861 }
850} 862}
851 863
@@ -882,7 +894,7 @@ static int srp_rport_reconnect(struct srp_rport *rport)
882 894
883 for (i = 0; i < target->req_ring_size; ++i) { 895 for (i = 0; i < target->req_ring_size; ++i) {
884 struct srp_request *req = &target->req_ring[i]; 896 struct srp_request *req = &target->req_ring[i];
885 srp_finish_req(target, req, DID_RESET << 16); 897 srp_finish_req(target, req, NULL, DID_RESET << 16);
886 } 898 }
887 899
888 INIT_LIST_HEAD(&target->free_tx); 900 INIT_LIST_HEAD(&target->free_tx);
@@ -1290,7 +1302,7 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
1290 complete(&target->tsk_mgmt_done); 1302 complete(&target->tsk_mgmt_done);
1291 } else { 1303 } else {
1292 req = &target->req_ring[rsp->tag]; 1304 req = &target->req_ring[rsp->tag];
1293 scmnd = srp_claim_req(target, req, NULL); 1305 scmnd = srp_claim_req(target, req, NULL, NULL);
1294 if (!scmnd) { 1306 if (!scmnd) {
1295 shost_printk(KERN_ERR, target->scsi_host, 1307 shost_printk(KERN_ERR, target->scsi_host,
1296 "Null scmnd for RSP w/tag %016llx\n", 1308 "Null scmnd for RSP w/tag %016llx\n",
@@ -2008,7 +2020,7 @@ static int srp_abort(struct scsi_cmnd *scmnd)
2008 2020
2009 shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n"); 2021 shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n");
2010 2022
2011 if (!req || !srp_claim_req(target, req, scmnd)) 2023 if (!req || !srp_claim_req(target, req, NULL, scmnd))
2012 return SUCCESS; 2024 return SUCCESS;
2013 if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, 2025 if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun,
2014 SRP_TSK_ABORT_TASK) == 0) 2026 SRP_TSK_ABORT_TASK) == 0)
@@ -2039,8 +2051,7 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
2039 2051
2040 for (i = 0; i < target->req_ring_size; ++i) { 2052 for (i = 0; i < target->req_ring_size; ++i) {
2041 struct srp_request *req = &target->req_ring[i]; 2053 struct srp_request *req = &target->req_ring[i];
2042 if (req->scmnd && req->scmnd->device == scmnd->device) 2054 srp_finish_req(target, req, scmnd->device, DID_RESET << 16);
2043 srp_finish_req(target, req, DID_RESET << 16);
2044 } 2055 }
2045 2056
2046 return SUCCESS; 2057 return SUCCESS;