From aeb167bb16485afcf9e94a902ebd398e7c34b83e Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Thu, 4 Apr 2013 22:52:56 +0200 Subject: [PATCH] Adds --test-skip-sequential to disable the sequential hint for the disk cache. --- Makefile.am | 4 ++-- check.c | 12 ++++++------ dry.c | 6 +++--- handle.c | 45 ++++++++++++++++++++++++++++++--------------- handle.h | 4 ++-- import.c | 18 ++++++++++++------ parity.c | 49 ++++++++++++++++++++++++++----------------------- parity.h | 4 ++-- snapraid.c | 12 +++++++++++- state.c | 4 +++- state.h | 3 ++- sync.c | 6 +++--- util.c | 12 ++++++++++++ 13 files changed, 114 insertions(+), 65 deletions(-) diff --git a/Makefile.am b/Makefile.am index e66eb0be..031b7b18 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 diff --git a/check.c b/check.c index 7a93f269..21ae660b 100644 --- a/check.c +++ b/check.c @@ -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 */ diff --git a/dry.c b/dry.c index c64306d6..2c1ecf1b 100644 --- a/dry.c +++ b/dry.c @@ -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 */ diff --git a/handle.c b/handle.c index 0ba280d7..be319294 100644 --- a/handle.c +++ b/handle.c @@ -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 diff --git a/handle.h b/handle.h index 006d015e..d39120d3 100644 --- a/handle.h +++ b/handle.h @@ -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. diff --git a/import.c b/import.c index 644d418f..c35c8570 100644 --- a/import.c +++ b/import.c @@ -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 diff --git a/parity.c b/parity.c index 55c3781a..7c234159 100644 --- a/parity.c +++ b/parity.c @@ -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 diff --git a/parity.h b/parity.h index 6a940752..4f7176aa 100644 --- a/parity.h +++ b/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 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. diff --git a/snapraid.c b/snapraid.c index 74d94bea..6ae9fe76 100644 --- a/snapraid.c +++ b/snapraid.c @@ -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); diff --git a/state.c b/state.c index ebeecb97..5c143167 100644 --- a/state.c +++ b/state.c @@ -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) { diff --git a/state.h b/state.h index 831e6ca8..a751b863 100644 --- a/state.h +++ b/state.h @@ -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. diff --git a/sync.c b/sync.c index 11228c72..e045be36 100644 --- a/sync.c +++ b/sync.c @@ -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); diff --git a/util.c b/util.c index 8c608bf8..4c05bec9 100644 --- a/util.c +++ b/util.c @@ -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;