refcount_t type and corresponding API can protect refcounters from
accidental underflow and overflow and further use-after-free situations.

Signed-off-by: Xiyu Yang <xiyuyan...@fudan.edu.cn>
Signed-off-by: Xin Tan <tanxin....@gmail.com>
---
 fs/fscache/operation.c        | 38 +++++++++++++++++++-------------------
 include/linux/fscache-cache.h |  3 ++-
 2 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c
index 4a5651d4904e..619ed21d24e7 100644
--- a/fs/fscache/operation.c
+++ b/fs/fscache/operation.c
@@ -35,7 +35,7 @@ void fscache_operation_init(struct fscache_cookie *cookie,
                            fscache_operation_release_t release)
 {
        INIT_WORK(&op->work, fscache_op_work_func);
-       atomic_set(&op->usage, 1);
+       refcount_set(&op->usage, 1);
        op->state = FSCACHE_OP_ST_INITIALISED;
        op->debug_id = atomic_inc_return(&fscache_op_debug_id);
        op->processor = processor;
@@ -60,12 +60,12 @@ void fscache_enqueue_operation(struct fscache_operation *op)
        struct fscache_cookie *cookie = op->object->cookie;
        
        _enter("{OBJ%x OP%x,%u}",
-              op->object->debug_id, op->debug_id, atomic_read(&op->usage));
+              op->object->debug_id, op->debug_id, refcount_read(&op->usage));
 
        ASSERT(list_empty(&op->pend_link));
        ASSERT(op->processor != NULL);
        ASSERT(fscache_object_is_available(op->object));
-       ASSERTCMP(atomic_read(&op->usage), >, 0);
+       ASSERTCMP(refcount_read(&op->usage), >, 0);
        ASSERTIFCMP(op->state != FSCACHE_OP_ST_IN_PROGRESS,
                    op->state, ==,  FSCACHE_OP_ST_CANCELLED);
 
@@ -74,7 +74,7 @@ void fscache_enqueue_operation(struct fscache_operation *op)
        case FSCACHE_OP_ASYNC:
                trace_fscache_op(cookie, op, fscache_op_enqueue_async);
                _debug("queue async");
-               atomic_inc(&op->usage);
+               refcount_inc(&op->usage);
                if (!queue_work(fscache_op_wq, &op->work))
                        fscache_put_operation(op);
                break;
@@ -163,7 +163,7 @@ int fscache_submit_exclusive_op(struct fscache_object 
*object,
        trace_fscache_op(object->cookie, op, fscache_op_submit_ex);
 
        ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED);
-       ASSERTCMP(atomic_read(&op->usage), >, 0);
+       ASSERTCMP(refcount_read(&op->usage), >, 0);
 
        spin_lock(&object->lock);
        ASSERTCMP(object->n_ops, >=, object->n_in_progress);
@@ -190,11 +190,11 @@ int fscache_submit_exclusive_op(struct fscache_object 
*object,
                object->n_exclusive++;  /* reads and writes must wait */
 
                if (object->n_in_progress > 0) {
-                       atomic_inc(&op->usage);
+                       refcount_inc(&op->usage);
                        list_add_tail(&op->pend_link, &object->pending_ops);
                        fscache_stat(&fscache_n_op_pend);
                } else if (!list_empty(&object->pending_ops)) {
-                       atomic_inc(&op->usage);
+                       refcount_inc(&op->usage);
                        list_add_tail(&op->pend_link, &object->pending_ops);
                        fscache_stat(&fscache_n_op_pend);
                        fscache_start_operations(object);
@@ -210,7 +210,7 @@ int fscache_submit_exclusive_op(struct fscache_object 
*object,
                op->object = object;
                object->n_ops++;
                object->n_exclusive++;  /* reads and writes must wait */
-               atomic_inc(&op->usage);
+               refcount_inc(&op->usage);
                list_add_tail(&op->pend_link, &object->pending_ops);
                fscache_stat(&fscache_n_op_pend);
                ret = 0;
@@ -245,12 +245,12 @@ int fscache_submit_op(struct fscache_object *object,
        int ret;
 
        _enter("{OBJ%x OP%x},{%u}",
-              object->debug_id, op->debug_id, atomic_read(&op->usage));
+              object->debug_id, op->debug_id, refcount_read(&op->usage));
 
        trace_fscache_op(object->cookie, op, fscache_op_submit);
 
        ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED);
-       ASSERTCMP(atomic_read(&op->usage), >, 0);
+       ASSERTCMP(refcount_read(&op->usage), >, 0);
 
        spin_lock(&object->lock);
        ASSERTCMP(object->n_ops, >=, object->n_in_progress);
@@ -276,11 +276,11 @@ int fscache_submit_op(struct fscache_object *object,
                object->n_ops++;
 
                if (object->n_exclusive > 0) {
-                       atomic_inc(&op->usage);
+                       refcount_inc(&op->usage);
                        list_add_tail(&op->pend_link, &object->pending_ops);
                        fscache_stat(&fscache_n_op_pend);
                } else if (!list_empty(&object->pending_ops)) {
-                       atomic_inc(&op->usage);
+                       refcount_inc(&op->usage);
                        list_add_tail(&op->pend_link, &object->pending_ops);
                        fscache_stat(&fscache_n_op_pend);
                        fscache_start_operations(object);
@@ -292,7 +292,7 @@ int fscache_submit_op(struct fscache_object *object,
        } else if (flags & BIT(FSCACHE_OBJECT_IS_LOOKED_UP)) {
                op->object = object;
                object->n_ops++;
-               atomic_inc(&op->usage);
+               refcount_inc(&op->usage);
                list_add_tail(&op->pend_link, &object->pending_ops);
                fscache_stat(&fscache_n_op_pend);
                ret = 0;
@@ -370,7 +370,7 @@ int fscache_cancel_op(struct fscache_operation *op,
 
        ASSERTCMP(op->state, >=, FSCACHE_OP_ST_PENDING);
        ASSERTCMP(op->state, !=, FSCACHE_OP_ST_CANCELLED);
-       ASSERTCMP(atomic_read(&op->usage), >, 0);
+       ASSERTCMP(refcount_read(&op->usage), >, 0);
 
        spin_lock(&object->lock);
 
@@ -497,11 +497,11 @@ void fscache_put_operation(struct fscache_operation *op)
 
        _enter("{OBJ%x OP%x,%d}",
               op->object ? op->object->debug_id : 0,
-              op->debug_id, atomic_read(&op->usage));
+              op->debug_id, refcount_read(&op->usage));
 
-       ASSERTCMP(atomic_read(&op->usage), >, 0);
+       ASSERTCMP(refcount_read(&op->usage), >, 0);
 
-       if (!atomic_dec_and_test(&op->usage))
+       if (!refcount_dec_and_test(&op->usage))
                return;
 
        trace_fscache_op(op->object ? op->object->cookie : NULL, op, 
fscache_op_put);
@@ -589,7 +589,7 @@ void fscache_operation_gc(struct work_struct *work)
                       object->debug_id, op->debug_id);
                fscache_stat(&fscache_n_op_gc);
 
-               ASSERTCMP(atomic_read(&op->usage), ==, 0);
+               ASSERTCMP(refcount_read(&op->usage), ==, 0);
                ASSERTCMP(op->state, ==, FSCACHE_OP_ST_DEAD);
 
                ASSERTCMP(object->n_ops, >, 0);
@@ -619,7 +619,7 @@ void fscache_op_work_func(struct work_struct *work)
        unsigned long start;
 
        _enter("{OBJ%x OP%x,%d}",
-              op->object->debug_id, op->debug_id, atomic_read(&op->usage));
+              op->object->debug_id, op->debug_id, refcount_read(&op->usage));
 
        trace_fscache_op(op->object->cookie, op, fscache_op_work);
 
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index 3235ddbdcc09..9fddf7817948 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -14,6 +14,7 @@
 #ifndef _LINUX_FSCACHE_CACHE_H
 #define _LINUX_FSCACHE_CACHE_H
 
+#include <linux/refcount.h>
 #include <linux/fscache.h>
 #include <linux/sched.h>
 #include <linux/workqueue.h>
@@ -110,7 +111,7 @@ struct fscache_operation {
 #define FSCACHE_OP_KEEP_FLAGS  0x00f0  /* flags to keep when repurposing an op 
*/
 
        enum fscache_operation_state state;
-       atomic_t                usage;
+       refcount_t              usage;
        unsigned                debug_id;       /* debugging ID */
 
        /* operation processor callback
-- 
2.7.4

--
Linux-cachefs mailing list
Linux-cachefs@redhat.com
https://listman.redhat.com/mailman/listinfo/linux-cachefs

Reply via email to