s390/extmem: use refcount_t for refcount
authorChuhong Yuan <hslester96@gmail.com>
Thu, 8 Aug 2019 07:18:17 +0000 (15:18 +0800)
committerVasily Gorbik <gor@linux.ibm.com>
Wed, 21 Aug 2019 10:41:43 +0000 (12:41 +0200)
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.

Link: http://lkml.kernel.org/r/20190808071817.6595-1-hslester96@gmail.com
Signed-off-by: Chuhong Yuan <hslester96@gmail.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/mm/extmem.c

index 0b5622714c12c3bce64f23db9634ca38ee89c8e0..fd0dae9d10f4757508269196abbabc65e3539e23 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/memblock.h>
 #include <linux/ctype.h>
 #include <linux/ioport.h>
+#include <linux/refcount.h>
 #include <asm/diag.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -64,7 +65,7 @@ struct dcss_segment {
        char res_name[16];
        unsigned long start_addr;
        unsigned long end;
-       atomic_t ref_count;
+       refcount_t ref_count;
        int do_nonshared;
        unsigned int vm_segtype;
        struct qrange range[6];
@@ -362,7 +363,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
        seg->start_addr = start_addr;
        seg->end = end_addr;
        seg->do_nonshared = do_nonshared;
-       atomic_set(&seg->ref_count, 1);
+       refcount_set(&seg->ref_count, 1);
        list_add(&seg->list, &dcss_list);
        *addr = seg->start_addr;
        *end  = seg->end;
@@ -422,7 +423,7 @@ segment_load (char *name, int do_nonshared, unsigned long *addr,
                rc = __segment_load (name, do_nonshared, addr, end);
        else {
                if (do_nonshared == seg->do_nonshared) {
-                       atomic_inc(&seg->ref_count);
+                       refcount_inc(&seg->ref_count);
                        *addr = seg->start_addr;
                        *end  = seg->end;
                        rc    = seg->vm_segtype;
@@ -468,7 +469,7 @@ segment_modify_shared (char *name, int do_nonshared)
                rc = 0;
                goto out_unlock;
        }
-       if (atomic_read (&seg->ref_count) != 1) {
+       if (refcount_read(&seg->ref_count) != 1) {
                pr_warn("DCSS %s is in use and cannot be reloaded\n", name);
                rc = -EAGAIN;
                goto out_unlock;
@@ -544,7 +545,7 @@ segment_unload(char *name)
                pr_err("Unloading unknown DCSS %s failed\n", name);
                goto out_unlock;
        }
-       if (atomic_dec_return(&seg->ref_count) != 0)
+       if (!refcount_dec_and_test(&seg->ref_count))
                goto out_unlock;
        release_resource(seg->res);
        kfree(seg->res);