Adds --test-skip-sequential to disable the sequential hint for the disk cache.

This commit is contained in:
Andrea Mazzoleni 2013-04-04 22:52:56 +02:00
parent a85aa08276
commit aeb167bb16
13 changed files with 114 additions and 65 deletions

View file

@ -133,8 +133,8 @@ endif
ln test/disk3/file_hardlink1 test/disk3/file_hardlink3
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -v -c $(srcdir)/test-raid5.conf diff
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -v -c $(srcdir)/test-raid5.conf dup
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -v -c $(srcdir)/test-raid5.conf sync
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf check
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-skip-fallocate -v -c $(srcdir)/test-raid5.conf sync
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self --test-skip-sequential -c $(srcdir)/test-raid5.conf check
if HAVE_SYMLINK
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-self -c $(srcdir)/test-raid5.conf pool
endif

12
check.c
View file

@ -605,7 +605,7 @@ static int state_check_process(struct snapraid_state* state, int check, int fix,
/* 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));
ret = handle_create(&handle[j], block_file_get(block), state->skip_sequential);
if (ret == -1) {
if (errno == EACCES) {
fprintf(stderr, "WARNING! Please give write permission to the file.\n");
@ -629,7 +629,7 @@ static int state_check_process(struct snapraid_state* state, int check, int fix,
}
} else {
/* if checking or hashing, open the file only for reading */
ret = handle_open(&handle[j], block_file_get(block), stdlog);
ret = handle_open(&handle[j], block_file_get(block), stdlog, state->skip_sequential);
if (ret == -1) {
/* save the failed block for the check/fix */
failed[failed_count].is_bad = 1;
@ -1498,7 +1498,7 @@ void state_check(struct snapraid_state* state, int check, int fix, block_off_t b
/* if fixing, create the file and open for writing */
/* if it fails, we cannot continue */
parity_ptr = &parity;
ret = parity_create(parity_ptr, state->parity, &out_size);
ret = parity_create(parity_ptr, state->parity, &out_size, state->skip_sequential);
if (ret == -1) {
fprintf(stderr, "WARNING! Without an accessible Parity file, it isn't possible to fix any error.\n");
exit(EXIT_FAILURE);
@ -1512,7 +1512,7 @@ void state_check(struct snapraid_state* state, int check, int fix, block_off_t b
if (state->level >= 2) {
qarity_ptr = &qarity;
ret = parity_create(qarity_ptr, state->qarity, &out_size);
ret = parity_create(qarity_ptr, state->qarity, &out_size, state->skip_sequential);
if (ret == -1) {
fprintf(stderr, "WARNING! Without an accessible Q-Parity file, it isn't possible to fix any error.\n");
exit(EXIT_FAILURE);
@ -1530,7 +1530,7 @@ void state_check(struct snapraid_state* state, int check, int fix, block_off_t b
/* if checking, open the file for reading */
/* it may fail if the file doesn't exist, in this case we continue to check the files */
parity_ptr = &parity;
ret = parity_open(parity_ptr, state->parity);
ret = parity_open(parity_ptr, state->parity, state->skip_sequential);
if (ret == -1) {
printf("No accessible Parity file, only files will be checked.\n");
/* continue anyway */
@ -1539,7 +1539,7 @@ void state_check(struct snapraid_state* state, int check, int fix, block_off_t b
if (state->level >= 2) {
qarity_ptr = &qarity;
ret = parity_open(qarity_ptr, state->qarity);
ret = parity_open(qarity_ptr, state->qarity, state->skip_sequential);
if (ret == -1) {
printf("No accessible Q-Parity file, only files will be checked.\n");
/* continue anyway */

6
dry.c
View file

@ -74,7 +74,7 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit
}
/* open the file for reading */
ret = handle_open(&handle[j], block_file_get(block), stdlog);
ret = handle_open(&handle[j], block_file_get(block), stdlog, state->skip_sequential);
if (ret == -1) {
fprintf(stdlog, "error:%u:%s:%s: Open error at position %u\n", i, handle[j].disk->name, block_file_get(block)->sub, block_file_pos(block));
++error;
@ -174,7 +174,7 @@ void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t
/* open the file for reading */
/* it may fail if the file doesn't exist, in this case we continue to dry the files */
parity_ptr = &parity;
ret = parity_open(parity_ptr, state->parity);
ret = parity_open(parity_ptr, state->parity, state->skip_sequential);
if (ret == -1) {
printf("No accessible Parity file.\n");
/* continue anyway */
@ -183,7 +183,7 @@ void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t
if (state->level >= 2) {
qarity_ptr = &qarity;
ret = parity_open(qarity_ptr, state->qarity);
ret = parity_open(qarity_ptr, state->qarity, state->skip_sequential);
if (ret == -1) {
printf("No accessible Q-Parity file.\n");
/* continue anyway */

View file

@ -24,9 +24,10 @@
/****************************************************************************/
/* handle */
int handle_create(struct snapraid_handle* handle, struct snapraid_file* file)
int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, int skip_sequential)
{
int ret;
int flags;
/* if it's the same file, and already opened, nothing to do */
if (handle->file == file && handle->f != -1) {
@ -43,12 +44,18 @@ int handle_create(struct snapraid_handle* handle, struct snapraid_file* file)
/* open for read write */
/* O_SEQUENTIAL: opening in sequential mode in Windows */
/* O_NOFOLLOW: do not follow links to ensure to open the real file */
handle->f = open(handle->path, O_RDWR | O_CREAT | O_BINARY | O_SEQUENTIAL | O_NOFOLLOW, 0600);
flags = O_RDWR | O_CREAT | O_BINARY | O_NOFOLLOW;
if (!skip_sequential)
flags |= O_SEQUENTIAL;
handle->f = open(handle->path, flags, 0600);
/* if failed for missing permission */
if (handle->f == -1 && errno == EACCES) {
/* retry without requesting write permission */
handle->f = open(handle->path, O_RDONLY | O_BINARY | O_SEQUENTIAL | O_NOFOLLOW);
flags = O_RDONLY | O_BINARY | O_NOFOLLOW;
if (!skip_sequential)
flags |= O_SEQUENTIAL;
handle->f = open(handle->path, flags);
}
if (handle->f == -1) {
@ -93,11 +100,13 @@ int handle_create(struct snapraid_handle* handle, struct snapraid_file* file)
}
#if HAVE_POSIX_FADVISE
/* advise sequential access */
ret = posix_fadvise(handle->f, 0, 0, POSIX_FADV_SEQUENTIAL);
if (ret != 0) {
fprintf(stderr, "Error advising file '%s'. %s.\n", handle->path, strerror(ret));
return -1;
if (!skip_sequential) {
/* advise sequential access */
ret = posix_fadvise(handle->f, 0, 0, POSIX_FADV_SEQUENTIAL);
if (ret != 0) {
fprintf(stderr, "Error advising file '%s'. %s.\n", handle->path, strerror(ret));
return -1;
}
}
#endif
@ -109,9 +118,10 @@ int handle_create(struct snapraid_handle* handle, struct snapraid_file* file)
return 0;
}
int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, FILE* out)
int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, FILE* out, int skip_sequential)
{
int ret;
int flags;
/* if already opened, nothing to do */
if (handle->file == file && handle->f != -1) {
@ -124,7 +134,10 @@ int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, FILE
/* O_SEQUENTIAL: opening in sequential mode in Windows */
/* O_NOFOLLOW: do not follow links to ensure to open the real file */
/* O_NOATIME: do not change access time */
handle->f = open_noatime(handle->path, O_RDONLY | O_BINARY | O_SEQUENTIAL | O_NOFOLLOW);
flags = O_RDONLY | O_BINARY | O_NOFOLLOW;
if (!skip_sequential)
flags |= O_SEQUENTIAL;
handle->f = open_noatime(handle->path, flags);
if (handle->f == -1) {
/* invalidate for error */
handle->file = 0;
@ -149,11 +162,13 @@ int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, FILE
handle->valid_size = handle->st.st_size;
#if HAVE_POSIX_FADVISE
/* advise sequential access */
ret = posix_fadvise(handle->f, 0, 0, POSIX_FADV_SEQUENTIAL);
if (ret != 0) {
fprintf(out, "Error advising file '%s'. %s.\n", handle->path, strerror(ret));
return -1;
if (!skip_sequential) {
/* advise sequential access */
ret = posix_fadvise(handle->f, 0, 0, POSIX_FADV_SEQUENTIAL);
if (ret != 0) {
fprintf(out, "Error advising file '%s'. %s.\n", handle->path, strerror(ret));
return -1;
}
}
#endif

View file

@ -41,13 +41,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 handle_create(struct snapraid_handle* handle, struct snapraid_file* file, int skip_sequential);
/**
* Opens a file.
* The file is opened for reading.
*/
int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, FILE* out);
int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, FILE* out, int skip_sequential);
/**
* Closes a file.

View file

@ -48,6 +48,7 @@ static void import_file(struct snapraid_state* state, const char* path, uint64_t
void* buffer;
int ret;
int f;
int flags;
unsigned block_size = state->block_size;
unsigned hash = state->hash;
@ -61,18 +62,23 @@ static void import_file(struct snapraid_state* state, const char* path, uint64_t
/* open for read */
/* O_SEQUENTIAL: opening in sequential mode in Windows */
f = open(path, O_RDONLY | O_BINARY | O_SEQUENTIAL);
flags = O_RDONLY | O_BINARY;
if (!state->skip_sequential)
flags |= O_SEQUENTIAL;
f = open(path, flags);
if (f == -1) {
fprintf(stderr, "Error opening file '%s'. %s.\n", path, strerror(errno));
exit(EXIT_FAILURE);
}
#if HAVE_POSIX_FADVISE
/* advise sequential access */
ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL);
if (ret != 0) {
fprintf(stderr, "Error advising file '%s'. %s.\n", path, strerror(ret));
exit(EXIT_FAILURE);
if (!state->skip_sequential) {
/* advise sequential access */
ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL);
if (ret != 0) {
fprintf(stderr, "Error advising file '%s'. %s.\n", path, strerror(ret));
exit(EXIT_FAILURE);
}
}
#endif

View file

@ -90,15 +90,19 @@ 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 parity_create(struct snapraid_parity* parity, const char* path, data_off_t* out_size, int skip_sequential)
{
int ret;
int flags;
pathcpy(parity->path, sizeof(parity->path), path);
/* opening in sequential mode in Windows */
/* O_SEQUENTIAL: opening in sequential mode in Windows */
parity->f = open(parity->path, O_RDWR | O_CREAT | O_BINARY | O_SEQUENTIAL, 0600);
flags = O_RDWR | O_CREAT | O_BINARY | O_SEQUENTIAL;
if (!skip_sequential)
flags |= O_SEQUENTIAL;
parity->f = open(parity->path, flags, 0600);
if (parity->f == -1) {
fprintf(stderr, "Error opening parity file '%s'. %s.\n", parity->path, strerror(errno));
return -1;
@ -112,11 +116,13 @@ int parity_create(struct snapraid_parity* parity, const char* path, data_off_t*
}
#if HAVE_POSIX_FADVISE
/* advise sequential access */
ret = posix_fadvise(parity->f, 0, 0, POSIX_FADV_SEQUENTIAL);
if (ret != 0) {
fprintf(stderr, "Error advising parity file '%s'. %s.\n", parity->path, strerror(ret));
goto bail;
if (!skip_sequential) {
/* advise sequential access */
ret = posix_fadvise(parity->f, 0, 0, POSIX_FADV_SEQUENTIAL);
if (ret != 0) {
fprintf(stderr, "Error advising parity file '%s'. %s.\n", parity->path, strerror(ret));
goto bail;
}
}
#endif
@ -221,15 +227,6 @@ int parity_chsize(struct snapraid_parity* parity, data_off_t size, data_off_t* o
parity->valid_size = size;
}
#if HAVE_POSIX_FADVISE
/* advise sequential access */
ret = posix_fadvise(parity->f, 0, 0, POSIX_FADV_SEQUENTIAL);
if (ret != 0) {
fprintf(stderr, "Error advising parity file '%s'. %s.\n", parity->path, strerror(ret));
goto bail;
}
#endif
return 0;
bail:
@ -237,16 +234,20 @@ bail:
return -1;
}
int parity_open(struct snapraid_parity* parity, const char* path)
int parity_open(struct snapraid_parity* parity, const char* path, int skip_sequential)
{
int ret;
int flags;
pathcpy(parity->path, sizeof(parity->path), path);
/* open for read */
/* O_SEQUENTIAL: opening in sequential mode in Windows */
/* O_NOATIME: do not change access time */
parity->f = open_noatime(parity->path, O_RDONLY | O_BINARY | O_SEQUENTIAL);
flags = O_RDONLY | O_BINARY;
if (!skip_sequential)
flags |= O_SEQUENTIAL;
parity->f = open_noatime(parity->path, flags);
if (parity->f == -1) {
fprintf(stderr, "Error opening parity file '%s'. %s.\n", parity->path, strerror(errno));
return -1;
@ -263,11 +264,13 @@ int parity_open(struct snapraid_parity* parity, const char* path)
parity->valid_size = parity->st.st_size;
#if HAVE_POSIX_FADVISE
/* advise sequential access */
ret = posix_fadvise(parity->f, 0, 0, POSIX_FADV_SEQUENTIAL);
if (ret != 0) {
fprintf(stderr, "Error advising parity file '%s'. %s.\n", parity->path, strerror(ret));
goto bail;
if (!skip_sequential) {
/* advise sequential access */
ret = posix_fadvise(parity->f, 0, 0, POSIX_FADV_SEQUENTIAL);
if (ret != 0) {
fprintf(stderr, "Error advising parity file '%s'. %s.\n", parity->path, strerror(ret));
goto bail;
}
}
#endif

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 parity_create(struct snapraid_parity* parity, const char* path, data_off_t* out_size, int skip_sequential);
/**
* 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 parity_open(struct snapraid_parity* parity, const char* path, int skip_sequential);
/**
* Flushes the parity file in the disk.

View file

@ -81,6 +81,7 @@ void usage(void)
#define OPT_TEST_SKIP_SIGN 260
#define OPT_TEST_SKIP_FALLOCATE 261
#define OPT_TEST_SKIP_DEVICE 262
#define OPT_TEST_SKIP_SEQUENTIAL 263
#if HAVE_GETOPT_LONG
@ -124,8 +125,12 @@ struct option long_options[] = {
/* Skip the fallocate() when growing the parity files */
{ "test-skip-fallocate", 0, 0, OPT_TEST_SKIP_FALLOCATE },
/* Skip the sequential hint when reading files */
{ "test-skip-sequential", 0, 0, OPT_TEST_SKIP_SEQUENTIAL },
/* Skip the device check */
{ "test-skip-device", 0, 0, OPT_TEST_SKIP_DEVICE },
{ 0, 0, 0, 0 }
};
#endif
@ -167,6 +172,7 @@ int main(int argc, char* argv[])
int test_skip_self;
int test_skip_sign;
int test_skip_fallocate;
int test_skip_sequential;
int test_skip_device;
const char* conf;
struct snapraid_state state;
@ -199,6 +205,7 @@ int main(int argc, char* argv[])
test_skip_self = 0;
test_skip_sign = 0;
test_skip_fallocate = 0;
test_skip_sequential = 0;
test_skip_device = 0;
blockstart = 0;
blockcount = 0;
@ -315,6 +322,9 @@ int main(int argc, char* argv[])
case OPT_TEST_SKIP_FALLOCATE :
test_skip_fallocate = 1;
break;
case OPT_TEST_SKIP_SEQUENTIAL :
test_skip_sequential = 1;
break;
case OPT_TEST_SKIP_DEVICE :
test_skip_device = 1;
break;
@ -409,7 +419,7 @@ int main(int argc, char* argv[])
state_init(&state);
state_config(&state, conf, command, verbose, gui, force_zero, force_empty, force_uuid, find_by_name, test_expect_unrecoverable, test_expect_recoverable, test_skip_sign, test_skip_fallocate, test_skip_device);
state_config(&state, conf, command, verbose, gui, force_zero, force_empty, force_uuid, find_by_name, test_expect_unrecoverable, test_expect_recoverable, test_skip_sign, test_skip_fallocate, test_skip_sequential, test_skip_device);
if (import != 0) {
state_import(&state, import);

View file

@ -35,6 +35,7 @@ void state_init(struct snapraid_state* state)
state->expect_recoverable = 0;
state->skip_sign = 0;
state->skip_fallocate = 0;
state->skip_sequential = 0;
state->need_write = 0;
state->block_size = 256 * 1024; /* default 256 KiB */
state->parity[0] = 0;
@ -219,7 +220,7 @@ static void state_config_check(struct snapraid_state* state, const char* path, i
}
}
void state_config(struct snapraid_state* state, const char* path, const char* command, int verbose, int gui, int force_zero, int force_empty, int force_uuid, int find_by_name, int expect_unrecoverable, int expect_recoverable, int skip_sign, int skip_fallocate, int skip_device)
void state_config(struct snapraid_state* state, const char* path, const char* command, int verbose, int gui, int force_zero, int force_empty, int force_uuid, int find_by_name, int expect_unrecoverable, int expect_recoverable, int skip_sign, int skip_fallocate, int skip_sequential, int skip_device)
{
STREAM* f;
unsigned line;
@ -236,6 +237,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
state->expect_recoverable = expect_recoverable;
state->skip_sign = skip_sign;
state->skip_fallocate = skip_fallocate;
state->skip_sequential = skip_sequential;
state->command = command;
if (state->gui) {

View file

@ -39,6 +39,7 @@ struct snapraid_state {
int expect_recoverable; /**< Expect presence of recoverable error in checking. */
int skip_sign; /**< Skip the sign check for content files. */
int skip_fallocate; /**< Skip the use of fallocate(). */
int skip_sequential; /**< Skip sequential hint. */
int need_write; /**< If the state is changed. */
uint32_t block_size; /**< Block size in bytes. */
char parity[PATH_MAX]; /**< Path of the parity file. */
@ -76,7 +77,7 @@ void state_done(struct snapraid_state* state);
/**
* Reads the configuration file.
*/
void state_config(struct snapraid_state* state, const char* path, const char* command, int verbose, int gui, int force_zero, int force_empty, int force_uuid, int find_by_name, int expect_unrecoverable, int expect_recoverable, int skip_sign, int skip_fallocate, int skip_device);
void state_config(struct snapraid_state* state, const char* path, const char* command, int verbose, int gui, int force_zero, int force_empty, int force_uuid, int find_by_name, int expect_unrecoverable, int expect_recoverable, int skip_sign, int skip_fallocate, int skip_sequential, int skip_device);
/**
* Reads the state.

6
sync.c
View file

@ -185,7 +185,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
}
}
ret = handle_open(&handle[j], block_file_get(block), stderr);
ret = handle_open(&handle[j], block_file_get(block), stderr, state->skip_sequential);
if (ret == -1) {
if (errno == ENOENT) {
fprintf(stderr, "Missing file '%s'.\n", handle[j].path);
@ -410,7 +410,7 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
/* create the file and open for writing */
parity_ptr = &parity;
ret = parity_create(parity_ptr, state->parity, &out_size);
ret = parity_create(parity_ptr, state->parity, &out_size, state->skip_sequential);
if (ret == -1) {
fprintf(stderr, "WARNING! Without an accessible Parity file, it isn't possible to sync.\n");
exit(EXIT_FAILURE);
@ -431,7 +431,7 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
if (state->level >= 2) {
qarity_ptr = &qarity;
ret = parity_create(qarity_ptr, state->qarity, &out_size);
ret = parity_create(qarity_ptr, state->qarity, &out_size, state->skip_sequential);
if (ret == -1) {
fprintf(stderr, "WARNING! Without an accessible Q-Parity file, it isn't possible to sync.\n");
exit(EXIT_FAILURE);

12
util.c
View file

@ -49,6 +49,7 @@ static unsigned strdecset[256] =
STREAM* sopen_read(const char* file)
{
int ret;
STREAM* s = malloc_nofail(sizeof(STREAM));
s->handle_size = 1;
@ -62,6 +63,17 @@ STREAM* sopen_read(const char* file)
return 0;
}
#if HAVE_POSIX_FADVISE
/* advise sequential access */
ret = posix_fadvise(s->handle[0].f, 0, 0, POSIX_FADV_SEQUENTIAL);
if (ret != 0) {
close(s->handle[0].f);
free(s->handle);
free(s);
return 0;
}
#endif
s->buffer = malloc_nofail(STREAM_SIZE);
s->pos = s->buffer;
s->end = s->buffer;