Skip to content

Commit

Permalink
IB/fmr_pool: ib_fmr_pool_flush() should flush all dirty FMRs
Browse files Browse the repository at this point in the history
When a FMR is released via ib_fmr_pool_unmap(), the FMR usually ends
up on the free_list rather than the dirty_list (because we allow a
certain number of remappings before actually requiring a flush).

However, ib_fmr_batch_release() only looks at dirty_list when flushing
out old mappings.  This means that when ib_fmr_pool_flush() is used to
force a flush of the FMR pool, some dirty FMRs that have not reached
their maximum remap count will not actually be flushed.

Fix this by flushing all FMRs that have been used at least once in
ib_fmr_batch_release().

Signed-off-by: Olaf Kirch <olaf.kirch@oracle.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
  • Loading branch information
Olaf Kirch authored and Roland Dreier committed Jan 25, 2008
1 parent a656eb7 commit a3cd7d9
Showing 1 changed file with 15 additions and 6 deletions.
21 changes: 15 additions & 6 deletions drivers/infiniband/core/fmr_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ static inline struct ib_pool_fmr *ib_fmr_cache_lookup(struct ib_fmr_pool *pool,
static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
{
int ret;
struct ib_pool_fmr *fmr;
struct ib_pool_fmr *fmr, *next;
LIST_HEAD(unmap_list);
LIST_HEAD(fmr_list);

Expand All @@ -158,6 +158,20 @@ static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
#endif
}

/*
* The free_list may hold FMRs that have been put there
* because they haven't reached the max_remap count.
* Invalidate their mapping as well.
*/
list_for_each_entry_safe(fmr, next, &pool->free_list, list) {
if (fmr->remap_count == 0)
continue;
hlist_del_init(&fmr->cache_node);
fmr->remap_count = 0;
list_add_tail(&fmr->fmr->list, &fmr_list);
list_move(&fmr->list, &unmap_list);
}

list_splice(&pool->dirty_list, &unmap_list);
INIT_LIST_HEAD(&pool->dirty_list);
pool->dirty_len = 0;
Expand Down Expand Up @@ -367,11 +381,6 @@ void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)

i = 0;
list_for_each_entry_safe(fmr, tmp, &pool->free_list, list) {
if (fmr->remap_count) {
INIT_LIST_HEAD(&fmr_list);
list_add_tail(&fmr->fmr->list, &fmr_list);
ib_unmap_fmr(&fmr_list);
}
ib_dealloc_fmr(fmr->fmr);
list_del(&fmr->list);
kfree(fmr);
Expand Down

0 comments on commit a3cd7d9

Please sign in to comment.