#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/backing-dev.h>
+#include <linux/task_io_accounting_ops.h>
#include <linux/pagevec.h>
void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping)
{
ra->ra_pages = mapping->backing_dev_info->ra_pages;
- ra->prev_page = -1;
+ ra->prev_index = -1;
}
EXPORT_SYMBOL_GPL(file_ra_state_init);
if (!pagevec_add(&lru_pvec, page))
__pagevec_lru_add(&lru_pvec);
if (ret) {
- while (!list_empty(pages)) {
- struct page *victim;
-
- victim = list_to_page(pages);
- list_del(&victim->lru);
- page_cache_release(victim);
- }
+ put_pages_list(pages);
break;
}
+ task_io_account_read(PAGE_CACHE_SIZE);
}
pagevec_lru_add(&lru_pvec);
return ret;
* size: Number of pages in that read
* Together, these form the "current window".
* Together, start and size represent the `readahead window'.
- * prev_page: The page which the readahead algorithm most-recently inspected.
+ * prev_index: The page which the readahead algorithm most-recently inspected.
* It is mainly used to detect sequential file reading.
* 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_index 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.
*
* When readahead is in the off state (size == 0), readahead is disabled.
- * In this state, prev_page is used to detect the resumption of sequential I/O.
+ * In this state, prev_index is used to detect the resumption of sequential I/O.
*
* The readahead code manages two windows - the "current" and the "ahead"
* windows. The intent is that while the application is walking the pages
ra->ahead_size = get_next_ra_size(ra);
ra->ahead_start = ra->start + ra->size;
- block = force || (ra->prev_page >= ra->ahead_start);
+ block = force || (ra->prev_index >= ra->ahead_start);
ret = blockable_page_cache_readahead(mapping, filp,
ra->ahead_start, ra->ahead_size, ra, block);
*
* Note that @filp is purely used for passing on to the ->readpage[s]()
* handler: it may refer to a different file from @mapping (so we may not use
- * @filp->f_mapping or @filp->f_dentry->d_inode here).
+ * @filp->f_mapping or @filp->f_path.dentry->d_inode here).
* Also, @ra may not be equal to &@filp->f_ra.
*
*/
* We avoid doing extra work and bogusly perturbing the readahead
* window expansion logic.
*/
- if (offset == ra->prev_page && --req_size)
+ if (offset == ra->prev_index && --req_size)
++offset;
- /* Note that prev_page == -1 if it is a first read */
- sequential = (offset == ra->prev_page + 1);
- ra->prev_page = offset;
+ /* Note that prev_index == -1 if it is a first read */
+ sequential = (offset == ra->prev_index + 1);
+ ra->prev_index = offset;
+ ra->prev_offset = 0;
max = get_max_readahead(ra);
newsize = min(req_size, max);
if (newsize == 0 || (ra->flags & RA_FLAG_INCACHE))
goto out;
- ra->prev_page += newsize - 1;
+ ra->prev_index += newsize - 1;
/*
* Special case - first read at start of file. We'll assume it's
* we get called back on the first page of the ahead window which
* will allow us to submit more IO.
*/
- if (ra->prev_page >= ra->ahead_start) {
+ if (ra->prev_index >= ra->ahead_start) {
ra->start = ra->ahead_start;
ra->size = ra->ahead_size;
make_ahead_window(mapping, filp, ra, 0);
recheck:
- /* prev_page shouldn't overrun the ahead window */
- ra->prev_page = min(ra->prev_page,
+ /* prev_index shouldn't overrun the ahead window */
+ ra->prev_index = min(ra->prev_index,
ra->ahead_start + ra->ahead_size - 1);
}
out:
- return ra->prev_page + 1;
+ return ra->prev_index + 1;
}
EXPORT_SYMBOL_GPL(page_cache_readahead);
*/
unsigned long max_sane_readahead(unsigned long nr)
{
- unsigned long active;
- unsigned long inactive;
- unsigned long free;
-
- __get_zone_counts(&active, &inactive, &free, NODE_DATA(numa_node_id()));
- return min(nr, (inactive + free) / 2);
+ return min(nr, (node_page_state(numa_node_id(), NR_INACTIVE)
+ + node_page_state(numa_node_id(), NR_FREE_PAGES)) / 2);
}