aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2007-05-06 17:49:25 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-07 15:12:52 -0400
commitec0f16372277052a29a6c17527c6cae5e898b3fd (patch)
tree35636edac6ed01baf301f3aca96f090caae82c9d
parentb813e931b4c8235bb42e301096ea97dbdee3e8fe (diff)
readahead: improve heuristic detecting sequential reads
Introduce ra.offset and store in it an offset where the previous read ended. This way we can detect whether reads are really sequential (and thus we should not mark the page as accessed repeatedly) or whether they are random and just happen to be in the same page (and the page should really be marked accessed again). Signed-off-by: Jan Kara <jack@suse.cz> Acked-by: Nick Piggin <nickpiggin@yahoo.com.au> Cc: WU Fengguang <wfg@mail.ustc.edu.cn> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/fs.h1
-rw-r--r--mm/filemap.c9
-rw-r--r--mm/readahead.c3
3 files changed, 10 insertions, 3 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7c0077f06e24..0949e243b8b9 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -702,6 +702,7 @@ struct file_ra_state {
702 unsigned long ra_pages; /* Maximum readahead window */ 702 unsigned long ra_pages; /* Maximum readahead window */
703 unsigned long mmap_hit; /* Cache hit stat for mmap accesses */ 703 unsigned long mmap_hit; /* Cache hit stat for mmap accesses */
704 unsigned long mmap_miss; /* Cache miss stat for mmap accesses */ 704 unsigned long mmap_miss; /* Cache miss stat for mmap accesses */
705 unsigned int offset; /* Offset where last read() ended in a page */
705}; 706};
706#define RA_FLAG_MISS 0x01 /* a cache miss occured against this file */ 707#define RA_FLAG_MISS 0x01 /* a cache miss occured against this file */
707#define RA_FLAG_INCACHE 0x02 /* file is already in cache */ 708#define RA_FLAG_INCACHE 0x02 /* file is already in cache */
diff --git a/mm/filemap.c b/mm/filemap.c
index cbea95a25283..07f5b77114a3 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -868,6 +868,7 @@ void do_generic_mapping_read(struct address_space *mapping,
868 unsigned long last_index; 868 unsigned long last_index;
869 unsigned long next_index; 869 unsigned long next_index;
870 unsigned long prev_index; 870 unsigned long prev_index;
871 unsigned int prev_offset;
871 loff_t isize; 872 loff_t isize;
872 struct page *cached_page; 873 struct page *cached_page;
873 int error; 874 int error;
@@ -877,6 +878,7 @@ void do_generic_mapping_read(struct address_space *mapping,
877 index = *ppos >> PAGE_CACHE_SHIFT; 878 index = *ppos >> PAGE_CACHE_SHIFT;
878 next_index = index; 879 next_index = index;
879 prev_index = ra.prev_page; 880 prev_index = ra.prev_page;
881 prev_offset = ra.offset;
880 last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT; 882 last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
881 offset = *ppos & ~PAGE_CACHE_MASK; 883 offset = *ppos & ~PAGE_CACHE_MASK;
882 884
@@ -924,10 +926,10 @@ page_ok:
924 flush_dcache_page(page); 926 flush_dcache_page(page);
925 927
926 /* 928 /*
927 * When (part of) the same page is read multiple times 929 * When a sequential read accesses a page several times,
928 * in succession, only mark it as accessed the first time. 930 * only mark it as accessed the first time.
929 */ 931 */
930 if (prev_index != index) 932 if (prev_index != index || offset != prev_offset)
931 mark_page_accessed(page); 933 mark_page_accessed(page);
932 prev_index = index; 934 prev_index = index;
933 935
@@ -945,6 +947,7 @@ page_ok:
945 offset += ret; 947 offset += ret;
946 index += offset >> PAGE_CACHE_SHIFT; 948 index += offset >> PAGE_CACHE_SHIFT;
947 offset &= ~PAGE_CACHE_MASK; 949 offset &= ~PAGE_CACHE_MASK;
950 prev_offset = ra.offset = offset;
948 951
949 page_cache_release(page); 952 page_cache_release(page);
950 if (ret == nr && desc->count) 953 if (ret == nr && desc->count)
diff --git a/mm/readahead.c b/mm/readahead.c
index 93d9ee692fd8..0a6fed9d365c 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -207,6 +207,8 @@ out:
207 * If page_cache_readahead sees that it is again being called for 207 * If page_cache_readahead sees that it is again being called for
208 * a page which it just looked at, it can return immediately without 208 * a page which it just looked at, it can return immediately without
209 * making any state changes. 209 * making any state changes.
210 * offset: Offset in the prev_page where the last read ended - used for
211 * detection of sequential file reading.
210 * ahead_start, 212 * ahead_start,
211 * ahead_size: Together, these form the "ahead window". 213 * ahead_size: Together, these form the "ahead window".
212 * ra_pages: The externally controlled max readahead for this fd. 214 * ra_pages: The externally controlled max readahead for this fd.
@@ -473,6 +475,7 @@ page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra,
473 /* Note that prev_page == -1 if it is a first read */ 475 /* Note that prev_page == -1 if it is a first read */
474 sequential = (offset == ra->prev_page + 1); 476 sequential = (offset == ra->prev_page + 1);
475 ra->prev_page = offset; 477 ra->prev_page = offset;
478 ra->offset = 0;
476 479
477 max = get_max_readahead(ra); 480 max = get_max_readahead(ra);
478 newsize = min(req_size, max); 481 newsize = min(req_size, max);