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. |