From d1d4abaf31c81d4cfa3d5ad2be9a231a9f1b29ad Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Thu, 4 Sep 2014 22:46:51 +0200 Subject: [PATCH] Adds a new file_mode setting to control the access flags. --- cmdline/check.c | 8 ++++---- cmdline/dry.c | 4 ++-- cmdline/handle.c | 20 +++++++++++++------- cmdline/handle.h | 4 ++-- cmdline/import.c | 4 ++-- cmdline/parity.c | 17 +++++++++++------ cmdline/parity.h | 4 ++-- cmdline/state.c | 8 +++++++- cmdline/state.h | 7 +++++++ cmdline/sync.c | 6 +++--- 10 files changed, 53 insertions(+), 29 deletions(-) diff --git a/cmdline/check.c b/cmdline/check.c index 1a332059..deb364bc 100644 --- a/cmdline/check.c +++ b/cmdline/check.c @@ -773,7 +773,7 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna /* if fixing, and the file is not excluded, we must open for writing */ if (fix && !file_flag_has(block_file_get(block), FILE_IS_EXCLUDED)) { /* if fixing, create the file, open for writing and resize if required */ - ret = handle_create(&handle[j], block_file_get(block), state->opt.skip_sequential); + ret = handle_create(&handle[j], block_file_get(block), state->file_mode); if (ret == -1) { /* LCOV_EXCL_START */ if (errno == EACCES) { @@ -806,7 +806,7 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna } } else { /* if checking or hashing, open the file only for reading */ - ret = handle_open(&handle[j], block_file_get(block), state->opt.skip_sequential, stdlog); + ret = handle_open(&handle[j], block_file_get(block), state->file_mode, stdlog); if (ret == -1) { /* save the failed block for the check/fix */ failed[failed_count].is_bad = 1; @@ -1802,7 +1802,7 @@ int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, b /* if it fails, we cannot continue */ for(l=0;llevel;++l) { parity_ptr[l] = &parity[l]; - ret = parity_create(parity_ptr[l], state->parity_path[l], &out_size, state->opt.skip_sequential); + ret = parity_create(parity_ptr[l], state->parity_path[l], &out_size, state->file_mode); if (ret == -1) { /* LCOV_EXCL_START */ fprintf(stderr, "WARNING! Without an accessible %s file, it isn't possible to fix any error.\n", lev_name(l)); @@ -1823,7 +1823,7 @@ int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, b /* it may fail if the file doesn't exist, in this case we continue to check the files */ for(l=0;llevel;++l) { parity_ptr[l] = &parity[l]; - ret = parity_open(parity_ptr[l], state->parity_path[l], state->opt.skip_sequential); + ret = parity_open(parity_ptr[l], state->parity_path[l], state->file_mode); if (ret == -1) { printf("No accessible %s file, only files will be checked.\n", lev_name(l)); /* continue anyway */ diff --git a/cmdline/dry.c b/cmdline/dry.c index 6c7dadc5..5c314fb8 100644 --- a/cmdline/dry.c +++ b/cmdline/dry.c @@ -80,7 +80,7 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit } /* open the file only for reading */ - ret = handle_open(&handle[j], block_file_get(block), state->opt.skip_sequential, stdlog); + ret = handle_open(&handle[j], block_file_get(block), state->file_mode, stdlog); if (ret == -1) { /* LCOV_EXCL_START */ fprintf(stderr, "DANGER! Unexpected open error in a data disk, it isn't possible to dry.\n"); @@ -182,7 +182,7 @@ void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t /* it may fail if the file doesn't exist, in this case we continue to dry the files */ for(l=0;llevel;++l) { parity_ptr[l] = &parity[l]; - ret = parity_open(parity_ptr[l], state->parity_path[l], state->opt.skip_sequential); + ret = parity_open(parity_ptr[l], state->parity_path[l], state->file_mode); if (ret == -1) { printf("No accessible %s file.\n", lev_name(l)); /* continue anyway */ diff --git a/cmdline/handle.c b/cmdline/handle.c index 8d0df88a..94882ae9 100644 --- a/cmdline/handle.c +++ b/cmdline/handle.c @@ -24,7 +24,7 @@ /****************************************************************************/ /* handle */ -int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, int skip_sequential) +int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, int mode) { int ret; int flags; @@ -51,9 +51,12 @@ int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, in /* O_BINARY: open as binary file (Windows only) */ /* O_NOFOLLOW: do not follow links to ensure to open the real file */ /* O_SEQUENTIAL: improve performance for sequential access (Windows only) */ + /* O_DIRECT: required by libaio */ flags = O_BINARY | O_NOFOLLOW; - if (!skip_sequential) + if ((mode & MODE_SEQUENTIAL) != 0) flags |= O_SEQUENTIAL; + if ((mode & MODE_DIRECT) != 0) + flags |= O_DIRECT; /* open for read write */ handle->f = open(handle->path, flags | O_RDWR); @@ -135,8 +138,8 @@ int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, in } #if HAVE_POSIX_FADVISE - if (!skip_sequential) { - /* advise sequential access */ + if ((mode & MODE_SEQUENTIAL) != 0) { + /* advise sequential access */ ret = posix_fadvise(handle->f, 0, 0, POSIX_FADV_SEQUENTIAL); if (ret != 0) { /* LCOV_EXCL_START */ @@ -150,7 +153,7 @@ int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, in return 0; } -int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int skip_sequential, FILE* out) +int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int mode, FILE* out) { int ret; int flags; @@ -170,9 +173,12 @@ int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int /* O_BINARY: open as binary file (Windows only) */ /* O_NOFOLLOW: do not follow links to ensure to open the real file */ /* O_SEQUENTIAL: improve performance for sequential access (Windows only) */ + /* O_DIRECT: required by libaio */ flags = O_BINARY | O_NOFOLLOW; - if (!skip_sequential) + if ((mode & MODE_SEQUENTIAL) != 0) flags |= O_SEQUENTIAL; + if ((mode & MODE_DIRECT) != 0) + flags |= O_DIRECT; /* open for read */ handle->f = open_noatime(handle->path, flags | O_RDONLY); @@ -202,7 +208,7 @@ int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int handle->valid_size = handle->st.st_size; #if HAVE_POSIX_FADVISE - if (!skip_sequential) { + if ((mode & MODE_SEQUENTIAL) != 0) { /* advise sequential access */ ret = posix_fadvise(handle->f, 0, 0, POSIX_FADV_SEQUENTIAL); if (ret != 0) { diff --git a/cmdline/handle.h b/cmdline/handle.h index 7205d641..48279489 100644 --- a/cmdline/handle.h +++ b/cmdline/handle.h @@ -44,13 +44,13 @@ struct snapraid_handle { * If the file cannot be opened for write access, it's opened with read-only access. * The read-only access works only if the file has already the correct size and doesn't need to be modified. */ -int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, int skip_sequential); +int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, int mode); /** * Opens a file. * The file is opened for reading. */ -int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int skip_sequential, FILE* out); +int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int mode, FILE* out); /** * Closes a file. diff --git a/cmdline/import.c b/cmdline/import.c index 56b3d198..308569eb 100644 --- a/cmdline/import.c +++ b/cmdline/import.c @@ -70,7 +70,7 @@ static void import_file(struct snapraid_state* state, const char* path, uint64_t /* open for read */ /* O_SEQUENTIAL: opening in sequential mode in Windows */ flags = O_RDONLY | O_BINARY; - if (!state->opt.skip_sequential) + if ((state->file_mode & MODE_SEQUENTIAL) != 0) flags |= O_SEQUENTIAL; f = open(path, flags); if (f == -1) { @@ -81,7 +81,7 @@ static void import_file(struct snapraid_state* state, const char* path, uint64_t } #if HAVE_POSIX_FADVISE - if (!state->opt.skip_sequential) { + if ((state->file_mode & MODE_SEQUENTIAL) != 0) { /* advise sequential access */ ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL); if (ret != 0) { diff --git a/cmdline/parity.c b/cmdline/parity.c index 5d403892..63afea66 100644 --- a/cmdline/parity.c +++ b/cmdline/parity.c @@ -20,6 +20,7 @@ #include "elem.h" #include "state.h" #include "parity.h" +#include "handle.h" /****************************************************************************/ /* parity */ @@ -88,7 +89,7 @@ void parity_overflow(struct snapraid_state* state, data_off_t size) } } -int parity_create(struct snapraid_parity* parity, const char* path, data_off_t* out_size, int skip_sequential) +int parity_create(struct snapraid_parity* parity, const char* path, data_off_t* out_size, int mode) { int ret; int flags; @@ -98,8 +99,10 @@ int parity_create(struct snapraid_parity* parity, const char* path, data_off_t* /* opening in sequential mode in Windows */ /* O_SEQUENTIAL: opening in sequential mode in Windows */ flags = O_RDWR | O_CREAT | O_BINARY | O_SEQUENTIAL; - if (!skip_sequential) + if ((mode & MODE_SEQUENTIAL) != 0) flags |= O_SEQUENTIAL; + if ((mode & MODE_DIRECT) != 0) + flags |= O_DIRECT; parity->f = open(parity->path, flags, 0600); if (parity->f == -1) { /* LCOV_EXCL_START */ @@ -118,7 +121,7 @@ int parity_create(struct snapraid_parity* parity, const char* path, data_off_t* } #if HAVE_POSIX_FADVISE - if (!skip_sequential) { + if ((mode & MODE_SEQUENTIAL) != 0) { /* advise sequential access */ ret = posix_fadvise(parity->f, 0, 0, POSIX_FADV_SEQUENTIAL); if (ret != 0) { @@ -262,7 +265,7 @@ bail: /* LCOV_EXCL_STOP */ } -int parity_open(struct snapraid_parity* parity, const char* path, int skip_sequential) +int parity_open(struct snapraid_parity* parity, const char* path, int mode) { int ret; int flags; @@ -273,8 +276,10 @@ int parity_open(struct snapraid_parity* parity, const char* path, int skip_seque /* O_SEQUENTIAL: opening in sequential mode in Windows */ /* O_NOATIME: do not change access time */ flags = O_RDONLY | O_BINARY; - if (!skip_sequential) + if ((mode & MODE_SEQUENTIAL) != 0) flags |= O_SEQUENTIAL; + if ((mode & MODE_DIRECT) != 0) + flags |= O_DIRECT; parity->f = open_noatime(parity->path, flags); if (parity->f == -1) { fprintf(stderr, "Error opening parity file '%s'. %s.\n", parity->path, strerror(errno)); @@ -294,7 +299,7 @@ int parity_open(struct snapraid_parity* parity, const char* path, int skip_seque parity->valid_size = parity->st.st_size; #if HAVE_POSIX_FADVISE - if (!skip_sequential) { + if ((mode & MODE_SEQUENTIAL) != 0) { /* advise sequential access */ ret = posix_fadvise(parity->f, 0, 0, POSIX_FADV_SEQUENTIAL); if (ret != 0) { diff --git a/cmdline/parity.h b/cmdline/parity.h index 4f7176aa..383d6cc3 100644 --- a/cmdline/parity.h +++ b/cmdline/parity.h @@ -42,7 +42,7 @@ void parity_overflow(struct snapraid_state* state, data_off_t size); * Creates the parity file. * \param out_size Return the size of the parity file. */ -int parity_create(struct snapraid_parity* parity, const char* path, data_off_t* out_size, int skip_sequential); +int parity_create(struct snapraid_parity* parity, const char* path, data_off_t* out_size, int mode); /** * Changes the parity size. @@ -53,7 +53,7 @@ int parity_chsize(struct snapraid_parity* parity, data_off_t size, data_off_t* o /** * Opens an already existing parity file. */ -int parity_open(struct snapraid_parity* parity, const char* path, int skip_sequential); +int parity_open(struct snapraid_parity* parity, const char* path, int mode); /** * Flushes the parity file in the disk. diff --git a/cmdline/state.c b/cmdline/state.c index 9a0fbecd..47abd3f4 100644 --- a/cmdline/state.c +++ b/cmdline/state.c @@ -81,6 +81,7 @@ void state_init(struct snapraid_state* state) state->checked_read = 0; state->block_size = 256 * 1024; /* default 256 KiB */ state->raid_mode = RAID_MODE_CAUCHY; + state->file_mode = MODE_SEQUENTIAL; for(l=0;lparity_path[l][0] = 0; state->parity_device[l] = 0; @@ -368,7 +369,12 @@ void state_config(struct snapraid_state* state, const char* path, const char* co /* if unsed, sort by physical order */ if (!state->opt.force_order) state->opt.force_order = SORT_PHYSICAL; - + + /* adjust file mode */ + if (state->opt.skip_sequential) + state->file_mode &= ~MODE_SEQUENTIAL; + + /* store current command */ state->command = command; fprintf(stdlog, "conf:%s\n", path); diff --git a/cmdline/state.h b/cmdline/state.h index 9b8ebf7e..38e872e9 100644 --- a/cmdline/state.h +++ b/cmdline/state.h @@ -41,6 +41,12 @@ const char* lev_config_name(unsigned level); /****************************************************************************/ /* state */ +/** + * File modes. + */ +#define MODE_SEQUENTIAL 1 +#define MODE_DIRECT 2 + /** * Global variable to identify if Ctrl+C is pressed. */ @@ -95,6 +101,7 @@ struct snapraid_state { int checked_read; /**< If the state was read and checked. */ uint32_t block_size; /**< Block size in bytes. */ unsigned raid_mode; /**< Raid mode to use. RAID_MODE_DEFAULT or RAID_MODE_ALTERNATE. */ + int file_mode; /**< File access mode. Combination of MODE_* flags. */ char parity_path[LEV_MAX][PATH_MAX]; /**< Path of the parity file. One for each parity. */ uint64_t parity_device[LEV_MAX]; /**< Device identifier of the parity. One for each parity. */ char share[PATH_MAX]; /**< Path of the share tree. If !=0 pool links are created in a different way. */ diff --git a/cmdline/sync.c b/cmdline/sync.c index 661fafd4..1192b3e1 100644 --- a/cmdline/sync.c +++ b/cmdline/sync.c @@ -138,7 +138,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta } } - ret = handle_open(&handle[j], block_file_get(block), state->opt.skip_sequential, stderr); + ret = handle_open(&handle[j], block_file_get(block), state->file_mode, stderr); if (ret == -1) { /* file we are processing for error reporting */ struct snapraid_file* file = block_file_get(block); @@ -562,7 +562,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari } } - ret = handle_open(&handle[j], block_file_get(block), state->opt.skip_sequential, stderr); + ret = handle_open(&handle[j], block_file_get(block), state->file_mode, stderr); if (ret == -1) { /* file we are processing for error reporting */ struct snapraid_file* file = block_file_get(block); @@ -1050,7 +1050,7 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t for(l=0;lparity_path[l], &out_size, state->opt.skip_sequential); + ret = parity_create(parity_ptr[l], state->parity_path[l], &out_size, state->file_mode); if (ret == -1) { /* LCOV_EXCL_START */ fprintf(stderr, "WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l));