mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-25 18:40:19 -04:00
Add new IO window advise modes
This commit is contained in:
parent
4298a238e9
commit
397c58c41e
5 changed files with 104 additions and 107 deletions
11
HISTORY
11
HISTORY
|
|
@ -15,13 +15,12 @@ SnapRAID HISTORY
|
|||
'\'.
|
||||
* Added test options for selecting the file advise mode to use:
|
||||
--test-io-advise-none for standard mode
|
||||
--test-io-advise-sequential advise sequential operations (Linux/Windows)
|
||||
--test-io-advise-flush flush data after every operation (Linux)
|
||||
--test-io-advise-sequential advise sequential access (Linux/Windows)
|
||||
--test-io-advise-flush flush cache after every operation (Linux)
|
||||
--test-io-advise-flush-window flush cache every 8 MB (Linux)
|
||||
--test-io-advise-discard discard cache after every operation (Linux)
|
||||
--test-io-advise-discard-2 discard cache every 2 MB (Linux)
|
||||
--test-io-advise-discard-8 discard cache every 8 MB (Linux)
|
||||
--test-io-advise-discard-32 discard cache every 32 MB (Linux)
|
||||
--test-io-advise-direct use direct mode (Linux/Windows)
|
||||
--test-io-advise-discard-window discard cache every 8 MB (Linux)
|
||||
--test-io-advise-direct use direct/unbuffered mode (Linux/Windows)
|
||||
* Fixed running in Windows platforms that miss the RtlGenRandom
|
||||
function.
|
||||
* Added a new 'hashsize' configuration option. It could be useful in
|
||||
|
|
|
|||
|
|
@ -439,8 +439,8 @@ endif
|
|||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-none -c $(PAR1) sync -F
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-sequential -c $(PAR1) sync -F
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-flush -c $(PAR1) sync -F
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-discard -c $(PAR1) sync -F
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-flush-window -c $(PAR1) sync -F
|
||||
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-discard-window -c $(PAR1) sync -F
|
||||
#### CHANGE LINKS ####
|
||||
# Use a different size ("22" instead of "1") to ensure to recognize the file different
|
||||
# even if it gets the same timestamp in case subsecond timestamp is no available
|
||||
|
|
|
|||
|
|
@ -285,11 +285,10 @@ void config(char* conf, size_t conf_size, const char* argv0)
|
|||
#define OPT_TEST_IO_ADVISE_NONE 293
|
||||
#define OPT_TEST_IO_ADVISE_SEQUENTIAL 294
|
||||
#define OPT_TEST_IO_ADVISE_FLUSH 295
|
||||
#define OPT_TEST_IO_ADVISE_DISCARD 296
|
||||
#define OPT_TEST_IO_ADVISE_DISCARD_2 297
|
||||
#define OPT_TEST_IO_ADVISE_DISCARD_8 298
|
||||
#define OPT_TEST_IO_ADVISE_DISCARD_32 299
|
||||
#define OPT_TEST_IO_ADVISE_DIRECT 300
|
||||
#define OPT_TEST_IO_ADVISE_FLUSH_WINDOW 296
|
||||
#define OPT_TEST_IO_ADVISE_DISCARD 297
|
||||
#define OPT_TEST_IO_ADVISE_DISCARD_WINDOW 298
|
||||
#define OPT_TEST_IO_ADVISE_DIRECT 299
|
||||
#define OPT_TEST_PARITY_LIMIT 301
|
||||
#define OPT_TEST_SKIP_CONTENT_WRITE 302
|
||||
|
||||
|
|
@ -434,17 +433,14 @@ struct option long_options[] = {
|
|||
/* Set the io advise to flush */
|
||||
{ "test-io-advise-flush", 0, 0, OPT_TEST_IO_ADVISE_FLUSH },
|
||||
|
||||
/* Set the io advise to flush window */
|
||||
{ "test-io-advise-flush-window", 0, 0, OPT_TEST_IO_ADVISE_FLUSH_WINDOW },
|
||||
|
||||
/* Set the io advise to discard */
|
||||
{ "test-io-advise-discard", 0, 0, OPT_TEST_IO_ADVISE_DISCARD },
|
||||
|
||||
/* Set the io advise to discard */
|
||||
{ "test-io-advise-discard-2", 0, 0, OPT_TEST_IO_ADVISE_DISCARD_2 },
|
||||
|
||||
/* Set the io advise to discard */
|
||||
{ "test-io-advise-discard-8", 0, 0, OPT_TEST_IO_ADVISE_DISCARD_8 },
|
||||
|
||||
/* Set the io advise to discard */
|
||||
{ "test-io-advise-discard-32", 0, 0, OPT_TEST_IO_ADVISE_DISCARD_32 },
|
||||
/* Set the io advise to discard window */
|
||||
{ "test-io-advise-discard-window", 0, 0, OPT_TEST_IO_ADVISE_DISCARD_WINDOW },
|
||||
|
||||
/* Set the io advise to direct */
|
||||
{ "test-io-advise-direct", 0, 0, OPT_TEST_IO_ADVISE_DIRECT },
|
||||
|
|
@ -860,17 +856,14 @@ int main(int argc, char* argv[])
|
|||
case OPT_TEST_IO_ADVISE_FLUSH :
|
||||
opt.file_mode = ADVISE_FLUSH;
|
||||
break;
|
||||
case OPT_TEST_IO_ADVISE_FLUSH_WINDOW :
|
||||
opt.file_mode = ADVISE_FLUSH_WINDOW;
|
||||
break;
|
||||
case OPT_TEST_IO_ADVISE_DISCARD :
|
||||
opt.file_mode = ADVISE_DISCARD;
|
||||
break;
|
||||
case OPT_TEST_IO_ADVISE_DISCARD_2 :
|
||||
opt.file_mode = ADVISE_DISCARD_2;
|
||||
break;
|
||||
case OPT_TEST_IO_ADVISE_DISCARD_8 :
|
||||
opt.file_mode = ADVISE_DISCARD_8;
|
||||
break;
|
||||
case OPT_TEST_IO_ADVISE_DISCARD_32 :
|
||||
opt.file_mode = ADVISE_DISCARD_32;
|
||||
case OPT_TEST_IO_ADVISE_DISCARD_WINDOW :
|
||||
opt.file_mode = ADVISE_DISCARD_WINDOW;
|
||||
break;
|
||||
case OPT_TEST_IO_ADVISE_DIRECT :
|
||||
opt.file_mode = ADVISE_DIRECT;
|
||||
|
|
|
|||
|
|
@ -895,10 +895,9 @@ int advise_flags(struct advise_struct* advise)
|
|||
|
||||
if (advise->mode == ADVISE_SEQUENTIAL
|
||||
|| advise->mode == ADVISE_FLUSH
|
||||
|| advise->mode == ADVISE_FLUSH_WINDOW
|
||||
|| advise->mode == ADVISE_DISCARD
|
||||
|| advise->mode == ADVISE_DISCARD_2
|
||||
|| advise->mode == ADVISE_DISCARD_8
|
||||
|| advise->mode == ADVISE_DISCARD_32
|
||||
|| advise->mode == ADVISE_DISCARD_WINDOW
|
||||
)
|
||||
flags |= O_SEQUENTIAL;
|
||||
|
||||
|
|
@ -918,10 +917,9 @@ int advise_open(struct advise_struct* advise, int f)
|
|||
#if HAVE_POSIX_FADVISE
|
||||
if (advise->mode == ADVISE_SEQUENTIAL
|
||||
|| advise->mode == ADVISE_FLUSH
|
||||
|| advise->mode == ADVISE_FLUSH_WINDOW
|
||||
|| advise->mode == ADVISE_DISCARD
|
||||
|| advise->mode == ADVISE_DISCARD_2
|
||||
|| advise->mode == ADVISE_DISCARD_8
|
||||
|| advise->mode == ADVISE_DISCARD_32
|
||||
|| advise->mode == ADVISE_DISCARD_WINDOW
|
||||
) {
|
||||
int ret;
|
||||
|
||||
|
|
@ -939,26 +937,15 @@ int advise_open(struct advise_struct* advise, int f)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int advise_write(struct advise_struct* advise, int f, size_t offset, size_t size)
|
||||
int advise_write(struct advise_struct* advise, int f, uint64_t offset, uint64_t size)
|
||||
{
|
||||
(void)advise;
|
||||
uint64_t handle_offset;
|
||||
uint64_t handle_size;
|
||||
|
||||
(void)f;
|
||||
(void)offset;
|
||||
(void)size;
|
||||
|
||||
#if HAVE_SYNC_FILE_RANGE
|
||||
if (advise->mode == ADVISE_FLUSH) {
|
||||
int ret;
|
||||
|
||||
/* start writing immediately */
|
||||
ret = sync_file_range(f, offset, size, SYNC_FILE_RANGE_WRITE);
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
handle_offset = 0;
|
||||
handle_size = 0;
|
||||
|
||||
/*
|
||||
* Follow Linus recommendations about fast writes.
|
||||
|
|
@ -1013,54 +1000,74 @@ int advise_write(struct advise_struct* advise, int f, size_t offset, size_t size
|
|||
* ---
|
||||
*/
|
||||
|
||||
#if HAVE_SYNC_FILE_RANGE && HAVE_POSIX_FADVISE
|
||||
if (advise->mode == ADVISE_DISCARD
|
||||
|| advise->mode == ADVISE_DISCARD_2
|
||||
|| advise->mode == ADVISE_DISCARD_8
|
||||
|| advise->mode == ADVISE_DISCARD_32
|
||||
) {
|
||||
size_t dirty_offset = advise->dirty_begin;
|
||||
size_t dirty_size = advise->dirty_end - advise->dirty_begin;
|
||||
size_t limit;
|
||||
if (advise->mode == ADVISE_FLUSH || advise->mode == ADVISE_DISCARD) {
|
||||
handle_offset = offset;
|
||||
handle_size = size;
|
||||
}
|
||||
|
||||
switch (advise->mode) {
|
||||
default:
|
||||
case ADVISE_DISCARD : limit = 1; break;
|
||||
case ADVISE_DISCARD_2 : limit = 2 * 1024 * 1024; break;
|
||||
case ADVISE_DISCARD_8 : limit = 8 * 1024 * 1024; break;
|
||||
case ADVISE_DISCARD_32 : limit = 32 * 1024 * 1024; break;
|
||||
}
|
||||
if (advise->mode == ADVISE_FLUSH_WINDOW || advise->mode == ADVISE_DISCARD_WINDOW) {
|
||||
/* if the dirty range can be extended */
|
||||
if (advise->dirty_end == offset) {
|
||||
/* extent the dirty range */
|
||||
advise->dirty_end += size;
|
||||
|
||||
/* if we have to discard */
|
||||
if (dirty_size >= limit) {
|
||||
int ret;
|
||||
/* if we reached the double window size */
|
||||
if (advise->dirty_end - advise->dirty_begin >= 2 * ADVISE_WINDOW_SIZE) {
|
||||
/* handle the first window */
|
||||
handle_offset = advise->dirty_begin;
|
||||
handle_size = ADVISE_WINDOW_SIZE;
|
||||
|
||||
/* send the data to the disk and wait until it's written */
|
||||
ret = sync_file_range(f, dirty_offset, dirty_size, SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER);
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
/* remove it from the dirty range */
|
||||
advise->dirty_begin += ADVISE_WINDOW_SIZE;
|
||||
}
|
||||
} else {
|
||||
/* otherwise flush the existing dirty */
|
||||
handle_offset = advise->dirty_begin;
|
||||
handle_size = advise->dirty_end - advise->dirty_begin;
|
||||
|
||||
/* flush the data from the cache */
|
||||
ret = posix_fadvise(f, dirty_offset, dirty_size, POSIX_FADV_DONTNEED);
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
errno = ret; /* posix_fadvise return the error code */
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* set the new dirty range */
|
||||
/* and set the new range as dirty */
|
||||
advise->dirty_begin = offset;
|
||||
advise->dirty_end = offset + size;
|
||||
} else {
|
||||
/* extend the dirty range */
|
||||
if (advise->dirty_begin > offset)
|
||||
advise->dirty_begin = offset;
|
||||
if (advise->dirty_end < offset + size)
|
||||
advise->dirty_end = offset + size;
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_SYNC_FILE_RANGE
|
||||
if ((advise->mode == ADVISE_FLUSH || advise->mode == ADVISE_FLUSH_WINDOW)
|
||||
&& handle_size != 0
|
||||
) {
|
||||
int ret;
|
||||
|
||||
/* start writing immediately */
|
||||
ret = sync_file_range(f, handle_offset, handle_size, SYNC_FILE_RANGE_WRITE);
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_SYNC_FILE_RANGE && HAVE_POSIX_FADVISE
|
||||
if ((advise->mode == ADVISE_DISCARD || advise->mode == ADVISE_DISCARD_WINDOW)
|
||||
&& handle_size != 0
|
||||
) {
|
||||
int ret;
|
||||
|
||||
/* send the data to the disk and wait until it's written */
|
||||
ret = sync_file_range(f, handle_offset, handle_size, SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER);
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* flush the data from the cache */
|
||||
ret = posix_fadvise(f, handle_offset, handle_size, POSIX_FADV_DONTNEED);
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
errno = ret; /* posix_fadvise return the error code */
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1068,7 +1075,7 @@ int advise_write(struct advise_struct* advise, int f, size_t offset, size_t size
|
|||
return 0;
|
||||
}
|
||||
|
||||
int advise_read(struct advise_struct* advise, int f, size_t offset, size_t size)
|
||||
int advise_read(struct advise_struct* advise, int f, uint64_t offset, uint64_t size)
|
||||
{
|
||||
(void)advise;
|
||||
(void)f;
|
||||
|
|
@ -1077,9 +1084,7 @@ int advise_read(struct advise_struct* advise, int f, size_t offset, size_t size)
|
|||
|
||||
#if HAVE_POSIX_FADVISE
|
||||
if (advise->mode == ADVISE_DISCARD
|
||||
|| advise->mode == ADVISE_DISCARD_2
|
||||
|| advise->mode == ADVISE_DISCARD_8
|
||||
|| advise->mode == ADVISE_DISCARD_32
|
||||
|| advise->mode == ADVISE_DISCARD_WINDOW
|
||||
) {
|
||||
int ret;
|
||||
|
||||
|
|
@ -1143,7 +1148,6 @@ int advise_read(struct advise_struct* advise, int f, size_t offset, size_t size)
|
|||
*/
|
||||
static size_t mcounter;
|
||||
|
||||
|
||||
size_t malloc_counter_get(void)
|
||||
{
|
||||
size_t ret;
|
||||
|
|
|
|||
|
|
@ -332,23 +332,24 @@ int fmtime(int f, int64_t mtime_sec, int mtime_nsec);
|
|||
#define ADVISE_NONE 1 /**< Bare read/write mode. */
|
||||
#define ADVISE_SEQUENTIAL 2 /**< Sequential mode. */
|
||||
#define ADVISE_FLUSH 3 /**< Flush mode. */
|
||||
#define ADVISE_DISCARD 4 /**< Discard the cache after every operation. */
|
||||
#define ADVISE_DISCARD_2 5 /**< Discard the cache every 2MB. */
|
||||
#define ADVISE_DISCARD_8 6 /**< Discard the cache every 8MB. */
|
||||
#define ADVISE_DISCARD_32 7 /**< Discard the cache every 32MB. */
|
||||
#define ADVISE_DIRECT 8 /**< Direct mode. */
|
||||
#define ADVISE_FLUSH_WINDOW 4 /**< Flush mode with a window of 8MB. */
|
||||
#define ADVISE_DISCARD 5 /**< Discard the cache after every operation. */
|
||||
#define ADVISE_DISCARD_WINDOW 6 /**< Discard the cache with a window of 8MB. */
|
||||
#define ADVISE_DIRECT 7 /**< Direct mode. */
|
||||
|
||||
#define ADVISE_WINDOW_SIZE (8 * 1024 * 1024) /**< Window size. */
|
||||
|
||||
struct advise_struct {
|
||||
int mode;
|
||||
size_t dirty_begin;
|
||||
size_t dirty_end;
|
||||
uint64_t dirty_begin;
|
||||
uint64_t dirty_end;
|
||||
};
|
||||
|
||||
void advise_init(struct advise_struct* advise, int mode);
|
||||
int advise_flags(struct advise_struct* advise);
|
||||
int advise_open(struct advise_struct* advise, int f);
|
||||
int advise_write(struct advise_struct* advise, int f, size_t offset, size_t size);
|
||||
int advise_read(struct advise_struct* advise, int f, size_t offset, size_t size);
|
||||
int advise_write(struct advise_struct* advise, int f, uint64_t offset, uint64_t size);
|
||||
int advise_read(struct advise_struct* advise, int f, uint64_t offset, uint64_t size);
|
||||
|
||||
/****************************************************************************/
|
||||
/* memory */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue