aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorRoland Dreier <rolandd@cisco.com>2006-12-12 14:50:19 -0500
committerRoland Dreier <rolandd@cisco.com>2006-12-12 14:50:19 -0500
commitf47e22c6e4225f40e0dd662398e2cb204f6ec8ed (patch)
treecb8721c67941f3b261d6310830d4bb94f0b0ed9d /drivers/infiniband
parente1036502e5263851259d147771226161e5ccc85a (diff)
IB/fmr: ib_flush_fmr_pool() may wait too long
ib_flush_fmr_pool() stashes away the request generation number properly, but then goes ahead and rereads it every time it tests whether the flush generation number has caught up. This means that there is a theoretical possibility of livelock, if the request generation number keeps getting bumped and the flush generation number never catches up. The fix is simple: use the request generation number read at the beginning of the function. Also, atomic_inc() followed by atomic_read() can be replaced with atomic_int_return(). There's no real requirement for atomicity here but we might as well shrink the code. This bug was discovered using David Binderman's list of "set but never used" warnings from icc. Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/core/fmr_pool.c12
1 files changed, 2 insertions, 10 deletions
diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c
index 86a3b2d401db..8926a2bd4a87 100644
--- a/drivers/infiniband/core/fmr_pool.c
+++ b/drivers/infiniband/core/fmr_pool.c
@@ -394,20 +394,12 @@ EXPORT_SYMBOL(ib_destroy_fmr_pool);
394 */ 394 */
395int ib_flush_fmr_pool(struct ib_fmr_pool *pool) 395int ib_flush_fmr_pool(struct ib_fmr_pool *pool)
396{ 396{
397 int serial; 397 int serial = atomic_inc_return(&pool->req_ser);
398
399 atomic_inc(&pool->req_ser);
400 /*
401 * It's OK if someone else bumps req_ser again here -- we'll
402 * just wait a little longer.
403 */
404 serial = atomic_read(&pool->req_ser);
405 398
406 wake_up_process(pool->thread); 399 wake_up_process(pool->thread);
407 400
408 if (wait_event_interruptible(pool->force_wait, 401 if (wait_event_interruptible(pool->force_wait,
409 atomic_read(&pool->flush_ser) - 402 atomic_read(&pool->flush_ser) - serial >= 0))
410 atomic_read(&pool->req_ser) >= 0))
411 return -EINTR; 403 return -EINTR;
412 404
413 return 0; 405 return 0;