X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=mm%2Freadahead.c;h=a5e6906a01e03073ff399da20f75821efb47e2dc;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=7073392b3357784a514fe972a20e170ed85ee954;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/mm/readahead.c b/mm/readahead.c index 7073392b3..a5e6906a0 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -28,16 +28,15 @@ struct backing_dev_info default_backing_dev_info = { EXPORT_SYMBOL_GPL(default_backing_dev_info); /* - * Initialise a struct file's readahead state + * Initialise a struct file's readahead state. Assumes that the caller has + * memset *ra to zero. */ void file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping) { - memset(ra, 0, sizeof(*ra)); ra->ra_pages = mapping->backing_dev_info->ra_pages; ra->average = ra->ra_pages / 2; } -EXPORT_SYMBOL(file_ra_state_init); /* * Return max readahead size for this inode in number-of-pages. @@ -384,25 +383,10 @@ page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra, first_access=1; ra->next_size = max / 2; ra->prev_page = offset; - ra->serial_cnt++; + ra->currnt_wnd_hit++; goto do_io; } - if (offset == ra->prev_page + 1) { - if (ra->serial_cnt <= (max * 2)) - ra->serial_cnt++; - } else { - /* - * to avoid rounding errors, ensure that 'average' - * tends towards the value of ra->serial_cnt. - */ - average = ra->average; - if (average < ra->serial_cnt) { - average++; - } - ra->average = (average + ra->serial_cnt) / 2; - ra->serial_cnt = 1; - } ra->prev_page = offset; if (offset >= ra->start && offset <= (ra->start + ra->size)) { @@ -411,12 +395,22 @@ page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra, * page beyond the end. Expand the next readahead size. */ ra->next_size += 2; + + if (ra->currnt_wnd_hit <= (max * 2)) + ra->currnt_wnd_hit++; } else { /* * A miss - lseek, pagefault, pread, etc. Shrink the readahead * window. */ ra->next_size -= 2; + + average = ra->average; + if (average < ra->currnt_wnd_hit) { + average++; + } + ra->average = (average + ra->currnt_wnd_hit) / 2; + ra->currnt_wnd_hit = 1; } if ((long)ra->next_size > (long)max) @@ -469,8 +463,8 @@ do_io: * current window. */ average = ra->average; - if (ra->serial_cnt > average) - average = (ra->serial_cnt + ra->average + 1) / 2; + if (ra->currnt_wnd_hit > average) + average = (ra->currnt_wnd_hit + ra->average + 1) / 2; ra->next_size = min(average , (unsigned long)max); } @@ -505,8 +499,8 @@ do_io: * random. Hence don't bother to readahead. */ average = ra->average; - if (ra->serial_cnt > average) - average = (ra->serial_cnt + ra->average + 1) / 2; + if (ra->currnt_wnd_hit > average) + average = (ra->currnt_wnd_hit + ra->average + 1) / 2; if (average > max) { ra->ahead_start = ra->start + ra->size; @@ -577,6 +571,6 @@ unsigned long max_sane_readahead(unsigned long nr) unsigned long inactive; unsigned long free; - get_zone_counts(&active, &inactive, &free); + __get_zone_counts(&active, &inactive, &free, NODE_DATA(numa_node_id())); return min(nr, (inactive + free) / 2); }