Fix bug in smalloc size calculation
authorJiri Horky <jiri.horky@cesnet.cz>
Mon, 15 Aug 2011 13:18:03 +0000 (15:18 +0200)
committerJens Axboe <jaxboe@fusionio.com>
Mon, 15 Aug 2011 13:18:03 +0000 (15:18 +0200)
Jiri reports:

I think I found a bug. If the device (file) used in fio has "wrong" size, and is used with "wrong" block size, the fio fails to allocate memory for randommap.
Following conditions must be true, considering just one thread for simplicity:

 1) number of blocks on the device are too big to fill in the default's pool
 2) number of blocks on the device must be "right", so the size of newly allocated pool by smalloc.c:add_pool is exactly as big as requested size (there are some roundings in place, so not every size triggers this error)

When this is true, function smalloc.c:__smalloc_pool fails to use the newly created (exactly big enough) pool, because of this line:

                idx = find_next_zero(pool->bitmap[i], last_idx);

which always returns non-zero value (the minimum returned value is last_idx +1), and so in our case the idx is 1 even though, the block number 0 is free. As the direct consequence, the function doesn't find enough free space in the given pool and returns NULL pointer. This leads to another try to allocate enough memory in smalloc.c:smalloc_real function, and so on...

The behavior could be reprocuded using both stable 1.57 and git version of the tool. The values that triggers the error are:
init_random_map - real_file_size: 21999995584512, o.rw_min_bs: 4096, blocks: 5371092672, num_maps: 83923323, alloc size: 671386584

whereas this block device is fine:
init_random_map - real_file_size: 19999995985920, o.rw_min_bs: 4096, blocks: 4882811520, num_maps: 76293930, alloc size: 610351440

the configuration file used:

[global]
description=CESNET_test
[cesnet]
filename=/dev/sdd
rw=randread
size=10000g
ioengine=libaio
iodepth=4
bs=4k
runtime=10m
time_based
numjobs=1
group_reporting

Get rid of the +1, it looks like a remnant from when the pools
had a header associated with them.

Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
smalloc.c

index a925a653e5d5571e9fff8686b7378efe3a343704..0c7c6df7bdd17992a5fa3c8acb6b53a769621009 100644 (file)
--- a/smalloc.c
+++ b/smalloc.c
@@ -171,8 +171,8 @@ static void clear_blocks(struct pool *pool, unsigned int pool_idx,
 static int find_next_zero(int word, int start)
 {
        assert(word != -1U);
-       word >>= (start + 1);
-       return ffz(word) + start + 1;
+       word >>= start;
+       return ffz(word) + start;
 }
 
 static int add_pool(struct pool *pool, unsigned int alloc_size)