From: Santosh Shilimkar Date: Mon, 21 Mar 2016 06:24:32 +0000 (-0700) Subject: RDS: IB: purge receive frag cache on connection shutdown X-Git-Tag: v4.1.12-92~175^2~8 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=f74abcb01b6d42d42fc7e29ff888ffeccfdfdf57;p=users%2Fjedix%2Flinux-maple.git RDS: IB: purge receive frag cache on connection shutdown RDS IB connections can be formed with different fragment size across reconnect and hence the current frag cache needs to be purged to avoid stale frag usages. Orabug: 21894138 Signed-off-by: Santosh Shilimkar --- diff --git a/net/rds/ib.h b/net/rds/ib.h index e377bafc477c..231e5de50828 100644 --- a/net/rds/ib.h +++ b/net/rds/ib.h @@ -617,6 +617,7 @@ void rds_ib_recv_exit(void); int rds_ib_recv(struct rds_connection *conn); int rds_ib_recv_alloc_caches(struct rds_ib_connection *ic); void rds_ib_recv_free_caches(struct rds_ib_connection *ic); +void rds_ib_recv_purge_frag_cache(struct rds_ib_connection *ic); void rds_ib_recv_refill(struct rds_connection *conn, int prefill, gfp_t gfp); void rds_ib_inc_free(struct rds_incoming *inc); int rds_ib_inc_copy_to_user(struct rds_incoming *inc, struct iov_iter *to); diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index 59a07afb8236..a425a7690a87 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c @@ -1304,6 +1304,9 @@ void rds_ib_conn_shutdown(struct rds_connection *conn) reinit_completion(&ic->i_last_wqe_complete); + /* Purge the ic->i_cache_frags */ + rds_ib_recv_purge_frag_cache(ic); + ic->i_active_side = 0; } diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c index aed1ecf70134..cf6b63b0eac7 100644 --- a/net/rds/ib_recv.c +++ b/net/rds/ib_recv.c @@ -195,6 +195,38 @@ void rds_ib_recv_free_caches(struct rds_ib_connection *ic) } } +/* Called from rds_ib_conn_shutdown path on the way + * towards connection destroy or reconnect + */ +void rds_ib_recv_purge_frag_cache(struct rds_ib_connection *ic) +{ + struct rds_ib_cache_head *head; + struct rds_page_frag *frag, *frag_tmp; + LIST_HEAD(list); + int cpu; + + rds_ib_cache_xfer_to_ready(&ic->i_cache_frags); + rds_ib_cache_splice_all_lists(&ic->i_cache_frags, &list); + atomic_set(&ic->i_cache_allocs, 0); + + list_for_each_entry_safe(frag, frag_tmp, &list, f_cache_entry) { + list_del(&frag->f_cache_entry); + WARN_ON(!list_empty(&frag->f_item)); + kmem_cache_free(rds_ib_frag_slab, frag); + rds_ib_stats_add(s_ib_recv_added_to_cache, ic->i_frag_sz); + rds_ib_stats_add(s_ib_recv_removed_from_cache, ic->i_frag_sz); + } + + for_each_possible_cpu(cpu) { + head = per_cpu_ptr(ic->i_cache_frags.percpu, cpu); + head->first = NULL; + head->count = 0; + } + + ic->i_cache_frags.xfer = NULL; + ic->i_cache_frags.ready = NULL; +} + /* fwd decl */ static void rds_ib_recv_cache_put(struct list_head *new_item, struct rds_ib_refill_cache *cache);