lkml.org 
[lkml]   [2010]   [Feb]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH 08/15] readahead: record readahead patterns
    Record the readahead pattern in ra_flags. This info can be examined by
    users via the readahead tracing/stats interfaces.

    Currently 7 patterns are defined:

    pattern readahead for
    -----------------------------------------------------------
    RA_PATTERN_INITIAL start-of-file/oversize read
    RA_PATTERN_SUBSEQUENT trivial sequential read
    RA_PATTERN_CONTEXT interleaved sequential read
    RA_PATTERN_THRASH thrashed sequential read
    RA_PATTERN_MMAP_AROUND mmap fault
    RA_PATTERN_FADVISE posix_fadvise()
    RA_PATTERN_RANDOM random read

    CC: Ingo Molnar <mingo@elte.hu>
    CC: Jens Axboe <jens.axboe@oracle.com>
    CC: Peter Zijlstra <a.p.zijlstra@chello.nl>
    Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
    ---
    include/linux/fs.h | 32 ++++++++++++++++++++++++++++++++
    include/linux/mm.h | 4 +++-
    mm/filemap.c | 9 +++++++--
    mm/readahead.c | 17 +++++++++++++----
    4 files changed, 55 insertions(+), 7 deletions(-)

    --- linux.orig/include/linux/fs.h 2010-02-24 10:44:44.000000000 +0800
    +++ linux/include/linux/fs.h 2010-02-24 10:44:45.000000000 +0800
    @@ -894,8 +894,40 @@ struct file_ra_state {
    };

    /* ra_flags bits */
    +#define READAHEAD_PATTERN_SHIFT 20
    +#define READAHEAD_PATTERN 0x00f00000
    #define READAHEAD_MMAP_MISS 0x00000fff /* cache misses for mmap access */
    #define READAHEAD_THRASHED 0x10000000
    +#define READAHEAD_MMAP 0x20000000
    +
    +/*
    + * Which policy makes decision to do the current read-ahead IO?
    + */
    +enum readahead_pattern {
    + RA_PATTERN_INITIAL,
    + RA_PATTERN_SUBSEQUENT,
    + RA_PATTERN_CONTEXT,
    + RA_PATTERN_THRASH,
    + RA_PATTERN_MMAP_AROUND,
    + RA_PATTERN_FADVISE,
    + RA_PATTERN_RANDOM,
    + RA_PATTERN_ALL, /* for summary stats */
    + RA_PATTERN_MAX
    +};
    +
    +static inline int ra_pattern(int ra_flags)
    +{
    + int pattern = (ra_flags & READAHEAD_PATTERN)
    + >> READAHEAD_PATTERN_SHIFT;
    +
    + return min(pattern, RA_PATTERN_ALL);
    +}
    +
    +static inline void ra_set_pattern(struct file_ra_state *ra, int pattern)
    +{
    + ra->ra_flags = (ra->ra_flags & ~READAHEAD_PATTERN) |
    + (pattern << READAHEAD_PATTERN_SHIFT);
    +}

    /*
    * Don't do ra_flags++ directly to avoid possible overflow:
    --- linux.orig/mm/readahead.c 2010-02-24 10:44:44.000000000 +0800
    +++ linux/mm/readahead.c 2010-02-24 10:44:45.000000000 +0800
    @@ -339,7 +339,10 @@ unsigned long max_sane_readahead(unsigne
    * Submit IO for the read-ahead request in file_ra_state.
    */
    unsigned long ra_submit(struct file_ra_state *ra,
    - struct address_space *mapping, struct file *filp)
    + struct address_space *mapping,
    + struct file *filp,
    + pgoff_t offset,
    + unsigned long req_size)
    {
    int actual;

    @@ -473,6 +476,7 @@ ondemand_readahead(struct address_space
    * start of file
    */
    if (!offset) {
    + ra_set_pattern(ra, RA_PATTERN_INITIAL);
    ra->start = offset;
    ra->size = get_init_ra_size(req_size, max);
    ra->async_size = ra->size > req_size ?
    @@ -493,6 +497,7 @@ ondemand_readahead(struct address_space
    */
    if ((offset == (ra->start + ra->size - ra->async_size) ||
    offset == (ra->start + ra->size))) {
    + ra_set_pattern(ra, RA_PATTERN_SUBSEQUENT);
    ra->start += ra->size;
    ra->size = get_next_ra_size(ra, max);
    ra->async_size = ra->size;
    @@ -503,6 +508,7 @@ ondemand_readahead(struct address_space
    * oversize read, no need to query page cache
    */
    if (req_size > max && !hit_readahead_marker) {
    + ra_set_pattern(ra, RA_PATTERN_INITIAL);
    ra->start = offset;
    ra->size = max;
    ra->async_size = max;
    @@ -548,8 +554,10 @@ context_readahead:
    */
    if (!size && !hit_readahead_marker) {
    if (!ra_thrashed(ra, offset)) {
    + ra_set_pattern(ra, RA_PATTERN_RANDOM);
    ra->size = min(req_size, max);
    } else {
    + ra_set_pattern(ra, RA_PATTERN_THRASH);
    retain_inactive_pages(mapping, offset, min(2 * max,
    ra->start + ra->size - offset));
    ra->size = max_t(int, ra->size/2, MIN_READAHEAD_PAGES);
    @@ -566,12 +574,13 @@ context_readahead:
    if (size >= offset)
    size *= 2;
    /*
    - * pages to readahead are already cached
    + * Pages to readahead are already cached?
    */
    if (size <= start - offset)
    return 0;
    -
    size -= start - offset;
    +
    + ra_set_pattern(ra, RA_PATTERN_CONTEXT);
    ra->start = start;
    ra->size = clamp_t(unsigned int, size, MIN_READAHEAD_PAGES, max);
    ra->async_size = min(ra->size, 1 + size / READAHEAD_ASYNC_RATIO);
    @@ -587,7 +596,7 @@ readit:
    ra->size += ra->async_size;
    }

    - return ra_submit(ra, mapping, filp);
    + return ra_submit(ra, mapping, filp, offset, req_size);
    }

    /**
    --- linux.orig/include/linux/mm.h 2010-02-24 10:44:41.000000000 +0800
    +++ linux/include/linux/mm.h 2010-02-24 10:44:45.000000000 +0800
    @@ -1208,7 +1208,9 @@ void page_cache_async_readahead(struct a
    unsigned long max_sane_readahead(unsigned long nr);
    unsigned long ra_submit(struct file_ra_state *ra,
    struct address_space *mapping,
    - struct file *filp);
    + struct file *filp,
    + pgoff_t offset,
    + unsigned long req_size);

    /* Do stack extension */
    extern int expand_stack(struct vm_area_struct *vma, unsigned long address);
    --- linux.orig/mm/filemap.c 2010-02-24 10:44:43.000000000 +0800
    +++ linux/mm/filemap.c 2010-02-24 10:44:45.000000000 +0800
    @@ -1413,6 +1413,7 @@ static void do_sync_mmap_readahead(struc

    if (VM_SequentialReadHint(vma) ||
    offset - 1 == (ra->prev_pos >> PAGE_CACHE_SHIFT)) {
    + ra->ra_flags |= READAHEAD_MMAP;
    page_cache_sync_readahead(mapping, ra, file, offset,
    ra->ra_pages);
    return;
    @@ -1431,10 +1432,12 @@ static void do_sync_mmap_readahead(struc
    */
    ra_pages = max_sane_readahead(ra->ra_pages);
    if (ra_pages) {
    + ra->ra_flags |= READAHEAD_MMAP;
    + ra_set_pattern(ra, RA_PATTERN_MMAP_AROUND);
    ra->start = max_t(long, 0, offset - ra_pages/2);
    ra->size = ra_pages;
    ra->async_size = 0;
    - ra_submit(ra, mapping, file);
    + ra_submit(ra, mapping, file, offset, 1);
    }
    }

    @@ -1454,9 +1457,11 @@ static void do_async_mmap_readahead(stru
    if (VM_RandomReadHint(vma))
    return;
    ra_mmap_miss_dec(ra);
    - if (PageReadahead(page))
    + if (PageReadahead(page)) {
    + ra->ra_flags |= READAHEAD_MMAP;
    page_cache_async_readahead(mapping, ra, file,
    page, offset, ra->ra_pages);
    + }
    }

    /**



    \
     
     \ /
      Last update: 2010-02-24 04:15    [W:0.031 / U:1.936 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site