Patch "IB/qib: Support creating qps with GFP_NOIO flag" has been added to the 4.4-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
IB/qib: Support creating qps with GFP_NOIO flag
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
ib-qib-support-creating-qps-with-gfp_noio-flag.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
fbbeb8632bf0b46ab44cfcedc4654cd7831b7161Mon Sep 17 00:00:00 2001
From: Vinit Agnihotri <[email protected]>
Date: Mon, 11 Jan 2016 12:57:25 -0500
Subject: IB/qib: Support creating qps with GFP_NOIO flag
From: Vinit Agnihotri <[email protected]>
commit fbbeb8632bf0b46ab44cfcedc4654cd7831b7161 upstream.
The current code is problematic when the QP creation and ipoib is used to support NFS and NFS desires to do IO for paging purposes. In that case, the GFP_KERNEL allocation in qib_qp.c causes a deadlock in tight memory situations.
This fix adds support to create queue pair with GFP_NOIO flag for connected mode only to cleanly fail the create queue pair in those situations.
--- drivers/infiniband/hw/qib/qib_qp.c | 46 +++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 14 deletions(-)
drivers/infiniband/hw/qib/qib_qp.c +32 -14
@@ -100,9 +100,10 @@ static u32 credit_table[31] = { 32768 /* 1E */ }; -static void get_map_page (struct qib_qpn_table *qpt,struct qpn_map *map) +static void get_map_page (struct qib_qpn_table *qpt,struct qpn_map *map, +gfp_t gfp) { -unsigned long page =get_zeroed_page (GFP_KERNEL ); +unsigned long page =get_zeroed_page (gfp);/* * Free the page if someone raced with us installing it.
@@ -121,7 +122,7 @@ static void get_map_page(struct qib_qpn_* zero/one for QP type IB_QPT_SMI/IB_QPT_GSI. */ static int alloc_qpn (struct qib_devdata *dd,struct qib_qpn_table *qpt, -enum ib_qp_type type,u8 port) +enum ib_qp_type type,u8 port,gfp_t gfp) {u32 i, offset, max_scan, qpn;struct qpn_map *map;
@@ -151,7 +152,7 @@ static int alloc_qpn(struct qib_devdata max_scan = qpt->nmaps - !offset;for (i =0 ;;) {if (unlikely (!map->page)) { -get_map_page (qpt, map); +get_map_page (qpt, map, gfp);if (unlikely (!map->page))break ; }
@@ -983,13 +984,21 @@ struct ib_qp *qib_create_qp(struct ib_pdsize_t sz;size_t sg_list_sz;struct ib_qp *ret; +gfp_t gfp; +if (init_attr->cap.max_send_sge > ib_qib_max_sges || init_attr->cap.max_send_wr > ib_qib_max_qp_wrs || - init_attr->create_flags) { - ret =ERR_PTR (-EINVAL ); - goto bail; - } + init_attr->create_flags & ~(IB_QP_CREATE_USE_GFP_NOIO )) +return ERR_PTR (-EINVAL ); + +/* GFP_NOIO is applicable in RC QPs only */ +if (init_attr->create_flags &IB_QP_CREATE_USE_GFP_NOIO && + init_attr->qp_type !=IB_QPT_RC ) +return ERR_PTR (-EINVAL ); + + gfp = init_attr->create_flags &IB_QP_CREATE_USE_GFP_NOIO ? +GFP_NOIO :GFP_KERNEL ;/* Check receive queue parameters if no SRQ is specified. */ if (!init_attr->srq) {
@@ -1021,7 +1030,8 @@ struct ib_qp *qib_create_qp(struct ib_pd sz =sizeof (struct qib_sge ) * init_attr->cap.max_send_sge +sizeof (struct qib_swqe ); - swq =vmalloc ((init_attr->cap.max_send_wr +1 ) * sz); + swq =__vmalloc ((init_attr->cap.max_send_wr +1 ) * sz, + gfp,PAGE_KERNEL );if (swq ==NULL ) { ret =ERR_PTR (-ENOMEM ); goto bail;
@@ -1037,13 +1047,13 @@ struct ib_qp *qib_create_qp(struct ib_pd }else if (init_attr->cap.max_recv_sge >1 ) sg_list_sz =sizeof (*qp->r_sg_list) * (init_attr->cap.max_recv_sge -1 ); - qp =kzalloc (sz + sg_list_sz,GFP_KERNEL ); + qp =kzalloc (sz + sg_list_sz, gfp);if (!qp) { ret =ERR_PTR (-ENOMEM ); goto bail_swq; }RCU_INIT_POINTER (qp->next,NULL ); - qp->s_hdr =kzalloc (sizeof (*qp->s_hdr),GFP_KERNEL ); + qp->s_hdr =kzalloc (sizeof (*qp->s_hdr), gfp);if (!qp->s_hdr) { ret =ERR_PTR (-ENOMEM ); goto bail_qp;
@@ -1058,8 +1068,16 @@ struct ib_qp *qib_create_qp(struct ib_pd qp->r_rq.max_sge = init_attr->cap.max_recv_sge; sz = (sizeof (struct ib_sge ) * qp->r_rq.max_sge) +sizeof (struct qib_rwqe ); - qp->r_rq.wq =vmalloc_user (sizeof (struct qib_rwq ) + - qp->r_rq.size * sz); +if (gfp !=GFP_NOIO ) + qp->r_rq.wq =vmalloc_user ( +sizeof (struct qib_rwq ) + + qp->r_rq.size * sz); +else + qp->r_rq.wq =__vmalloc ( +sizeof (struct qib_rwq ) + + qp->r_rq.size * sz, + gfp,PAGE_KERNEL ); +if (!qp->r_rq.wq) { ret =ERR_PTR (-ENOMEM ); goto bail_qp;
@@ -1090,7 +1108,7 @@ struct ib_qp *qib_create_qp(struct ib_pd dev =to_idev (ibpd->device); dd =dd_from_dev (dev); err =alloc_qpn (dd, &dev->qpn_table, init_attr->qp_type, - init_attr->port_num); + init_attr->port_num, gfp);if (err <0 ) { ret =ERR_PTR (err);vfree (qp->r_rq.wq);
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/ib-qib-support-creating-qps-with-gfp_noio-flag.patch