Introduce a readahead flags field and embed the existing mmap_miss in it (to save space). It will be possible to lose the flags in race conditions, however the impact should be limited. CC: Nick Piggin <npiggin@xxxxxxx> CC: Andi Kleen <andi@xxxxxxxxxxxxxx> CC: Steven Whitehouse <swhiteho@xxxxxxxxxx> Signed-off-by: Wu Fengguang <fengguang.wu@xxxxxxxxx> --- include/linux/fs.h | 30 +++++++++++++++++++++++++++++- mm/filemap.c | 7 ++----- 2 files changed, 31 insertions(+), 6 deletions(-) --- linux.orig/include/linux/fs.h 2009-12-30 11:07:04.000000000 +0800 +++ linux/include/linux/fs.h 2009-12-30 12:59:28.000000000 +0800 @@ -889,10 +889,38 @@ struct file_ra_state { there are only # of pages ahead */ unsigned int ra_pages; /* Maximum readahead window */ - unsigned int mmap_miss; /* Cache miss stat for mmap accesses */ + unsigned int flags; loff_t prev_pos; /* Cache last read() position */ }; +/* low 16 bits: cache miss stat for mmap accesses */ +#define RA_FLAG_MMAP_MISS 0x0000ffff + +/* + * Don't do flags++ directly to avoid possible overflow: + * the ra fields can be accessed concurrently in a racy way. + */ +static inline unsigned int ra_mmap_miss_inc(struct file_ra_state *ra) +{ + unsigned int miss = ra->flags & RA_FLAG_MMAP_MISS; + + if (miss < RA_FLAG_MMAP_MISS) { + miss++; + ra->flags = miss | (ra->flags &~ RA_FLAG_MMAP_MISS); + } + return miss; +} + +static inline void ra_mmap_miss_dec(struct file_ra_state *ra) +{ + unsigned int miss = ra->flags & RA_FLAG_MMAP_MISS; + + if (miss) { + miss--; + ra->flags = miss | (ra->flags &~ RA_FLAG_MMAP_MISS); + } +} + /* * Check if @index falls in the readahead windows. */ --- linux.orig/mm/filemap.c 2009-12-30 11:07:04.000000000 +0800 +++ linux/mm/filemap.c 2009-12-30 11:07:22.000000000 +0800 @@ -1418,14 +1418,12 @@ static void do_sync_mmap_readahead(struc return; } - if (ra->mmap_miss < INT_MAX) - ra->mmap_miss++; /* * Do we miss much more than hit in this file? If so, * stop bothering with read-ahead. It will only hurt. */ - if (ra->mmap_miss > MMAP_LOTSAMISS) + if (ra_mmap_miss_inc(ra) > MMAP_LOTSAMISS) return; /* @@ -1455,8 +1453,7 @@ static void do_async_mmap_readahead(stru /* If we don't want any read-ahead, don't bother */ if (VM_RandomReadHint(vma)) return; - if (ra->mmap_miss > 0) - ra->mmap_miss--; + ra_mmap_miss_dec(ra); if (PageReadahead(page)) page_cache_async_readahead(mapping, ra, file, page, offset, ra->ra_pages); -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html