diff options
-rw-r--r-- | fs/9p/vfs_file.c | 2 | ||||
-rw-r--r-- | fs/btrfs/file.c | 1 | ||||
-rw-r--r-- | fs/cifs/file.c | 1 | ||||
-rw-r--r-- | fs/ext4/file.c | 1 | ||||
-rw-r--r-- | fs/f2fs/file.c | 1 | ||||
-rw-r--r-- | fs/fuse/file.c | 1 | ||||
-rw-r--r-- | fs/gfs2/file.c | 1 | ||||
-rw-r--r-- | fs/nfs/file.c | 1 | ||||
-rw-r--r-- | fs/nilfs2/file.c | 1 | ||||
-rw-r--r-- | fs/ubifs/file.c | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_file.c | 1 | ||||
-rw-r--r-- | include/linux/mm.h | 1 | ||||
-rw-r--r-- | mm/filemap.c | 74 | ||||
-rw-r--r-- | mm/nommu.c | 6 |
14 files changed, 93 insertions, 0 deletions
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index a16b0ff497ca..d8223209d4b1 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -832,6 +832,7 @@ static void v9fs_mmap_vm_close(struct vm_area_struct *vma) | |||
832 | 832 | ||
833 | static const struct vm_operations_struct v9fs_file_vm_ops = { | 833 | static const struct vm_operations_struct v9fs_file_vm_ops = { |
834 | .fault = filemap_fault, | 834 | .fault = filemap_fault, |
835 | .map_pages = filemap_map_pages, | ||
835 | .page_mkwrite = v9fs_vm_page_mkwrite, | 836 | .page_mkwrite = v9fs_vm_page_mkwrite, |
836 | .remap_pages = generic_file_remap_pages, | 837 | .remap_pages = generic_file_remap_pages, |
837 | }; | 838 | }; |
@@ -839,6 +840,7 @@ static const struct vm_operations_struct v9fs_file_vm_ops = { | |||
839 | static const struct vm_operations_struct v9fs_mmap_file_vm_ops = { | 840 | static const struct vm_operations_struct v9fs_mmap_file_vm_ops = { |
840 | .close = v9fs_mmap_vm_close, | 841 | .close = v9fs_mmap_vm_close, |
841 | .fault = filemap_fault, | 842 | .fault = filemap_fault, |
843 | .map_pages = filemap_map_pages, | ||
842 | .page_mkwrite = v9fs_vm_page_mkwrite, | 844 | .page_mkwrite = v9fs_vm_page_mkwrite, |
843 | .remap_pages = generic_file_remap_pages, | 845 | .remap_pages = generic_file_remap_pages, |
844 | }; | 846 | }; |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index e1ffb1e22898..c660527af838 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -2025,6 +2025,7 @@ out: | |||
2025 | 2025 | ||
2026 | static const struct vm_operations_struct btrfs_file_vm_ops = { | 2026 | static const struct vm_operations_struct btrfs_file_vm_ops = { |
2027 | .fault = filemap_fault, | 2027 | .fault = filemap_fault, |
2028 | .map_pages = filemap_map_pages, | ||
2028 | .page_mkwrite = btrfs_page_mkwrite, | 2029 | .page_mkwrite = btrfs_page_mkwrite, |
2029 | .remap_pages = generic_file_remap_pages, | 2030 | .remap_pages = generic_file_remap_pages, |
2030 | }; | 2031 | }; |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 834fce759d80..216d7e99f921 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -3113,6 +3113,7 @@ cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
3113 | 3113 | ||
3114 | static struct vm_operations_struct cifs_file_vm_ops = { | 3114 | static struct vm_operations_struct cifs_file_vm_ops = { |
3115 | .fault = filemap_fault, | 3115 | .fault = filemap_fault, |
3116 | .map_pages = filemap_map_pages, | ||
3116 | .page_mkwrite = cifs_page_mkwrite, | 3117 | .page_mkwrite = cifs_page_mkwrite, |
3117 | .remap_pages = generic_file_remap_pages, | 3118 | .remap_pages = generic_file_remap_pages, |
3118 | }; | 3119 | }; |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 6db7f7db7777..4e508fc83dcf 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -200,6 +200,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, | |||
200 | 200 | ||
201 | static const struct vm_operations_struct ext4_file_vm_ops = { | 201 | static const struct vm_operations_struct ext4_file_vm_ops = { |
202 | .fault = filemap_fault, | 202 | .fault = filemap_fault, |
203 | .map_pages = filemap_map_pages, | ||
203 | .page_mkwrite = ext4_page_mkwrite, | 204 | .page_mkwrite = ext4_page_mkwrite, |
204 | .remap_pages = generic_file_remap_pages, | 205 | .remap_pages = generic_file_remap_pages, |
205 | }; | 206 | }; |
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 0dfcef53a6ed..129a3bdb05ca 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
@@ -84,6 +84,7 @@ out: | |||
84 | 84 | ||
85 | static const struct vm_operations_struct f2fs_file_vm_ops = { | 85 | static const struct vm_operations_struct f2fs_file_vm_ops = { |
86 | .fault = filemap_fault, | 86 | .fault = filemap_fault, |
87 | .map_pages = filemap_map_pages, | ||
87 | .page_mkwrite = f2fs_vm_page_mkwrite, | 88 | .page_mkwrite = f2fs_vm_page_mkwrite, |
88 | .remap_pages = generic_file_remap_pages, | 89 | .remap_pages = generic_file_remap_pages, |
89 | }; | 90 | }; |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 65df7d8be4f5..48992cac714b 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -2117,6 +2117,7 @@ static int fuse_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
2117 | static const struct vm_operations_struct fuse_file_vm_ops = { | 2117 | static const struct vm_operations_struct fuse_file_vm_ops = { |
2118 | .close = fuse_vma_close, | 2118 | .close = fuse_vma_close, |
2119 | .fault = filemap_fault, | 2119 | .fault = filemap_fault, |
2120 | .map_pages = filemap_map_pages, | ||
2120 | .page_mkwrite = fuse_page_mkwrite, | 2121 | .page_mkwrite = fuse_page_mkwrite, |
2121 | .remap_pages = generic_file_remap_pages, | 2122 | .remap_pages = generic_file_remap_pages, |
2122 | }; | 2123 | }; |
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 6c794085abac..80d67253623c 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -494,6 +494,7 @@ out: | |||
494 | 494 | ||
495 | static const struct vm_operations_struct gfs2_vm_ops = { | 495 | static const struct vm_operations_struct gfs2_vm_ops = { |
496 | .fault = filemap_fault, | 496 | .fault = filemap_fault, |
497 | .map_pages = filemap_map_pages, | ||
497 | .page_mkwrite = gfs2_page_mkwrite, | 498 | .page_mkwrite = gfs2_page_mkwrite, |
498 | .remap_pages = generic_file_remap_pages, | 499 | .remap_pages = generic_file_remap_pages, |
499 | }; | 500 | }; |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 5bb790a69c71..284ca901fe16 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -617,6 +617,7 @@ out: | |||
617 | 617 | ||
618 | static const struct vm_operations_struct nfs_file_vm_ops = { | 618 | static const struct vm_operations_struct nfs_file_vm_ops = { |
619 | .fault = filemap_fault, | 619 | .fault = filemap_fault, |
620 | .map_pages = filemap_map_pages, | ||
620 | .page_mkwrite = nfs_vm_page_mkwrite, | 621 | .page_mkwrite = nfs_vm_page_mkwrite, |
621 | .remap_pages = generic_file_remap_pages, | 622 | .remap_pages = generic_file_remap_pages, |
622 | }; | 623 | }; |
diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c index 08fdb77852ac..f3a82fbcae02 100644 --- a/fs/nilfs2/file.c +++ b/fs/nilfs2/file.c | |||
@@ -134,6 +134,7 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
134 | 134 | ||
135 | static const struct vm_operations_struct nilfs_file_vm_ops = { | 135 | static const struct vm_operations_struct nilfs_file_vm_ops = { |
136 | .fault = filemap_fault, | 136 | .fault = filemap_fault, |
137 | .map_pages = filemap_map_pages, | ||
137 | .page_mkwrite = nilfs_page_mkwrite, | 138 | .page_mkwrite = nilfs_page_mkwrite, |
138 | .remap_pages = generic_file_remap_pages, | 139 | .remap_pages = generic_file_remap_pages, |
139 | }; | 140 | }; |
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 123c79b7261e..4f34dbae823d 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c | |||
@@ -1538,6 +1538,7 @@ out_unlock: | |||
1538 | 1538 | ||
1539 | static const struct vm_operations_struct ubifs_file_vm_ops = { | 1539 | static const struct vm_operations_struct ubifs_file_vm_ops = { |
1540 | .fault = filemap_fault, | 1540 | .fault = filemap_fault, |
1541 | .map_pages = filemap_map_pages, | ||
1541 | .page_mkwrite = ubifs_vm_page_mkwrite, | 1542 | .page_mkwrite = ubifs_vm_page_mkwrite, |
1542 | .remap_pages = generic_file_remap_pages, | 1543 | .remap_pages = generic_file_remap_pages, |
1543 | }; | 1544 | }; |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index f7abff8c16ca..003c0051b62f 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -1483,6 +1483,7 @@ const struct file_operations xfs_dir_file_operations = { | |||
1483 | 1483 | ||
1484 | static const struct vm_operations_struct xfs_file_vm_ops = { | 1484 | static const struct vm_operations_struct xfs_file_vm_ops = { |
1485 | .fault = filemap_fault, | 1485 | .fault = filemap_fault, |
1486 | .map_pages = filemap_map_pages, | ||
1486 | .page_mkwrite = xfs_vm_page_mkwrite, | 1487 | .page_mkwrite = xfs_vm_page_mkwrite, |
1487 | .remap_pages = generic_file_remap_pages, | 1488 | .remap_pages = generic_file_remap_pages, |
1488 | }; | 1489 | }; |
diff --git a/include/linux/mm.h b/include/linux/mm.h index f710d32291e8..9132faed1a41 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -1847,6 +1847,7 @@ extern void truncate_inode_pages_final(struct address_space *); | |||
1847 | 1847 | ||
1848 | /* generic vm_area_ops exported for stackable file systems */ | 1848 | /* generic vm_area_ops exported for stackable file systems */ |
1849 | extern int filemap_fault(struct vm_area_struct *, struct vm_fault *); | 1849 | extern int filemap_fault(struct vm_area_struct *, struct vm_fault *); |
1850 | extern void filemap_map_pages(struct vm_area_struct *vma, struct vm_fault *vmf); | ||
1850 | extern int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); | 1851 | extern int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); |
1851 | 1852 | ||
1852 | /* mm/page-writeback.c */ | 1853 | /* mm/page-writeback.c */ |
diff --git a/mm/filemap.c b/mm/filemap.c index 21781f1fe52b..3f9b5fbb623f 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/hardirq.h> /* for BUG_ON(!in_atomic()) only */ | 33 | #include <linux/hardirq.h> /* for BUG_ON(!in_atomic()) only */ |
34 | #include <linux/memcontrol.h> | 34 | #include <linux/memcontrol.h> |
35 | #include <linux/cleancache.h> | 35 | #include <linux/cleancache.h> |
36 | #include <linux/rmap.h> | ||
36 | #include "internal.h" | 37 | #include "internal.h" |
37 | 38 | ||
38 | #define CREATE_TRACE_POINTS | 39 | #define CREATE_TRACE_POINTS |
@@ -2064,6 +2065,78 @@ page_not_uptodate: | |||
2064 | } | 2065 | } |
2065 | EXPORT_SYMBOL(filemap_fault); | 2066 | EXPORT_SYMBOL(filemap_fault); |
2066 | 2067 | ||
2068 | void filemap_map_pages(struct vm_area_struct *vma, struct vm_fault *vmf) | ||
2069 | { | ||
2070 | struct radix_tree_iter iter; | ||
2071 | void **slot; | ||
2072 | struct file *file = vma->vm_file; | ||
2073 | struct address_space *mapping = file->f_mapping; | ||
2074 | loff_t size; | ||
2075 | struct page *page; | ||
2076 | unsigned long address = (unsigned long) vmf->virtual_address; | ||
2077 | unsigned long addr; | ||
2078 | pte_t *pte; | ||
2079 | |||
2080 | rcu_read_lock(); | ||
2081 | radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, vmf->pgoff) { | ||
2082 | if (iter.index > vmf->max_pgoff) | ||
2083 | break; | ||
2084 | repeat: | ||
2085 | page = radix_tree_deref_slot(slot); | ||
2086 | if (unlikely(!page)) | ||
2087 | goto next; | ||
2088 | if (radix_tree_exception(page)) { | ||
2089 | if (radix_tree_deref_retry(page)) | ||
2090 | break; | ||
2091 | else | ||
2092 | goto next; | ||
2093 | } | ||
2094 | |||
2095 | if (!page_cache_get_speculative(page)) | ||
2096 | goto repeat; | ||
2097 | |||
2098 | /* Has the page moved? */ | ||
2099 | if (unlikely(page != *slot)) { | ||
2100 | page_cache_release(page); | ||
2101 | goto repeat; | ||
2102 | } | ||
2103 | |||
2104 | if (!PageUptodate(page) || | ||
2105 | PageReadahead(page) || | ||
2106 | PageHWPoison(page)) | ||
2107 | goto skip; | ||
2108 | if (!trylock_page(page)) | ||
2109 | goto skip; | ||
2110 | |||
2111 | if (page->mapping != mapping || !PageUptodate(page)) | ||
2112 | goto unlock; | ||
2113 | |||
2114 | size = i_size_read(mapping->host) + PAGE_CACHE_SIZE - 1; | ||
2115 | if (page->index >= size >> PAGE_CACHE_SHIFT) | ||
2116 | goto unlock; | ||
2117 | |||
2118 | pte = vmf->pte + page->index - vmf->pgoff; | ||
2119 | if (!pte_none(*pte)) | ||
2120 | goto unlock; | ||
2121 | |||
2122 | if (file->f_ra.mmap_miss > 0) | ||
2123 | file->f_ra.mmap_miss--; | ||
2124 | addr = address + (page->index - vmf->pgoff) * PAGE_SIZE; | ||
2125 | do_set_pte(vma, addr, page, pte, false, false); | ||
2126 | unlock_page(page); | ||
2127 | goto next; | ||
2128 | unlock: | ||
2129 | unlock_page(page); | ||
2130 | skip: | ||
2131 | page_cache_release(page); | ||
2132 | next: | ||
2133 | if (iter.index == vmf->max_pgoff) | ||
2134 | break; | ||
2135 | } | ||
2136 | rcu_read_unlock(); | ||
2137 | } | ||
2138 | EXPORT_SYMBOL(filemap_map_pages); | ||
2139 | |||
2067 | int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | 2140 | int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) |
2068 | { | 2141 | { |
2069 | struct page *page = vmf->page; | 2142 | struct page *page = vmf->page; |
@@ -2093,6 +2166,7 @@ EXPORT_SYMBOL(filemap_page_mkwrite); | |||
2093 | 2166 | ||
2094 | const struct vm_operations_struct generic_file_vm_ops = { | 2167 | const struct vm_operations_struct generic_file_vm_ops = { |
2095 | .fault = filemap_fault, | 2168 | .fault = filemap_fault, |
2169 | .map_pages = filemap_map_pages, | ||
2096 | .page_mkwrite = filemap_page_mkwrite, | 2170 | .page_mkwrite = filemap_page_mkwrite, |
2097 | .remap_pages = generic_file_remap_pages, | 2171 | .remap_pages = generic_file_remap_pages, |
2098 | }; | 2172 | }; |
diff --git a/mm/nommu.c b/mm/nommu.c index a554e5a451cd..e19482533ce3 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
@@ -1985,6 +1985,12 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
1985 | } | 1985 | } |
1986 | EXPORT_SYMBOL(filemap_fault); | 1986 | EXPORT_SYMBOL(filemap_fault); |
1987 | 1987 | ||
1988 | void filemap_map_pages(struct vm_area_struct *vma, struct vm_fault *vmf) | ||
1989 | { | ||
1990 | BUG(); | ||
1991 | } | ||
1992 | EXPORT_SYMBOL(filemap_map_pages); | ||
1993 | |||
1988 | int generic_file_remap_pages(struct vm_area_struct *vma, unsigned long addr, | 1994 | int generic_file_remap_pages(struct vm_area_struct *vma, unsigned long addr, |
1989 | unsigned long size, pgoff_t pgoff) | 1995 | unsigned long size, pgoff_t pgoff) |
1990 | { | 1996 | { |