diff --git a/cmdline/check.c b/cmdline/check.c index fc5bead1..749039f2 100644 --- a/cmdline/check.c +++ b/cmdline/check.c @@ -869,6 +869,7 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna unsigned l; char esc_buffer[ESC_MAX]; char esc_buffer_alt[ESC_MAX]; + bit_vect_t* block_enabled; handle = handle_mapping(state, &diskmax); @@ -894,9 +895,11 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna /* first count the number of blocks to process */ countmax = 0; + block_enabled = calloc_nofail(1, bit_vect_size(blockmax)); /* preinitialize to 0 */ for (i = blockstart; i < blockmax; ++i) { if (!block_is_enabled(state, i, handle, diskmax)) continue; + bit_vect_set(block_enabled, i); ++countmax; } @@ -918,7 +921,7 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna snapraid_info info; int rehash; - if (!block_is_enabled(state, i, handle, diskmax)) { + if (!bit_vect_test(block_enabled, i)) { /* post process the files */ ret = file_post(state, fix, i, handle, diskmax); if (ret == -1) { @@ -1916,6 +1919,7 @@ bail: free(failed); free(failed_map); + free(block_enabled); free(handle); free(buffer_alloc); free(buffer); diff --git a/cmdline/dry.c b/cmdline/dry.c index 2fc3b18f..12c826a8 100644 --- a/cmdline/dry.c +++ b/cmdline/dry.c @@ -28,17 +28,6 @@ /****************************************************************************/ /* dry */ -/** - * Check if we have to process the specified block index ::i. - */ -static int block_is_enabled(void* void_plan, block_off_t i) -{ - (void)void_plan; - (void)i; - - return 1; -} - static void dry_data_reader(struct snapraid_worker* worker, struct snapraid_task* task) { struct snapraid_io* io = worker->io; @@ -208,7 +197,7 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit countpos = 0; /* start all the worker threads */ - io_start(&io, blockstart, blockmax, &block_is_enabled, 0); + io_start(&io, blockstart, blockmax, 0); state_progress_begin(state, blockstart, blockmax, countmax); while (1) { diff --git a/cmdline/io.c b/cmdline/io.c index 8611002c..53e16c01 100644 --- a/cmdline/io.c +++ b/cmdline/io.c @@ -21,7 +21,7 @@ void (*io_start)(struct snapraid_io* io, block_off_t blockstart, block_off_t blockmax, - int (*block_is_enabled)(void* arg, block_off_t), void* blockarg) = 0; + bit_vect_t* block_enabled) = 0; void (*io_stop)(struct snapraid_io* io) = 0; block_off_t (*io_read_next)(struct snapraid_io* io, void*** buffer) = 0; struct snapraid_task* (*io_data_read)(struct snapraid_io* io, unsigned* diskcur, unsigned* waiting_map, unsigned* waiting_mac) = 0; @@ -40,8 +40,10 @@ static block_off_t io_position_next(struct snapraid_io* io) block_off_t blockcur; /* get the next position */ - while (io->block_next < io->block_max && !io->block_is_enabled(io->block_arg, io->block_next)) - ++io->block_next; + if (io->block_enabled) { + while (io->block_next < io->block_max && !bit_vect_test(io->block_enabled, io->block_next)) + ++io->block_next; + } blockcur = io->block_next; @@ -257,12 +259,11 @@ static void io_parity_write_mono(struct snapraid_io* io, unsigned* pos, unsigned static void io_start_mono(struct snapraid_io* io, block_off_t blockstart, block_off_t blockmax, - int (*block_is_enabled)(void* arg, block_off_t), void* blockarg) + bit_vect_t* block_enabled) { io->block_start = blockstart; io->block_max = blockmax; - io->block_is_enabled = block_is_enabled; - io->block_arg = blockarg; + io->block_enabled = block_enabled; io->block_next = blockstart; } @@ -767,7 +768,7 @@ static void* io_writer_thread(void* arg) static void io_start_thread(struct snapraid_io* io, block_off_t blockstart, block_off_t blockmax, - int (*block_is_enabled)(void* arg, block_off_t), void* blockarg) + bit_vect_t* block_enabled) { unsigned i; tommy_node* j; @@ -780,8 +781,7 @@ static void io_start_thread(struct snapraid_io* io, io->block_start = blockstart; io->block_max = blockmax; - io->block_is_enabled = block_is_enabled; - io->block_arg = blockarg; + io->block_enabled = block_enabled; io->block_next = blockstart; io->done = 0; diff --git a/cmdline/io.h b/cmdline/io.h index a0cfb637..7df664f5 100644 --- a/cmdline/io.h +++ b/cmdline/io.h @@ -217,8 +217,7 @@ struct snapraid_io { block_off_t block_start; block_off_t block_max; block_off_t block_next; - int (*block_is_enabled)(void* arg, block_off_t); - void* block_arg; + bit_vect_t* block_enabled; /** * Buffers for data. @@ -315,7 +314,7 @@ void io_done(struct snapraid_io* io); */ extern void (*io_start)(struct snapraid_io* io, block_off_t blockstart, block_off_t blockmax, - int (*block_is_enabled)(void* arg, block_off_t), void* blockarg); + bit_vect_t* block_enabled); /** * Stop all the worker threads. diff --git a/cmdline/scrub.c b/cmdline/scrub.c index 65b20b00..4b59cddd 100644 --- a/cmdline/scrub.c +++ b/cmdline/scrub.c @@ -50,9 +50,8 @@ struct snapraid_plan { /** * Check if we have to process the specified block index ::i. */ -static int block_is_enabled(void* void_plan, block_off_t i) +static int block_is_enabled(struct snapraid_plan* plan, block_off_t i) { - struct snapraid_plan* plan = void_plan; time_t blocktime; snapraid_info info; @@ -268,6 +267,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par unsigned* waiting_map; unsigned waiting_mac; char esc_buffer[ESC_MAX]; + bit_vect_t* block_enabled; /* maps the disks to handles */ handle = handle_mapping(state, &diskmax); @@ -294,9 +294,11 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par /* first count the number of blocks to process */ countmax = 0; plan->countlast = 0; + block_enabled = calloc_nofail(1, bit_vect_size(blockmax)); /* preinitialize to 0 */ for (blockcur = blockstart; blockcur < blockmax; ++blockcur) { if (!block_is_enabled(plan, blockcur)) continue; + bit_vect_set(block_enabled, blockcur); ++countmax; } @@ -317,7 +319,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par msg_progress("Scrubbing...\n"); /* start all the worker threads */ - io_start(&io, blockstart, blockmax, &block_is_enabled, plan); + io_start(&io, blockstart, blockmax, block_enabled); state_progress_begin(state, blockstart, blockmax, countmax); while (1) { @@ -704,6 +706,7 @@ bail: free(rehandle_alloc); free(waiting_map); io_done(&io); + free(block_enabled); if (state->opt.expect_recoverable) { if (error + silent_error + io_error == 0) diff --git a/cmdline/sync.c b/cmdline/sync.c index e1d51455..efd58a40 100644 --- a/cmdline/sync.c +++ b/cmdline/sync.c @@ -440,9 +440,8 @@ struct snapraid_rehash { /** * Check if we have to process the specified block index ::i. */ -static int block_is_enabled(void* void_plan, block_off_t i) +static int block_is_enabled(struct snapraid_plan* plan, block_off_t i) { - struct snapraid_plan* plan = void_plan; unsigned j; int one_invalid; int one_valid; @@ -693,6 +692,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari unsigned* waiting_map; unsigned waiting_mac; char esc_buffer[ESC_MAX]; + bit_vect_t* block_enabled; /* the sync process assumes that all the hashes are correct */ /* including the ones from CHG and DELETED blocks */ @@ -739,9 +739,11 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari plan.handle_max = diskmax; plan.handle_map = handle; plan.force_full = state->opt.force_full; + block_enabled = calloc_nofail(1, bit_vect_size(blockmax)); /* preinitialize to 0 */ for (blockcur = blockstart; blockcur < blockmax; ++blockcur) { if (!block_is_enabled(&plan, blockcur)) continue; + bit_vect_set(block_enabled, blockcur); ++countmax; } @@ -761,7 +763,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari msg_progress("Syncing...\n"); /* start all the worker threads */ - io_start(&io, blockstart, blockmax, &block_is_enabled, &plan); + io_start(&io, blockstart, blockmax, block_enabled); if (!state_progress_begin(state, blockstart, blockmax, countmax)) goto end; @@ -1417,6 +1419,7 @@ bail: free(failed_map); free(waiting_map); io_done(&io); + free(block_enabled); if (state->opt.expect_recoverable) { if (error + silent_error + io_error == 0) diff --git a/cmdline/util.h b/cmdline/util.h index 8717a14c..4f9a5aa6 100644 --- a/cmdline/util.h +++ b/cmdline/util.h @@ -18,6 +18,7 @@ #ifndef __UTIL_H #define __UTIL_H + /****************************************************************************/ /* memory */ @@ -221,5 +222,34 @@ int lock_lock(const char* file); */ int lock_unlock(int f); +/****************************************************************************/ +/* bitvect */ + +typedef unsigned char bit_vect_t; +#define BIT_VECT_SIZE (sizeof(bit_vect_t) * 8) + +static inline size_t bit_vect_size(size_t max) +{ + return (max + BIT_VECT_SIZE - 1) / BIT_VECT_SIZE; +} + +static inline void bit_vect_set(bit_vect_t* bit_vect, size_t off) +{ + bit_vect_t mask = 1 << (off % BIT_VECT_SIZE); + bit_vect[off / BIT_VECT_SIZE] |= mask; +} + +static inline void bit_vect_clear(bit_vect_t* bit_vect, size_t off) +{ + bit_vect_t mask = 1 << (off % BIT_VECT_SIZE); + bit_vect[off / BIT_VECT_SIZE] &= ~mask; +} + +static inline int bit_vect_test(bit_vect_t* bit_vect, size_t off) +{ + bit_vect_t mask = 1 << (off % BIT_VECT_SIZE); + return (bit_vect[off / BIT_VECT_SIZE] & mask) != 0; +} + #endif