From 455c8d461c6daac02fc31376f435657c7e34b1b5 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Sun, 6 May 2007 14:49:25 -0700 Subject: [PATCH] --- yaml --- r: 54188 b: refs/heads/master c: ec0f16372277052a29a6c17527c6cae5e898b3fd h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/include/linux/fs.h | 1 + trunk/mm/filemap.c | 9 ++++++--- trunk/mm/readahead.c | 3 +++ 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index c27e3a2c3b0f..a2fb0478d5b1 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: b813e931b4c8235bb42e301096ea97dbdee3e8fe +refs/heads/master: ec0f16372277052a29a6c17527c6cae5e898b3fd diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index 7c0077f06e24..0949e243b8b9 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -702,6 +702,7 @@ struct file_ra_state { unsigned long ra_pages; /* Maximum readahead window */ unsigned long mmap_hit; /* Cache hit stat for mmap accesses */ unsigned long mmap_miss; /* Cache miss stat for mmap accesses */ + unsigned int offset; /* Offset where last read() ended in a page */ }; #define RA_FLAG_MISS 0x01 /* a cache miss occured against this file */ #define RA_FLAG_INCACHE 0x02 /* file is already in cache */ diff --git a/trunk/mm/filemap.c b/trunk/mm/filemap.c index cbea95a25283..07f5b77114a3 100644 --- a/trunk/mm/filemap.c +++ b/trunk/mm/filemap.c @@ -868,6 +868,7 @@ void do_generic_mapping_read(struct address_space *mapping, unsigned long last_index; unsigned long next_index; unsigned long prev_index; + unsigned int prev_offset; loff_t isize; struct page *cached_page; int error; @@ -877,6 +878,7 @@ void do_generic_mapping_read(struct address_space *mapping, index = *ppos >> PAGE_CACHE_SHIFT; next_index = index; prev_index = ra.prev_page; + prev_offset = ra.offset; last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT; offset = *ppos & ~PAGE_CACHE_MASK; @@ -924,10 +926,10 @@ void do_generic_mapping_read(struct address_space *mapping, flush_dcache_page(page); /* - * When (part of) the same page is read multiple times - * in succession, only mark it as accessed the first time. + * When a sequential read accesses a page several times, + * only mark it as accessed the first time. */ - if (prev_index != index) + if (prev_index != index || offset != prev_offset) mark_page_accessed(page); prev_index = index; @@ -945,6 +947,7 @@ void do_generic_mapping_read(struct address_space *mapping, offset += ret; index += offset >> PAGE_CACHE_SHIFT; offset &= ~PAGE_CACHE_MASK; + prev_offset = ra.offset = offset; page_cache_release(page); if (ret == nr && desc->count) diff --git a/trunk/mm/readahead.c b/trunk/mm/readahead.c index 93d9ee692fd8..0a6fed9d365c 100644 --- a/trunk/mm/readahead.c +++ b/trunk/mm/readahead.c @@ -207,6 +207,8 @@ static int read_pages(struct address_space *mapping, struct file *filp, * If page_cache_readahead sees that it is again being called for * a page which it just looked at, it can return immediately without * making any state changes. + * offset: Offset in the prev_page where the last read ended - used for + * detection of sequential file reading. * ahead_start, * ahead_size: Together, these form the "ahead window". * 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, /* Note that prev_page == -1 if it is a first read */ sequential = (offset == ra->prev_page + 1); ra->prev_page = offset; + ra->offset = 0; max = get_max_readahead(ra); newsize = min(req_size, max);