Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Konstantin Khlebnikov and committed by
Linus Torvalds
0b173bc4 4b6e1e37

+39 -23
-1
drivers/staging/android/ashmem.c
··· 332 332 if (vma->vm_file) 333 333 fput(vma->vm_file); 334 334 vma->vm_file = asma->file; 335 - vma->vm_flags |= VM_CAN_NONLINEAR; 336 335 337 336 out: 338 337 mutex_unlock(&ashmem_mutex);
+1
fs/9p/vfs_file.c
··· 738 738 static const struct vm_operations_struct v9fs_file_vm_ops = { 739 739 .fault = filemap_fault, 740 740 .page_mkwrite = v9fs_vm_page_mkwrite, 741 + .remap_pages = generic_file_remap_pages, 741 742 }; 742 743 743 744
+1 -1
fs/btrfs/file.c
··· 1599 1599 static const struct vm_operations_struct btrfs_file_vm_ops = { 1600 1600 .fault = filemap_fault, 1601 1601 .page_mkwrite = btrfs_page_mkwrite, 1602 + .remap_pages = generic_file_remap_pages, 1602 1603 }; 1603 1604 1604 1605 static int btrfs_file_mmap(struct file *filp, struct vm_area_struct *vma) ··· 1611 1610 1612 1611 file_accessed(filp); 1613 1612 vma->vm_ops = &btrfs_file_vm_ops; 1614 - vma->vm_flags |= VM_CAN_NONLINEAR; 1615 1613 1616 1614 return 0; 1617 1615 }
+1 -1
fs/ceph/addr.c
··· 1224 1224 static struct vm_operations_struct ceph_vmops = { 1225 1225 .fault = filemap_fault, 1226 1226 .page_mkwrite = ceph_page_mkwrite, 1227 + .remap_pages = generic_file_remap_pages, 1227 1228 }; 1228 1229 1229 1230 int ceph_mmap(struct file *file, struct vm_area_struct *vma) ··· 1235 1234 return -ENOEXEC; 1236 1235 file_accessed(file); 1237 1236 vma->vm_ops = &ceph_vmops; 1238 - vma->vm_flags |= VM_CAN_NONLINEAR; 1239 1237 return 0; 1240 1238 }
+1
fs/cifs/file.c
··· 3003 3003 static struct vm_operations_struct cifs_file_vm_ops = { 3004 3004 .fault = filemap_fault, 3005 3005 .page_mkwrite = cifs_page_mkwrite, 3006 + .remap_pages = generic_file_remap_pages, 3006 3007 }; 3007 3008 3008 3009 int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
+1 -1
fs/ext4/file.c
··· 207 207 static const struct vm_operations_struct ext4_file_vm_ops = { 208 208 .fault = filemap_fault, 209 209 .page_mkwrite = ext4_page_mkwrite, 210 + .remap_pages = generic_file_remap_pages, 210 211 }; 211 212 212 213 static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma) ··· 218 217 return -ENOEXEC; 219 218 file_accessed(file); 220 219 vma->vm_ops = &ext4_file_vm_ops; 221 - vma->vm_flags |= VM_CAN_NONLINEAR; 222 220 return 0; 223 221 } 224 222
+1
fs/fuse/file.c
··· 1379 1379 .close = fuse_vma_close, 1380 1380 .fault = filemap_fault, 1381 1381 .page_mkwrite = fuse_page_mkwrite, 1382 + .remap_pages = generic_file_remap_pages, 1382 1383 }; 1383 1384 1384 1385 static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
+1 -1
fs/gfs2/file.c
··· 492 492 static const struct vm_operations_struct gfs2_vm_ops = { 493 493 .fault = filemap_fault, 494 494 .page_mkwrite = gfs2_page_mkwrite, 495 + .remap_pages = generic_file_remap_pages, 495 496 }; 496 497 497 498 /** ··· 527 526 return error; 528 527 } 529 528 vma->vm_ops = &gfs2_vm_ops; 530 - vma->vm_flags |= VM_CAN_NONLINEAR; 531 529 532 530 return 0; 533 531 }
+1
fs/nfs/file.c
··· 578 578 static const struct vm_operations_struct nfs_file_vm_ops = { 579 579 .fault = filemap_fault, 580 580 .page_mkwrite = nfs_vm_page_mkwrite, 581 + .remap_pages = generic_file_remap_pages, 581 582 }; 582 583 583 584 static int nfs_need_sync_write(struct file *filp, struct inode *inode)
+1 -1
fs/nilfs2/file.c
··· 135 135 static const struct vm_operations_struct nilfs_file_vm_ops = { 136 136 .fault = filemap_fault, 137 137 .page_mkwrite = nilfs_page_mkwrite, 138 + .remap_pages = generic_file_remap_pages, 138 139 }; 139 140 140 141 static int nilfs_file_mmap(struct file *file, struct vm_area_struct *vma) 141 142 { 142 143 file_accessed(file); 143 144 vma->vm_ops = &nilfs_file_vm_ops; 144 - vma->vm_flags |= VM_CAN_NONLINEAR; 145 145 return 0; 146 146 } 147 147
+1 -1
fs/ocfs2/mmap.c
··· 173 173 static const struct vm_operations_struct ocfs2_file_vm_ops = { 174 174 .fault = ocfs2_fault, 175 175 .page_mkwrite = ocfs2_page_mkwrite, 176 + .remap_pages = generic_file_remap_pages, 176 177 }; 177 178 178 179 int ocfs2_mmap(struct file *file, struct vm_area_struct *vma) ··· 189 188 ocfs2_inode_unlock(file->f_dentry->d_inode, lock_level); 190 189 out: 191 190 vma->vm_ops = &ocfs2_file_vm_ops; 192 - vma->vm_flags |= VM_CAN_NONLINEAR; 193 191 return 0; 194 192 } 195 193
+1
fs/ubifs/file.c
··· 1536 1536 static const struct vm_operations_struct ubifs_file_vm_ops = { 1537 1537 .fault = filemap_fault, 1538 1538 .page_mkwrite = ubifs_vm_page_mkwrite, 1539 + .remap_pages = generic_file_remap_pages, 1539 1540 }; 1540 1541 1541 1542 static int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma)
+1 -1
fs/xfs/xfs_file.c
··· 940 940 struct vm_area_struct *vma) 941 941 { 942 942 vma->vm_ops = &xfs_file_vm_ops; 943 - vma->vm_flags |= VM_CAN_NONLINEAR; 944 943 945 944 file_accessed(filp); 946 945 return 0; ··· 1442 1443 static const struct vm_operations_struct xfs_file_vm_ops = { 1443 1444 .fault = filemap_fault, 1444 1445 .page_mkwrite = xfs_vm_page_mkwrite, 1446 + .remap_pages = generic_file_remap_pages, 1445 1447 };
+2
include/linux/fs.h
··· 2552 2552 2553 2553 extern int generic_file_mmap(struct file *, struct vm_area_struct *); 2554 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 2557 extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size); 2556 2558 int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk); 2557 2559 extern ssize_t generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t);
+4 -3
include/linux/mm.h
··· 105 105 #define VM_ARCH_1 0x01000000 /* Architecture-specific flag */ 106 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 108 #define VM_MIXEDMAP 0x10000000 /* Can contain "struct page" and pure PFN pages */ 110 109 #define VM_HUGEPAGE 0x20000000 /* MADV_HUGEPAGE marked this vma */ 111 110 #define VM_NOHUGEPAGE 0x40000000 /* MADV_NOHUGEPAGE marked this vma */ ··· 170 171 * of VM_FAULT_xxx flags that give details about how the fault was handled. 171 172 * 172 173 * pgoff should be used in favour of virtual_address, if possible. If pgoff 173 - * is used, one may set VM_CAN_NONLINEAR in the vma->vm_flags to get nonlinear 174 - * mapping support. 174 + * is used, one may implement ->remap_pages to get nonlinear mapping support. 175 175 */ 176 176 struct vm_fault { 177 177 unsigned int flags; /* FAULT_FLAG_xxx flags */ ··· 228 230 int (*migrate)(struct vm_area_struct *vma, const nodemask_t *from, 229 231 const nodemask_t *to, unsigned long flags); 230 232 #endif 233 + /* called by sys_remap_file_pages() to populate non-linear mapping */ 234 + int (*remap_pages)(struct vm_area_struct *vma, unsigned long addr, 235 + unsigned long size, pgoff_t pgoff); 231 236 }; 232 237 233 238 struct mmu_gather;
+1 -1
mm/filemap.c
··· 1737 1737 const struct vm_operations_struct generic_file_vm_ops = { 1738 1738 .fault = filemap_fault, 1739 1739 .page_mkwrite = filemap_page_mkwrite, 1740 + .remap_pages = generic_file_remap_pages, 1740 1741 }; 1741 1742 1742 1743 /* This is used for a general mmap of a disk file */ ··· 1750 1749 return -ENOEXEC; 1751 1750 file_accessed(file); 1752 1751 vma->vm_ops = &generic_file_vm_ops; 1753 - vma->vm_flags |= VM_CAN_NONLINEAR; 1754 1752 return 0; 1755 1753 } 1756 1754
+2 -1
mm/filemap_xip.c
··· 305 305 static const struct vm_operations_struct xip_file_vm_ops = { 306 306 .fault = xip_file_fault, 307 307 .page_mkwrite = filemap_page_mkwrite, 308 + .remap_pages = generic_file_remap_pages, 308 309 }; 309 310 310 311 int xip_file_mmap(struct file * file, struct vm_area_struct * vma) ··· 314 313 315 314 file_accessed(file); 316 315 vma->vm_ops = &xip_file_vm_ops; 317 - vma->vm_flags |= VM_CAN_NONLINEAR | VM_MIXEDMAP; 316 + vma->vm_flags |= VM_MIXEDMAP; 318 317 return 0; 319 318 } 320 319 EXPORT_SYMBOL_GPL(xip_file_mmap);
+8 -6
mm/fremap.c
··· 5 5 * 6 6 * started by Ingo Molnar, Copyright (C) 2002, 2003 7 7 */ 8 + #include <linux/export.h> 8 9 #include <linux/backing-dev.h> 9 10 #include <linux/mm.h> 10 11 #include <linux/swap.h> ··· 81 80 return err; 82 81 } 83 82 84 - static int populate_range(struct mm_struct *mm, struct vm_area_struct *vma, 85 - unsigned long addr, unsigned long size, pgoff_t pgoff) 83 + int generic_file_remap_pages(struct vm_area_struct *vma, unsigned long addr, 84 + unsigned long size, pgoff_t pgoff) 86 85 { 86 + struct mm_struct *mm = vma->vm_mm; 87 87 int err; 88 88 89 89 do { ··· 97 95 pgoff++; 98 96 } while (size); 99 97 100 - return 0; 101 - 98 + return 0; 102 99 } 100 + EXPORT_SYMBOL(generic_file_remap_pages); 103 101 104 102 /** 105 103 * sys_remap_file_pages - remap arbitrary pages of an existing VM_SHARED vma ··· 169 167 if (vma->vm_private_data && !(vma->vm_flags & VM_NONLINEAR)) 170 168 goto out; 171 169 172 - if (!(vma->vm_flags & VM_CAN_NONLINEAR)) 170 + if (!vma->vm_ops->remap_pages) 173 171 goto out; 174 172 175 173 if (start < vma->vm_start || start + size > vma->vm_end) ··· 230 228 } 231 229 232 230 mmu_notifier_invalidate_range_start(mm, start, start + size); 233 - err = populate_range(mm, vma, start, size, pgoff); 231 + err = vma->vm_ops->remap_pages(vma, start, size, pgoff); 234 232 mmu_notifier_invalidate_range_end(mm, start, start + size); 235 233 if (!err && !(flags & MAP_NONBLOCK)) { 236 234 if (vma->vm_flags & VM_LOCKED) {
+1 -2
mm/mmap.c
··· 669 669 static inline int is_mergeable_vma(struct vm_area_struct *vma, 670 670 struct file *file, unsigned long vm_flags) 671 671 { 672 - /* VM_CAN_NONLINEAR may get set later by f_op->mmap() */ 673 - if ((vma->vm_flags ^ vm_flags) & ~VM_CAN_NONLINEAR) 672 + if (vma->vm_flags ^ vm_flags) 674 673 return 0; 675 674 if (vma->vm_file != file) 676 675 return 0;
+8
mm/nommu.c
··· 1961 1961 } 1962 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 1972 static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm, 1965 1973 unsigned long addr, void *buf, int len, int write) 1966 1974 {
+1 -2
mm/shmem.c
··· 1339 1339 { 1340 1340 file_accessed(file); 1341 1341 vma->vm_ops = &shmem_vm_ops; 1342 - vma->vm_flags |= VM_CAN_NONLINEAR; 1343 1342 return 0; 1344 1343 } 1345 1344 ··· 2642 2643 .set_policy = shmem_set_policy, 2643 2644 .get_policy = shmem_get_policy, 2644 2645 #endif 2646 + .remap_pages = generic_file_remap_pages, 2645 2647 }; 2646 2648 2647 2649 static struct dentry *shmem_mount(struct file_system_type *fs_type, ··· 2836 2836 fput(vma->vm_file); 2837 2837 vma->vm_file = file; 2838 2838 vma->vm_ops = &shmem_vm_ops; 2839 - vma->vm_flags |= VM_CAN_NONLINEAR; 2840 2839 return 0; 2841 2840 } 2842 2841