diff options
-rw-r--r-- | include/linux/fs.h | 1 | ||||
-rw-r--r-- | mm/filemap.c | 9 | ||||
-rw-r--r-- | mm/readahead.c | 3 |
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); |