smalloc: fix off-by-one in ptr_valid()
[fio.git] / smalloc.c
index cdc9ed858579c27e9421e5763767644565d517b3..e97ba011319bd83e33549b51880d63fa2031806a 100644 (file)
--- a/smalloc.c
+++ b/smalloc.c
@@ -90,11 +90,16 @@ static inline void global_write_unlock(void)
 
 static inline int ptr_valid(struct pool *pool, void *ptr)
 {
-       unsigned int pool_size = pool->nr_blocks * SMALLOC_BPL;
+       unsigned int pool_size = (pool->nr_blocks + 1) * SMALLOC_BPL;
 
        return (ptr >= pool->map) && (ptr < pool->map + pool_size);
 }
 
+static inline unsigned int size_to_blocks(unsigned int size)
+{
+       return (size + SMALLOC_BPB - 1) / SMALLOC_BPB;
+}
+
 static int blocks_iter(unsigned int *map, unsigned int idx,
                       unsigned int nr_blocks,
                       int (*func)(unsigned int *map, unsigned int mask))
@@ -122,7 +127,6 @@ static int blocks_iter(unsigned int *map, unsigned int idx,
        }
 
        return 1;
-
 }
 
 static int mask_cmp(unsigned int *map, unsigned int mask)
@@ -200,8 +204,6 @@ static int add_pool(struct pool *pool, unsigned int alloc_size)
        void *ptr;
        int fd, bitmap_blocks;
 
-       printf("add pool %u\n", alloc_size);
-
        strcpy(pool->file, "/tmp/.fio_smalloc.XXXXXX");
        fd = mkstemp(pool->file);
        if (fd < 0)
@@ -322,7 +324,7 @@ static void sfree_check_redzone(struct block_hdr *hdr)
 static void sfree_pool(struct pool *pool, void *ptr)
 {
        struct block_hdr *hdr;
-       unsigned int nr_blocks, i, idx;
+       unsigned int i, idx;
        unsigned long offset;
 
        if (!ptr)
@@ -333,7 +335,6 @@ static void sfree_pool(struct pool *pool, void *ptr)
 
        assert(ptr_valid(pool, ptr));
 
-       nr_blocks = (hdr->size + SMALLOC_BPB - 1) / SMALLOC_BPB;
        sfree_check_redzone(hdr);
 
        offset = ptr - pool->map;
@@ -341,10 +342,10 @@ static void sfree_pool(struct pool *pool, void *ptr)
        idx = (offset % SMALLOC_BPL) / SMALLOC_BPB;
 
        pool_lock(pool);
-       clear_blocks(&pool->bitmap[i], idx, nr_blocks);
+       clear_blocks(&pool->bitmap[i], idx, size_to_blocks(hdr->size));
        if (i < pool->next_non_full)
                pool->next_non_full = i;
-       pool->free_blocks += nr_blocks;
+       pool->free_blocks += size_to_blocks(hdr->size);
        pool_unlock(pool);
 }
 
@@ -379,9 +380,9 @@ static void *__smalloc_pool(struct pool *pool, unsigned int size)
        unsigned int last_idx;
        void *ret = NULL;
 
-       nr_blocks = (size + SMALLOC_BPB - 1) / SMALLOC_BPB;
-
        pool_lock(pool);
+
+       nr_blocks = size_to_blocks(size);
        if (nr_blocks > pool->free_blocks)
                goto fail;
 
@@ -438,10 +439,8 @@ static void *smalloc_pool(struct pool *pool, unsigned int size)
 #endif
 
        ptr = __smalloc_pool(pool, alloc_size);
-       if (!ptr) {
-               printf("failed allocating %u\n", alloc_size);
+       if (!ptr)
                return NULL;
-       }
 
        hdr = ptr;
        hdr->size = alloc_size;