maple_tree: revise limit checks in mas_empty_area{_rev}()
authorLiam R. Howlett <Liam.Howlett@oracle.com>
Thu, 18 May 2023 14:55:34 +0000 (10:55 -0400)
committerAndrew Morton <akpm@linux-foundation.org>
Fri, 9 Jun 2023 23:25:33 +0000 (16:25 -0700)
Since the maple tree is inclusive in range, ensure that a range of 1 (min
= max) works for searching for a gap in either direction, and make sure
the size is at least 1 but not larger than the delta between min and max.

This commit also updates the testing.  Unfortunately there isn't a way to
safely update the tests and code without a test failure.

Link: https://lkml.kernel.org/r/20230518145544.1722059-26-Liam.Howlett@oracle.com
Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
Suggested-by: Peng Zhang <zhangpeng.00@bytedance.com>
Cc: David Binderman <dcb314@hotmail.com>
Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
Cc: Vernon Yang <vernon2gm@gmail.com>
Cc: Wei Yang <richard.weiyang@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
lib/maple_tree.c
lib/test_maple_tree.c

index cd14c1d..536504c 100644 (file)
@@ -5283,7 +5283,10 @@ int mas_empty_area(struct ma_state *mas, unsigned long min,
        unsigned long *pivots;
        enum maple_type mt;
 
-       if (min >= max)
+       if (min > max)
+               return -EINVAL;
+
+       if (size == 0 || max - min < size - 1)
                return -EINVAL;
 
        if (mas_is_start(mas))
@@ -5332,7 +5335,10 @@ int mas_empty_area_rev(struct ma_state *mas, unsigned long min,
 {
        struct maple_enode *last = mas->node;
 
-       if (min >= max)
+       if (min > max)
+               return -EINVAL;
+
+       if (size == 0 || max - min < size - 1)
                return -EINVAL;
 
        if (mas_is_start(mas)) {
@@ -5368,7 +5374,7 @@ int mas_empty_area_rev(struct ma_state *mas, unsigned long min,
                return -EBUSY;
 
        /* Trim the upper limit to the max. */
-       if (max <= mas->last)
+       if (max < mas->last)
                mas->last = max;
 
        mas->index = mas->last - size + 1;
@@ -6404,7 +6410,7 @@ int mtree_alloc_range(struct maple_tree *mt, unsigned long *startp,
 {
        int ret = 0;
 
-       MA_STATE(mas, mt, min, max - size);
+       MA_STATE(mas, mt, min, min);
        if (!mt_is_alloc(mt))
                return -EINVAL;
 
@@ -6424,7 +6430,7 @@ int mtree_alloc_range(struct maple_tree *mt, unsigned long *startp,
 retry:
        mas.offset = 0;
        mas.index = min;
-       mas.last = max - size;
+       mas.last = max - size + 1;
        ret = mas_alloc(&mas, entry, size, startp);
        if (mas_nomem(&mas, gfp))
                goto retry;
@@ -6440,14 +6446,14 @@ int mtree_alloc_rrange(struct maple_tree *mt, unsigned long *startp,
 {
        int ret = 0;
 
-       MA_STATE(mas, mt, min, max - size);
+       MA_STATE(mas, mt, min, max - size + 1);
        if (!mt_is_alloc(mt))
                return -EINVAL;
 
        if (WARN_ON_ONCE(mt_is_reserved(entry)))
                return -EINVAL;
 
-       if (min >= max)
+       if (min > max)
                return -EINVAL;
 
        if (max < size - 1)
index 19b130c..f167d6e 100644 (file)
@@ -123,7 +123,7 @@ static noinline void __init check_mtree_alloc_rrange(struct maple_tree *mt,
        unsigned long result = expected + 1;
        int ret;
 
-       ret = mtree_alloc_rrange(mt, &result, ptr, size, start, end - 1,
+       ret = mtree_alloc_rrange(mt, &result, ptr, size, start, end,
                        GFP_KERNEL);
        MT_BUG_ON(mt, ret != eret);
        if (ret)
@@ -701,7 +701,7 @@ static noinline void __init check_alloc_rev_range(struct maple_tree *mt)
                0,              /* Return value success. */
 
                0x0,            /* Min */
-               0x565234AF1 << 12,    /* Max */
+               0x565234AF0 << 12,    /* Max */
                0x3000,         /* Size */
                0x565234AEE << 12,  /* max - 3. */
                0,              /* Return value success. */
@@ -713,14 +713,14 @@ static noinline void __init check_alloc_rev_range(struct maple_tree *mt)
                0,              /* Return value success. */
 
                0x0,            /* Min */
-               0x7F36D510A << 12,    /* Max */
+               0x7F36D5109 << 12,    /* Max */
                0x4000,         /* Size */
                0x7F36D5106 << 12,    /* First rev hole of size 0x4000 */
                0,              /* Return value success. */
 
                /* Ascend test. */
                0x0,
-               34148798629 << 12,
+               34148798628 << 12,
                19 << 12,
                34148797418 << 12,
                0x0,
@@ -732,6 +732,12 @@ static noinline void __init check_alloc_rev_range(struct maple_tree *mt)
                0x0,
                -EBUSY,
 
+               /* Single space test. */
+               34148798725 << 12,
+               34148798725 << 12,
+               1 << 12,
+               34148798725 << 12,
+               0,
        };
 
        int i, range_count = ARRAY_SIZE(range);
@@ -780,9 +786,9 @@ static noinline void __init check_alloc_rev_range(struct maple_tree *mt)
        mas_unlock(&mas);
        for (i = 0; i < req_range_count; i += 5) {
 #if DEBUG_REV_RANGE
-               pr_debug("\tReverse request between %lu-%lu size %lu, should get %lu\n",
-                               req_range[i] >> 12,
-                               (req_range[i + 1] >> 12) - 1,
+               pr_debug("\tReverse request %d between %lu-%lu size %lu, should get %lu\n",
+                               i, req_range[i] >> 12,
+                               (req_range[i + 1] >> 12),
                                req_range[i+2] >> 12,
                                req_range[i+3] >> 12);
 #endif
@@ -798,6 +804,7 @@ static noinline void __init check_alloc_rev_range(struct maple_tree *mt)
 
        mt_set_non_kernel(1);
        mtree_erase(mt, 34148798727); /* create a deleted range. */
+       mtree_erase(mt, 34148798725);
        check_mtree_alloc_rrange(mt, 0, 34359052173, 210253414,
                        34148798725, 0, mt);
 
@@ -901,6 +908,13 @@ static noinline void __init check_alloc_range(struct maple_tree *mt)
                4503599618982063UL << 12,  /* Size */
                34359052178 << 12,  /* Expected location */
                -EBUSY,             /* Return failure. */
+
+               /* Test a single entry */
+               34148798648 << 12,              /* Min */
+               34148798648 << 12,              /* Max */
+               4096,                   /* Size of 1 */
+               34148798648 << 12,      /* Location is the same as min/max */
+               0,                      /* Success */
        };
        int i, range_count = ARRAY_SIZE(range);
        int req_range_count = ARRAY_SIZE(req_range);