From 99515f610cb4197496194969c15a735595f303cb Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Fri, 23 Sep 2011 21:48:50 +0200 Subject: [PATCH] Separates the disk array in a disk list and a handle mapping vector. --- check.c | 12 +++------ dry.c | 10 +++----- elem.h | 3 +++ handle.c | 22 ++++++++++++++++ handle.h | 9 +++++++ parity.c | 12 ++++----- scan.c | 76 +++++++++++++++++++++++++++++++------------------------- state.c | 61 +++++++++++++++++++++------------------------ state.h | 2 +- sync.c | 11 +++----- 10 files changed, 123 insertions(+), 95 deletions(-) diff --git a/check.c b/check.c index 4f4be9bb..5a69a372 100644 --- a/check.c +++ b/check.c @@ -157,7 +157,7 @@ static int repair(struct snapraid_state* state, unsigned i, unsigned diskmax, st static int state_check_process(struct snapraid_state* state, int fix, int parity_f, int qarity_f, block_off_t blockstart, block_off_t blockmax) { struct snapraid_handle* handle; - unsigned diskmax = tommy_array_size(&state->diskarr); + unsigned diskmax; block_off_t i; unsigned j; void* buffer_alloc; @@ -173,6 +173,8 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity unsigned recovered_error; struct failed_struct* failed; + handle = handle_map(state, &diskmax); + /* we need disk + 2 for each parity level buffers + 1 zero buffer */ buffermax = diskmax + state->level * 2 + 1; @@ -185,12 +187,6 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity failed = malloc_nofail(diskmax * sizeof(struct failed_struct)); - handle = malloc_nofail(diskmax * sizeof(struct snapraid_handle)); - for(i=0;idiskarr, i); - handle[i].file = 0; - handle[i].f = -1; - } error = 0; unrecoverable_error = 0; recovered_error = 0; @@ -597,7 +593,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity /* check all the links */ for(i=0;idiskarr, i); + struct snapraid_disk* disk = handle[i].disk; /* for each link in the disk */ node = disk->linklist; diff --git a/dry.c b/dry.c index 4cc6c937..7cba59f6 100644 --- a/dry.c +++ b/dry.c @@ -29,7 +29,7 @@ static int state_dry_process(struct snapraid_state* state, int parity_f, int qarity_f, block_off_t blockstart, block_off_t blockmax) { struct snapraid_handle* handle; - unsigned diskmax = tommy_array_size(&state->diskarr); + unsigned diskmax; block_off_t i; unsigned j; unsigned char* buffer; @@ -39,14 +39,10 @@ static int state_dry_process(struct snapraid_state* state, int parity_f, int qar block_off_t countmax; unsigned error; + handle = handle_map(state, &diskmax); + buffer = malloc_nofail(state->block_size); - handle = malloc_nofail(diskmax * sizeof(struct snapraid_handle)); - for(i=0;idiskarr, i); - handle[i].file = 0; - handle[i].f = -1; - } error = 0; countmax = blockmax - blockstart; diff --git a/elem.h b/elem.h index 746120f6..adf22d99 100644 --- a/elem.h +++ b/elem.h @@ -128,6 +128,9 @@ struct snapraid_disk { tommy_list linklist; /**< List of all the links. */ tommy_hashdyn linkset; /**< Hashtable by name of all the links. */ tommy_array blockarr; /**< Block array of the disk. */ + + /* nodes for data structures */ + tommy_node node; }; /** diff --git a/handle.c b/handle.c index e235d6e8..90fb1393 100644 --- a/handle.c +++ b/handle.c @@ -323,3 +323,25 @@ int handle_utime(struct snapraid_handle* handle) return 0; } +struct snapraid_handle* handle_map(struct snapraid_state* state, unsigned* handlemax) +{ + tommy_node* i; + unsigned j; + struct snapraid_handle* handle; + + /* first count the disks */ + *handlemax = 0; + for(i=state->disklist;i!=0;i=i->next) + ++*handlemax; + + handle = malloc_nofail(*handlemax * sizeof(struct snapraid_handle)); + + /* set the vector */ + for(i=state->disklist,j=0;i!=0;i=i->next,++j) { + handle[j].disk = i->data; + handle[j].file = 0; + handle[j].f = -1; + } + + return handle; +} diff --git a/handle.h b/handle.h index 2e5d2be2..a816f469 100644 --- a/handle.h +++ b/handle.h @@ -18,6 +18,8 @@ #ifndef __HANDLE_H #define __HANDLE_H +#include "state.h" + /****************************************************************************/ /* handle */ @@ -72,5 +74,12 @@ int handle_write(struct snapraid_handle* handle, struct snapraid_block* block, u */ int handle_utime(struct snapraid_handle* handle); +/** + * Maps the unsorted list of disk to an ordered vector. + * \param diskmax The size of the vector. + * \return The allocated vector of pointers. + */ +struct snapraid_handle* handle_map(struct snapraid_state* state, unsigned* diskmax); + #endif diff --git a/parity.c b/parity.c index b461aa45..d7119157 100644 --- a/parity.c +++ b/parity.c @@ -26,23 +26,23 @@ block_off_t parity_resize(struct snapraid_state* state) { - unsigned diskmax = tommy_array_size(&state->diskarr); block_off_t parity_block; - unsigned i; + tommy_node* i; /* compute the size of the parity file */ parity_block = 0; - for(i=0;idiskarr, i); + for(i=state->disklist;i!=0;i=i->next) { + struct snapraid_disk* disk = i->data; /* start from the declared size */ block_off_t block = tommy_array_size(&disk->blockarr); /* decrease the block until an allocated block */ - while (block > 0 && tommy_array_get(&disk->blockarr, block - 1) == 0) + while (block > parity_block && tommy_array_get(&disk->blockarr, block - 1) == 0) --block; - if (i == 0 || parity_block < block) + /* get the highest value */ + if (block > parity_block) parity_block = block; } diff --git a/scan.c b/scan.c index 3217fe1c..b5cb7fc1 100644 --- a/scan.c +++ b/scan.c @@ -33,6 +33,9 @@ struct snapraid_scan { tommy_list file_insert_list; /**< Files to insert. */ tommy_list link_insert_list; /**< Links to insert. */ + + /* nodes for data structures */ + tommy_node node; }; /** @@ -40,8 +43,7 @@ struct snapraid_scan { */ static void scan_file_remove(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) { - block_off_t i, j; - unsigned diskmax = tommy_array_size(&state->diskarr); + block_off_t i; /* state changed */ state->need_write = 1; @@ -49,6 +51,7 @@ static void scan_file_remove(struct snapraid_state* state, struct snapraid_disk* /* free all the blocks of the file */ for(i=0;iblockmax;++i) { block_off_t block_pos = file->blockvec[i].parity_pos; + tommy_node* j; /* adjust the first free position */ if (disk->first_free_block > block_pos) @@ -58,8 +61,8 @@ static void scan_file_remove(struct snapraid_state* state, struct snapraid_disk* tommy_array_set(&disk->blockarr, block_pos, 0); /* invalidate the block of all the other disks */ - for(j=0;jdiskarr, j); + for(j=state->disklist;j!=0;j=j->next) { + struct snapraid_disk* oth_disk = j->data; struct snapraid_block* oth_block = disk_block_get(oth_disk, block_pos); if (oth_block) { /* remove the parity info for this block */ @@ -454,28 +457,31 @@ static void scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, i void state_scan(struct snapraid_state* state, int output) { - unsigned diskmax = tommy_array_size(&state->diskarr); - unsigned i; - struct snapraid_scan* scan; + tommy_node* i; + tommy_node* j; + tommy_list scanlist; - scan = malloc_nofail(diskmax * sizeof(struct snapraid_scan)); - for(i=0;idiskarr, i); + for(i=state->disklist;i!=0;i=i->next) { + struct snapraid_disk* disk = i->data; + struct snapraid_scan* scan; tommy_node* node; + scan = malloc_nofail(sizeof(struct snapraid_scan)); + scan->count_equal = 0; + scan->count_moved = 0; + scan->count_change = 0; + scan->count_remove = 0; + scan->count_insert = 0; + tommy_list_init(&scan->file_insert_list); + tommy_list_init(&scan->link_insert_list); + + tommy_list_insert_tail(&scanlist, &scan->node, scan); + printf("Scanning disk %s...\n", disk->name); - scan_dir(&scan[i], state, output, disk, disk->dir, ""); + scan_dir(scan, state, output, disk, disk->dir, ""); /* check for removed files */ node = disk->filelist; @@ -487,7 +493,7 @@ void state_scan(struct snapraid_state* state, int output) /* remove if not present */ if (!file_flag_has(file, FILE_IS_PRESENT)) { - ++scan[i].count_remove; + ++scan->count_remove; if (state->gui) { fprintf(stderr, "scan:remove:%s:%s\n", disk->name, file->sub); @@ -511,7 +517,7 @@ void state_scan(struct snapraid_state* state, int output) /* remove if not present */ if (!link_flag_has(link, FILE_IS_PRESENT)) { - ++scan[i].count_remove; + ++scan->count_remove; if (state->gui) { fprintf(stderr, "scan:remove:%s:%s\n", disk->name, link->sub); @@ -527,7 +533,7 @@ void state_scan(struct snapraid_state* state, int output) /* insert all the new files, we insert them only after the deletion */ /* to reuse the just freed space */ - node = scan[i].file_insert_list; + node = scan->file_insert_list; while (node) { struct snapraid_file* file = node->data; @@ -550,7 +556,7 @@ void state_scan(struct snapraid_state* state, int output) } /* insert all the new links */ - node = scan[i].link_insert_list; + node = scan->link_insert_list; while (node) { struct snapraid_link* link = node->data; @@ -576,10 +582,11 @@ void state_scan(struct snapraid_state* state, int output) /* checks for disks where all the previously existing files where removed */ if (!state->force_empty) { int has_empty = 0; - for(i=0;idiskarr, i); + for(i=state->disklist,j=scanlist;i!=0;i=i->next,j=j->next) { + struct snapraid_disk* disk = i->data; + struct snapraid_scan* scan = j->data; - if (scan[i].count_equal == 0 && scan[i].count_moved == 0 && scan[i].count_remove != 0) { + if (scan->count_equal == 0 && scan->count_moved == 0 && scan->count_remove != 0) { if (!has_empty) { has_empty = 1; fprintf(stderr, "All the files previously present in disk '%s' at dir '%s'", disk->name, disk->dir); @@ -605,12 +612,13 @@ void state_scan(struct snapraid_state* state, int output) total.count_remove = 0; total.count_insert = 0; - for(i=0;inext) { + struct snapraid_scan* scan = i->data; + total.count_equal += scan->count_equal; + total.count_moved += scan->count_moved; + total.count_change += scan->count_change; + total.count_remove += scan->count_remove; + total.count_insert += scan->count_insert; } if (state->verbose) { @@ -628,6 +636,6 @@ void state_scan(struct snapraid_state* state, int output) } } - free(scan); + tommy_list_foreach(&scanlist, (tommy_foreach_func*)free); } diff --git a/state.c b/state.c index 7e995811..b5795ae7 100644 --- a/state.c +++ b/state.c @@ -37,18 +37,14 @@ void state_init(struct snapraid_state* state) state->qarity_device = 0; state->level = 1; /* default is the lowest protection */ state->hash = HASH_MURMUR3; /* default is the fastest */ - tommy_array_init(&state->diskarr); + tommy_list_init(&state->disklist); tommy_list_init(&state->contentlist); tommy_list_init(&state->filterlist); } void state_done(struct snapraid_state* state) { - unsigned i; - - for(i=0;idiskarr);++i) - disk_free(tommy_array_get(&state->diskarr, i)); - tommy_array_done(&state->diskarr); + tommy_list_foreach(&state->disklist, (tommy_foreach_func*)disk_free); tommy_list_foreach(&state->contentlist, (tommy_foreach_func*)content_free); tommy_list_foreach(&state->filterlist, (tommy_foreach_func*)filter_free); } @@ -219,6 +215,7 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i char dir[PATH_MAX]; char device[PATH_MAX]; struct stat st; + struct snapraid_disk* disk; ret = sgettok(f, buffer, sizeof(buffer)); if (ret < 0) { @@ -241,7 +238,9 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i exit(EXIT_FAILURE); } - tommy_array_insert(&state->diskarr, disk_alloc(buffer, dir, st.st_dev)); + disk = disk_alloc(buffer, dir, st.st_dev); + + tommy_list_insert_tail(&state->disklist, &disk->node, disk); } else if (strcmp(tag, "exclude") == 0) { struct snapraid_filter* filter; @@ -350,15 +349,13 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i /* check if all the data and parity disks are different */ if (!skip_device) { - unsigned j; - unsigned diskmax; - diskmax = tommy_array_size(&state->diskarr); - for(j=0;jdiskarr, j); + tommy_node* i; + for(i=state->disklist;i!=0;i=i->next) { + tommy_node* j; + struct snapraid_disk* disk = i->data; - for(k=j+1;kdiskarr, k); + for(j=i->next;j!=0;j=j->next) { + struct snapraid_disk* other = j->data; if (disk->device == other->device) { fprintf(stderr, "Disks '%s' and '%s' are on the same device.\n", disk->dir, other->dir); exit(EXIT_FAILURE); @@ -382,10 +379,10 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i } if (state->gui) { - unsigned i; + tommy_node* i; fprintf(stderr, "blocksize:%u\n", state->block_size); - for(i=0;idiskarr);++i) { - struct snapraid_disk* disk = tommy_array_get(&state->diskarr, i); + for(i=state->disklist;i!=0;i=i->next) { + struct snapraid_disk* disk = i->data; fprintf(stderr, "disk:%s:%s\n", disk->name, disk->dir); } if (state->qarity[0] != 0) @@ -563,7 +560,7 @@ void state_read(struct snapraid_state* state) uint64_t v_size; uint64_t v_mtime; uint64_t v_inode; - unsigned i; + tommy_node* i; if (file) { fprintf(stderr, "Missing 'blk' specification in '%s' at line %u\n", path, line); @@ -630,12 +627,12 @@ void state_read(struct snapraid_state* state) } /* find the disk */ - for(i=0;idiskarr);++i) { - disk = tommy_array_get(&state->diskarr, i); + for(i=state->disklist;i!=0;i=i->next) { + disk = i->data; if (strcmp(disk->name, buffer) == 0) break; } - if (i == tommy_array_size(&state->diskarr)) { + if (!i) { fprintf(stderr, "Disk named '%s' not found in '%s' at line %u\n", buffer, path, line); exit(EXIT_FAILURE); } @@ -663,7 +660,7 @@ void state_read(struct snapraid_state* state) char sub[PATH_MAX]; char linkto[PATH_MAX]; char tokento[32]; - unsigned i; + tommy_node* i; struct snapraid_link* link; ret = sgettok(f, buffer, sizeof(buffer)); @@ -719,12 +716,12 @@ void state_read(struct snapraid_state* state) } /* find the disk */ - for(i=0;idiskarr);++i) { - disk = tommy_array_get(&state->diskarr, i); + for(i=state->disklist;i!=0;i=i->next) { + disk = i->data; if (strcmp(disk->name, buffer) == 0) break; } - if (i == tommy_array_size(&state->diskarr)) { + if (!i) { fprintf(stderr, "Disk named '%s' not found in '%s' at line %u\n", buffer, path, line); exit(EXIT_FAILURE); } @@ -819,7 +816,7 @@ static void state_write_one(struct snapraid_state* state, const char* path, unsi unsigned count_file; unsigned count_block; unsigned count_link; - unsigned i; + tommy_node* i; int ret; count_file = 0; @@ -852,9 +849,9 @@ static void state_write_one(struct snapraid_state* state, const char* path, unsi } /* for each disk */ - for(i=0;idiskarr);++i) { + for(i=state->disklist;i!=0;i=i->next) { tommy_node* j; - struct snapraid_disk* disk = tommy_array_get(&state->diskarr, i); + struct snapraid_disk* disk = i->data; /* for each file */ for(j=disk->filelist;j!=0;j=j->next) { @@ -980,7 +977,7 @@ void state_write(struct snapraid_state* state) void state_filter(struct snapraid_state* state, tommy_list* filterlist) { - unsigned i; + tommy_node* i; /* if no filter, include all */ if (tommy_list_empty(filterlist)) @@ -1000,9 +997,9 @@ void state_filter(struct snapraid_state* state, tommy_list* filterlist) } /* for each disk */ - for(i=0;idiskarr);++i) { + for(i=state->disklist;i!=0;i=i->next) { tommy_node* j; - struct snapraid_disk* disk = tommy_array_get(&state->diskarr, i); + struct snapraid_disk* disk = i->data; /* for each file */ for(j=tommy_list_head(&disk->filelist);j!=0;j=j->next) { diff --git a/state.h b/state.h index 68a4848f..33032341 100644 --- a/state.h +++ b/state.h @@ -45,7 +45,7 @@ struct snapraid_state { unsigned level; /**< Number of parity levels. 1 for RAID5, 2 for RAID6. */ unsigned hash; /**< Hash kind used. */ tommy_list contentlist; /**< List of content files. */ - tommy_array diskarr; /**< Disk array. */ + tommy_list disklist; /**< List of all the disks. */ tommy_list filterlist; /**< List of inclusion/exclusion. */ time_t progress_start; /**< Start of processing for progress visualization. */ time_t progress_last; /**< Last update of progress visualization. */ diff --git a/sync.c b/sync.c index b5861cdf..f8500ca6 100644 --- a/sync.c +++ b/sync.c @@ -30,7 +30,7 @@ static int state_sync_process(struct snapraid_state* state, int parity_f, int qarity_f, block_off_t blockstart, block_off_t blockmax) { struct snapraid_handle* handle; - unsigned diskmax = tommy_array_size(&state->diskarr); + unsigned diskmax; block_off_t i; unsigned j; void* buffer_alloc; @@ -43,6 +43,9 @@ static int state_sync_process(struct snapraid_state* state, int parity_f, int qa int ret; unsigned unrecoverable_error; + /* maps the disks to handles */ + handle = handle_map(state, &diskmax); + /* we need disk + 1 for each parity level buffers */ buffermax = diskmax + state->level; @@ -52,12 +55,6 @@ static int state_sync_process(struct snapraid_state* state, int parity_f, int qa buffer[i] = buffer_aligned + i * state->block_size; } - handle = malloc_nofail(diskmax * sizeof(struct snapraid_handle)); - for(i=0;idiskarr, i); - handle[i].file = 0; - handle[i].f = -1; - } unrecoverable_error = 0; /* first count the number of blocks to process */