mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Enforce BLOCK_MAX limits on both 32-bit and 64-bit builds
This commit is contained in:
parent
31718bdc4f
commit
237c9f0497
4 changed files with 67 additions and 26 deletions
|
|
@ -468,12 +468,14 @@ struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_
|
|||
if (size % block_size != 0)
|
||||
++blockmax;
|
||||
|
||||
if (blockmax > BLOCK_MAX) {
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
if (blockmax > (block_off_t)(SIZE_MAX / block_sizeof())) {
|
||||
log_fatal(ESOFT, "File '%s' with %" PRIu64 " blocks is too large for a 32-bit build. Use a 64-bit build or increase the block size.\n", sub, blockmax);
|
||||
#else
|
||||
log_fatal(ESOFT, "File '%s' with %" PRIu64 " blocks is too large. Increase the block size.\n", sub, blockmax);
|
||||
#endif
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
file = malloc_nofail(sizeof(struct snapraid_file));
|
||||
file->sub = strdup_nofail(sub);
|
||||
|
|
@ -501,12 +503,14 @@ struct snapraid_file* file_dup(struct snapraid_file* copy)
|
|||
struct snapraid_file* file;
|
||||
block_off_t i;
|
||||
|
||||
if (copy->blockmax > BLOCK_MAX) {
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
if (copy->blockmax > (block_off_t)(SIZE_MAX / block_sizeof())) {
|
||||
log_fatal(ESOFT, "File '%s' with %" PRIu64 " blocks is too large for a 32-bit build. Use a 64-bit build or increase the block size.\n", copy->sub, copy->blockmax);
|
||||
#else
|
||||
log_fatal(ESOFT, "File '%s' with %" PRIu64 " blocks is too large. Increase the block size.\n", copy->sub, copy->blockmax);
|
||||
#endif
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
file = malloc_nofail(sizeof(struct snapraid_file));
|
||||
file->sub = strdup_nofail(copy->sub);
|
||||
|
|
@ -872,12 +876,14 @@ struct snapraid_dealloc* dealloc_alloc(unsigned block_size, const char* sub, dat
|
|||
if (size % block_size != 0)
|
||||
++blockmax;
|
||||
|
||||
if (blockmax > BLOCK_MAX) {
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
if (blockmax > (block_off_t)(SIZE_MAX / BLOCK_HASH_SIZE)) {
|
||||
log_fatal(ESOFT, "File '%s' with %" PRIu64 " blocks is too large for a 32-bit build. Use a 64-bit build or increase the block size.\n", sub, blockmax);
|
||||
#else
|
||||
log_fatal(ESOFT, "File '%s' with %" PRIu64 " blocks is too large. Increase the block size.\n", sub, blockmax);
|
||||
#endif
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
dealloc = malloc_nofail(sizeof(struct snapraid_dealloc));
|
||||
dealloc->sub = strdup_nofail(sub);
|
||||
|
|
@ -1519,14 +1525,16 @@ void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snap
|
|||
struct snapraid_extent* parity_extent;
|
||||
struct snapraid_extent* file_extent;
|
||||
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
if (parity_pos > (block_off_t)(SIZE_MAX - 4096)) {
|
||||
if (parity_pos >= BLOCK_MAX) {
|
||||
/* 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);
|
||||
#else
|
||||
log_fatal(ESOFT, "Parity position %" PRIu64 " is too large. Increase the block size.\n", parity_pos);
|
||||
#endif
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
#endif
|
||||
|
||||
fs_lock(disk);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,35 @@
|
|||
/****************************************************************************/
|
||||
/* snapraid */
|
||||
|
||||
/*
|
||||
* Maximum number of block positions in a data/parity disk span.
|
||||
*
|
||||
* With the default 256 KiB block size, this limits the maximum supported
|
||||
* size of the largest data/parity disk to:
|
||||
*
|
||||
* 32-bit: 2^27 blocks = 32 TiB
|
||||
* 64-bit: 2^42 blocks = 1 EiB
|
||||
*
|
||||
* The limit scales linearly with the configured block size. For example,
|
||||
* on 64-bit systems a 512 KiB block size allows 2 EiB per disk.
|
||||
*
|
||||
* This is an architectural sanity limit, not a memory-usage limit.
|
||||
* SnapRAID stores per-block metadata in memory, so practical configurations
|
||||
* will reach memory constraints long before BLOCK_MAX. The actual memory
|
||||
* requirement depends on block size, hash size, number of data disks, and
|
||||
* array layout.
|
||||
*
|
||||
* Based on historical HDD capacity growth, single disks are not expected
|
||||
* to approach 1 EiB before approximately the year 2100. If necessary,
|
||||
* larger disks can still be supported without changing BLOCK_MAX simply
|
||||
* by increasing the configured block size.
|
||||
*/
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
#define BLOCK_MAX (1ULL << 27)
|
||||
#else
|
||||
#define BLOCK_MAX (1ULL << 42)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Number of measures of the operation progress.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -55,12 +55,18 @@ static void import_file(struct snapraid_state* state, const char* path, uint64_t
|
|||
if (size % block_size != 0)
|
||||
++blockmax;
|
||||
|
||||
if (blockmax > BLOCK_MAX
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
|| blockmax > (block_off_t)(SIZE_MAX / sizeof(struct snapraid_import_block))
|
||||
#endif
|
||||
) {
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
if (blockmax > (block_off_t)(SIZE_MAX / sizeof(struct snapraid_import_block))) {
|
||||
log_fatal(ESOFT, "File '%s' with %" PRIu64 " blocks is too large for a 32-bit build. Use a 64-bit build or increase the block size.\n", path, blockmax);
|
||||
#else
|
||||
log_fatal(ESOFT, "File '%s' with %" PRIu64 " blocks is too large. Increase the block size.\n", path, blockmax);
|
||||
#endif
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
file = malloc_nofail(sizeof(struct snapraid_import_file));
|
||||
file->path = strdup_nofail(path);
|
||||
|
|
@ -173,12 +179,18 @@ static void import_dealloc(struct snapraid_state* state, const char* dir, struct
|
|||
if (size % block_size != 0)
|
||||
++blockmax;
|
||||
|
||||
if (blockmax > BLOCK_MAX
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
|| blockmax > (block_off_t)(SIZE_MAX / sizeof(struct snapraid_import_block))
|
||||
#endif
|
||||
) {
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
if (blockmax > (block_off_t)(SIZE_MAX / sizeof(struct snapraid_import_block))) {
|
||||
log_fatal(ESOFT, "File '%s' with %" PRIu64 " blocks is too large for a 32-bit build. Use a 64-bit build or increase the block size.\n", path, blockmax);
|
||||
#else
|
||||
log_fatal(ESOFT, "File '%s' with %" PRIu64 " blocks is too large. Increase the block size.\n", path, blockmax);
|
||||
#endif
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
file = malloc_nofail(sizeof(struct snapraid_import_file));
|
||||
file->path = strdup_nofail(path);
|
||||
|
|
|
|||
|
|
@ -2016,16 +2016,6 @@ static void state_content_check(struct snapraid_state* state, const char* path)
|
|||
{
|
||||
tommy_node* i;
|
||||
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
block_off_t blockmax = parity_allocated_size(state);
|
||||
if (blockmax > (block_off_t)(SIZE_MAX / sizeof(snapraid_info))) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(ESOFT, "Array with %" PRIu64 " blocks in '%s' is too large for a 32-bit build. Use a 64-bit build or increase the block size.\n", blockmax, path);
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check that any map has different name and position */
|
||||
for (i = state->maplist; i != 0; i = i->next) {
|
||||
struct snapraid_map* map = i->data;
|
||||
|
|
@ -3138,15 +3128,17 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
|
|||
os_abort();
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
if (blockmax > (block_off_t)(SIZE_MAX / sizeof(snapraid_info))) {
|
||||
if (blockmax > BLOCK_MAX) {
|
||||
/* LCOV_EXCL_START */
|
||||
decoding_error(path, f);
|
||||
#if SIZE_MAX == UINT32_MAX
|
||||
log_fatal(ESOFT, "Array with %" PRIu64 " blocks in '%s' is too large for a 32-bit build. Use a 64-bit build or increase the block size.\n", blockmax, path);
|
||||
#else
|
||||
log_fatal(ESOFT, "Array with %" PRIu64 " blocks in '%s' is too large. Increase the block size.\n", blockmax, path);
|
||||
#endif
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
#endif
|
||||
} else if (c == 'm' || c == 'M') {
|
||||
struct snapraid_map* map;
|
||||
char uuid[UUID_MAX];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue