Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=a656eb758fc6e6a42659ecf5ba34a5c5a2aeec17
Commit:     a656eb758fc6e6a42659ecf5ba34a5c5a2aeec17
Parent:     2fe7e6f7c9f55eac24c5b3cdf56af29ab9b0ca81
Author:     Olaf Kirch <[EMAIL PROTECTED]>
AuthorDate: Wed Jan 16 18:36:27 2008 +0100
Committer:  Roland Dreier <[EMAIL PROTECTED]>
CommitDate: Fri Jan 25 14:15:42 2008 -0800

    IB/fmr_pool: Flush serial numbers can get out of sync
    
    Normally, the serial numbers for flush requests and flushes executed
    for an FMR pool should be in sync.
    
    However, if the FMR pool flushes dirty FMRs because the
    dirty_watermark was reached, we wake up the cleanup thread and let it
    do its stuff.  As a side effect, the cleanup thread increments
    pool->flush_ser, which leaves it one higher than pool->req_ser.  The
    next time the user calls ib_flush_fmr_pool(), the cleanup thread will
    be woken up, but ib_flush_fmr_pool() won't wait for the flush to
    complete because flush_ser is already past req_ser.  This means the
    FMRs that the user expects to be flushed may not have all been flushed
    when the function returns.
    
    Fix this by telling the cleanup thread to do work exclusively by
    incrementing req_ser, and by moving the comparison of dirty_len and
    dirty_watermark into ib_fmr_pool_unmap().
    
    Signed-off-by: Olaf Kirch <[EMAIL PROTECTED]>
---
 drivers/infiniband/core/fmr_pool.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/infiniband/core/fmr_pool.c 
b/drivers/infiniband/core/fmr_pool.c
index e8d5f6b..4a476a8 100644
--- a/drivers/infiniband/core/fmr_pool.c
+++ b/drivers/infiniband/core/fmr_pool.c
@@ -182,8 +182,7 @@ static int ib_fmr_cleanup_thread(void *pool_ptr)
        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 *pool_ptr)
                }
 
                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);
@@ -511,8 +509,10 @@ int ib_fmr_pool_unmap(struct ib_pool_fmr *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);
+                       }
                }
        }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to