Separates the disk array in a disk list and a handle mapping vector.

This commit is contained in:
Andrea Mazzoleni 2011-09-23 21:48:50 +02:00
parent 7a10f95465
commit 99515f610c
10 changed files with 123 additions and 95 deletions

12
check.c
View file

@ -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;i<diskmax;++i) {
handle[i].disk = tommy_array_get(&state->diskarr, 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;i<diskmax;++i) {
tommy_node* node;
struct snapraid_disk* disk = tommy_array_get(&state->diskarr, i);
struct snapraid_disk* disk = handle[i].disk;
/* for each link in the disk */
node = disk->linklist;

10
dry.c
View file

@ -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;i<diskmax;++i) {
handle[i].disk = tommy_array_get(&state->diskarr, i);
handle[i].file = 0;
handle[i].f = -1;
}
error = 0;
countmax = blockmax - blockstart;

3
elem.h
View file

@ -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;
};
/**

View file

@ -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;
}

View file

@ -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

View file

@ -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;i<diskmax;++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;
/* 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;
}

76
scan.c
View file

@ -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;i<file->blockmax;++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;j<diskmax;++j) {
struct snapraid_disk* oth_disk = tommy_array_get(&state->diskarr, 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;i<diskmax;++i) {
scan[i].count_equal = 0;
scan[i].count_moved = 0;
scan[i].count_change = 0;
scan[i].count_remove = 0;
scan[i].count_insert = 0;
tommy_list_init(&scan[i].file_insert_list);
tommy_list_init(&scan[i].link_insert_list);
}
tommy_list_init(&scanlist);
for(i=0;i<diskmax;++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;
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;i<diskmax;++i) {
struct snapraid_disk* disk = tommy_array_get(&state->diskarr, 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;i<diskmax;++i) {
total.count_equal += scan[i].count_equal;
total.count_moved += scan[i].count_moved;
total.count_change += scan[i].count_change;
total.count_remove += scan[i].count_remove;
total.count_insert += scan[i].count_insert;
for(i=scanlist;i!=0;i=i->next) {
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);
}

61
state.c
View file

@ -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;i<tommy_array_size(&state->diskarr);++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;j<diskmax;++j) {
unsigned k;
struct snapraid_disk* disk = tommy_array_get(&state->diskarr, 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;k<diskmax;++k) {
struct snapraid_disk* other = tommy_array_get(&state->diskarr, 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;i<tommy_array_size(&state->diskarr);++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;i<tommy_array_size(&state->diskarr);++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;i<tommy_array_size(&state->diskarr);++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;i<tommy_array_size(&state->diskarr);++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;i<tommy_array_size(&state->diskarr);++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) {

View file

@ -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. */

11
sync.c
View file

@ -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;i<diskmax;++i) {
handle[i].disk = tommy_array_get(&state->diskarr, i);
handle[i].file = 0;
handle[i].f = -1;
}
unrecoverable_error = 0;
/* first count the number of blocks to process */