mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Allocate content extents by run instead of by block
This commit is contained in:
parent
b14f703d2b
commit
17b24c8d21
4 changed files with 34 additions and 34 deletions
|
|
@ -1495,34 +1495,40 @@ block_off_t fs_file2par_find(struct snapraid_disk* disk, struct snapraid_file* f
|
|||
}
|
||||
|
||||
/**
|
||||
* Allocate a file block mapping it to a parity position.
|
||||
* Allocate a run of file blocks mapping it to a run of parity positions.
|
||||
*
|
||||
* If the block is contiguous with the previous block of the file and follows
|
||||
* the current extent in parity space, the existing extent is extended in-place.
|
||||
* Otherwise, a new extent is created and inserted into the parity and file trees.
|
||||
*
|
||||
* Callers ensure allocations are sequential and do not overwrite live blocks.
|
||||
* To keep per-block allocation fast, full overlap checks across all existing
|
||||
* To keep run allocation fast, full overlap checks across all existing
|
||||
* extents are omitted here; global non-overlap and complete coverage invariants
|
||||
* are verified in batch by fs_check() at major checkpoints (after read/scan,
|
||||
* before write).
|
||||
*/
|
||||
void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos)
|
||||
void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count)
|
||||
{
|
||||
struct snapraid_extent* extent;
|
||||
struct snapraid_extent* parity_extent;
|
||||
struct snapraid_extent* file_extent;
|
||||
|
||||
if (parity_pos >= BLOCK_MAX) {
|
||||
if (count > BLOCK_MAX || parity_pos > BLOCK_MAX - count) {
|
||||
/* LCOV_EXCL_START */
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
log_fatal(ESOFT, "Parity position %" PRIu64 " is too large for a 32-bit build. Use a 64-bit build or increase the block size.\n", parity_pos);
|
||||
log_fatal(ESOFT, "Parity range %" PRIu64 ":%" PRIu64 " is too large for a 32-bit build. Use a 64-bit build or increase the block size.\n", parity_pos, count);
|
||||
#else
|
||||
log_fatal(ESOFT, "Parity position %" PRIu64 " is too large. Increase the block size.\n", parity_pos);
|
||||
log_fatal(ESOFT, "Parity range %" PRIu64 ":%" PRIu64 " is too large. Increase the block size.\n", parity_pos, count);
|
||||
#endif
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
if (count > file->blockmax || file_pos > file->blockmax - count) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EINTERNAL, "Internal inconsistency: Allocating file '%s' at position '%" PRIu64 ":%" PRIu64 "/%" PRIu64 "' in disk '%s'\n", file->sub, file_pos, count, file->blockmax, disk->name);
|
||||
os_abort();
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
fs_lock(disk);
|
||||
|
||||
|
|
@ -1531,14 +1537,6 @@ void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snap
|
|||
extent = fs_file2extent_get_unlock(disk, &disk->fs_last, file, file_pos - 1);
|
||||
|
||||
if (extent != 0 && parity_pos == extent->parity_pos + extent->count) {
|
||||
/* check if the position will go outside the limit */
|
||||
if (extent->parity_pos + extent->count == POS_NULL) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EINTERNAL, "Internal inconsistency: Parity position overflow allocating file '%s' at position '%" PRIu64 "/%" PRIu64 "' with count '%" PRIu64 "' in disk '%s'\n", file->sub, file_pos, file->blockmax, extent->count, disk->name);
|
||||
os_abort();
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* ensure that we are extending the extent at the end */
|
||||
if (file_pos != extent->file_pos + extent->count) {
|
||||
/* LCOV_EXCL_START */
|
||||
|
|
@ -1547,8 +1545,8 @@ void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snap
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* extend the existing extent */
|
||||
++extent->count;
|
||||
/* extend the existing extent with the whole run */
|
||||
extent->count += count;
|
||||
|
||||
fs_unlock(disk);
|
||||
return;
|
||||
|
|
@ -1556,7 +1554,7 @@ void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snap
|
|||
}
|
||||
|
||||
/* a extent doesn't exist, and we have to create a new one */
|
||||
extent = extent_alloc(parity_pos, file, file_pos, 1);
|
||||
extent = extent_alloc(parity_pos, file, file_pos, count);
|
||||
|
||||
/* insert the extent in the trees */
|
||||
parity_extent = tommy_tree_insert(&disk->fs_parity, &extent->parity_node, extent);
|
||||
|
|
|
|||
|
|
@ -1154,14 +1154,14 @@ int fs_is_empty(struct snapraid_disk* disk, block_off_t blockmax);
|
|||
int fs_check(struct snapraid_disk* disk);
|
||||
|
||||
/**
|
||||
* Allocate a parity position for the specified file position.
|
||||
* Allocate a run of parity positions for the specified file positions.
|
||||
*
|
||||
* After this call you can use the par2file/par2block operations
|
||||
* to query the relation.
|
||||
*
|
||||
* \note This function is NOT thread-safe as it uses the disk cache. +
|
||||
*/
|
||||
void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos);
|
||||
void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count);
|
||||
|
||||
/**
|
||||
* Deallocate the parity position.
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ static void scan_file_allocate(struct snapraid_scan* scan, struct snapraid_file*
|
|||
}
|
||||
|
||||
/* store in the disk map, after invalidating all the other blocks */
|
||||
fs_allocate(disk, parity_pos, file, i);
|
||||
fs_allocate(disk, parity_pos, file, i, 1);
|
||||
|
||||
/* set the new free position */
|
||||
disk->first_free_block = parity_pos + 1;
|
||||
|
|
|
|||
|
|
@ -2440,6 +2440,8 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
|
|||
while (v_idx < file->blockmax) {
|
||||
block_off_t v_pos;
|
||||
block_off_t v_count;
|
||||
block_off_t v_file_pos;
|
||||
block_off_t v_end;
|
||||
|
||||
/* get the "subcommand */
|
||||
c = sgetc(f);
|
||||
|
|
@ -2460,7 +2462,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
if (v_count > file->blockmax || v_idx > file->blockmax - v_count) {
|
||||
if (v_count == 0 || v_count > file->blockmax || v_idx > file->blockmax - v_count) {
|
||||
/* LCOV_EXCL_START */
|
||||
decoding_error(path, f);
|
||||
log_fatal(EINTERNAL, "Internal inconsistency: Block number out of range\n");
|
||||
|
|
@ -2476,8 +2478,11 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
v_file_pos = v_idx;
|
||||
v_end = v_idx + v_count;
|
||||
|
||||
/* fill the blocks in the run */
|
||||
while (v_count) {
|
||||
while (v_idx < v_end) {
|
||||
struct snapraid_block* block = fs_file2block_get(file, v_idx);
|
||||
|
||||
switch (c) {
|
||||
|
|
@ -2532,14 +2537,12 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
|
|||
block_state_set(block, BLOCK_STATE_CHG);
|
||||
}
|
||||
|
||||
/* set the parity association */
|
||||
fs_allocate(disk, v_pos, file, v_idx);
|
||||
|
||||
/* go to the next block */
|
||||
++v_idx;
|
||||
++v_pos;
|
||||
--v_count;
|
||||
}
|
||||
|
||||
/* set the parity association for the whole run */
|
||||
fs_allocate(disk, v_pos, file, v_file_pos, v_count);
|
||||
}
|
||||
|
||||
/* stat */
|
||||
|
|
@ -2729,7 +2732,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
if (v_count > blockmax || v_pos > blockmax - v_count) {
|
||||
if (v_count == 0 || v_count > blockmax || v_pos > blockmax - v_count) {
|
||||
/* LCOV_EXCL_START */
|
||||
decoding_error(path, f);
|
||||
log_fatal(EINTERNAL, "Internal inconsistency: Hole size %" PRIu64 "/%" PRIu64 "!\n", blockmax, v_pos + v_count);
|
||||
|
|
@ -2767,7 +2770,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
|
|||
|
||||
/* process all blocks */
|
||||
v_idx = 0;
|
||||
while (v_count) {
|
||||
while (v_idx < v_count) {
|
||||
struct snapraid_block* block = fs_file2block_get(deleted, v_idx);
|
||||
|
||||
/* set the block as deleted */
|
||||
|
|
@ -2782,14 +2785,13 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* insert the block in the block array */
|
||||
fs_allocate(disk, v_pos, deleted, v_idx);
|
||||
|
||||
/* go to next block */
|
||||
++v_pos;
|
||||
++v_idx;
|
||||
--v_count;
|
||||
}
|
||||
|
||||
/* insert the whole deleted run in the extent map */
|
||||
fs_allocate(disk, v_pos, deleted, 0, v_count);
|
||||
v_pos += v_count;
|
||||
break;
|
||||
case 'O' :
|
||||
/* go to the next run */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue