From d226464acaacccd240da43dcc22372fbf8cb04a6 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Wed, 1 Jun 2016 09:16:25 -0400 Subject: [PATCH] LU-8057 ko2iblnd: Replace sg++ with sg = sg_next(sg) With scatterlist chaining, simply incrementing the array does not work. sg_next macro was thus introduced to follow the chain links when necessary. So replace sg++ with sg_next. This change was made with the help of the following Coccinelle semantic patch: // @@ struct scatterlist *sg; @@ -sg++ +sg = sg_next(sg) // In my test of the upstream client this change exposed a long standing issues where we have a offset that is not page aligned would cause us to access memory beyond the scatter gather list which was causing memory corruption when all 256 fragments were in use. Signed-off-by: James Simmons Change-Id: I5bc140645b841aa2a92da434ffa65795112c6cec Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman Reviewed-on: http://review.whamcloud.com/19342 Tested-by: Jenkins Reviewed-by: Andreas Dilger Reviewed-by: Doug Oucharek Tested-by: Maloo Reviewed-by: Oleg Drokin --- lnet/klnds/o2iblnd/o2iblnd.c | 9 +++++---- lnet/klnds/o2iblnd/o2iblnd_cb.c | 16 ++++++++++++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/lnet/klnds/o2iblnd/o2iblnd.c b/lnet/klnds/o2iblnd/o2iblnd.c index 92254b8..09d4f56 100644 --- a/lnet/klnds/o2iblnd/o2iblnd.c +++ b/lnet/klnds/o2iblnd/o2iblnd.c @@ -2216,8 +2216,8 @@ kiblnd_destroy_tx_pool(kib_pool_t *pool) sizeof(*tx->tx_pages)); if (tx->tx_frags != NULL) LIBCFS_FREE(tx->tx_frags, - IBLND_MAX_RDMA_FRAGS * - sizeof(*tx->tx_frags)); + (1 + IBLND_MAX_RDMA_FRAGS) * + sizeof(*tx->tx_frags)); if (tx->tx_wrq != NULL) LIBCFS_FREE(tx->tx_wrq, (1 + IBLND_MAX_RDMA_FRAGS) * @@ -2295,11 +2295,12 @@ kiblnd_create_tx_pool(kib_poolset_t *ps, int size, kib_pool_t **pp_po) } LIBCFS_CPT_ALLOC(tx->tx_frags, lnet_cpt_table(), ps->ps_cpt, - IBLND_MAX_RDMA_FRAGS * sizeof(*tx->tx_frags)); + (1 + IBLND_MAX_RDMA_FRAGS) * + sizeof(*tx->tx_frags)); if (tx->tx_frags == NULL) break; - sg_init_table(tx->tx_frags, IBLND_MAX_RDMA_FRAGS); + sg_init_table(tx->tx_frags, IBLND_MAX_RDMA_FRAGS + 1); LIBCFS_CPT_ALLOC(tx->tx_wrq, lnet_cpt_table(), ps->ps_cpt, (1 + IBLND_MAX_RDMA_FRAGS) * diff --git a/lnet/klnds/o2iblnd/o2iblnd_cb.c b/lnet/klnds/o2iblnd/o2iblnd_cb.c index 4ff2e98..6b4bd30 100644 --- a/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -688,7 +688,11 @@ kiblnd_setup_rd_iov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd, fragnob = min(fragnob, (int)PAGE_SIZE - page_offset); sg_set_page(sg, page, fragnob, page_offset); - sg++; + sg = sg_next(sg); + if (!sg) { + CERROR("lacking enough sg entries to map tx\n"); + return -EFAULT; + } if (offset + fragnob < iov->iov_len) { offset += fragnob; @@ -730,9 +734,13 @@ kiblnd_setup_rd_kiov (lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd, fragnob = min((int)(kiov->kiov_len - offset), nob); - sg_set_page(sg, kiov->kiov_page, fragnob, - kiov->kiov_offset + offset); - sg++; + sg_set_page(sg, kiov->kiov_page, fragnob, + kiov->kiov_offset + offset); + sg = sg_next(sg); + if (!sg) { + CERROR("lacking enough sg entries to map tx\n"); + return -EFAULT; + } offset = 0; kiov++; -- 1.8.3.1