diff options
| author | Jens Axboe <axboe@suse.de> | 2006-04-27 02:46:01 -0400 |
|---|---|---|
| committer | Jens Axboe <axboe@nelson.home.kernel.dk> | 2006-04-27 02:59:48 -0400 |
| commit | ebf43500ef148a380bd132743c3fc530111ac620 (patch) | |
| tree | 01ddb60f5662cf92b96b0468bf9820518a611209 | |
| parent | eb645a24de82496434cc81171d7f350edb327399 (diff) | |
[PATCH] Add find_get_pages_contig(): contiguous variant of find_get_pages()
find_get_pages_contig() will break out if we hit a hole in the page cache.
From Andrew Morton, small modifications and documentation by me.
Signed-off-by: Jens Axboe <axboe@suse.de>
| -rw-r--r-- | include/linux/pagemap.h | 2 | ||||
| -rw-r--r-- | mm/filemap.c | 32 |
2 files changed, 34 insertions, 0 deletions
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 9539efd4f7e6..7a1af574dedf 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h | |||
| @@ -78,6 +78,8 @@ extern struct page * find_or_create_page(struct address_space *mapping, | |||
| 78 | unsigned long index, gfp_t gfp_mask); | 78 | unsigned long index, gfp_t gfp_mask); |
| 79 | unsigned find_get_pages(struct address_space *mapping, pgoff_t start, | 79 | unsigned find_get_pages(struct address_space *mapping, pgoff_t start, |
| 80 | unsigned int nr_pages, struct page **pages); | 80 | unsigned int nr_pages, struct page **pages); |
| 81 | unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t start, | ||
| 82 | unsigned int nr_pages, struct page **pages); | ||
| 81 | unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index, | 83 | unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index, |
| 82 | int tag, unsigned int nr_pages, struct page **pages); | 84 | int tag, unsigned int nr_pages, struct page **pages); |
| 83 | 85 | ||
diff --git a/mm/filemap.c b/mm/filemap.c index 3ef20739e725..fd57442186cb 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
| @@ -697,6 +697,38 @@ unsigned find_get_pages(struct address_space *mapping, pgoff_t start, | |||
| 697 | return ret; | 697 | return ret; |
| 698 | } | 698 | } |
| 699 | 699 | ||
| 700 | /** | ||
| 701 | * find_get_pages_contig - gang contiguous pagecache lookup | ||
| 702 | * @mapping: The address_space to search | ||
| 703 | * @index: The starting page index | ||
| 704 | * @nr_pages: The maximum number of pages | ||
| 705 | * @pages: Where the resulting pages are placed | ||
| 706 | * | ||
| 707 | * find_get_pages_contig() works exactly like find_get_pages(), except | ||
| 708 | * that the returned number of pages are guaranteed to be contiguous. | ||
| 709 | * | ||
| 710 | * find_get_pages_contig() returns the number of pages which were found. | ||
| 711 | */ | ||
| 712 | unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index, | ||
| 713 | unsigned int nr_pages, struct page **pages) | ||
| 714 | { | ||
| 715 | unsigned int i; | ||
| 716 | unsigned int ret; | ||
| 717 | |||
| 718 | read_lock_irq(&mapping->tree_lock); | ||
| 719 | ret = radix_tree_gang_lookup(&mapping->page_tree, | ||
| 720 | (void **)pages, index, nr_pages); | ||
| 721 | for (i = 0; i < ret; i++) { | ||
| 722 | if (pages[i]->mapping == NULL || pages[i]->index != index) | ||
| 723 | break; | ||
| 724 | |||
| 725 | page_cache_get(pages[i]); | ||
| 726 | index++; | ||
| 727 | } | ||
| 728 | read_unlock_irq(&mapping->tree_lock); | ||
| 729 | return i; | ||
| 730 | } | ||
| 731 | |||
| 700 | /* | 732 | /* |
| 701 | * Like find_get_pages, except we only return pages which are tagged with | 733 | * Like find_get_pages, except we only return pages which are tagged with |
| 702 | * `tag'. We update *index to index the next page for the traversal. | 734 | * `tag'. We update *index to index the next page for the traversal. |
