[PATCH 1/3] drbd: Use refcount_t for refcount

From: Chuhong Yuan
Date: Thu Aug 08 2019 - 09:10:49 EST


Reference counters are preferred to use refcount_t instead of
atomic_t.
This is because the implementation of refcount_t can prevent
overflows and detect possible use-after-free.
So convert atomic_t ref counters to refcount_t.

Signed-off-by: Chuhong Yuan <hslester96@xxxxxxxxx>
---
drivers/block/drbd/drbd_int.h | 3 ++-
drivers/block/drbd/drbd_main.c | 4 ++--
drivers/block/drbd/drbd_req.c | 16 ++++++++--------
3 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index ddbf56014c51..d5167a7a87db 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -30,6 +30,7 @@
#include <linux/genhd.h>
#include <linux/idr.h>
#include <linux/dynamic_debug.h>
+#include <linux/refcount.h>
#include <net/tcp.h>
#include <linux/lru_cache.h>
#include <linux/prefetch.h>
@@ -354,7 +355,7 @@ struct drbd_request {


/* once it hits 0, we may complete the master_bio */
- atomic_t completion_ref;
+ refcount_t completion_ref;
/* once it hits 0, we may destroy this drbd_request object */
struct kref kref;

diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 9bd4ddd12b25..37746708ee84 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -2295,14 +2295,14 @@ static void do_retry(struct work_struct *ws)
bool expected;

expected =
- expect(atomic_read(&req->completion_ref) == 0) &&
+ expect(refcount_read(&req->completion_ref) == 0) &&
expect(req->rq_state & RQ_POSTPONED) &&
expect((req->rq_state & RQ_LOCAL_PENDING) == 0 ||
(req->rq_state & RQ_LOCAL_ABORTED) != 0);

if (!expected)
drbd_err(device, "req=%p completion_ref=%d rq_state=%x\n",
- req, atomic_read(&req->completion_ref),
+ req, refcount_read(&req->completion_ref),
req->rq_state);

/* We still need to put one kref associated with the
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index f86cea4c0f8d..cb5d573e7ea2 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -69,7 +69,7 @@ static struct drbd_request *drbd_req_new(struct drbd_device *device, struct bio
INIT_LIST_HEAD(&req->req_pending_local);

/* one reference to be put by __drbd_make_request */
- atomic_set(&req->completion_ref, 1);
+ refcount_set(&req->completion_ref, 1);
/* one kref as long as completion_ref > 0 */
kref_init(&req->kref);
return req;
@@ -95,11 +95,11 @@ void drbd_req_destroy(struct kref *kref)
const unsigned s = req->rq_state;

if ((req->master_bio && !(s & RQ_POSTPONED)) ||
- atomic_read(&req->completion_ref) ||
+ refcount_read(&req->completion_ref) ||
(s & RQ_LOCAL_PENDING) ||
((s & RQ_NET_MASK) && !(s & RQ_NET_DONE))) {
drbd_err(device, "drbd_req_destroy: Logic BUG rq_state = 0x%x, completion_ref = %d\n",
- s, atomic_read(&req->completion_ref));
+ s, refcount_read(&req->completion_ref));
return;
}

@@ -315,7 +315,7 @@ static void drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and
if (!put)
return;

- if (!atomic_sub_and_test(put, &req->completion_ref))
+ if (!refcount_sub_and_test(put, &req->completion_ref))
return;

drbd_req_complete(req, m);
@@ -440,15 +440,15 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
kref_get(&req->kref);

if (!(s & RQ_LOCAL_PENDING) && (set & RQ_LOCAL_PENDING))
- atomic_inc(&req->completion_ref);
+ refcount_inc(&req->completion_ref);

if (!(s & RQ_NET_PENDING) && (set & RQ_NET_PENDING)) {
inc_ap_pending(device);
- atomic_inc(&req->completion_ref);
+ refcount_inc(&req->completion_ref);
}

if (!(s & RQ_NET_QUEUED) && (set & RQ_NET_QUEUED)) {
- atomic_inc(&req->completion_ref);
+ refcount_inc(&req->completion_ref);
set_if_null_req_next(peer_device, req);
}

@@ -466,7 +466,7 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
}

if (!(s & RQ_COMPLETION_SUSP) && (set & RQ_COMPLETION_SUSP))
- atomic_inc(&req->completion_ref);
+ refcount_inc(&req->completion_ref);

/* progress: put references */

--
2.20.1