diff options
author | Konstantin Khlebnikov <khlebnikov@openvz.org> | 2012-10-08 19:28:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-09 03:22:17 -0400 |
commit | 0b173bc4daa8f8ec03a85abf5e47b23502ff80af (patch) | |
tree | 173d0523555e02a077e0af4563bd4cadea46cb23 | |
parent | 4b6e1e37026ec7dae9b23d78ffcebdd5ddb1bfa1 (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.c | 1 | ||||
-rw-r--r-- | fs/9p/vfs_file.c | 1 | ||||
-rw-r--r-- | fs/btrfs/file.c | 2 | ||||
-rw-r--r-- | fs/ceph/addr.c | 2 | ||||
-rw-r--r-- | fs/cifs/file.c | 1 | ||||
-rw-r--r-- | fs/ext4/file.c | 2 | ||||
-rw-r--r-- | fs/fuse/file.c | 1 | ||||
-rw-r--r-- | fs/gfs2/file.c | 2 | ||||
-rw-r--r-- | fs/nfs/file.c | 1 | ||||
-rw-r--r-- | fs/nilfs2/file.c | 2 | ||||
-rw-r--r-- | fs/ocfs2/mmap.c | 2 | ||||
-rw-r--r-- | fs/ubifs/file.c | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_file.c | 2 | ||||
-rw-r--r-- | include/linux/fs.h | 2 | ||||
-rw-r--r-- | include/linux/mm.h | 7 | ||||
-rw-r--r-- | mm/filemap.c | 2 | ||||
-rw-r--r-- | mm/filemap_xip.c | 3 | ||||
-rw-r--r-- | mm/fremap.c | 14 | ||||
-rw-r--r-- | mm/mmap.c | 3 | ||||
-rw-r--r-- | mm/nommu.c | 8 | ||||
-rw-r--r-- | mm/shmem.c | 3 |
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 | ||
337 | out: | 336 | out: |
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, | |||
738 | static const struct vm_operations_struct v9fs_file_vm_ops = { | 738 | static 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: | |||
1599 | static const struct vm_operations_struct btrfs_file_vm_ops = { | 1599 | static 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 | ||
1604 | static int btrfs_file_mmap(struct file *filp, struct vm_area_struct *vma) | 1605 | static 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: | |||
1224 | static struct vm_operations_struct ceph_vmops = { | 1224 | static 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 | ||
1229 | int ceph_mmap(struct file *file, struct vm_area_struct *vma) | 1230 | int 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) | |||
3003 | static struct vm_operations_struct cifs_file_vm_ops = { | 3003 | static 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 | ||
3008 | int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) | 3009 | int 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, | |||
207 | static const struct vm_operations_struct ext4_file_vm_ops = { | 207 | static 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 | ||
212 | static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma) | 213 | static 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 | ||
1384 | static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) | 1385 | static 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: | |||
492 | static const struct vm_operations_struct gfs2_vm_ops = { | 492 | static 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: | |||
578 | static const struct vm_operations_struct nfs_file_vm_ops = { | 578 | static 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 | ||
583 | static int nfs_need_sync_write(struct file *filp, struct inode *inode) | 584 | static 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) | |||
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 | .page_mkwrite = nilfs_page_mkwrite, | 137 | .page_mkwrite = nilfs_page_mkwrite, |
138 | .remap_pages = generic_file_remap_pages, | ||
138 | }; | 139 | }; |
139 | 140 | ||
140 | static int nilfs_file_mmap(struct file *file, struct vm_area_struct *vma) | 141 | static 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: | |||
173 | static const struct vm_operations_struct ocfs2_file_vm_ops = { | 173 | static 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 | ||
178 | int ocfs2_mmap(struct file *file, struct vm_area_struct *vma) | 179 | int 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); |
189 | out: | 190 | out: |
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: | |||
1536 | static const struct vm_operations_struct ubifs_file_vm_ops = { | 1536 | static 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 | ||
1541 | static int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma) | 1542 | static 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 = { | |||
1443 | static const struct vm_operations_struct xfs_file_vm_ops = { | 1442 | static 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 | ||
2553 | extern int generic_file_mmap(struct file *, struct vm_area_struct *); | 2553 | extern int generic_file_mmap(struct file *, struct vm_area_struct *); |
2554 | extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *); | 2554 | extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *); |
2555 | extern int generic_file_remap_pages(struct vm_area_struct *, unsigned long addr, | ||
2556 | unsigned long size, pgoff_t pgoff); | ||
2555 | extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size); | 2557 | extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size); |
2556 | int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk); | 2558 | int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk); |
2557 | extern ssize_t generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t); | 2559 | extern 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 | */ |
177 | struct vm_fault { | 175 | struct 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 | ||
235 | struct mmu_gather; | 236 | struct 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); | |||
1737 | const struct vm_operations_struct generic_file_vm_ops = { | 1737 | const 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: | |||
305 | static const struct vm_operations_struct xip_file_vm_ops = { | 305 | static 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 | ||
310 | int xip_file_mmap(struct file * file, struct vm_area_struct * vma) | 311 | int 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 | } |
319 | EXPORT_SYMBOL_GPL(xip_file_mmap); | 320 | EXPORT_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 | ||
83 | static int populate_range(struct mm_struct *mm, struct vm_area_struct *vma, | 84 | int 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 | } |
102 | EXPORT_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) { |
@@ -669,8 +669,7 @@ again: remove_next = 1 + (end > next->vm_end); | |||
669 | static inline int is_mergeable_vma(struct vm_area_struct *vma, | 669 | static 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 | } |
1962 | EXPORT_SYMBOL(filemap_fault); | 1962 | EXPORT_SYMBOL(filemap_fault); |
1963 | 1963 | ||
1964 | int 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 | } | ||
1970 | EXPORT_SYMBOL(generic_file_remap_pages); | ||
1971 | |||
1964 | static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm, | 1972 | static 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 | ||
2648 | static struct dentry *shmem_mount(struct file_system_type *fs_type, | 2648 | static 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 | ||