From: Jens Axboe Date: Thu, 21 Feb 2013 14:18:17 +0000 (+0100) Subject: Fix problem with terminating on unaligned sizes X-Git-Tag: fio-2.0.14~1 X-Git-Url: https://git.kernel.dk/?p=fio.git;a=commitdiff_plain;h=53737ae01ca65f88089d3b8639df7be5b2f7ef0e Fix problem with terminating on unaligned sizes Three separate little issues: - Don't round up the number of blocks needed. That means we end up with potential partial blocks, which we can never do IO to. - Fix an axmap bug where we only check against the specific bit in the mask, but we really want to check for "this bit or any higher bit". This makes axmap_next_free() behave more like it should, instead of failing way too often. - For the almost-full case, we can return a next available bit that is just outside the allowed range. Punt to first-free for that case. Signed-off-by: Jens Axboe --- diff --git a/filesetup.c b/filesetup.c index 5aadf126..ac1804bd 100644 --- a/filesetup.c +++ b/filesetup.c @@ -958,8 +958,8 @@ int init_random_map(struct thread_data *td) for_each_file(td, f, i) { uint64_t file_size = min(f->real_file_size, f->io_size); - blocks = (file_size + td->o.rw_min_bs - 1) / - (unsigned long long) td->o.rw_min_bs; + blocks = file_size / (unsigned long long) td->o.rw_min_bs; + if (td->o.random_generator == FIO_RAND_GEN_LFSR) { unsigned long seed; diff --git a/lib/axmap.c b/lib/axmap.c index 533a155c..eeb32d42 100644 --- a/lib/axmap.c +++ b/lib/axmap.c @@ -374,9 +374,9 @@ static int axmap_next_free_fn(struct axmap_level *al, unsigned long offset, unsigned int bit, void *__data) { struct axmap_next_free_data *data = __data; - uint64_t mask = ~((1UL << ((data->bit & BLOCKS_PER_UNIT_MASK) + 1)) - 1); + uint64_t mask = ~bit_masks[(data->bit + 1) & BLOCKS_PER_UNIT_MASK]; - if (!(mask & al->map[offset])) + if (!(mask & ~al->map[offset])) return 0; if (al->map[offset] != -1UL) { @@ -395,6 +395,7 @@ static int axmap_next_free_fn(struct axmap_level *al, unsigned long offset, uint64_t axmap_next_free(struct axmap *axmap, uint64_t bit_nr) { struct axmap_next_free_data data = { .level = -1U, .bit = bit_nr, }; + uint64_t ret; if (firstfree_valid(axmap) && bit_nr < axmap->first_free) return axmap->first_free; @@ -404,5 +405,14 @@ uint64_t axmap_next_free(struct axmap *axmap, uint64_t bit_nr) assert(data.level != -1U); - return axmap_find_first_free(axmap, data.level, data.offset); + /* + * In the rare case that the map is unaligned, we might end up + * finding an offset that's beyond the valid end. For that case, + * find the first free one, the map is practically full. + */ + ret = axmap_find_first_free(axmap, data.level, data.offset); + if (ret != -1ULL) + return ret; + + return axmap_first_free(axmap); }