diff options
Diffstat (limited to 'mm/readahead.c')
| -rw-r--r-- | mm/readahead.c | 65 |
1 files changed, 38 insertions, 27 deletions
diff --git a/mm/readahead.c b/mm/readahead.c index bec83c15a78f..133b6d525513 100644 --- a/mm/readahead.c +++ b/mm/readahead.c | |||
| @@ -17,19 +17,6 @@ | |||
| 17 | #include <linux/pagevec.h> | 17 | #include <linux/pagevec.h> |
| 18 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
| 19 | 19 | ||
| 20 | void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) | ||
| 21 | { | ||
| 22 | } | ||
| 23 | EXPORT_SYMBOL(default_unplug_io_fn); | ||
| 24 | |||
| 25 | struct backing_dev_info default_backing_dev_info = { | ||
| 26 | .ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE, | ||
| 27 | .state = 0, | ||
| 28 | .capabilities = BDI_CAP_MAP_COPY, | ||
| 29 | .unplug_io_fn = default_unplug_io_fn, | ||
| 30 | }; | ||
| 31 | EXPORT_SYMBOL_GPL(default_backing_dev_info); | ||
| 32 | |||
| 33 | /* | 20 | /* |
| 34 | * Initialise a struct file's readahead state. Assumes that the caller has | 21 | * Initialise a struct file's readahead state. Assumes that the caller has |
| 35 | * memset *ra to zero. | 22 | * memset *ra to zero. |
| @@ -44,6 +31,42 @@ EXPORT_SYMBOL_GPL(file_ra_state_init); | |||
| 44 | 31 | ||
| 45 | #define list_to_page(head) (list_entry((head)->prev, struct page, lru)) | 32 | #define list_to_page(head) (list_entry((head)->prev, struct page, lru)) |
| 46 | 33 | ||
| 34 | /* | ||
| 35 | * see if a page needs releasing upon read_cache_pages() failure | ||
| 36 | * - the caller of read_cache_pages() may have set PG_private or PG_fscache | ||
| 37 | * before calling, such as the NFS fs marking pages that are cached locally | ||
| 38 | * on disk, thus we need to give the fs a chance to clean up in the event of | ||
| 39 | * an error | ||
| 40 | */ | ||
| 41 | static void read_cache_pages_invalidate_page(struct address_space *mapping, | ||
| 42 | struct page *page) | ||
| 43 | { | ||
| 44 | if (page_has_private(page)) { | ||
| 45 | if (!trylock_page(page)) | ||
| 46 | BUG(); | ||
| 47 | page->mapping = mapping; | ||
| 48 | do_invalidatepage(page, 0); | ||
| 49 | page->mapping = NULL; | ||
| 50 | unlock_page(page); | ||
| 51 | } | ||
| 52 | page_cache_release(page); | ||
| 53 | } | ||
| 54 | |||
| 55 | /* | ||
| 56 | * release a list of pages, invalidating them first if need be | ||
| 57 | */ | ||
| 58 | static void read_cache_pages_invalidate_pages(struct address_space *mapping, | ||
| 59 | struct list_head *pages) | ||
| 60 | { | ||
| 61 | struct page *victim; | ||
| 62 | |||
| 63 | while (!list_empty(pages)) { | ||
| 64 | victim = list_to_page(pages); | ||
| 65 | list_del(&victim->lru); | ||
| 66 | read_cache_pages_invalidate_page(mapping, victim); | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 47 | /** | 70 | /** |
| 48 | * read_cache_pages - populate an address space with some pages & start reads against them | 71 | * read_cache_pages - populate an address space with some pages & start reads against them |
| 49 | * @mapping: the address_space | 72 | * @mapping: the address_space |
| @@ -65,14 +88,14 @@ int read_cache_pages(struct address_space *mapping, struct list_head *pages, | |||
| 65 | list_del(&page->lru); | 88 | list_del(&page->lru); |
| 66 | if (add_to_page_cache_lru(page, mapping, | 89 | if (add_to_page_cache_lru(page, mapping, |
| 67 | page->index, GFP_KERNEL)) { | 90 | page->index, GFP_KERNEL)) { |
| 68 | page_cache_release(page); | 91 | read_cache_pages_invalidate_page(mapping, page); |
| 69 | continue; | 92 | continue; |
| 70 | } | 93 | } |
| 71 | page_cache_release(page); | 94 | page_cache_release(page); |
| 72 | 95 | ||
| 73 | ret = filler(data, page); | 96 | ret = filler(data, page); |
| 74 | if (unlikely(ret)) { | 97 | if (unlikely(ret)) { |
| 75 | put_pages_list(pages); | 98 | read_cache_pages_invalidate_pages(mapping, pages); |
| 76 | break; | 99 | break; |
| 77 | } | 100 | } |
| 78 | task_io_account_read(PAGE_CACHE_SIZE); | 101 | task_io_account_read(PAGE_CACHE_SIZE); |
| @@ -233,18 +256,6 @@ unsigned long max_sane_readahead(unsigned long nr) | |||
| 233 | + node_page_state(numa_node_id(), NR_FREE_PAGES)) / 2); | 256 | + node_page_state(numa_node_id(), NR_FREE_PAGES)) / 2); |
| 234 | } | 257 | } |
| 235 | 258 | ||
| 236 | static int __init readahead_init(void) | ||
| 237 | { | ||
| 238 | int err; | ||
| 239 | |||
| 240 | err = bdi_init(&default_backing_dev_info); | ||
| 241 | if (!err) | ||
| 242 | bdi_register(&default_backing_dev_info, NULL, "default"); | ||
| 243 | |||
| 244 | return err; | ||
| 245 | } | ||
| 246 | subsys_initcall(readahead_init); | ||
| 247 | |||
| 248 | /* | 259 | /* |
| 249 | * Submit IO for the read-ahead request in file_ra_state. | 260 | * Submit IO for the read-ahead request in file_ra_state. |
| 250 | */ | 261 | */ |
