mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 02:49:02 -04:00
Improve the discard-window write strategy
Now flush the window before discarding it in the previous loop, following exactly the Linus advices.
This commit is contained in:
parent
b5e5a0791b
commit
7d65eb83b1
1 changed files with 62 additions and 26 deletions
|
|
@ -932,15 +932,21 @@ int advise_open(struct advise_struct* advise, int f)
|
|||
|
||||
int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_off_t size)
|
||||
{
|
||||
data_off_t handle_offset;
|
||||
data_off_t handle_size;
|
||||
data_off_t flush_offset;
|
||||
data_off_t flush_size;
|
||||
data_off_t discard_offset;
|
||||
data_off_t discard_size;
|
||||
|
||||
(void)f;
|
||||
(void)handle_offset;
|
||||
(void)handle_size;
|
||||
(void)flush_offset;
|
||||
(void)flush_size;
|
||||
(void)discard_offset;
|
||||
(void)discard_size;
|
||||
|
||||
handle_offset = 0;
|
||||
handle_size = 0;
|
||||
flush_offset = 0;
|
||||
flush_size = 0;
|
||||
discard_offset = 0;
|
||||
discard_size = 0;
|
||||
|
||||
/*
|
||||
* Follow Linus recommendations about fast writes.
|
||||
|
|
@ -995,12 +1001,41 @@ int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_of
|
|||
* ---
|
||||
*/
|
||||
|
||||
if (advise->mode == ADVISE_FLUSH || advise->mode == ADVISE_DISCARD) {
|
||||
handle_offset = offset;
|
||||
handle_size = size;
|
||||
}
|
||||
switch (advise->mode) {
|
||||
case ADVISE_FLUSH :
|
||||
flush_offset = offset;
|
||||
flush_size = size;
|
||||
break;
|
||||
case ADVISE_DISCARD :
|
||||
discard_offset = offset;
|
||||
discard_size = size;
|
||||
break;
|
||||
case ADVISE_FLUSH_WINDOW :
|
||||
/* if the dirty range can be extended */
|
||||
if (advise->dirty_end == offset) {
|
||||
/* extent the dirty range */
|
||||
advise->dirty_end += size;
|
||||
|
||||
if (advise->mode == ADVISE_FLUSH_WINDOW || advise->mode == ADVISE_DISCARD_WINDOW) {
|
||||
/* if we reached the window size */
|
||||
if (advise->dirty_end - advise->dirty_begin >= ADVISE_WINDOW_SIZE) {
|
||||
/* flush the window */
|
||||
flush_offset = advise->dirty_begin;
|
||||
flush_size = ADVISE_WINDOW_SIZE;
|
||||
|
||||
/* remove it from the dirty range */
|
||||
advise->dirty_begin += ADVISE_WINDOW_SIZE;
|
||||
}
|
||||
} else {
|
||||
/* otherwise flush the existing dirty */
|
||||
flush_offset = advise->dirty_begin;
|
||||
flush_size = advise->dirty_end - advise->dirty_begin;
|
||||
|
||||
/* and set the new range as dirty */
|
||||
advise->dirty_begin = offset;
|
||||
advise->dirty_end = offset + size;
|
||||
}
|
||||
break;
|
||||
case ADVISE_DISCARD_WINDOW :
|
||||
/* if the dirty range can be extended */
|
||||
if (advise->dirty_end == offset) {
|
||||
/* extent the dirty range */
|
||||
|
|
@ -1008,32 +1043,35 @@ int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_of
|
|||
|
||||
/* 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;
|
||||
/* discard the first window */
|
||||
discard_offset = advise->dirty_begin;
|
||||
discard_size = ADVISE_WINDOW_SIZE;
|
||||
|
||||
/* remove it from the dirty range */
|
||||
advise->dirty_begin += ADVISE_WINDOW_SIZE;
|
||||
|
||||
/* flush the second window */
|
||||
flush_offset = advise->dirty_begin;
|
||||
flush_size = ADVISE_WINDOW_SIZE;
|
||||
}
|
||||
} else {
|
||||
/* otherwise flush the existing dirty */
|
||||
handle_offset = advise->dirty_begin;
|
||||
handle_size = advise->dirty_end - advise->dirty_begin;
|
||||
/* otherwise discard the existing dirty */
|
||||
discard_offset = advise->dirty_begin;
|
||||
discard_size = advise->dirty_end - advise->dirty_begin;
|
||||
|
||||
/* and set the new range as dirty */
|
||||
advise->dirty_begin = offset;
|
||||
advise->dirty_end = offset + size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if HAVE_SYNC_FILE_RANGE
|
||||
if ((advise->mode == ADVISE_FLUSH || advise->mode == ADVISE_FLUSH_WINDOW)
|
||||
&& handle_size != 0
|
||||
) {
|
||||
if (flush_size != 0) {
|
||||
int ret;
|
||||
|
||||
/* start writing immediately */
|
||||
ret = sync_file_range(f, handle_offset, handle_size, SYNC_FILE_RANGE_WRITE);
|
||||
ret = sync_file_range(f, flush_offset, flush_size, SYNC_FILE_RANGE_WRITE);
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
return -1;
|
||||
|
|
@ -1043,13 +1081,11 @@ int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_of
|
|||
#endif
|
||||
|
||||
#if HAVE_SYNC_FILE_RANGE && HAVE_POSIX_FADVISE
|
||||
if ((advise->mode == ADVISE_DISCARD || advise->mode == ADVISE_DISCARD_WINDOW)
|
||||
&& handle_size != 0
|
||||
) {
|
||||
if (discard_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);
|
||||
ret = sync_file_range(f, discard_offset, discard_size, SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER);
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
return -1;
|
||||
|
|
@ -1057,7 +1093,7 @@ int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_of
|
|||
}
|
||||
|
||||
/* flush the data from the cache */
|
||||
ret = posix_fadvise(f, handle_offset, handle_size, POSIX_FADV_DONTNEED);
|
||||
ret = posix_fadvise(f, discard_offset, discard_size, POSIX_FADV_DONTNEED);
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
errno = ret; /* posix_fadvise return the error code */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue