From bed8959d470a88c2dbe7dc4efceeace2a7a52c36 Mon Sep 17 00:00:00 2001 From: nick Date: Wed, 24 Jul 2013 17:42:08 +0100 Subject: [PATCH] bitset: Fix large runs --- src/bitset.h | 12 +++++++----- src/client.c | 2 +- src/ioutil.c | 2 +- src/mirror.c | 4 ++++ tests/unit/check_bitset.c | 18 ++++++++++++++++++ 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/bitset.h b/src/bitset.h index 28ba806..ae1326f 100644 --- a/src/bitset.h +++ b/src/bitset.h @@ -74,7 +74,7 @@ static inline void bit_clear_range(char* b, uint64_t from, uint64_t len) * up to a maximum number of bits ''len''. Returns the number of contiguous * bits that are the same as the first one specified. */ -static inline int bit_run_count(char* b, uint64_t from, uint64_t len) { +static inline uint64_t bit_run_count(char* b, uint64_t from, uint64_t len) { uint64_t* current_block; uint64_t count = 0; int first_value = bit_is_set(b, from); @@ -138,8 +138,8 @@ static inline struct bitset_mapping* bitset_alloc( #define INT_FIRST_AND_LAST \ uint64_t first = from/set->resolution, \ - last = (from+len-1)/set->resolution, \ - bitlen = last-first+1 + last = ((from+len)-1)/set->resolution, \ + bitlen = (last-first)+1 #define BITSET_LOCK \ FATAL_IF_NEGATIVE(pthread_mutex_lock(&set->lock), "Error locking bitset") @@ -214,10 +214,12 @@ static inline uint64_t bitset_run_count( len = ( len + from ) > set->size ? ( set->size - from ) : len; INT_FIRST_AND_LAST; + BITSET_LOCK; - run = (bit_run_count(set->bits, first, bitlen) * set->resolution) - - (from % set->resolution); + run = bit_run_count(set->bits, first, bitlen) * set->resolution; + run -= (from % set->resolution); BITSET_UNLOCK; + return run; } diff --git a/src/client.c b/src/client.c index b514446..fb7a366 100644 --- a/src/client.c +++ b/src/client.c @@ -140,7 +140,7 @@ void write_not_zeroes(struct client* client, uint64_t from, uint64_t len) char zerobuffer[block_allocation_resolution]; /* not allocated, read in block_allocation_resoution */ while (run > 0) { - int blockrun = block_allocation_resolution - + uint64_t blockrun = block_allocation_resolution - (from % block_allocation_resolution); if (blockrun > run) blockrun = run; diff --git a/src/ioutil.c b/src/ioutil.c index b855912..bcdf7f3 100644 --- a/src/ioutil.c +++ b/src/ioutil.c @@ -270,7 +270,7 @@ int fd_is_closed( int fd_in ) } -static inline int io_errno_permanent() +static inline int io_errno_permanent(void) { return ( errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR ); } diff --git a/src/mirror.c b/src/mirror.c index 71a4948..d544fb2 100644 --- a/src/mirror.c +++ b/src/mirror.c @@ -106,6 +106,10 @@ void mirror_reset( struct mirror * mirror ) NULLCHECK( mirror->dirty_map ); mirror_set_state( mirror, MS_INIT ); bitset_set(mirror->dirty_map); + + uint64_t run = bitset_run_count(mirror->dirty_map, 0, mirror->dirty_map->size); + warn( "bitset_run_count: %"PRIu64, run); + } diff --git a/tests/unit/check_bitset.c b/tests/unit/check_bitset.c index d093a5b..2324170 100644 --- a/tests/unit/check_bitset.c +++ b/tests/unit/check_bitset.c @@ -188,6 +188,9 @@ START_TEST( test_bitset_run_count ) assert_bitset_is( map, 0x0000000000000000 ); + run = bitset_run_count( map, 0, 64 ); + ck_assert_int_eq( 64, run ); + bitset_set_range( map, 0, 32 ); assert_bitset_is( map, 0x00000000ffffffff ); @@ -215,6 +218,11 @@ START_TEST( test_bitset_run_count ) free( map ); map = bitset_alloc( 6400, 100 ); + assert_bitset_is( map, 0x0000000000000000 ); + + run = bitset_run_count( map, 0, 6400 ); + ck_assert_int_eq( 6400, run ); + bitset_set_range( map, 0, 3200 ); run = bitset_run_count( map, 0, 6400 ); @@ -228,6 +236,16 @@ START_TEST( test_bitset_run_count ) run = bitset_run_count( map, 6500, 6400 ); ck_assert_int_eq( 0, run ); + free( map ); + + // Now do something large and representative + map = bitset_alloc( 53687091200, 4096 ); + bitset_set( map ); + run = bitset_run_count( map, 0, 53687091200 ); + ck_assert_int_eq( run, 53687091200 ); + + free( map ); + } END_TEST