mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Resolve file-to-parity mappings once per extent while writing content
This commit is contained in:
parent
69e3a845e4
commit
a1ff18fcbd
4 changed files with 82 additions and 7 deletions
|
|
@ -1475,7 +1475,7 @@ struct snapraid_file* fs_par2file_find(struct snapraid_disk* disk, block_off_t p
|
|||
return file;
|
||||
}
|
||||
|
||||
block_off_t fs_file2par_find(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos)
|
||||
block_off_t fs_file2par_find_run(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos, block_off_t* count)
|
||||
{
|
||||
struct snapraid_extent* extent;
|
||||
block_off_t ret;
|
||||
|
|
@ -1488,12 +1488,20 @@ block_off_t fs_file2par_find(struct snapraid_disk* disk, struct snapraid_file* f
|
|||
return POS_NULL;
|
||||
}
|
||||
|
||||
if (count)
|
||||
*count = extent->count - (file_pos - extent->file_pos);
|
||||
|
||||
ret = extent->parity_pos + (file_pos - extent->file_pos);
|
||||
|
||||
fs_unlock(disk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
block_off_t fs_file2par_find(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos)
|
||||
{
|
||||
return fs_file2par_find_run(disk, file, file_pos, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a run of file blocks mapping it to a run of parity positions.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1209,13 +1209,21 @@ static inline struct snapraid_file* fs_par2file_get(struct snapraid_disk* disk,
|
|||
block_off_t fs_file2par_find(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos);
|
||||
|
||||
/**
|
||||
* Get the parity position from the file position.
|
||||
* Get the parity position from the file position. If count is specified, return
|
||||
* the number of blocks remaining in the same extent, including the current one.
|
||||
* Return POS_NULL if no parity is allocated.
|
||||
*/
|
||||
static inline block_off_t fs_file2par_get(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos)
|
||||
block_off_t fs_file2par_find_run(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos, block_off_t* count);
|
||||
|
||||
/**
|
||||
* Get the parity position and the number of blocks remaining in the same extent,
|
||||
* including the current one, from the file position.
|
||||
*/
|
||||
static inline block_off_t fs_file2par_get_run(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos, block_off_t* count)
|
||||
{
|
||||
block_off_t ret;
|
||||
|
||||
ret = fs_file2par_find(disk, file, file_pos);
|
||||
ret = fs_file2par_find_run(disk, file, file_pos, count);
|
||||
if (ret == POS_NULL) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EINTERNAL, "Internal inconsistency: Resolving file '%s' at position '%" PRIu64 "/%" PRIu64 "' in disk '%s'\n", file->sub, file_pos, file->blockmax, disk->name);
|
||||
|
|
@ -1226,6 +1234,14 @@ static inline block_off_t fs_file2par_get(struct snapraid_disk* disk, struct sna
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parity position from the file position.
|
||||
*/
|
||||
static inline block_off_t fs_file2par_get(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos)
|
||||
{
|
||||
return fs_file2par_get_run(disk, file, file_pos, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block from the parity position.
|
||||
* Return BLOCK_NULL==0 if the block is over the end of the disk or not used.
|
||||
|
|
|
|||
|
|
@ -1852,6 +1852,42 @@ static void test_stream(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void test_extent_run(void)
|
||||
{
|
||||
struct snapraid_disk* disk;
|
||||
struct snapraid_file* file;
|
||||
block_off_t parity_pos;
|
||||
block_off_t count;
|
||||
|
||||
disk = disk_alloc("test", "", 0, "", 0);
|
||||
file = file_alloc(4096, "file", 6 * 4096, 0, 0, 0);
|
||||
|
||||
fs_allocate(disk, 10, file, 0, 3);
|
||||
fs_allocate(disk, 20, file, 3, 2);
|
||||
fs_allocate(disk, 22, file, 5, 1);
|
||||
|
||||
parity_pos = fs_file2par_get_run(disk, file, 0, &count);
|
||||
if (parity_pos != 10 || count != 3) {
|
||||
log_fatal(EINTERNAL, "test_extent_run: first extent failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
parity_pos = fs_file2par_get_run(disk, file, 1, &count);
|
||||
if (parity_pos != 11 || count != 2) {
|
||||
log_fatal(EINTERNAL, "test_extent_run: extent remainder failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
parity_pos = fs_file2par_get_run(disk, file, 3, &count);
|
||||
if (parity_pos != 20 || count != 3) {
|
||||
log_fatal(EINTERNAL, "test_extent_run: extended extent failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
disk_free(disk);
|
||||
file_free(file);
|
||||
}
|
||||
|
||||
static void test_raid(void)
|
||||
{
|
||||
/* vandermonde raid parity generation with 32 data disks */
|
||||
|
|
@ -2551,6 +2587,9 @@ void test(int argc, char* argv[])
|
|||
/* buffered streaming i/o and crc verification */
|
||||
test_stream();
|
||||
|
||||
/* extent-aware file-to-parity run lookup */
|
||||
test_extent_run();
|
||||
|
||||
/* wildcard and path pattern matching */
|
||||
test_wnmatch();
|
||||
|
||||
|
|
|
|||
|
|
@ -4161,7 +4161,9 @@ static void* state_write_thread(void* arg)
|
|||
struct snapraid_block* block = file_block(file, begin);
|
||||
unsigned char* end_block_ptr = (unsigned char*)block + block_stride;
|
||||
unsigned v_state = block_state_get(block);
|
||||
block_off_t v_pos = fs_file2par_get(disk, file, begin);
|
||||
block_off_t extent_count;
|
||||
block_off_t v_pos = fs_file2par_get_run(disk, file, begin, &extent_count);
|
||||
block_off_t extent_end = begin + extent_count;
|
||||
block_off_t v_count;
|
||||
|
||||
block_off_t end;
|
||||
|
|
@ -4172,8 +4174,18 @@ static void* state_write_thread(void* arg)
|
|||
block = (struct snapraid_block*)end_block_ptr;
|
||||
if (v_state != block_state_get(block))
|
||||
break;
|
||||
if (v_pos + (end - begin) != fs_file2par_get(disk, file, end))
|
||||
break;
|
||||
|
||||
/* Resolve the mapping only when crossing an extent boundary. */
|
||||
if (end == extent_end) {
|
||||
block_off_t next_count;
|
||||
block_off_t next_pos = fs_file2par_get_run(disk, file, end, &next_count);
|
||||
|
||||
if (v_pos + (end - begin) != next_pos)
|
||||
break;
|
||||
|
||||
extent_end += next_count;
|
||||
}
|
||||
|
||||
end_block_ptr += block_stride;
|
||||
++end;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue