Adds a new file_mode setting to control the access flags.

This commit is contained in:
Andrea Mazzoleni 2014-09-04 22:46:51 +02:00
parent 6d4d75ad0b
commit d1d4abaf31
10 changed files with 53 additions and 29 deletions

View file

@ -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;l<state->level;++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;l<state->level;++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 */

View file

@ -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;l<state->level;++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 */

View file

@ -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) {

View file

@ -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.

View file

@ -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) {

View file

@ -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) {

View file

@ -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.

View file

@ -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;l<LEV_MAX;++l) {
state->parity_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);

View file

@ -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. */

View file

@ -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;l<level;++l) {
/* create the file and open for writing */
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 sync.\n", lev_name(l));