aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonstantin Khlebnikov <khlebnikov@openvz.org>2012-10-08 19:28:46 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-09 03:22:17 -0400
commit0b173bc4daa8f8ec03a85abf5e47b23502ff80af (patch)
tree173d0523555e02a077e0af4563bd4cadea46cb23
parent4b6e1e37026ec7dae9b23d78ffcebdd5ddb1bfa1 (diff)
mm: kill vma flag VM_CAN_NONLINEAR
Move actual pte filling for non-linear file mappings into the new special vma operation: ->remap_pages(). Filesystems must implement this method to get non-linear mapping support, if it uses filemap_fault() then generic_file_remap_pages() can be used. Now device drivers can implement this method and obtain nonlinear vma support. Signed-off-by: Konstantin Khlebnikov <khlebnikov@openvz.org> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Carsten Otte <cotte@de.ibm.com> Cc: Chris Metcalf <cmetcalf@tilera.com> #arch/tile Cc: Cyrill Gorcunov <gorcunov@openvz.org> Cc: Eric Paris <eparis@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Hugh Dickins <hughd@google.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Morris <james.l.morris@oracle.com> Cc: Jason Baron <jbaron@redhat.com> Cc: Kentaro Takeda <takedakn@nttdata.co.jp> Cc: Matt Helsley <matthltc@us.ibm.com> Cc: Nick Piggin <npiggin@kernel.dk> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Robert Richter <robert.richter@amd.com> Cc: Suresh Siddha <suresh.b.siddha@intel.com> Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Cc: Venkatesh Pallipadi <venki@google.com> Acked-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/staging/android/ashmem.c1
-rw-r--r--fs/9p/vfs_file.c1
-rw-r--r--fs/btrfs/file.c2
-rw-r--r--fs/ceph/addr.c2
-rw-r--r--fs/cifs/file.c1
-rw-r--r--fs/ext4/file.c2
-rw-r--r--fs/fuse/file.c1
-rw-r--r--fs/gfs2/file.c2
-rw-r--r--fs/nfs/file.c1
-rw-r--r--fs/nilfs2/file.c2
-rw-r--r--fs/ocfs2/mmap.c2
-rw-r--r--fs/ubifs/file.c1
-rw-r--r--fs/xfs/xfs_file.c2
-rw-r--r--include/linux/fs.h2
-rw-r--r--include/linux/mm.h7
-rw-r--r--mm/filemap.c2
-rw-r--r--mm/filemap_xip.c3
-rw-r--r--mm/fremap.c14
-rw-r--r--mm/mmap.c3
-rw-r--r--mm/nommu.c8
-rw-r--r--mm/shmem.c3
21 files changed, 39 insertions, 23 deletions
diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c
index 94a740d2883d..634b9ae713e0 100644
--- a/drivers/staging/android/ashmem.c
+++ b/drivers/staging/android/ashmem.c
@@ -332,7 +332,6 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
332 if (vma->vm_file) 332 if (vma->vm_file)
333 fput(vma->vm_file); 333 fput(vma->vm_file);
334 vma->vm_file = asma->file; 334 vma->vm_file = asma->file;
335 vma->vm_flags |= VM_CAN_NONLINEAR;
336 335
337out: 336out:
338 mutex_unlock(&ashmem_mutex); 337 mutex_unlock(&ashmem_mutex);
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index dd6f7ee1e312..c2483e97beee 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -738,6 +738,7 @@ v9fs_cached_file_write(struct file *filp, const char __user * data,
738static const struct vm_operations_struct v9fs_file_vm_ops = { 738static const struct vm_operations_struct v9fs_file_vm_ops = {
739 .fault = filemap_fault, 739 .fault = filemap_fault,
740 .page_mkwrite = v9fs_vm_page_mkwrite, 740 .page_mkwrite = v9fs_vm_page_mkwrite,
741 .remap_pages = generic_file_remap_pages,
741}; 742};
742 743
743 744
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 5caf285c6e4d..f6b40e86121b 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1599,6 +1599,7 @@ out:
1599static const struct vm_operations_struct btrfs_file_vm_ops = { 1599static const struct vm_operations_struct btrfs_file_vm_ops = {
1600 .fault = filemap_fault, 1600 .fault = filemap_fault,
1601 .page_mkwrite = btrfs_page_mkwrite, 1601 .page_mkwrite = btrfs_page_mkwrite,
1602 .remap_pages = generic_file_remap_pages,
1602}; 1603};
1603 1604
1604static int btrfs_file_mmap(struct file *filp, struct vm_area_struct *vma) 1605static int btrfs_file_mmap(struct file *filp, struct vm_area_struct *vma)
@@ -1610,7 +1611,6 @@ static int btrfs_file_mmap(struct file *filp, struct vm_area_struct *vma)
1610 1611
1611 file_accessed(filp); 1612 file_accessed(filp);
1612 vma->vm_ops = &btrfs_file_vm_ops; 1613 vma->vm_ops = &btrfs_file_vm_ops;
1613 vma->vm_flags |= VM_CAN_NONLINEAR;
1614 1614
1615 return 0; 1615 return 0;
1616} 1616}
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 22b6e4583faa..6690269f5dde 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -1224,6 +1224,7 @@ out:
1224static struct vm_operations_struct ceph_vmops = { 1224static struct vm_operations_struct ceph_vmops = {
1225 .fault = filemap_fault, 1225 .fault = filemap_fault,
1226 .page_mkwrite = ceph_page_mkwrite, 1226 .page_mkwrite = ceph_page_mkwrite,
1227 .remap_pages = generic_file_remap_pages,
1227}; 1228};
1228 1229
1229int ceph_mmap(struct file *file, struct vm_area_struct *vma) 1230int ceph_mmap(struct file *file, struct vm_area_struct *vma)
@@ -1234,6 +1235,5 @@ int ceph_mmap(struct file *file, struct vm_area_struct *vma)
1234 return -ENOEXEC; 1235 return -ENOEXEC;
1235 file_accessed(file); 1236 file_accessed(file);
1236 vma->vm_ops = &ceph_vmops; 1237 vma->vm_ops = &ceph_vmops;
1237 vma->vm_flags |= VM_CAN_NONLINEAR;
1238 return 0; 1238 return 0;
1239} 1239}
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 7d7bbdc4c8e7..edb25b4bbb95 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -3003,6 +3003,7 @@ cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
3003static struct vm_operations_struct cifs_file_vm_ops = { 3003static struct vm_operations_struct cifs_file_vm_ops = {
3004 .fault = filemap_fault, 3004 .fault = filemap_fault,
3005 .page_mkwrite = cifs_page_mkwrite, 3005 .page_mkwrite = cifs_page_mkwrite,
3006 .remap_pages = generic_file_remap_pages,
3006}; 3007};
3007 3008
3008int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) 3009int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index ca6f07afe601..bf3966bccd34 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -207,6 +207,7 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
207static const struct vm_operations_struct ext4_file_vm_ops = { 207static const struct vm_operations_struct ext4_file_vm_ops = {
208 .fault = filemap_fault, 208 .fault = filemap_fault,
209 .page_mkwrite = ext4_page_mkwrite, 209 .page_mkwrite = ext4_page_mkwrite,
210 .remap_pages = generic_file_remap_pages,
210}; 211};
211 212
212static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma) 213static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
@@ -217,7 +218,6 @@ static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
217 return -ENOEXEC; 218 return -ENOEXEC;
218 file_accessed(file); 219 file_accessed(file);
219 vma->vm_ops = &ext4_file_vm_ops; 220 vma->vm_ops = &ext4_file_vm_ops;
220 vma->vm_flags |= VM_CAN_NONLINEAR;
221 return 0; 221 return 0;
222} 222}
223 223
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index aba15f1b7ad2..78d2837bc940 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1379,6 +1379,7 @@ static const struct vm_operations_struct fuse_file_vm_ops = {
1379 .close = fuse_vma_close, 1379 .close = fuse_vma_close,
1380 .fault = filemap_fault, 1380 .fault = filemap_fault,
1381 .page_mkwrite = fuse_page_mkwrite, 1381 .page_mkwrite = fuse_page_mkwrite,
1382 .remap_pages = generic_file_remap_pages,
1382}; 1383};
1383 1384
1384static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) 1385static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 30e21997a1a1..0def0504afc1 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -492,6 +492,7 @@ out:
492static const struct vm_operations_struct gfs2_vm_ops = { 492static const struct vm_operations_struct gfs2_vm_ops = {
493 .fault = filemap_fault, 493 .fault = filemap_fault,
494 .page_mkwrite = gfs2_page_mkwrite, 494 .page_mkwrite = gfs2_page_mkwrite,
495 .remap_pages = generic_file_remap_pages,
495}; 496};
496 497
497/** 498/**
@@ -526,7 +527,6 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
526 return error; 527 return error;
527 } 528 }
528 vma->vm_ops = &gfs2_vm_ops; 529 vma->vm_ops = &gfs2_vm_ops;
529 vma->vm_flags |= VM_CAN_NONLINEAR;
530 530
531 return 0; 531 return 0;
532} 532}
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 6a7fcab7ecb3..f692be97676d 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -578,6 +578,7 @@ out:
578static const struct vm_operations_struct nfs_file_vm_ops = { 578static const struct vm_operations_struct nfs_file_vm_ops = {
579 .fault = filemap_fault, 579 .fault = filemap_fault,
580 .page_mkwrite = nfs_vm_page_mkwrite, 580 .page_mkwrite = nfs_vm_page_mkwrite,
581 .remap_pages = generic_file_remap_pages,
581}; 582};
582 583
583static int nfs_need_sync_write(struct file *filp, struct inode *inode) 584static int nfs_need_sync_write(struct file *filp, struct inode *inode)
diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c
index 5b387a4c293e..16f35f7423c5 100644
--- a/fs/nilfs2/file.c
+++ b/fs/nilfs2/file.c
@@ -135,13 +135,13 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
135static const struct vm_operations_struct nilfs_file_vm_ops = { 135static const struct vm_operations_struct nilfs_file_vm_ops = {
136 .fault = filemap_fault, 136 .fault = filemap_fault,
137 .page_mkwrite = nilfs_page_mkwrite, 137 .page_mkwrite = nilfs_page_mkwrite,
138 .remap_pages = generic_file_remap_pages,
138}; 139};
139 140
140static int nilfs_file_mmap(struct file *file, struct vm_area_struct *vma) 141static int nilfs_file_mmap(struct file *file, struct vm_area_struct *vma)
141{ 142{
142 file_accessed(file); 143 file_accessed(file);
143 vma->vm_ops = &nilfs_file_vm_ops; 144 vma->vm_ops = &nilfs_file_vm_ops;
144 vma->vm_flags |= VM_CAN_NONLINEAR;
145 return 0; 145 return 0;
146} 146}
147 147
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c
index d150372fd81d..47a87dda54ce 100644
--- a/fs/ocfs2/mmap.c
+++ b/fs/ocfs2/mmap.c
@@ -173,6 +173,7 @@ out:
173static const struct vm_operations_struct ocfs2_file_vm_ops = { 173static const struct vm_operations_struct ocfs2_file_vm_ops = {
174 .fault = ocfs2_fault, 174 .fault = ocfs2_fault,
175 .page_mkwrite = ocfs2_page_mkwrite, 175 .page_mkwrite = ocfs2_page_mkwrite,
176 .remap_pages = generic_file_remap_pages,
176}; 177};
177 178
178int ocfs2_mmap(struct file *file, struct vm_area_struct *vma) 179int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
@@ -188,7 +189,6 @@ int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
188 ocfs2_inode_unlock(file->f_dentry->d_inode, lock_level); 189 ocfs2_inode_unlock(file->f_dentry->d_inode, lock_level);
189out: 190out:
190 vma->vm_ops = &ocfs2_file_vm_ops; 191 vma->vm_ops = &ocfs2_file_vm_ops;
191 vma->vm_flags |= VM_CAN_NONLINEAR;
192 return 0; 192 return 0;
193} 193}
194 194
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index ff48c5a85309..5bc77817f382 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1536,6 +1536,7 @@ out_unlock:
1536static const struct vm_operations_struct ubifs_file_vm_ops = { 1536static const struct vm_operations_struct ubifs_file_vm_ops = {
1537 .fault = filemap_fault, 1537 .fault = filemap_fault,
1538 .page_mkwrite = ubifs_vm_page_mkwrite, 1538 .page_mkwrite = ubifs_vm_page_mkwrite,
1539 .remap_pages = generic_file_remap_pages,
1539}; 1540};
1540 1541
1541static int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma) 1542static int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma)
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 1eaeb8be3aae..aa473fa640a2 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -940,7 +940,6 @@ xfs_file_mmap(
940 struct vm_area_struct *vma) 940 struct vm_area_struct *vma)
941{ 941{
942 vma->vm_ops = &xfs_file_vm_ops; 942 vma->vm_ops = &xfs_file_vm_ops;
943 vma->vm_flags |= VM_CAN_NONLINEAR;
944 943
945 file_accessed(filp); 944 file_accessed(filp);
946 return 0; 945 return 0;
@@ -1443,4 +1442,5 @@ const struct file_operations xfs_dir_file_operations = {
1443static const struct vm_operations_struct xfs_file_vm_ops = { 1442static const struct vm_operations_struct xfs_file_vm_ops = {
1444 .fault = filemap_fault, 1443 .fault = filemap_fault,
1445 .page_mkwrite = xfs_vm_page_mkwrite, 1444 .page_mkwrite = xfs_vm_page_mkwrite,
1445 .remap_pages = generic_file_remap_pages,
1446}; 1446};
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ca6d8c806f47..5a8a273d5b2f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2552,6 +2552,8 @@ extern int sb_min_blocksize(struct super_block *, int);
2552 2552
2553extern int generic_file_mmap(struct file *, struct vm_area_struct *); 2553extern int generic_file_mmap(struct file *, struct vm_area_struct *);
2554extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *); 2554extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *);
2555extern int generic_file_remap_pages(struct vm_area_struct *, unsigned long addr,
2556 unsigned long size, pgoff_t pgoff);
2555extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size); 2557extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
2556int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk); 2558int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk);
2557extern ssize_t generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t); 2559extern ssize_t generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index fb0685b17914..44d3fc25f556 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -105,7 +105,6 @@ extern unsigned int kobjsize(const void *objp);
105#define VM_ARCH_1 0x01000000 /* Architecture-specific flag */ 105#define VM_ARCH_1 0x01000000 /* Architecture-specific flag */
106#define VM_NODUMP 0x04000000 /* Do not include in the core dump */ 106#define VM_NODUMP 0x04000000 /* Do not include in the core dump */
107 107
108#define VM_CAN_NONLINEAR 0x08000000 /* Has ->fault & does nonlinear pages */
109#define VM_MIXEDMAP 0x10000000 /* Can contain "struct page" and pure PFN pages */ 108#define VM_MIXEDMAP 0x10000000 /* Can contain "struct page" and pure PFN pages */
110#define VM_HUGEPAGE 0x20000000 /* MADV_HUGEPAGE marked this vma */ 109#define VM_HUGEPAGE 0x20000000 /* MADV_HUGEPAGE marked this vma */
111#define VM_NOHUGEPAGE 0x40000000 /* MADV_NOHUGEPAGE marked this vma */ 110#define VM_NOHUGEPAGE 0x40000000 /* MADV_NOHUGEPAGE marked this vma */
@@ -171,8 +170,7 @@ extern pgprot_t protection_map[16];
171 * of VM_FAULT_xxx flags that give details about how the fault was handled. 170 * of VM_FAULT_xxx flags that give details about how the fault was handled.
172 * 171 *
173 * pgoff should be used in favour of virtual_address, if possible. If pgoff 172 * pgoff should be used in favour of virtual_address, if possible. If pgoff
174 * is used, one may set VM_CAN_NONLINEAR in the vma->vm_flags to get nonlinear 173 * is used, one may implement ->remap_pages to get nonlinear mapping support.
175 * mapping support.
176 */ 174 */
177struct vm_fault { 175struct vm_fault {
178 unsigned int flags; /* FAULT_FLAG_xxx flags */ 176 unsigned int flags; /* FAULT_FLAG_xxx flags */
@@ -230,6 +228,9 @@ struct vm_operations_struct {
230 int (*migrate)(struct vm_area_struct *vma, const nodemask_t *from, 228 int (*migrate)(struct vm_area_struct *vma, const nodemask_t *from,
231 const nodemask_t *to, unsigned long flags); 229 const nodemask_t *to, unsigned long flags);
232#endif 230#endif
231 /* called by sys_remap_file_pages() to populate non-linear mapping */
232 int (*remap_pages)(struct vm_area_struct *vma, unsigned long addr,
233 unsigned long size, pgoff_t pgoff);
233}; 234};
234 235
235struct mmu_gather; 236struct mmu_gather;
diff --git a/mm/filemap.c b/mm/filemap.c
index 384344575c37..a9827b42556e 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1737,6 +1737,7 @@ EXPORT_SYMBOL(filemap_page_mkwrite);
1737const struct vm_operations_struct generic_file_vm_ops = { 1737const struct vm_operations_struct generic_file_vm_ops = {
1738 .fault = filemap_fault, 1738 .fault = filemap_fault,
1739 .page_mkwrite = filemap_page_mkwrite, 1739 .page_mkwrite = filemap_page_mkwrite,
1740 .remap_pages = generic_file_remap_pages,
1740}; 1741};
1741 1742
1742/* This is used for a general mmap of a disk file */ 1743/* This is used for a general mmap of a disk file */
@@ -1749,7 +1750,6 @@ int generic_file_mmap(struct file * file, struct vm_area_struct * vma)
1749 return -ENOEXEC; 1750 return -ENOEXEC;
1750 file_accessed(file); 1751 file_accessed(file);
1751 vma->vm_ops = &generic_file_vm_ops; 1752 vma->vm_ops = &generic_file_vm_ops;
1752 vma->vm_flags |= VM_CAN_NONLINEAR;
1753 return 0; 1753 return 0;
1754} 1754}
1755 1755
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index 13e013b1270c..91750227a191 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -305,6 +305,7 @@ out:
305static const struct vm_operations_struct xip_file_vm_ops = { 305static const struct vm_operations_struct xip_file_vm_ops = {
306 .fault = xip_file_fault, 306 .fault = xip_file_fault,
307 .page_mkwrite = filemap_page_mkwrite, 307 .page_mkwrite = filemap_page_mkwrite,
308 .remap_pages = generic_file_remap_pages,
308}; 309};
309 310
310int xip_file_mmap(struct file * file, struct vm_area_struct * vma) 311int xip_file_mmap(struct file * file, struct vm_area_struct * vma)
@@ -313,7 +314,7 @@ int xip_file_mmap(struct file * file, struct vm_area_struct * vma)
313 314
314 file_accessed(file); 315 file_accessed(file);
315 vma->vm_ops = &xip_file_vm_ops; 316 vma->vm_ops = &xip_file_vm_ops;
316 vma->vm_flags |= VM_CAN_NONLINEAR | VM_MIXEDMAP; 317 vma->vm_flags |= VM_MIXEDMAP;
317 return 0; 318 return 0;
318} 319}
319EXPORT_SYMBOL_GPL(xip_file_mmap); 320EXPORT_SYMBOL_GPL(xip_file_mmap);
diff --git a/mm/fremap.c b/mm/fremap.c
index 048659c0c03d..3d731a498788 100644
--- a/mm/fremap.c
+++ b/mm/fremap.c
@@ -5,6 +5,7 @@
5 * 5 *
6 * started by Ingo Molnar, Copyright (C) 2002, 2003 6 * started by Ingo Molnar, Copyright (C) 2002, 2003
7 */ 7 */
8#include <linux/export.h>
8#include <linux/backing-dev.h> 9#include <linux/backing-dev.h>
9#include <linux/mm.h> 10#include <linux/mm.h>
10#include <linux/swap.h> 11#include <linux/swap.h>
@@ -80,9 +81,10 @@ out:
80 return err; 81 return err;
81} 82}
82 83
83static int populate_range(struct mm_struct *mm, struct vm_area_struct *vma, 84int generic_file_remap_pages(struct vm_area_struct *vma, unsigned long addr,
84 unsigned long addr, unsigned long size, pgoff_t pgoff) 85 unsigned long size, pgoff_t pgoff)
85{ 86{
87 struct mm_struct *mm = vma->vm_mm;
86 int err; 88 int err;
87 89
88 do { 90 do {
@@ -95,9 +97,9 @@ static int populate_range(struct mm_struct *mm, struct vm_area_struct *vma,
95 pgoff++; 97 pgoff++;
96 } while (size); 98 } while (size);
97 99
98 return 0; 100 return 0;
99
100} 101}
102EXPORT_SYMBOL(generic_file_remap_pages);
101 103
102/** 104/**
103 * sys_remap_file_pages - remap arbitrary pages of an existing VM_SHARED vma 105 * sys_remap_file_pages - remap arbitrary pages of an existing VM_SHARED vma
@@ -167,7 +169,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
167 if (vma->vm_private_data && !(vma->vm_flags & VM_NONLINEAR)) 169 if (vma->vm_private_data && !(vma->vm_flags & VM_NONLINEAR))
168 goto out; 170 goto out;
169 171
170 if (!(vma->vm_flags & VM_CAN_NONLINEAR)) 172 if (!vma->vm_ops->remap_pages)
171 goto out; 173 goto out;
172 174
173 if (start < vma->vm_start || start + size > vma->vm_end) 175 if (start < vma->vm_start || start + size > vma->vm_end)
@@ -228,7 +230,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
228 } 230 }
229 231
230 mmu_notifier_invalidate_range_start(mm, start, start + size); 232 mmu_notifier_invalidate_range_start(mm, start, start + size);
231 err = populate_range(mm, vma, start, size, pgoff); 233 err = vma->vm_ops->remap_pages(vma, start, size, pgoff);
232 mmu_notifier_invalidate_range_end(mm, start, start + size); 234 mmu_notifier_invalidate_range_end(mm, start, start + size);
233 if (!err && !(flags & MAP_NONBLOCK)) { 235 if (!err && !(flags & MAP_NONBLOCK)) {
234 if (vma->vm_flags & VM_LOCKED) { 236 if (vma->vm_flags & VM_LOCKED) {
diff --git a/mm/mmap.c b/mm/mmap.c
index b0989f4d4f09..d0686d355113 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -669,8 +669,7 @@ again: remove_next = 1 + (end > next->vm_end);
669static inline int is_mergeable_vma(struct vm_area_struct *vma, 669static inline int is_mergeable_vma(struct vm_area_struct *vma,
670 struct file *file, unsigned long vm_flags) 670 struct file *file, unsigned long vm_flags)
671{ 671{
672 /* VM_CAN_NONLINEAR may get set later by f_op->mmap() */ 672 if (vma->vm_flags ^ vm_flags)
673 if ((vma->vm_flags ^ vm_flags) & ~VM_CAN_NONLINEAR)
674 return 0; 673 return 0;
675 if (vma->vm_file != file) 674 if (vma->vm_file != file)
676 return 0; 675 return 0;
diff --git a/mm/nommu.c b/mm/nommu.c
index dee2ff89fd58..98318dcff742 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1961,6 +1961,14 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
1961} 1961}
1962EXPORT_SYMBOL(filemap_fault); 1962EXPORT_SYMBOL(filemap_fault);
1963 1963
1964int generic_file_remap_pages(struct vm_area_struct *vma, unsigned long addr,
1965 unsigned long size, pgoff_t pgoff)
1966{
1967 BUG();
1968 return 0;
1969}
1970EXPORT_SYMBOL(generic_file_remap_pages);
1971
1964static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm, 1972static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
1965 unsigned long addr, void *buf, int len, int write) 1973 unsigned long addr, void *buf, int len, int write)
1966{ 1974{
diff --git a/mm/shmem.c b/mm/shmem.c
index d3752110c8c7..cc12072f8787 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1339,7 +1339,6 @@ static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
1339{ 1339{
1340 file_accessed(file); 1340 file_accessed(file);
1341 vma->vm_ops = &shmem_vm_ops; 1341 vma->vm_ops = &shmem_vm_ops;
1342 vma->vm_flags |= VM_CAN_NONLINEAR;
1343 return 0; 1342 return 0;
1344} 1343}
1345 1344
@@ -2643,6 +2642,7 @@ static const struct vm_operations_struct shmem_vm_ops = {
2643 .set_policy = shmem_set_policy, 2642 .set_policy = shmem_set_policy,
2644 .get_policy = shmem_get_policy, 2643 .get_policy = shmem_get_policy,
2645#endif 2644#endif
2645 .remap_pages = generic_file_remap_pages,
2646}; 2646};
2647 2647
2648static struct dentry *shmem_mount(struct file_system_type *fs_type, 2648static struct dentry *shmem_mount(struct file_system_type *fs_type,
@@ -2836,7 +2836,6 @@ int shmem_zero_setup(struct vm_area_struct *vma)
2836 fput(vma->vm_file); 2836 fput(vma->vm_file);
2837 vma->vm_file = file; 2837 vma->vm_file = file;
2838 vma->vm_ops = &shmem_vm_ops; 2838 vma->vm_ops = &shmem_vm_ops;
2839 vma->vm_flags |= VM_CAN_NONLINEAR;
2840 return 0; 2839 return 0;
2841} 2840}
2842 2841