diff options
author | Hugh Dickins <hughd@google.com> | 2011-06-27 19:18:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-06-27 21:00:12 -0400 |
commit | d9d90e5eb70e09903dadff42099b6c948f814050 (patch) | |
tree | c3ab73df6dee61f9403bfd819a6b0cb9f3ca6085 | |
parent | 94c1e62df4494b79782cb9c7279f827212d1de70 (diff) |
tmpfs: add shmem_read_mapping_page_gfp
Although it is used (by i915) on nothing but tmpfs, read_cache_page_gfp()
is unsuited to tmpfs, because it inserts a page into pagecache before
calling the filesystem's ->readpage: tmpfs may have pages in swapcache
which only it knows how to locate and switch to filecache.
At present tmpfs provides a ->readpage method, and copes with this by
copying pages; but soon we can simplify it by removing its ->readpage.
Provide shmem_read_mapping_page_gfp() now, ready for that transition,
Export shmem_read_mapping_page_gfp() and add it to list in shmem_fs.h,
with shmem_read_mapping_page() inline for the common mapping_gfp case.
(shmem_read_mapping_page_gfp or shmem_read_cache_page_gfp? Generally the
read_mapping_page functions use the mapping's ->readpage, and the
read_cache_page functions use the supplied filler, so I think
read_cache_page_gfp was slightly misnamed.)
Signed-off-by: Hugh Dickins <hughd@google.com>
Cc: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | include/linux/shmem_fs.h | 17 | ||||
-rw-r--r-- | mm/shmem.c | 23 |
2 files changed, 33 insertions, 7 deletions
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index 22a20af4d785..aa08fa8fd79b 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h | |||
@@ -3,15 +3,9 @@ | |||
3 | 3 | ||
4 | #include <linux/swap.h> | 4 | #include <linux/swap.h> |
5 | #include <linux/mempolicy.h> | 5 | #include <linux/mempolicy.h> |
6 | #include <linux/pagemap.h> | ||
6 | #include <linux/percpu_counter.h> | 7 | #include <linux/percpu_counter.h> |
7 | 8 | ||
8 | struct page; | ||
9 | struct file; | ||
10 | struct inode; | ||
11 | struct super_block; | ||
12 | struct user_struct; | ||
13 | struct vm_area_struct; | ||
14 | |||
15 | /* inode in-kernel data */ | 9 | /* inode in-kernel data */ |
16 | 10 | ||
17 | #define SHMEM_NR_DIRECT 16 | 11 | #define SHMEM_NR_DIRECT 16 |
@@ -61,9 +55,18 @@ extern struct file *shmem_file_setup(const char *name, | |||
61 | loff_t size, unsigned long flags); | 55 | loff_t size, unsigned long flags); |
62 | extern int shmem_zero_setup(struct vm_area_struct *); | 56 | extern int shmem_zero_setup(struct vm_area_struct *); |
63 | extern int shmem_lock(struct file *file, int lock, struct user_struct *user); | 57 | extern int shmem_lock(struct file *file, int lock, struct user_struct *user); |
58 | extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping, | ||
59 | pgoff_t index, gfp_t gfp_mask); | ||
64 | extern void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end); | 60 | extern void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end); |
65 | extern int shmem_unuse(swp_entry_t entry, struct page *page); | 61 | extern int shmem_unuse(swp_entry_t entry, struct page *page); |
66 | extern void mem_cgroup_get_shmem_target(struct inode *inode, pgoff_t pgoff, | 62 | extern void mem_cgroup_get_shmem_target(struct inode *inode, pgoff_t pgoff, |
67 | struct page **pagep, swp_entry_t *ent); | 63 | struct page **pagep, swp_entry_t *ent); |
68 | 64 | ||
65 | static inline struct page *shmem_read_mapping_page( | ||
66 | struct address_space *mapping, pgoff_t index) | ||
67 | { | ||
68 | return shmem_read_mapping_page_gfp(mapping, index, | ||
69 | mapping_gfp_mask(mapping)); | ||
70 | } | ||
71 | |||
69 | #endif | 72 | #endif |
diff --git a/mm/shmem.c b/mm/shmem.c index f1714758ea96..fcedf5464eb7 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -3035,3 +3035,26 @@ int shmem_zero_setup(struct vm_area_struct *vma) | |||
3035 | vma->vm_flags |= VM_CAN_NONLINEAR; | 3035 | vma->vm_flags |= VM_CAN_NONLINEAR; |
3036 | return 0; | 3036 | return 0; |
3037 | } | 3037 | } |
3038 | |||
3039 | /** | ||
3040 | * shmem_read_mapping_page_gfp - read into page cache, using specified page allocation flags. | ||
3041 | * @mapping: the page's address_space | ||
3042 | * @index: the page index | ||
3043 | * @gfp: the page allocator flags to use if allocating | ||
3044 | * | ||
3045 | * This behaves as a tmpfs "read_cache_page_gfp(mapping, index, gfp)", | ||
3046 | * with any new page allocations done using the specified allocation flags. | ||
3047 | * But read_cache_page_gfp() uses the ->readpage() method: which does not | ||
3048 | * suit tmpfs, since it may have pages in swapcache, and needs to find those | ||
3049 | * for itself; although drivers/gpu/drm i915 and ttm rely upon this support. | ||
3050 | * | ||
3051 | * Provide a stub for those callers to start using now, then later | ||
3052 | * flesh it out to call shmem_getpage() with additional gfp mask, when | ||
3053 | * shmem_file_splice_read() is added and shmem_readpage() is removed. | ||
3054 | */ | ||
3055 | struct page *shmem_read_mapping_page_gfp(struct address_space *mapping, | ||
3056 | pgoff_t index, gfp_t gfp) | ||
3057 | { | ||
3058 | return read_cache_page_gfp(mapping, index, gfp); | ||
3059 | } | ||
3060 | EXPORT_SYMBOL_GPL(shmem_read_mapping_page_gfp); | ||