Last active
October 10, 2015 18:48
-
-
Save SaveTheRbtz/3734932 to your computer and use it in GitHub Desktop.
Added "fade" readahead type
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit e95636528228a11ed22e5d17e160d69325e8572f | |
Author: Alexey Ivanov <rbtz@yandex-team.ru> | |
Date: Tue Jul 31 01:48:45 2012 +0400 | |
YANDEX: Added "fade" readahead type | |
This replaces comlicated logic with simple one: | |
* If we've already read more than file size -- read 8 pages | |
* Else if we read more than file size / 2 -- read (ra_pages / 4) pages | |
* Otherwise read 8 pages | |
Turned on by vm.readahead_fade sysctl | |
Submitted by: ironpeter@ | |
diff --git a/include/linux/fs.h b/include/linux/fs.h | |
index c4f307a..52c4d74 100644 | |
--- a/include/linux/fs.h | |
+++ b/include/linux/fs.h | |
@@ -953,6 +953,7 @@ struct file_ra_state { | |
unsigned int ra_pages; /* Maximum readahead window */ | |
unsigned int mmap_miss; /* Cache miss stat for mmap accesses */ | |
loff_t prev_pos; /* Cache last read() position */ | |
+ unsigned long pages_read; /* Pages read by readahead */ | |
}; | |
/* | |
diff --git a/include/linux/mm.h b/include/linux/mm.h | |
index 670f041..3c29190 100644 | |
--- a/include/linux/mm.h | |
+++ b/include/linux/mm.h | |
@@ -28,6 +28,7 @@ struct writeback_control; | |
extern unsigned long max_mapnr; | |
#endif | |
+extern int mm_readahead_fade; | |
extern unsigned long num_physpages; | |
extern unsigned long totalram_pages; | |
extern void * high_memory; | |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c | |
index 7b5e9eb..e51ae49 100644 | |
--- a/kernel/sysctl.c | |
+++ b/kernel/sysctl.c | |
@@ -1120,6 +1120,14 @@ static struct ctl_table vm_table[] = { | |
.extra1 = &zero, | |
.extra2 = &one_hundred, | |
}, | |
+ { | |
+ .procname = "readahead_fade", | |
+ .data = &mm_readahead_fade, | |
+ .maxlen = sizeof(mm_readahead_fade), | |
+ .mode = 0644, | |
+ .proc_handler = proc_dointvec_minmax, | |
+ .extra1 = &zero, | |
+ }, | |
#ifdef CONFIG_HUGETLB_PAGE | |
{ | |
.procname = "nr_hugepages", | |
diff --git a/mm/filemap.c b/mm/filemap.c | |
index 7fe956c..8478e78 100644 | |
--- a/mm/filemap.c | |
+++ b/mm/filemap.c | |
@@ -1607,6 +1607,57 @@ static void do_sync_mmap_readahead(struct vm_area_struct *vma, | |
ra_submit(ra, mapping, file); | |
} | |
+static void do_fade_readahead(struct vm_area_struct *vma, | |
+ struct file_ra_state *ra, | |
+ struct file *file, | |
+ pgoff_t offset, | |
+ int readback) | |
+{ | |
+ unsigned long ra_pages; | |
+ unsigned long pages_read; | |
+ unsigned long vma_num_pages; | |
+ unsigned long ra_pages_read; | |
+ unsigned long ra_pages_back; | |
+ struct address_space *mapping = file->f_mapping; | |
+ struct file_ra_state local_ra; | |
+ /* If we don't want any read-ahead, don't bother */ | |
+ if (VM_RandomReadHint(vma)) | |
+ return; | |
+ if (!ra->ra_pages) | |
+ return; | |
+ if (!vma) | |
+ return; | |
+ /* | |
+ * fade logic. Do max(ra_pages, 8), max(ra_pages / 4, 8), 8 pages read | |
+ */ | |
+ memset(&local_ra, 0, sizeof(local_ra)); | |
+ ra_pages = max_sane_readahead(ra->ra_pages); | |
+ vma_num_pages = (vma->vm_end - vma->vm_start) >> PAGE_CACHE_SHIFT; | |
+ ra_pages_read = ra->pages_read; | |
+ if (ra_pages_read >= vma_num_pages) | |
+ ra_pages = 8; | |
+ else if (ra_pages_read >= vma_num_pages / 2) | |
+ ra_pages = ra_pages / 4; | |
+ if (ra_pages < 8) | |
+ ra_pages = 8; | |
+ ra_pages_back = readback * ra_pages / 4; | |
+ if (offset > ra_pages_back) | |
+ local_ra.start = offset - ra_pages_back; | |
+ local_ra.size = ra_pages; | |
+ local_ra.async_size = ra_pages / 4; | |
+ pages_read = ra_submit(&local_ra, mapping, file); | |
+ /* | |
+ * work with overflow | |
+ */ | |
+ if (pages_read + ra_pages_read > ra_pages_read) | |
+ ra_pages_read += pages_read; | |
+ else | |
+ ra_pages_read = (unsigned long)-1; | |
+ ra->pages_read = ra_pages_read; | |
+} | |
+ | |
+ | |
+ | |
/* | |
* Asynchronous readahead happens when we find the page and PG_readahead, | |
* so we want to possibly extend the readahead further.. | |
@@ -1666,10 +1717,18 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |
* We found the page, so try async readahead before | |
* waiting for the lock. | |
*/ | |
- do_async_mmap_readahead(vma, ra, file, page, offset); | |
+ if (mm_readahead_fade == 0) | |
+ do_async_mmap_readahead(vma, ra, file, page, offset); | |
+ else if (PageReadahead(page) && !PageWriteback(page)) { | |
+ ClearPageReadahead(page); | |
+ do_fade_readahead(vma, ra, file, offset, 0); | |
+ } | |
} else { | |
/* No page in the page cache at all */ | |
- do_sync_mmap_readahead(vma, ra, file, offset); | |
+ if (mm_readahead_fade == 0) | |
+ do_sync_mmap_readahead(vma, ra, file, offset); | |
+ else | |
+ do_fade_readahead(vma, ra, file, offset, 1); | |
count_vm_event(PGMAJFAULT); | |
mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT); | |
ret = VM_FAULT_MAJOR; | |
@@ -2663,3 +2722,4 @@ int try_to_release_page(struct page *page, gfp_t gfp_mask) | |
} | |
EXPORT_SYMBOL(try_to_release_page); | |
+int mm_readahead_fade = 0; | |
\ No newline at end of file | |
diff --git a/mm/readahead.c b/mm/readahead.c | |
index 2acb815..7548a22 100644 | |
--- a/mm/readahead.c | |
+++ b/mm/readahead.c | |
@@ -27,6 +27,7 @@ file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping) | |
{ | |
ra->ra_pages = mapping->backing_dev_info->ra_pages; | |
ra->prev_pos = -1; | |
+ ra->pages_read = 0; | |
} | |
EXPORT_SYMBOL_GPL(file_ra_state_init); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment