All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 for-next 00/13] RDMA: Use refcount_t for reference counting
@ 2021-05-25  6:51 Weihang Li
  2021-05-25  6:51 ` [PATCH v3 for-next 01/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of iwcm_id_private Weihang Li
                   ` (12 more replies)
  0 siblings, 13 replies; 19+ messages in thread
From: Weihang Li @ 2021-05-25  6:51 UTC (permalink / raw)
  To: dledford, jgg; +Cc: leon, linux-rdma, linuxarm, Weihang Li

There are some refcnt in type of atomic_t in RDMA subsystem, almost all of
them is wrote before the refcount_t is acheived in kernel. refcount_t is
better than integer for reference counting, it will WARN on
overflow/underflow and avoid use-after-free risks.

Changes since v2:
* Drop i40iw related parts because this driver will be removed soon.
* Link: https://patchwork.kernel.org/project/linux-rdma/cover/1621590825-60693-1-git-send-email-liweihang@huawei.com/

Changes since v1:
* Split these patches by variable granularity.
* Fix a warning on refcount of struct mcast_group.
* Add a patch on rdmavt.
* Drop "RDMA/hns: Use refcount_t APIs for HEM".
* Link: https://patchwork.kernel.org/project/linux-rdma/cover/1620958299-4869-1-git-send-email-liweihang@huawei.com/

Weihang Li (13):
  RDMA/core: Use refcount_t instead of atomic_t on refcount of
    iwcm_id_private
  RDMA/core: Use refcount_t instead of atomic_t on refcount of
    iwpm_admin_data
  RDMA/core: Use refcount_t instead of atomic_t on refcount of
    ib_mad_snoop_private
  RDMA/core: Use refcount_t instead of atomic_t on refcount of
    mcast_member
  RDMA/core: Use refcount_t instead of atomic_t on refcount of
    mcast_port
  RDMA/core: Use refcount_t instead of atomic_t on refcount of
    mcast_group
  RDMA/core: Use refcount_t instead of atomic_t on refcount of
    ib_uverbs_device
  RDMA/hns: Use refcount_t instead of atomic_t for CQ reference counting
  RDMA/hns: Use refcount_t instead of atomic_t for SRQ reference
    counting
  RDMA/hns: Use refcount_t instead of atomic_t for QP reference counting
  RDMA/cxgb4: Use refcount_t instead of atomic_t for reference counting
  RDMA/ipoib: Use refcount_t instead of atomic_t for reference counting
  RDMA/rdmavt: Use refcount_t instead of atomic_t on refcount of
    rvt_mcast

 drivers/infiniband/core/iwcm.c              |  9 ++++---
 drivers/infiniband/core/iwcm.h              |  2 +-
 drivers/infiniband/core/iwpm_util.c         | 12 ++++++----
 drivers/infiniband/core/iwpm_util.h         |  2 +-
 drivers/infiniband/core/mad_priv.h          |  2 +-
 drivers/infiniband/core/multicast.c         | 37 ++++++++++++++++-------------
 drivers/infiniband/core/uverbs.h            |  2 +-
 drivers/infiniband/core/uverbs_main.c       | 12 +++++-----
 drivers/infiniband/hw/cxgb4/cq.c            |  6 ++---
 drivers/infiniband/hw/cxgb4/ev.c            |  8 +++----
 drivers/infiniband/hw/cxgb4/iw_cxgb4.h      |  2 +-
 drivers/infiniband/hw/hfi1/verbs.c          |  3 ++-
 drivers/infiniband/hw/hns/hns_roce_cq.c     |  8 +++----
 drivers/infiniband/hw/hns/hns_roce_device.h |  6 ++---
 drivers/infiniband/hw/hns/hns_roce_qp.c     | 12 +++++-----
 drivers/infiniband/hw/hns/hns_roce_srq.c    |  8 +++----
 drivers/infiniband/hw/qib/qib_verbs.c       |  3 ++-
 drivers/infiniband/sw/rdmavt/mcast.c        | 11 ++++-----
 drivers/infiniband/ulp/ipoib/ipoib.h        |  4 ++--
 drivers/infiniband/ulp/ipoib/ipoib_main.c   |  8 +++----
 include/rdma/rdmavt_qp.h                    |  2 +-
 21 files changed, 84 insertions(+), 75 deletions(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v3 for-next 01/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of iwcm_id_private
  2021-05-25  6:51 [PATCH v3 for-next 00/13] RDMA: Use refcount_t for reference counting Weihang Li
@ 2021-05-25  6:51 ` Weihang Li
  2021-05-25  6:51 ` [PATCH v3 for-next 02/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of iwpm_admin_data Weihang Li
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Weihang Li @ 2021-05-25  6:51 UTC (permalink / raw)
  To: dledford, jgg; +Cc: leon, linux-rdma, linuxarm, Weihang Li

The refcount_t API will WARN on underflow and overflow of a reference
counter, and avoid use-after-free risks.

Signed-off-by: Weihang Li <liweihang@huawei.com>
---
 drivers/infiniband/core/iwcm.c | 9 ++++-----
 drivers/infiniband/core/iwcm.h | 2 +-
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
index da8adad..4226115 100644
--- a/drivers/infiniband/core/iwcm.c
+++ b/drivers/infiniband/core/iwcm.c
@@ -211,8 +211,7 @@ static void free_cm_id(struct iwcm_id_private *cm_id_priv)
  */
 static int iwcm_deref_id(struct iwcm_id_private *cm_id_priv)
 {
-	BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
-	if (atomic_dec_and_test(&cm_id_priv->refcount)) {
+	if (refcount_dec_and_test(&cm_id_priv->refcount)) {
 		BUG_ON(!list_empty(&cm_id_priv->work_list));
 		free_cm_id(cm_id_priv);
 		return 1;
@@ -225,7 +224,7 @@ static void add_ref(struct iw_cm_id *cm_id)
 {
 	struct iwcm_id_private *cm_id_priv;
 	cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
-	atomic_inc(&cm_id_priv->refcount);
+	refcount_inc(&cm_id_priv->refcount);
 }
 
 static void rem_ref(struct iw_cm_id *cm_id)
@@ -257,7 +256,7 @@ struct iw_cm_id *iw_create_cm_id(struct ib_device *device,
 	cm_id_priv->id.add_ref = add_ref;
 	cm_id_priv->id.rem_ref = rem_ref;
 	spin_lock_init(&cm_id_priv->lock);
-	atomic_set(&cm_id_priv->refcount, 1);
+	refcount_set(&cm_id_priv->refcount, 1);
 	init_waitqueue_head(&cm_id_priv->connect_wait);
 	init_completion(&cm_id_priv->destroy_comp);
 	INIT_LIST_HEAD(&cm_id_priv->work_list);
@@ -1094,7 +1093,7 @@ static int cm_event_handler(struct iw_cm_id *cm_id,
 		}
 	}
 
-	atomic_inc(&cm_id_priv->refcount);
+	refcount_inc(&cm_id_priv->refcount);
 	if (list_empty(&cm_id_priv->work_list)) {
 		list_add_tail(&work->list, &cm_id_priv->work_list);
 		queue_work(iwcm_wq, &work->work);
diff --git a/drivers/infiniband/core/iwcm.h b/drivers/infiniband/core/iwcm.h
index 82c2cd1..bf74639 100644
--- a/drivers/infiniband/core/iwcm.h
+++ b/drivers/infiniband/core/iwcm.h
@@ -52,7 +52,7 @@ struct iwcm_id_private {
 	wait_queue_head_t connect_wait;
 	struct list_head work_list;
 	spinlock_t lock;
-	atomic_t refcount;
+	refcount_t refcount;
 	struct list_head work_free_list;
 };
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 for-next 02/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of iwpm_admin_data
  2021-05-25  6:51 [PATCH v3 for-next 00/13] RDMA: Use refcount_t for reference counting Weihang Li
  2021-05-25  6:51 ` [PATCH v3 for-next 01/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of iwcm_id_private Weihang Li
@ 2021-05-25  6:51 ` Weihang Li
  2021-05-25  6:51 ` [PATCH v3 for-next 03/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of ib_mad_snoop_private Weihang Li
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Weihang Li @ 2021-05-25  6:51 UTC (permalink / raw)
  To: dledford, jgg; +Cc: leon, linux-rdma, linuxarm, Weihang Li

The refcount_t API will WARN on underflow and overflow of a reference
counter, and avoid use-after-free risks. Increase refcount_t from 0 to 1 is
regarded as there is a risk about use-after-free. So it should be set to 1
directly during initialization.

Signed-off-by: Weihang Li <liweihang@huawei.com>
---
 drivers/infiniband/core/iwpm_util.c | 12 ++++++++----
 drivers/infiniband/core/iwpm_util.h |  2 +-
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/infiniband/core/iwpm_util.c b/drivers/infiniband/core/iwpm_util.c
index f80e555..b8f40e6 100644
--- a/drivers/infiniband/core/iwpm_util.c
+++ b/drivers/infiniband/core/iwpm_util.c
@@ -61,7 +61,7 @@ int iwpm_init(u8 nl_client)
 {
 	int ret = 0;
 	mutex_lock(&iwpm_admin_lock);
-	if (atomic_read(&iwpm_admin.refcount) == 0) {
+	if (!refcount_read(&iwpm_admin.refcount)) {
 		iwpm_hash_bucket = kcalloc(IWPM_MAPINFO_HASH_SIZE,
 					   sizeof(struct hlist_head),
 					   GFP_KERNEL);
@@ -77,8 +77,12 @@ int iwpm_init(u8 nl_client)
 			ret = -ENOMEM;
 			goto init_exit;
 		}
+
+		refcount_set(&iwpm_admin.refcount, 1);
+	} else {
+		refcount_inc(&iwpm_admin.refcount);
 	}
-	atomic_inc(&iwpm_admin.refcount);
+
 init_exit:
 	mutex_unlock(&iwpm_admin_lock);
 	if (!ret) {
@@ -105,12 +109,12 @@ int iwpm_exit(u8 nl_client)
 	if (!iwpm_valid_client(nl_client))
 		return -EINVAL;
 	mutex_lock(&iwpm_admin_lock);
-	if (atomic_read(&iwpm_admin.refcount) == 0) {
+	if (!refcount_read(&iwpm_admin.refcount)) {
 		mutex_unlock(&iwpm_admin_lock);
 		pr_err("%s Incorrect usage - negative refcount\n", __func__);
 		return -EINVAL;
 	}
-	if (atomic_dec_and_test(&iwpm_admin.refcount)) {
+	if (refcount_dec_and_test(&iwpm_admin.refcount)) {
 		free_hash_bucket();
 		free_reminfo_bucket();
 		pr_debug("%s: Resources are destroyed\n", __func__);
diff --git a/drivers/infiniband/core/iwpm_util.h b/drivers/infiniband/core/iwpm_util.h
index eeb8e60..5002ac6 100644
--- a/drivers/infiniband/core/iwpm_util.h
+++ b/drivers/infiniband/core/iwpm_util.h
@@ -90,7 +90,7 @@ struct iwpm_remote_info {
 };
 
 struct iwpm_admin_data {
-	atomic_t refcount;
+	refcount_t refcount;
 	atomic_t nlmsg_seq;
 	int      client_list[RDMA_NL_NUM_CLIENTS];
 	u32      reg_list[RDMA_NL_NUM_CLIENTS];
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 for-next 03/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of ib_mad_snoop_private
  2021-05-25  6:51 [PATCH v3 for-next 00/13] RDMA: Use refcount_t for reference counting Weihang Li
  2021-05-25  6:51 ` [PATCH v3 for-next 01/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of iwcm_id_private Weihang Li
  2021-05-25  6:51 ` [PATCH v3 for-next 02/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of iwpm_admin_data Weihang Li
@ 2021-05-25  6:51 ` Weihang Li
  2021-05-25  6:51 ` [PATCH v3 for-next 04/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of mcast_member Weihang Li
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Weihang Li @ 2021-05-25  6:51 UTC (permalink / raw)
  To: dledford, jgg; +Cc: leon, linux-rdma, linuxarm, Weihang Li

The refcount_t API will WARN on underflow and overflow of a reference
counter, and avoid use-after-free risks.

Signed-off-by: Weihang Li <liweihang@huawei.com>
---
 drivers/infiniband/core/mad_priv.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h
index 4aa16b3..25e573d 100644
--- a/drivers/infiniband/core/mad_priv.h
+++ b/drivers/infiniband/core/mad_priv.h
@@ -115,7 +115,7 @@ struct ib_mad_snoop_private {
 	struct ib_mad_qp_info *qp_info;
 	int snoop_index;
 	int mad_snoop_flags;
-	atomic_t refcount;
+	refcount_t refcount;
 	struct completion comp;
 };
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 for-next 04/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of mcast_member
  2021-05-25  6:51 [PATCH v3 for-next 00/13] RDMA: Use refcount_t for reference counting Weihang Li
                   ` (2 preceding siblings ...)
  2021-05-25  6:51 ` [PATCH v3 for-next 03/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of ib_mad_snoop_private Weihang Li
@ 2021-05-25  6:51 ` Weihang Li
  2021-05-25  6:51 ` [PATCH v3 for-next 05/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of mcast_port Weihang Li
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Weihang Li @ 2021-05-25  6:51 UTC (permalink / raw)
  To: dledford, jgg; +Cc: leon, linux-rdma, linuxarm, Weihang Li

The refcount_t API will WARN on underflow and overflow of a reference
counter, and avoid use-after-free risks.

Signed-off-by: Weihang Li <liweihang@huawei.com>
---
 drivers/infiniband/core/multicast.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
index a5dd4b7..de134a4 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -117,7 +117,7 @@ struct mcast_member {
 	struct mcast_group	*group;
 	struct list_head	list;
 	enum mcast_state	state;
-	atomic_t		refcount;
+	refcount_t		refcount;
 	struct completion	comp;
 };
 
@@ -199,7 +199,7 @@ static void release_group(struct mcast_group *group)
 
 static void deref_member(struct mcast_member *member)
 {
-	if (atomic_dec_and_test(&member->refcount))
+	if (refcount_dec_and_test(&member->refcount))
 		complete(&member->comp);
 }
 
@@ -401,7 +401,7 @@ static void process_group_error(struct mcast_group *group)
 	while (!list_empty(&group->active_list)) {
 		member = list_entry(group->active_list.next,
 				    struct mcast_member, list);
-		atomic_inc(&member->refcount);
+		refcount_inc(&member->refcount);
 		list_del_init(&member->list);
 		adjust_membership(group, member->multicast.rec.join_state, -1);
 		member->state = MCAST_ERROR;
@@ -445,7 +445,7 @@ static void mcast_work_handler(struct work_struct *work)
 				    struct mcast_member, list);
 		multicast = &member->multicast;
 		join_state = multicast->rec.join_state;
-		atomic_inc(&member->refcount);
+		refcount_inc(&member->refcount);
 
 		if (join_state == (group->rec.join_state & join_state)) {
 			status = cmp_rec(&group->rec, &multicast->rec,
@@ -497,7 +497,7 @@ static void process_join_error(struct mcast_group *group, int status)
 	member = list_entry(group->pending_list.next,
 			    struct mcast_member, list);
 	if (group->last_join == member) {
-		atomic_inc(&member->refcount);
+		refcount_inc(&member->refcount);
 		list_del_init(&member->list);
 		spin_unlock_irq(&group->lock);
 		ret = member->multicast.callback(status, &member->multicast);
@@ -632,7 +632,7 @@ ib_sa_join_multicast(struct ib_sa_client *client,
 	member->multicast.callback = callback;
 	member->multicast.context = context;
 	init_completion(&member->comp);
-	atomic_set(&member->refcount, 1);
+	refcount_set(&member->refcount, 1);
 	member->state = MCAST_JOINING;
 
 	member->group = acquire_group(&dev->port[port_num - dev->start_port],
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 for-next 05/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of mcast_port
  2021-05-25  6:51 [PATCH v3 for-next 00/13] RDMA: Use refcount_t for reference counting Weihang Li
                   ` (3 preceding siblings ...)
  2021-05-25  6:51 ` [PATCH v3 for-next 04/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of mcast_member Weihang Li
@ 2021-05-25  6:51 ` Weihang Li
  2021-05-25  6:51 ` [PATCH v3 for-next 06/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of mcast_group Weihang Li
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Weihang Li @ 2021-05-25  6:51 UTC (permalink / raw)
  To: dledford, jgg; +Cc: leon, linux-rdma, linuxarm, Weihang Li

The refcount_t API will WARN on underflow and overflow of a reference
counter, and avoid use-after-free risks.

Signed-off-by: Weihang Li <liweihang@huawei.com>
---
 drivers/infiniband/core/multicast.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
index de134a4..a236532 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -61,7 +61,7 @@ struct mcast_port {
 	struct mcast_device	*dev;
 	spinlock_t		lock;
 	struct rb_root		table;
-	atomic_t		refcount;
+	refcount_t		refcount;
 	struct completion	comp;
 	u32			port_num;
 };
@@ -178,7 +178,7 @@ static struct mcast_group *mcast_insert(struct mcast_port *port,
 
 static void deref_port(struct mcast_port *port)
 {
-	if (atomic_dec_and_test(&port->refcount))
+	if (refcount_dec_and_test(&port->refcount))
 		complete(&port->comp);
 }
 
@@ -589,7 +589,7 @@ static struct mcast_group *acquire_group(struct mcast_port *port,
 		kfree(group);
 		group = cur_group;
 	} else
-		atomic_inc(&port->refcount);
+		refcount_inc(&port->refcount);
 found:
 	atomic_inc(&group->refcount);
 	spin_unlock_irqrestore(&port->lock, flags);
@@ -840,7 +840,7 @@ static int mcast_add_one(struct ib_device *device)
 		spin_lock_init(&port->lock);
 		port->table = RB_ROOT;
 		init_completion(&port->comp);
-		atomic_set(&port->refcount, 1);
+		refcount_set(&port->refcount, 1);
 		++count;
 	}
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 for-next 06/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of mcast_group
  2021-05-25  6:51 [PATCH v3 for-next 00/13] RDMA: Use refcount_t for reference counting Weihang Li
                   ` (4 preceding siblings ...)
  2021-05-25  6:51 ` [PATCH v3 for-next 05/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of mcast_port Weihang Li
@ 2021-05-25  6:51 ` Weihang Li
  2021-05-25  6:51 ` [PATCH v3 for-next 07/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of ib_uverbs_device Weihang Li
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Weihang Li @ 2021-05-25  6:51 UTC (permalink / raw)
  To: dledford, jgg; +Cc: leon, linux-rdma, linuxarm, Weihang Li

The refcount_t API will WARN on underflow and overflow of a reference
counter, and avoid use-after-free risks. Increase refcount_t from 0 to 1 is
regarded as there is a risk about use-after-free. So it should be set to 1
directly during initialization.

Signed-off-by: Weihang Li <liweihang@huawei.com>
---
 drivers/infiniband/core/multicast.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
index a236532..17abc21 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -103,7 +103,7 @@ struct mcast_group {
 	struct list_head	active_list;
 	struct mcast_member	*last_join;
 	int			members[NUM_JOIN_MEMBERSHIP_TYPES];
-	atomic_t		refcount;
+	refcount_t		refcount;
 	enum mcast_group_state	state;
 	struct ib_sa_query	*query;
 	u16			pkey_index;
@@ -188,7 +188,7 @@ static void release_group(struct mcast_group *group)
 	unsigned long flags;
 
 	spin_lock_irqsave(&port->lock, flags);
-	if (atomic_dec_and_test(&group->refcount)) {
+	if (refcount_dec_and_test(&group->refcount)) {
 		rb_erase(&group->node, &port->table);
 		spin_unlock_irqrestore(&port->lock, flags);
 		kfree(group);
@@ -212,7 +212,7 @@ static void queue_join(struct mcast_member *member)
 	list_add_tail(&member->list, &group->pending_list);
 	if (group->state == MCAST_IDLE) {
 		group->state = MCAST_BUSY;
-		atomic_inc(&group->refcount);
+		refcount_inc(&group->refcount);
 		queue_work(mcast_wq, &group->work);
 	}
 	spin_unlock_irqrestore(&group->lock, flags);
@@ -565,8 +565,11 @@ static struct mcast_group *acquire_group(struct mcast_port *port,
 	if (!is_mgid0) {
 		spin_lock_irqsave(&port->lock, flags);
 		group = mcast_find(port, mgid);
-		if (group)
+		if (group) {
+			refcount_inc(&group->refcount);
 			goto found;
+		}
+
 		spin_unlock_irqrestore(&port->lock, flags);
 	}
 
@@ -590,8 +593,10 @@ static struct mcast_group *acquire_group(struct mcast_port *port,
 		group = cur_group;
 	} else
 		refcount_inc(&port->refcount);
+
+	refcount_set(&group->refcount, 1);
+
 found:
-	atomic_inc(&group->refcount);
 	spin_unlock_irqrestore(&port->lock, flags);
 	return group;
 }
@@ -780,7 +785,7 @@ static void mcast_groups_event(struct mcast_port *port,
 		group = rb_entry(node, struct mcast_group, node);
 		spin_lock(&group->lock);
 		if (group->state == MCAST_IDLE) {
-			atomic_inc(&group->refcount);
+			refcount_inc(&group->refcount);
 			queue_work(mcast_wq, &group->work);
 		}
 		if (group->state != MCAST_GROUP_ERROR)
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 for-next 07/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of ib_uverbs_device
  2021-05-25  6:51 [PATCH v3 for-next 00/13] RDMA: Use refcount_t for reference counting Weihang Li
                   ` (5 preceding siblings ...)
  2021-05-25  6:51 ` [PATCH v3 for-next 06/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of mcast_group Weihang Li
@ 2021-05-25  6:51 ` Weihang Li
  2021-05-25  6:51 ` [PATCH v3 for-next 08/13] RDMA/hns: Use refcount_t instead of atomic_t for CQ reference counting Weihang Li
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Weihang Li @ 2021-05-25  6:51 UTC (permalink / raw)
  To: dledford, jgg; +Cc: leon, linux-rdma, linuxarm, Weihang Li

The refcount_t API will WARN on underflow and overflow of a reference
counter, and avoid use-after-free risks.

Signed-off-by: Weihang Li <liweihang@huawei.com>
---
 drivers/infiniband/core/uverbs.h      |  2 +-
 drivers/infiniband/core/uverbs_main.c | 12 ++++++------
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 53a1047..821d93c 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -97,7 +97,7 @@ ib_uverbs_init_udata_buf_or_null(struct ib_udata *udata,
  */
 
 struct ib_uverbs_device {
-	atomic_t				refcount;
+	refcount_t				refcount;
 	u32					num_comp_vectors;
 	struct completion			comp;
 	struct device				dev;
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index f173ecd..d544340 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -197,7 +197,7 @@ void ib_uverbs_release_file(struct kref *ref)
 		module_put(ib_dev->ops.owner);
 	srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
 
-	if (atomic_dec_and_test(&file->device->refcount))
+	if (refcount_dec_and_test(&file->device->refcount))
 		ib_uverbs_comp_dev(file->device);
 
 	if (file->default_async_file)
@@ -891,7 +891,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
 	int srcu_key;
 
 	dev = container_of(inode->i_cdev, struct ib_uverbs_device, cdev);
-	if (!atomic_inc_not_zero(&dev->refcount))
+	if (!refcount_inc_not_zero(&dev->refcount))
 		return -ENXIO;
 
 	get_device(&dev->dev);
@@ -955,7 +955,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
 err:
 	mutex_unlock(&dev->lists_mutex);
 	srcu_read_unlock(&dev->disassociate_srcu, srcu_key);
-	if (atomic_dec_and_test(&dev->refcount))
+	if (refcount_dec_and_test(&dev->refcount))
 		ib_uverbs_comp_dev(dev);
 
 	put_device(&dev->dev);
@@ -1124,7 +1124,7 @@ static int ib_uverbs_add_one(struct ib_device *device)
 	uverbs_dev->dev.release = ib_uverbs_release_dev;
 	uverbs_dev->groups[0] = &dev_attr_group;
 	uverbs_dev->dev.groups = uverbs_dev->groups;
-	atomic_set(&uverbs_dev->refcount, 1);
+	refcount_set(&uverbs_dev->refcount, 1);
 	init_completion(&uverbs_dev->comp);
 	uverbs_dev->xrcd_tree = RB_ROOT;
 	mutex_init(&uverbs_dev->xrcd_tree_mutex);
@@ -1166,7 +1166,7 @@ static int ib_uverbs_add_one(struct ib_device *device)
 err_uapi:
 	ida_free(&uverbs_ida, devnum);
 err:
-	if (atomic_dec_and_test(&uverbs_dev->refcount))
+	if (refcount_dec_and_test(&uverbs_dev->refcount))
 		ib_uverbs_comp_dev(uverbs_dev);
 	wait_for_completion(&uverbs_dev->comp);
 	put_device(&uverbs_dev->dev);
@@ -1229,7 +1229,7 @@ static void ib_uverbs_remove_one(struct ib_device *device, void *client_data)
 		wait_clients = 0;
 	}
 
-	if (atomic_dec_and_test(&uverbs_dev->refcount))
+	if (refcount_dec_and_test(&uverbs_dev->refcount))
 		ib_uverbs_comp_dev(uverbs_dev);
 	if (wait_clients)
 		wait_for_completion(&uverbs_dev->comp);
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 for-next 08/13] RDMA/hns: Use refcount_t instead of atomic_t for CQ reference counting
  2021-05-25  6:51 [PATCH v3 for-next 00/13] RDMA: Use refcount_t for reference counting Weihang Li
                   ` (6 preceding siblings ...)
  2021-05-25  6:51 ` [PATCH v3 for-next 07/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of ib_uverbs_device Weihang Li
@ 2021-05-25  6:51 ` Weihang Li
  2021-05-25  6:51 ` [PATCH v3 for-next 09/13] RDMA/hns: Use refcount_t instead of atomic_t for SRQ " Weihang Li
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Weihang Li @ 2021-05-25  6:51 UTC (permalink / raw)
  To: dledford, jgg; +Cc: leon, linux-rdma, linuxarm, Weihang Li

The refcount_t API will WARN on underflow and overflow of a reference
counter, and avoid use-after-free risks.

Signed-off-by: Weihang Li <liweihang@huawei.com>
---
 drivers/infiniband/hw/hns/hns_roce_cq.c     | 8 ++++----
 drivers/infiniband/hw/hns/hns_roce_device.h | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/infiniband/hw/hns/hns_roce_cq.c b/drivers/infiniband/hw/hns/hns_roce_cq.c
index 488d86b..1422bdc 100644
--- a/drivers/infiniband/hw/hns/hns_roce_cq.c
+++ b/drivers/infiniband/hw/hns/hns_roce_cq.c
@@ -154,7 +154,7 @@ static int alloc_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
 	hr_cq->cons_index = 0;
 	hr_cq->arm_sn = 1;
 
-	atomic_set(&hr_cq->refcount, 1);
+	refcount_set(&hr_cq->refcount, 1);
 	init_completion(&hr_cq->free);
 
 	return 0;
@@ -188,7 +188,7 @@ static void free_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
 	synchronize_irq(hr_dev->eq_table.eq[hr_cq->vector].irq);
 
 	/* wait for all interrupt processed */
-	if (atomic_dec_and_test(&hr_cq->refcount))
+	if (refcount_dec_and_test(&hr_cq->refcount))
 		complete(&hr_cq->free);
 	wait_for_completion(&hr_cq->free);
 
@@ -480,7 +480,7 @@ void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type)
 		return;
 	}
 
-	atomic_inc(&hr_cq->refcount);
+	refcount_inc(&hr_cq->refcount);
 
 	ibcq = &hr_cq->ib_cq;
 	if (ibcq->event_handler) {
@@ -490,7 +490,7 @@ void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type)
 		ibcq->event_handler(&event, ibcq->cq_context);
 	}
 
-	if (atomic_dec_and_test(&hr_cq->refcount))
+	if (refcount_dec_and_test(&hr_cq->refcount))
 		complete(&hr_cq->free);
 }
 
diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
index 111cab5..d90a39c 100644
--- a/drivers/infiniband/hw/hns/hns_roce_device.h
+++ b/drivers/infiniband/hw/hns/hns_roce_device.h
@@ -446,7 +446,7 @@ struct hns_roce_cq {
 	int				cqe_size;
 	unsigned long			cqn;
 	u32				vector;
-	atomic_t			refcount;
+	refcount_t			refcount;
 	struct completion		free;
 	struct list_head		sq_list; /* all qps on this send cq */
 	struct list_head		rq_list; /* all qps on this recv cq */
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 for-next 09/13] RDMA/hns: Use refcount_t instead of atomic_t for SRQ reference counting
  2021-05-25  6:51 [PATCH v3 for-next 00/13] RDMA: Use refcount_t for reference counting Weihang Li
                   ` (7 preceding siblings ...)
  2021-05-25  6:51 ` [PATCH v3 for-next 08/13] RDMA/hns: Use refcount_t instead of atomic_t for CQ reference counting Weihang Li
@ 2021-05-25  6:51 ` Weihang Li
  2021-05-25  6:51 ` [PATCH v3 for-next 10/13] RDMA/hns: Use refcount_t instead of atomic_t for QP " Weihang Li
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Weihang Li @ 2021-05-25  6:51 UTC (permalink / raw)
  To: dledford, jgg; +Cc: leon, linux-rdma, linuxarm, Weihang Li

The refcount_t API will WARN on underflow and overflow of a reference
counter, and avoid use-after-free risks.

Signed-off-by: Weihang Li <liweihang@huawei.com>
---
 drivers/infiniband/hw/hns/hns_roce_device.h | 2 +-
 drivers/infiniband/hw/hns/hns_roce_srq.c    | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
index d90a39c..24d177c 100644
--- a/drivers/infiniband/hw/hns/hns_roce_device.h
+++ b/drivers/infiniband/hw/hns/hns_roce_device.h
@@ -473,7 +473,7 @@ struct hns_roce_srq {
 	u32			xrcdn;
 	void __iomem		*db_reg;
 
-	atomic_t		refcount;
+	refcount_t		refcount;
 	struct completion	free;
 
 	struct hns_roce_mtr	buf_mtr;
diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c
index 546d182..327f7aa 100644
--- a/drivers/infiniband/hw/hns/hns_roce_srq.c
+++ b/drivers/infiniband/hw/hns/hns_roce_srq.c
@@ -17,7 +17,7 @@ void hns_roce_srq_event(struct hns_roce_dev *hr_dev, u32 srqn, int event_type)
 	xa_lock(&srq_table->xa);
 	srq = xa_load(&srq_table->xa, srqn & (hr_dev->caps.num_srqs - 1));
 	if (srq)
-		atomic_inc(&srq->refcount);
+		refcount_inc(&srq->refcount);
 	xa_unlock(&srq_table->xa);
 
 	if (!srq) {
@@ -27,7 +27,7 @@ void hns_roce_srq_event(struct hns_roce_dev *hr_dev, u32 srqn, int event_type)
 
 	srq->event(srq, event_type);
 
-	if (atomic_dec_and_test(&srq->refcount))
+	if (refcount_dec_and_test(&srq->refcount))
 		complete(&srq->free);
 }
 
@@ -149,7 +149,7 @@ static void free_srqc(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq)
 
 	xa_erase(&srq_table->xa, srq->srqn);
 
-	if (atomic_dec_and_test(&srq->refcount))
+	if (refcount_dec_and_test(&srq->refcount))
 		complete(&srq->free);
 	wait_for_completion(&srq->free);
 
@@ -417,7 +417,7 @@ int hns_roce_create_srq(struct ib_srq *ib_srq,
 
 	srq->db_reg = hr_dev->reg_base + SRQ_DB_REG;
 	srq->event = hns_roce_ib_srq_event;
-	atomic_set(&srq->refcount, 1);
+	refcount_set(&srq->refcount, 1);
 	init_completion(&srq->free);
 
 	return 0;
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 for-next 10/13] RDMA/hns: Use refcount_t instead of atomic_t for QP reference counting
  2021-05-25  6:51 [PATCH v3 for-next 00/13] RDMA: Use refcount_t for reference counting Weihang Li
                   ` (8 preceding siblings ...)
  2021-05-25  6:51 ` [PATCH v3 for-next 09/13] RDMA/hns: Use refcount_t instead of atomic_t for SRQ " Weihang Li
@ 2021-05-25  6:51 ` Weihang Li
  2021-05-25  6:51 ` [PATCH v3 for-next 11/13] RDMA/cxgb4: Use refcount_t instead of atomic_t for " Weihang Li
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 19+ messages in thread
From: Weihang Li @ 2021-05-25  6:51 UTC (permalink / raw)
  To: dledford, jgg; +Cc: leon, linux-rdma, linuxarm, Weihang Li

The refcount_t API will WARN on underflow and overflow of a reference
counter, and avoid use-after-free risks.

Signed-off-by: Weihang Li <liweihang@huawei.com>
---
 drivers/infiniband/hw/hns/hns_roce_device.h |  2 +-
 drivers/infiniband/hw/hns/hns_roce_qp.c     | 12 ++++++------
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
index 24d177c..501b48f 100644
--- a/drivers/infiniband/hw/hns/hns_roce_device.h
+++ b/drivers/infiniband/hw/hns/hns_roce_device.h
@@ -641,7 +641,7 @@ struct hns_roce_qp {
 
 	u32			xrcdn;
 
-	atomic_t		refcount;
+	refcount_t		refcount;
 	struct completion	free;
 
 	struct hns_roce_sge	sge;
diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c
index c6e120e..ad26d4d 100644
--- a/drivers/infiniband/hw/hns/hns_roce_qp.c
+++ b/drivers/infiniband/hw/hns/hns_roce_qp.c
@@ -65,7 +65,7 @@ static void flush_work_handle(struct work_struct *work)
 	 * make sure we signal QP destroy leg that flush QP was completed
 	 * so that it can safely proceed ahead now and destroy QP
 	 */
-	if (atomic_dec_and_test(&hr_qp->refcount))
+	if (refcount_dec_and_test(&hr_qp->refcount))
 		complete(&hr_qp->free);
 }
 
@@ -75,7 +75,7 @@ void init_flush_work(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
 
 	flush_work->hr_dev = hr_dev;
 	INIT_WORK(&flush_work->work, flush_work_handle);
-	atomic_inc(&hr_qp->refcount);
+	refcount_inc(&hr_qp->refcount);
 	queue_work(hr_dev->irq_workq, &flush_work->work);
 }
 
@@ -87,7 +87,7 @@ void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type)
 	xa_lock(&hr_dev->qp_table_xa);
 	qp = __hns_roce_qp_lookup(hr_dev, qpn);
 	if (qp)
-		atomic_inc(&qp->refcount);
+		refcount_inc(&qp->refcount);
 	xa_unlock(&hr_dev->qp_table_xa);
 
 	if (!qp) {
@@ -108,7 +108,7 @@ void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type)
 
 	qp->event(qp, (enum hns_roce_event)event_type);
 
-	if (atomic_dec_and_test(&qp->refcount))
+	if (refcount_dec_and_test(&qp->refcount))
 		complete(&qp->free);
 }
 
@@ -1076,7 +1076,7 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
 
 	hr_qp->ibqp.qp_num = hr_qp->qpn;
 	hr_qp->event = hns_roce_ib_qp_event;
-	atomic_set(&hr_qp->refcount, 1);
+	refcount_set(&hr_qp->refcount, 1);
 	init_completion(&hr_qp->free);
 
 	return 0;
@@ -1099,7 +1099,7 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
 void hns_roce_qp_destroy(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
 			 struct ib_udata *udata)
 {
-	if (atomic_dec_and_test(&hr_qp->refcount))
+	if (refcount_dec_and_test(&hr_qp->refcount))
 		complete(&hr_qp->free);
 	wait_for_completion(&hr_qp->free);
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 for-next 11/13] RDMA/cxgb4: Use refcount_t instead of atomic_t for reference counting
  2021-05-25  6:51 [PATCH v3 for-next 00/13] RDMA: Use refcount_t for reference counting Weihang Li
                   ` (9 preceding siblings ...)
  2021-05-25  6:51 ` [PATCH v3 for-next 10/13] RDMA/hns: Use refcount_t instead of atomic_t for QP " Weihang Li
@ 2021-05-25  6:51 ` Weihang Li
  2021-05-25  6:51 ` [PATCH v3 for-next 12/13] RDMA/ipoib: " Weihang Li
  2021-05-25  6:51 ` [PATCH v3 for-next 13/13] RDMA/rdmavt: Use refcount_t instead of atomic_t on refcount of rvt_mcast Weihang Li
  12 siblings, 0 replies; 19+ messages in thread
From: Weihang Li @ 2021-05-25  6:51 UTC (permalink / raw)
  To: dledford, jgg; +Cc: leon, linux-rdma, linuxarm, Weihang Li, Potnuri Bharat Teja

The refcount_t API will WARN on underflow and overflow of a reference
counter, and avoid use-after-free risks.

Cc: Potnuri Bharat Teja <bharat@chelsio.com>
Signed-off-by: Weihang Li <liweihang@huawei.com>
---
 drivers/infiniband/hw/cxgb4/cq.c       | 6 +++---
 drivers/infiniband/hw/cxgb4/ev.c       | 8 ++++----
 drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 2 +-
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c
index 44c2416..6c8c910 100644
--- a/drivers/infiniband/hw/cxgb4/cq.c
+++ b/drivers/infiniband/hw/cxgb4/cq.c
@@ -976,8 +976,8 @@ int c4iw_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata)
 	chp = to_c4iw_cq(ib_cq);
 
 	xa_erase_irq(&chp->rhp->cqs, chp->cq.cqid);
-	atomic_dec(&chp->refcnt);
-	wait_event(chp->wait, !atomic_read(&chp->refcnt));
+	refcount_dec(&chp->refcnt);
+	wait_event(chp->wait, !refcount_read(&chp->refcnt));
 
 	ucontext = rdma_udata_to_drv_context(udata, struct c4iw_ucontext,
 					     ibucontext);
@@ -1080,7 +1080,7 @@ int c4iw_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
 	chp->ibcq.cqe = entries - 2;
 	spin_lock_init(&chp->lock);
 	spin_lock_init(&chp->comp_handler_lock);
-	atomic_set(&chp->refcnt, 1);
+	refcount_set(&chp->refcnt, 1);
 	init_waitqueue_head(&chp->wait);
 	ret = xa_insert_irq(&rhp->cqs, chp->cq.cqid, chp, GFP_KERNEL);
 	if (ret)
diff --git a/drivers/infiniband/hw/cxgb4/ev.c b/drivers/infiniband/hw/cxgb4/ev.c
index 4cd877b..7798d090 100644
--- a/drivers/infiniband/hw/cxgb4/ev.c
+++ b/drivers/infiniband/hw/cxgb4/ev.c
@@ -151,7 +151,7 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
 	}
 
 	c4iw_qp_add_ref(&qhp->ibqp);
-	atomic_inc(&chp->refcnt);
+	refcount_inc(&chp->refcnt);
 	xa_unlock_irq(&dev->qps);
 
 	/* Bad incoming write */
@@ -213,7 +213,7 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
 		break;
 	}
 done:
-	if (atomic_dec_and_test(&chp->refcnt))
+	if (refcount_dec_and_test(&chp->refcnt))
 		wake_up(&chp->wait);
 	c4iw_qp_rem_ref(&qhp->ibqp);
 out:
@@ -228,13 +228,13 @@ int c4iw_ev_handler(struct c4iw_dev *dev, u32 qid)
 	xa_lock_irqsave(&dev->cqs, flag);
 	chp = xa_load(&dev->cqs, qid);
 	if (chp) {
-		atomic_inc(&chp->refcnt);
+		refcount_inc(&chp->refcnt);
 		xa_unlock_irqrestore(&dev->cqs, flag);
 		t4_clear_cq_armed(&chp->cq);
 		spin_lock_irqsave(&chp->comp_handler_lock, flag);
 		(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
 		spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
-		if (atomic_dec_and_test(&chp->refcnt))
+		if (refcount_dec_and_test(&chp->refcnt))
 			wake_up(&chp->wait);
 	} else {
 		pr_debug("unknown cqid 0x%x\n", qid);
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index cdec5de..3883af3 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -427,7 +427,7 @@ struct c4iw_cq {
 	struct t4_cq cq;
 	spinlock_t lock;
 	spinlock_t comp_handler_lock;
-	atomic_t refcnt;
+	refcount_t refcnt;
 	wait_queue_head_t wait;
 	struct c4iw_wr_wait *wr_waitp;
 };
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 for-next 12/13] RDMA/ipoib: Use refcount_t instead of atomic_t for reference counting
  2021-05-25  6:51 [PATCH v3 for-next 00/13] RDMA: Use refcount_t for reference counting Weihang Li
                   ` (10 preceding siblings ...)
  2021-05-25  6:51 ` [PATCH v3 for-next 11/13] RDMA/cxgb4: Use refcount_t instead of atomic_t for " Weihang Li
@ 2021-05-25  6:51 ` Weihang Li
  2021-05-25  6:51 ` [PATCH v3 for-next 13/13] RDMA/rdmavt: Use refcount_t instead of atomic_t on refcount of rvt_mcast Weihang Li
  12 siblings, 0 replies; 19+ messages in thread
From: Weihang Li @ 2021-05-25  6:51 UTC (permalink / raw)
  To: dledford, jgg; +Cc: leon, linux-rdma, linuxarm, Weihang Li

The refcount_t API will WARN on underflow and overflow of a reference
counter, and avoid use-after-free risks.

Signed-off-by: Weihang Li <liweihang@huawei.com>
---
 drivers/infiniband/ulp/ipoib/ipoib.h      | 4 ++--
 drivers/infiniband/ulp/ipoib/ipoib_main.c | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 75cd447..44d8d15 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -454,7 +454,7 @@ struct ipoib_neigh {
 	struct list_head    list;
 	struct ipoib_neigh __rcu *hnext;
 	struct rcu_head     rcu;
-	atomic_t	    refcnt;
+	refcount_t	    refcnt;
 	unsigned long       alive;
 };
 
@@ -464,7 +464,7 @@ struct ipoib_neigh {
 void ipoib_neigh_dtor(struct ipoib_neigh *neigh);
 static inline void ipoib_neigh_put(struct ipoib_neigh *neigh)
 {
-	if (atomic_dec_and_test(&neigh->refcnt))
+	if (refcount_dec_and_test(&neigh->refcnt))
 		ipoib_neigh_dtor(neigh);
 }
 struct ipoib_neigh *ipoib_neigh_get(struct net_device *dev, u8 *daddr);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index bbb1808..ac39610 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1287,7 +1287,7 @@ struct ipoib_neigh *ipoib_neigh_get(struct net_device *dev, u8 *daddr)
 	     neigh = rcu_dereference_bh(neigh->hnext)) {
 		if (memcmp(daddr, neigh->daddr, INFINIBAND_ALEN) == 0) {
 			/* found, take one ref on behalf of the caller */
-			if (!atomic_inc_not_zero(&neigh->refcnt)) {
+			if (!refcount_inc_not_zero(&neigh->refcnt)) {
 				/* deleted */
 				neigh = NULL;
 				goto out_unlock;
@@ -1382,7 +1382,7 @@ static struct ipoib_neigh *ipoib_neigh_ctor(u8 *daddr,
 	INIT_LIST_HEAD(&neigh->list);
 	ipoib_cm_set(neigh, NULL);
 	/* one ref on behalf of the caller */
-	atomic_set(&neigh->refcnt, 1);
+	refcount_set(&neigh->refcnt, 1);
 
 	return neigh;
 }
@@ -1414,7 +1414,7 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr,
 					       lockdep_is_held(&priv->lock))) {
 		if (memcmp(daddr, neigh->daddr, INFINIBAND_ALEN) == 0) {
 			/* found, take one ref on behalf of the caller */
-			if (!atomic_inc_not_zero(&neigh->refcnt)) {
+			if (!refcount_inc_not_zero(&neigh->refcnt)) {
 				/* deleted */
 				neigh = NULL;
 				break;
@@ -1429,7 +1429,7 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr,
 		goto out_unlock;
 
 	/* one ref on behalf of the hash table */
-	atomic_inc(&neigh->refcnt);
+	refcount_inc(&neigh->refcnt);
 	neigh->alive = jiffies;
 	/* put in hash */
 	rcu_assign_pointer(neigh->hnext,
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v3 for-next 13/13] RDMA/rdmavt: Use refcount_t instead of atomic_t on refcount of rvt_mcast
  2021-05-25  6:51 [PATCH v3 for-next 00/13] RDMA: Use refcount_t for reference counting Weihang Li
                   ` (11 preceding siblings ...)
  2021-05-25  6:51 ` [PATCH v3 for-next 12/13] RDMA/ipoib: " Weihang Li
@ 2021-05-25  6:51 ` Weihang Li
  2021-05-27 13:08   ` Marciniszyn, Mike
  12 siblings, 1 reply; 19+ messages in thread
From: Weihang Li @ 2021-05-25  6:51 UTC (permalink / raw)
  To: dledford, jgg
  Cc: leon, linux-rdma, linuxarm, Weihang Li, Mike Marciniszyn,
	Dennis Dalessandro

The refcount_t API will WARN on underflow and overflow of a reference
counter, and avoid use-after-free risks. Increase refcount_t from 0 to 1 is
regarded as there is a risk about use-after-free. So it should be set to 1
directly during initialization.

Cc: Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>
Cc: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
Signed-off-by: Weihang Li <liweihang@huawei.com>
---
 drivers/infiniband/hw/hfi1/verbs.c    |  3 ++-
 drivers/infiniband/hw/qib/qib_verbs.c |  3 ++-
 drivers/infiniband/sw/rdmavt/mcast.c  | 11 +++++------
 include/rdma/rdmavt_qp.h              |  2 +-
 4 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c
index 5542943..d67f707 100644
--- a/drivers/infiniband/hw/hfi1/verbs.c
+++ b/drivers/infiniband/hw/hfi1/verbs.c
@@ -534,7 +534,8 @@ static inline void hfi1_handle_packet(struct hfi1_packet *packet,
 		 * Notify rvt_multicast_detach() if it is waiting for us
 		 * to finish.
 		 */
-		if (atomic_dec_return(&mcast->refcount) <= 1)
+		refcount_dec(&mcast->refcount);
+		if (refcount_read(&mcast->refcount) <= 1)
 			wake_up(&mcast->wait);
 	} else {
 		/* Get the destination QP number. */
diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c
index d17d034..d6a7cc9 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.c
+++ b/drivers/infiniband/hw/qib/qib_verbs.c
@@ -336,7 +336,8 @@ void qib_ib_rcv(struct qib_ctxtdata *rcd, void *rhdr, void *data, u32 tlen)
 		 * Notify rvt_multicast_detach() if it is waiting for us
 		 * to finish.
 		 */
-		if (atomic_dec_return(&mcast->refcount) <= 1)
+		refcount_dec(&mcast->refcount);
+		if (refcount_read(&mcast->refcount) <= 1)
 			wake_up(&mcast->wait);
 	} else {
 		rcu_read_lock();
diff --git a/drivers/infiniband/sw/rdmavt/mcast.c b/drivers/infiniband/sw/rdmavt/mcast.c
index 951abac..7746d5c 100644
--- a/drivers/infiniband/sw/rdmavt/mcast.c
+++ b/drivers/infiniband/sw/rdmavt/mcast.c
@@ -117,7 +117,6 @@ static struct rvt_mcast *rvt_mcast_alloc(union ib_gid *mgid, u16 lid)
 
 	INIT_LIST_HEAD(&mcast->qp_list);
 	init_waitqueue_head(&mcast->wait);
-	atomic_set(&mcast->refcount, 0);
 
 bail:
 	return mcast;
@@ -169,7 +168,7 @@ struct rvt_mcast *rvt_mcast_find(struct rvt_ibport *ibp, union ib_gid *mgid,
 		} else {
 			/* MGID/MLID must match */
 			if (mcast->mcast_addr.lid == lid) {
-				atomic_inc(&mcast->refcount);
+				refcount_inc(&mcast->refcount);
 				found = mcast;
 			}
 			break;
@@ -257,7 +256,7 @@ static int rvt_mcast_add(struct rvt_dev_info *rdi, struct rvt_ibport *ibp,
 
 	list_add_tail_rcu(&mqp->list, &mcast->qp_list);
 
-	atomic_inc(&mcast->refcount);
+	refcount_set(&mcast->refcount, 1);
 	rb_link_node(&mcast->rb_node, pn, n);
 	rb_insert_color(&mcast->rb_node, &ibp->mcast_tree);
 
@@ -410,12 +409,12 @@ int rvt_detach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 	 * Wait for any list walkers to finish before freeing the
 	 * list element.
 	 */
-	wait_event(mcast->wait, atomic_read(&mcast->refcount) <= 1);
+	wait_event(mcast->wait, refcount_read(&mcast->refcount) <= 1);
 	rvt_mcast_qp_free(delp);
 
 	if (last) {
-		atomic_dec(&mcast->refcount);
-		wait_event(mcast->wait, !atomic_read(&mcast->refcount));
+		refcount_dec(&mcast->refcount);
+		wait_event(mcast->wait, !refcount_read(&mcast->refcount));
 		rvt_mcast_free(mcast);
 		spin_lock_irq(&rdi->n_mcast_grps_lock);
 		rdi->n_mcast_grps_allocated--;
diff --git a/include/rdma/rdmavt_qp.h b/include/rdma/rdmavt_qp.h
index 8275954..cd19573 100644
--- a/include/rdma/rdmavt_qp.h
+++ b/include/rdma/rdmavt_qp.h
@@ -520,7 +520,7 @@ struct rvt_mcast {
 	struct rvt_mcast_addr mcast_addr;
 	struct list_head qp_list;
 	wait_queue_head_t wait;
-	atomic_t refcount;
+	refcount_t refcount;
 	int n_attached;
 };
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* RE: [PATCH v3 for-next 13/13] RDMA/rdmavt: Use refcount_t instead of atomic_t on refcount of rvt_mcast
  2021-05-25  6:51 ` [PATCH v3 for-next 13/13] RDMA/rdmavt: Use refcount_t instead of atomic_t on refcount of rvt_mcast Weihang Li
@ 2021-05-27 13:08   ` Marciniszyn, Mike
  2021-05-27 13:15     ` Jason Gunthorpe
  0 siblings, 1 reply; 19+ messages in thread
From: Marciniszyn, Mike @ 2021-05-27 13:08 UTC (permalink / raw)
  To: Weihang Li, dledford, jgg; +Cc: leon, linux-rdma, linuxarm, Dalessandro, Dennis

> +++ b/drivers/infiniband/hw/hfi1/verbs.c
> @@ -534,7 +534,8 @@ static inline void hfi1_handle_packet(struct
> hfi1_packet *packet,
>  		 * Notify rvt_multicast_detach() if it is waiting for us
>  		 * to finish.
>  		 */
> -		if (atomic_dec_return(&mcast->refcount) <= 1)
> +		refcount_dec(&mcast->refcount);
> +		if (refcount_read(&mcast->refcount) <= 1)
>  			wake_up(&mcast->wait);

Is there refcount_ that preserves the atomic characteristics of the single call?

Mike

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 for-next 13/13] RDMA/rdmavt: Use refcount_t instead of atomic_t on refcount of rvt_mcast
  2021-05-27 13:08   ` Marciniszyn, Mike
@ 2021-05-27 13:15     ` Jason Gunthorpe
  2021-05-28  3:58       ` liweihang
  0 siblings, 1 reply; 19+ messages in thread
From: Jason Gunthorpe @ 2021-05-27 13:15 UTC (permalink / raw)
  To: Marciniszyn, Mike
  Cc: Weihang Li, dledford, leon, linux-rdma, linuxarm, Dalessandro, Dennis

On Thu, May 27, 2021 at 01:08:37PM +0000, Marciniszyn, Mike wrote:
> > +++ b/drivers/infiniband/hw/hfi1/verbs.c
> > @@ -534,7 +534,8 @@ static inline void hfi1_handle_packet(struct
> > hfi1_packet *packet,
> >  		 * Notify rvt_multicast_detach() if it is waiting for us
> >  		 * to finish.
> >  		 */
> > -		if (atomic_dec_return(&mcast->refcount) <= 1)
> > +		refcount_dec(&mcast->refcount);
> > +		if (refcount_read(&mcast->refcount) <= 1)
> >  			wake_up(&mcast->wait);
> 
> Is there refcount_ that preserves the atomic characteristics of the single call?

You are supposed to us refcount_dec_and_test() for patterns like this,
this hunk looks wrong to me

Jason

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 for-next 13/13] RDMA/rdmavt: Use refcount_t instead of atomic_t on refcount of rvt_mcast
  2021-05-27 13:15     ` Jason Gunthorpe
@ 2021-05-28  3:58       ` liweihang
  2021-05-28  7:01         ` Peter Zijlstra
  0 siblings, 1 reply; 19+ messages in thread
From: liweihang @ 2021-05-28  3:58 UTC (permalink / raw)
  To: Jason Gunthorpe, Marciniszyn, Mike, Peter Zijlstra
  Cc: dledford, leon, linux-rdma, Linuxarm, Dalessandro, Dennis

On 2021/5/27 21:16, Jason Gunthorpe wrote:
> On Thu, May 27, 2021 at 01:08:37PM +0000, Marciniszyn, Mike wrote:
>>> +++ b/drivers/infiniband/hw/hfi1/verbs.c
>>> @@ -534,7 +534,8 @@ static inline void hfi1_handle_packet(struct
>>> hfi1_packet *packet,
>>>  		 * Notify rvt_multicast_detach() if it is waiting for us
>>>  		 * to finish.
>>>  		 */
>>> -		if (atomic_dec_return(&mcast->refcount) <= 1)
>>> +		refcount_dec(&mcast->refcount);
>>> +		if (refcount_read(&mcast->refcount) <= 1)
>>>  			wake_up(&mcast->wait);
>>
>> Is there refcount_ that preserves the atomic characteristics of the single call?
> 
> You are supposed to us refcount_dec_and_test() for patterns like this,
> this hunk looks wrong to me
> 
> Jason
> 

I made a mistake, thank you.

refcount_dec_and_test() test only if the refcount is 0, so I couldn't find a
good way to replace the atomic_t with refcount_t here.

And there is no refcount_dec/inc_return() for a refcount_t, I found some
previous disscussdion:

https://www.openwall.com/lists/kernel-hardening/2016/11/28/8
https://www.openwall.com/lists/kernel-hardening/2016/12/01/1
https://lkml.org/lkml/2017/9/1/389
https://yhbt.net/lore/all/20200921112218.GB2139@willie-the-truck/t/#md37f8b6084bccbc0ebf76ba249c069372b4d8497

I think such functions undermines the design of refcount. But to be honest, I
didn't find a clear reason.

Peter, could you please explain why you said "add_return and sub_return are
horrible interface for refcount"?

You can review the whole patch at:

https://patchwork.kernel.org/project/linux-rdma/patch/1621925504-33019-14-git-send-email-liweihang@huawei.com/

Thanks
Weihang

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 for-next 13/13] RDMA/rdmavt: Use refcount_t instead of atomic_t on refcount of rvt_mcast
  2021-05-28  3:58       ` liweihang
@ 2021-05-28  7:01         ` Peter Zijlstra
  2021-05-28  8:22           ` liweihang
  0 siblings, 1 reply; 19+ messages in thread
From: Peter Zijlstra @ 2021-05-28  7:01 UTC (permalink / raw)
  To: liweihang
  Cc: Jason Gunthorpe, Marciniszyn, Mike, dledford, leon, linux-rdma,
	Linuxarm, Dalessandro, Dennis

On Fri, May 28, 2021 at 03:58:42AM +0000, liweihang wrote:
> Peter, could you please explain why you said "add_return and sub_return are
> horrible interface for refcount"?

What would you need them for? The only special value is 0. Once you hit
0 the object is dead and you cannot revive.

If I look at drivers/infiniband/sw/rdmavt/mcast.c, which seems to be the
relevant file, the thing that's called ->refcount is not in fact a
reference count.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v3 for-next 13/13] RDMA/rdmavt: Use refcount_t instead of atomic_t on refcount of rvt_mcast
  2021-05-28  7:01         ` Peter Zijlstra
@ 2021-05-28  8:22           ` liweihang
  0 siblings, 0 replies; 19+ messages in thread
From: liweihang @ 2021-05-28  8:22 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Jason Gunthorpe, Marciniszyn, Mike, dledford, leon, linux-rdma,
	Linuxarm, Dalessandro, Dennis

On 2021/5/28 15:01, Peter Zijlstra wrote:
> On Fri, May 28, 2021 at 03:58:42AM +0000, liweihang wrote:
>> Peter, could you please explain why you said "add_return and sub_return are
>> horrible interface for refcount"?
> 
> What would you need them for? The only special value is 0. Once you hit
> 0 the object is dead and you cannot revive.
>> If I look at drivers/infiniband/sw/rdmavt/mcast.c, which seems to be the
> relevant file, the thing that's called ->refcount is not in fact a
> reference count.
> 

I see, thank you.

refcount_t is not suitable for the current logic, so let's leave it as it is. I
will drop this patch from the series.

Weihang

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2021-05-28  8:22 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-25  6:51 [PATCH v3 for-next 00/13] RDMA: Use refcount_t for reference counting Weihang Li
2021-05-25  6:51 ` [PATCH v3 for-next 01/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of iwcm_id_private Weihang Li
2021-05-25  6:51 ` [PATCH v3 for-next 02/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of iwpm_admin_data Weihang Li
2021-05-25  6:51 ` [PATCH v3 for-next 03/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of ib_mad_snoop_private Weihang Li
2021-05-25  6:51 ` [PATCH v3 for-next 04/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of mcast_member Weihang Li
2021-05-25  6:51 ` [PATCH v3 for-next 05/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of mcast_port Weihang Li
2021-05-25  6:51 ` [PATCH v3 for-next 06/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of mcast_group Weihang Li
2021-05-25  6:51 ` [PATCH v3 for-next 07/13] RDMA/core: Use refcount_t instead of atomic_t on refcount of ib_uverbs_device Weihang Li
2021-05-25  6:51 ` [PATCH v3 for-next 08/13] RDMA/hns: Use refcount_t instead of atomic_t for CQ reference counting Weihang Li
2021-05-25  6:51 ` [PATCH v3 for-next 09/13] RDMA/hns: Use refcount_t instead of atomic_t for SRQ " Weihang Li
2021-05-25  6:51 ` [PATCH v3 for-next 10/13] RDMA/hns: Use refcount_t instead of atomic_t for QP " Weihang Li
2021-05-25  6:51 ` [PATCH v3 for-next 11/13] RDMA/cxgb4: Use refcount_t instead of atomic_t for " Weihang Li
2021-05-25  6:51 ` [PATCH v3 for-next 12/13] RDMA/ipoib: " Weihang Li
2021-05-25  6:51 ` [PATCH v3 for-next 13/13] RDMA/rdmavt: Use refcount_t instead of atomic_t on refcount of rvt_mcast Weihang Li
2021-05-27 13:08   ` Marciniszyn, Mike
2021-05-27 13:15     ` Jason Gunthorpe
2021-05-28  3:58       ` liweihang
2021-05-28  7:01         ` Peter Zijlstra
2021-05-28  8:22           ` liweihang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.