public inbox for linux-rdma@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] IB/srp: fix race condition on srp_target_port.req_lim
@ 2010-07-25 16:12 Bart Van Assche
       [not found] ` <201007251812.42757.bvanassche-HInyCGIudOg@public.gmane.org>
  0 siblings, 1 reply; 3+ messages in thread
From: Bart Van Assche @ 2010-07-25 16:12 UTC (permalink / raw)
  To: linux-rdma-u79uwXL29TY76Z2rM5mHXA; +Cc: Roland Dreier

In the current implementation of ib_srp the req_lim field of
struct srp_target_port can be manipulated in a non-atomic way by
more than one CPU at a time: one CPU can be modifying req_lim in
function srp_process_rsp() while another CPU can concurrently be
decrementing req_lim in function __srp_get_tx_iu(). This is a
race condition which can result in incorrect manipulation of the
req_lim field. The patch below fixes this race condition by
converting all manipulations of req_lim into atomic operations.

Signed-off-by: Bart Van Assche <bart.vanassche-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Cc: Roland Dreier <rolandd-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org>

diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index ed3f9eb..3d334b5 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -822,7 +822,7 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
 
 	spin_lock_irqsave(target->scsi_host->host_lock, flags);
 
-	target->req_lim += delta;
+	atomic_add(delta, &target->req_lim);
 
 	req = &target->req_ring[rsp->tag & ~SRP_TAG_TSK_MGMT];
 
@@ -1008,7 +1008,7 @@ static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
 	if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
 		return NULL;
 
-	if (target->req_lim < min) {
+	if (atomic_read(&target->req_lim) < min) {
 		++target->zero_req_lim;
 		return NULL;
 	}
@@ -1042,7 +1042,7 @@ static int __srp_post_send(struct srp_target_port *target,
 
 	if (!ret) {
 		++target->tx_head;
-		--target->req_lim;
+		atomic_dec(&target->req_lim);
 	}
 
 	return ret;
@@ -1266,10 +1266,12 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
 			struct srp_login_rsp *rsp = event->private_data;
 
 			target->max_ti_iu_len = be32_to_cpu(rsp->max_ti_iu_len);
-			target->req_lim       = be32_to_cpu(rsp->req_lim_delta);
+			atomic_set(&target->req_lim,
+				   be32_to_cpu(rsp->req_lim_delta));
 
-			target->scsi_host->can_queue = min(target->req_lim,
-							   target->scsi_host->can_queue);
+			target->scsi_host->can_queue
+				= min(atomic_read(&target->req_lim),
+				      target->scsi_host->can_queue);
 		} else {
 			shost_printk(KERN_WARNING, target->scsi_host,
 				    PFX "Unhandled RSP opcode %#x\n", opcode);
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index 5a80eac..048f213 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -135,7 +135,7 @@ struct srp_target_port {
 	struct ib_qp	       *qp;
 
 	int			max_ti_iu_len;
-	s32			req_lim;
+	atomic_t		req_lim;
 
 	int			zero_req_lim;
 
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] IB/srp: fix race condition on srp_target_port.req_lim
       [not found] ` <201007251812.42757.bvanassche-HInyCGIudOg@public.gmane.org>
@ 2010-07-25 18:36   ` David Dillow
       [not found]     ` <1280082992.10629.44.camel-1q1vX8mYZiGLUyTwlgNVppKKF0rrzTr+@public.gmane.org>
  0 siblings, 1 reply; 3+ messages in thread
From: David Dillow @ 2010-07-25 18:36 UTC (permalink / raw)
  To: Bart Van Assche; +Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA, Roland Dreier

On Sun, 2010-07-25 at 18:12 +0200, Bart Van Assche wrote:
> In the current implementation of ib_srp the req_lim field of
> struct srp_target_port can be manipulated in a non-atomic way by
> more than one CPU at a time: one CPU can be modifying req_lim in
> function srp_process_rsp() while another CPU can concurrently be
> decrementing req_lim in function __srp_get_tx_iu(). This is a
> race condition which can result in incorrect manipulation of the
> req_lim field. The patch below fixes this race condition by
> converting all manipulations of req_lim into atomic operations.

This is not needed -- all modifications of target->req_lim are protected
by scsi_dev->host_lock. It is held implicitly in srp_queuecommand() by
the SCSI mid-layer, and we take that lock before modifying req_lim
elsewhere -- or we're initializing and there won't be concurrent access.

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] IB/srp: fix race condition on srp_target_port.req_lim
       [not found]     ` <1280082992.10629.44.camel-1q1vX8mYZiGLUyTwlgNVppKKF0rrzTr+@public.gmane.org>
@ 2010-07-26  7:55       ` Bart Van Assche
  0 siblings, 0 replies; 3+ messages in thread
From: Bart Van Assche @ 2010-07-26  7:55 UTC (permalink / raw)
  To: David Dillow; +Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA, Roland Dreier

On Sun, Jul 25, 2010 at 8:36 PM, David Dillow <dave-i1Mk8JYDVaaSihdK6806/g@public.gmane.org> wrote:
>
> On Sun, 2010-07-25 at 18:12 +0200, Bart Van Assche wrote:
> > In the current implementation of ib_srp the req_lim field of
> > struct srp_target_port can be manipulated in a non-atomic way by
> > more than one CPU at a time: one CPU can be modifying req_lim in
> > function srp_process_rsp() while another CPU can concurrently be
> > decrementing req_lim in function __srp_get_tx_iu(). This is a
> > race condition which can result in incorrect manipulation of the
> > req_lim field. The patch below fixes this race condition by
> > converting all manipulations of req_lim into atomic operations.
>
> This is not needed -- all modifications of target->req_lim are protected
> by scsi_dev->host_lock. It is held implicitly in srp_queuecommand() by
> the SCSI mid-layer, and we take that lock before modifying req_lim
> elsewhere -- or we're initializing and there won't be concurrent access.

It would be helpful for anyone who is reviewing or modifying the SRP
initiator source code if the locking policy was documented. As an
example, in kernels 2.6.33 and before there was a single notification
processing function srp_completion() that incremented target->tx_tail
non-atomically and without protection of scsi_host->host_lock. It was
not possible to tell from the source code comments whether or not this
access pattern was intentional.

Bart.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2010-07-26  7:55 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-25 16:12 [PATCH] IB/srp: fix race condition on srp_target_port.req_lim Bart Van Assche
     [not found] ` <201007251812.42757.bvanassche-HInyCGIudOg@public.gmane.org>
2010-07-25 18:36   ` David Dillow
     [not found]     ` <1280082992.10629.44.camel-1q1vX8mYZiGLUyTwlgNVppKKF0rrzTr+@public.gmane.org>
2010-07-26  7:55       ` Bart Van Assche

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox