diff --git a/HISTORY b/HISTORY index 312c5f39..67a67e69 100644 --- a/HISTORY +++ b/HISTORY @@ -1,7 +1,7 @@ SnapRAID HISTORY ================ -11.0 2016/09 +11.0 2016/10 ============ * Added support for splitting the parity in multiple partitions. You can now specify multiple files for a single parity. As soon a file diff --git a/cmdline/check.c b/cmdline/check.c index 293139b7..b2d120e1 100644 --- a/cmdline/check.c +++ b/cmdline/check.c @@ -1955,7 +1955,7 @@ int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, b /* LCOV_EXCL_STOP */ } - ret = parity_chsize(parity_ptr[l], &state->parity[l], 0, size, state->block_size, state->opt.skip_fallocate); + ret = parity_chsize(parity_ptr[l], &state->parity[l], 0, size, state->block_size, state->opt.skip_fallocate, state->opt.skip_space_holder); if (ret == -1) { /* LCOV_EXCL_START */ log_fatal("WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l)); diff --git a/cmdline/parity.c b/cmdline/parity.c index 32356748..907caae6 100644 --- a/cmdline/parity.c +++ b/cmdline/parity.c @@ -346,7 +346,7 @@ uint64_t hbit_u64(uint64_t v) return 1ULL << ilog; } -static int parity_handle_fill(struct snapraid_split_handle* split, data_off_t size, uint32_t block_size, int skip_fallocate) +static int parity_handle_fill(struct snapraid_split_handle* split, data_off_t size, uint32_t block_size, int skip_fallocate, int skip_space_holder) { data_off_t base; data_off_t delta; @@ -362,38 +362,43 @@ static int parity_handle_fill(struct snapraid_split_handle* split, data_off_t si * the disk. */ char spaceholder_path[PATH_MAX]; - data_off_t spaceholder_size = 256 * 1024 * 1024; - int spaceholder_f; pathprint(spaceholder_path, sizeof(spaceholder_path), "%s%s", split->path, ".spaceholder"); - spaceholder_f = open(spaceholder_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0600); - if (spaceholder_f == -1) { - log_fatal("Failed to create space holder file '%s'.\n", spaceholder_path); - return -1; - } + if (!skip_space_holder) { + data_off_t spaceholder_size = 256 * 1024 * 1024; + int spaceholder_f; - /* note that in Windows ftruncate is really allocating space */ - if (ftruncate(spaceholder_f, spaceholder_size) != 0) { - log_fatal("WARNING Failed to resize the space holder file '%s' to %llu bytes.\n", spaceholder_path, spaceholder_size); - log_fatal("Assuming that no more space is available.\n"); - close(spaceholder_f); - remove(spaceholder_path); - return 0; - } + spaceholder_f = open(spaceholder_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0600); + if (spaceholder_f == -1) { + log_fatal("Failed to create space holder file '%s'.\n", spaceholder_path); + return -1; + } - if (fsync(spaceholder_f) != 0) { - log_fatal("Failed to sync the space holder file '%s'.\n", spaceholder_path); - close(spaceholder_f); - remove(spaceholder_path); - return -1; - } + /* note that in Windows ftruncate is really allocating space */ + if (ftruncate(spaceholder_f, spaceholder_size) != 0) { + log_fatal("WARNING Failed to resize the space holder file '%s' to %llu bytes.\n", spaceholder_path, spaceholder_size); + log_fatal("Assuming that no more space is available.\n"); + close(spaceholder_f); + remove(spaceholder_path); + return 0; + } - if (close(spaceholder_f) != 0) { - log_fatal("Failed to close the space holder file '%s'.\n", spaceholder_path); - remove(spaceholder_path); - return -1; + if (fsync(spaceholder_f) != 0) { + log_fatal("Failed to sync the space holder file '%s'.\n", spaceholder_path); + close(spaceholder_f); + remove(spaceholder_path); + return -1; + } + + if (close(spaceholder_f) != 0) { + log_fatal("Failed to close the space holder file '%s'.\n", spaceholder_path); + remove(spaceholder_path); + return -1; + } } +#else + (void)skip_space_holder; #endif /* mask of bits used by the block size */ @@ -451,7 +456,7 @@ static int parity_handle_fill(struct snapraid_split_handle* split, data_off_t si return parity_handle_shrink(split, base); } -static int parity_handle_chsize(struct snapraid_split_handle* split, data_off_t size, uint32_t block_size, int skip_fallocate) +static int parity_handle_chsize(struct snapraid_split_handle* split, data_off_t size, uint32_t block_size, int skip_fallocate, int skip_space_holder) { int ret; int f_ret; @@ -459,7 +464,7 @@ static int parity_handle_chsize(struct snapraid_split_handle* split, data_off_t int f_dir; if (split->st.st_size < size) { - f_ret = parity_handle_fill(split, size, block_size, skip_fallocate); + f_ret = parity_handle_fill(split, size, block_size, skip_fallocate, skip_space_holder); f_errno = errno; f_dir = 1; } else if (split->st.st_size > size) { @@ -516,7 +521,7 @@ static int parity_split_is_fixed(struct snapraid_parity_handle* handle, unsigned return 1; } -int parity_chsize(struct snapraid_parity_handle* handle, struct snapraid_parity* parity, int* is_modified, data_off_t size, uint32_t block_size, int skip_fallocate) +int parity_chsize(struct snapraid_parity_handle* handle, struct snapraid_parity* parity, int* is_modified, data_off_t size, uint32_t block_size, int skip_fallocate, int skip_space_holder) { int ret; unsigned s; @@ -557,7 +562,7 @@ int parity_chsize(struct snapraid_parity_handle* handle, struct snapraid_parity* run = size; } - ret = parity_handle_chsize(split, run, block_size, skip_fallocate); + ret = parity_handle_chsize(split, run, block_size, skip_fallocate, skip_space_holder); if (ret != 0) return -1; diff --git a/cmdline/parity.h b/cmdline/parity.h index 6099416e..056362eb 100644 --- a/cmdline/parity.h +++ b/cmdline/parity.h @@ -94,7 +94,7 @@ int parity_create(struct snapraid_parity_handle* handle, const struct snapraid_p * Change the parity size. * \param out_size Return the size of the parity file. The out_size is set also on error to reflect a partial resize. */ -int parity_chsize(struct snapraid_parity_handle* handle, struct snapraid_parity* parity, int* is_modified, data_off_t size, uint32_t block_size, int skip_fallocate); +int parity_chsize(struct snapraid_parity_handle* handle, struct snapraid_parity* parity, int* is_modified, data_off_t size, uint32_t block_size, int skip_fallocate, int skip_space_holder); /** * Get the size of the parity. diff --git a/cmdline/snapraid.c b/cmdline/snapraid.c index 5cfe2803..01eb1bbd 100644 --- a/cmdline/snapraid.c +++ b/cmdline/snapraid.c @@ -292,6 +292,7 @@ void config(char* conf, size_t conf_size, const char* argv0) #define OPT_TEST_IO_ADVISE_DIRECT 299 #define OPT_TEST_PARITY_LIMIT 301 #define OPT_TEST_SKIP_CONTENT_WRITE 302 +#define OPT_TEST_SKIP_SPACE_HOLDER 303 #if HAVE_GETOPT_LONG struct option long_options[] = { @@ -453,6 +454,9 @@ struct option long_options[] = { /* Skip content write */ { "test-skip-content-write", 0, 0, OPT_TEST_SKIP_CONTENT_WRITE }, + /* Skip space holder file in parity disks */ + { "test-skip-space-holder", 0, 0, OPT_TEST_SKIP_SPACE_HOLDER }, + { 0, 0, 0, 0 } }; #endif @@ -879,6 +883,9 @@ int main(int argc, char* argv[]) case OPT_TEST_SKIP_CONTENT_WRITE : opt.skip_content_write = 1; break; + case OPT_TEST_SKIP_SPACE_HOLDER : + opt.skip_space_holder = 1; + break; default : /* LCOV_EXCL_START */ log_fatal("Unknown option '%c'\n", (char)c); diff --git a/cmdline/state.h b/cmdline/state.h index 188d0a22..6e190e82 100644 --- a/cmdline/state.h +++ b/cmdline/state.h @@ -89,6 +89,7 @@ struct snapraid_option { int skip_device; /**< Skip devices matching checks. */ int skip_sign; /**< Skip the sign check for content files. */ int skip_fallocate; /**< Skip the use of fallocate(). */ + int skip_space_holder; /**< Skip the use of spaceholder file. */ int file_mode; /**< File mode. Mask of ADVISE_* flags. */ int skip_lock; /**< Skip the lock file protection. */ int skip_self; /**< Skip the self-test. */ diff --git a/cmdline/sync.c b/cmdline/sync.c index 7d4b6c8c..bababec1 100644 --- a/cmdline/sync.c +++ b/cmdline/sync.c @@ -1514,7 +1514,7 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t /* change the size of the parity file, truncating or extending it */ /* from this point all the DELETED blocks after the end of the parity are invalid */ /* and they are automatically removed when we save the new content file */ - ret = parity_chsize(&parity_handle[l], &state->parity[l], &is_modified, size, state->block_size, state->opt.skip_fallocate); + ret = parity_chsize(&parity_handle[l], &state->parity[l], &is_modified, size, state->block_size, state->opt.skip_fallocate, state->opt.skip_space_holder); if (ret == -1) { /* LCOV_EXCL_START */ data_off_t out_size;