Commit ec0f16372277052a29a6c17527c6cae5e898b3fd

Authored by Jan Kara
Committed by Linus Torvalds
1 parent b813e931b4

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>

Showing 3 changed files with 10 additions and 3 deletions Side-by-side Diff

... ... @@ -702,6 +702,7 @@
702 702 unsigned long ra_pages; /* Maximum readahead window */
703 703 unsigned long mmap_hit; /* Cache hit stat for mmap accesses */
704 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 707 #define RA_FLAG_MISS 0x01 /* a cache miss occured against this file */
707 708 #define RA_FLAG_INCACHE 0x02 /* file is already in cache */
... ... @@ -868,6 +868,7 @@
868 868 unsigned long last_index;
869 869 unsigned long next_index;
870 870 unsigned long prev_index;
  871 + unsigned int prev_offset;
871 872 loff_t isize;
872 873 struct page *cached_page;
873 874 int error;
... ... @@ -877,6 +878,7 @@
877 878 index = *ppos >> PAGE_CACHE_SHIFT;
878 879 next_index = index;
879 880 prev_index = ra.prev_page;
  881 + prev_offset = ra.offset;
880 882 last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
881 883 offset = *ppos & ~PAGE_CACHE_MASK;
882 884  
883 885  
... ... @@ -924,10 +926,10 @@
924 926 flush_dcache_page(page);
925 927  
926 928 /*
927   - * When (part of) the same page is read multiple times
928   - * in succession, only mark it as accessed the first time.
  929 + * When a sequential read accesses a page several times,
  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 933 mark_page_accessed(page);
932 934 prev_index = index;
933 935  
... ... @@ -945,6 +947,7 @@
945 947 offset += ret;
946 948 index += offset >> PAGE_CACHE_SHIFT;
947 949 offset &= ~PAGE_CACHE_MASK;
  950 + prev_offset = ra.offset = offset;
948 951  
949 952 page_cache_release(page);
950 953 if (ret == nr && desc->count)
... ... @@ -207,6 +207,8 @@
207 207 * If page_cache_readahead sees that it is again being called for
208 208 * a page which it just looked at, it can return immediately without
209 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 212 * ahead_start,
211 213 * ahead_size: Together, these form the "ahead window".
212 214 * ra_pages: The externally controlled max readahead for this fd.
... ... @@ -473,6 +475,7 @@
473 475 /* Note that prev_page == -1 if it is a first read */
474 476 sequential = (offset == ra->prev_page + 1);
475 477 ra->prev_page = offset;
  478 + ra->offset = 0;
476 479  
477 480 max = get_max_readahead(ra);
478 481 newsize = min(req_size, max);