[ewg] [PATCH 1/2] fmr_pool flush serials can get out of sync

Olaf Kirch olaf.kirch at oracle.com
Wed Jan 16 09:36:27 PST 2008


From: Olaf Kirch <olaf.kirch at oracle.com>
Subject: [fmr_pool] fmr_pool flush serials can get out of sync

Normally, the serial numbers for flush requests and flushes
executed should be in sync.

When we decide to flush dirty MRs because there are too many of them, we
wake up the cleanup thread and let it do its stuff.  As a side effect, it
increments pool->flush_ser, which leaves it one higher than req_ser. The
next time the user calls ib_flush_fmr_pool, it will wake up the cleanup
thread, but won't wait for the flush to complete. This can cause memory
corruption, as the user expects the flush to have taken place.

Signed-off-by: Olaf Kirch <olaf.kirch at oracle.com>
---
 drivers/infiniband/core/fmr_pool.c |   16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

Index: ofa_kernel-1.3/drivers/infiniband/core/fmr_pool.c
===================================================================
--- ofa_kernel-1.3.orig/drivers/infiniband/core/fmr_pool.c
+++ ofa_kernel-1.3/drivers/infiniband/core/fmr_pool.c
@@ -182,8 +182,7 @@ static int ib_fmr_cleanup_thread(void *p
 	struct ib_fmr_pool *pool = pool_ptr;
 
 	do {
-		if (pool->dirty_len >= pool->dirty_watermark ||
-		    atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) < 0) {
+		if (atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) < 0) {
 			ib_fmr_batch_release(pool);
 
 			atomic_inc(&pool->flush_ser);
@@ -194,8 +193,7 @@ static int ib_fmr_cleanup_thread(void *p
 		}
 
 		set_current_state(TASK_INTERRUPTIBLE);
-		if (pool->dirty_len < pool->dirty_watermark &&
-		    atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) >= 0 &&
+		if (atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) >= 0 &&
 		    !kthread_should_stop())
 			schedule();
 		__set_current_state(TASK_RUNNING);
@@ -397,6 +395,7 @@ EXPORT_SYMBOL(ib_destroy_fmr_pool);
  */
 int ib_flush_fmr_pool(struct ib_fmr_pool *pool)
 {
+	int flush_count = atomic_read(&pool->flush_ser);
 	int serial = atomic_inc_return(&pool->req_ser);
 
 	wake_up_process(pool->thread);
@@ -405,6 +404,9 @@ int ib_flush_fmr_pool(struct ib_fmr_pool
 				     atomic_read(&pool->flush_ser) - serial >= 0))
 		return -EINTR;
 
+	flush_count = atomic_read(&pool->flush_ser) - flush_count;
+	BUG_ON(flush_count == 0);
+
 	return 0;
 }
 EXPORT_SYMBOL(ib_flush_fmr_pool);
@@ -511,8 +513,10 @@ int ib_fmr_pool_unmap(struct ib_pool_fmr
 			list_add_tail(&fmr->list, &pool->free_list);
 		} else {
 			list_add_tail(&fmr->list, &pool->dirty_list);
-			++pool->dirty_len;
-			wake_up_process(pool->thread);
+			if (++pool->dirty_len >= pool->dirty_watermark) {
+				atomic_inc(&pool->req_ser);
+				wake_up_process(pool->thread);
+			}
 		}
 	}
 

-- 
Olaf Kirch  |  --- o --- Nous sommes du soleil we love when we play
okir at lst.de |    / | \   sol.dhoop.naytheet.ah kin.ir.samse.qurax



More information about the ewg mailing list