smalloc: fix garbage collection problem
authorVincent Fu <vincent.fu@wdc.com>
Tue, 30 Jul 2019 15:00:56 +0000 (09:00 -0600)
committerVincent Fu <vincent.fu@wdc.com>
Wed, 31 Jul 2019 18:17:44 +0000 (14:17 -0400)
If a large request arrives when pool->next_non_full points to empty
space that is insufficient to satisfy the request, pool->next_non_full
will be inappropriately advanced when the free space is followed by
lines of fully allocated space. The free space originally pointed to by
pool->next_non_full will be unavailable unless a subsequent sfree() call
frees allocated space above it. Resolve this issue by advancing
pool->next_non_full only outside the search loop and only when it points
to fully allocated space.

smalloc.c

index c1ae08b..c97bcba 100644 (file)
--- a/smalloc.c
+++ b/smalloc.c
@@ -338,6 +338,17 @@ void sfree(void *ptr)
        log_err("smalloc: ptr %p not from smalloc pool\n", ptr);
 }
 
+static unsigned int firstfree(struct pool *pool)
+{
+        unsigned int i;
+
+        for (i = 0; i < pool->nr_blocks; i++)
+                if (pool->bitmap[i] != -1U)
+                        return i;
+
+        assert(0);
+}
+
 static void *__smalloc_pool(struct pool *pool, size_t size)
 {
        size_t nr_blocks;
@@ -352,7 +363,14 @@ static void *__smalloc_pool(struct pool *pool, size_t size)
        if (nr_blocks > pool->free_blocks)
                goto fail;
 
-       i = pool->next_non_full;
+       for (i = pool->next_non_full; pool->bitmap[i] == -1U; i++)
+               if (i == pool->nr_blocks - 1) {
+                       i = firstfree(pool);
+                       break;
+               }
+
+       pool->next_non_full = i;
+
        last_idx = 0;
        offset = -1U;
        while (i < pool->nr_blocks) {
@@ -360,7 +378,6 @@ static void *__smalloc_pool(struct pool *pool, size_t size)
 
                if (pool->bitmap[i] == -1U) {
                        i++;
-                       pool->next_non_full = i;
                        last_idx = 0;
                        continue;
                }