diff options
author | Kirill A. Shutemov <kirill.shutemov@linux.intel.com> | 2015-09-22 17:59:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-22 18:09:53 -0400 |
commit | 8a04446ab0cf4f35d9f583cd6adcbf7c534e4995 (patch) | |
tree | c0a245eb875c5399b8c02b6ddcb9d10e303d9e0b /mm/mmap.c | |
parent | 09f7298100ea9767324298ab0c7979f6d7463183 (diff) |
mm, dax: VMA with vm_ops->pfn_mkwrite wants to be write-notified
For VM_PFNMAP and VM_MIXEDMAP we use vm_ops->pfn_mkwrite instead of
vm_ops->page_mkwrite to notify abort write access. This means we want
vma->vm_page_prot to be write-protected if the VMA provides this vm_ops.
A theoretical scenario that will cause these missed events is:
On writable mapping with vm_ops->pfn_mkwrite, but without
vm_ops->page_mkwrite: read fault followed by write access to the pfn.
Writable pte will be set up on read fault and write fault will not be
generated.
I found it examining Dave's complaint on generic/080:
http://lkml.kernel.org/g/20150831233803.GO3902@dastard
Although I don't think it's the reason.
It shouldn't be a problem for ext2/ext4 as they provide both pfn_mkwrite
and page_mkwrite.
[akpm@linux-foundation.org: add local vm_ops to avoid 80-cols mess]
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Yigal Korman <yigal@plexistor.com>
Acked-by: Boaz Harrosh <boaz@plexistor.com>
Cc: Matthew Wilcox <matthew.r.wilcox@intel.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Dave Chinner <david@fromorbit.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/mmap.c')
-rw-r--r-- | mm/mmap.c | 3 |
1 files changed, 2 insertions, 1 deletions
@@ -1490,13 +1490,14 @@ SYSCALL_DEFINE1(old_mmap, struct mmap_arg_struct __user *, arg) | |||
1490 | int vma_wants_writenotify(struct vm_area_struct *vma) | 1490 | int vma_wants_writenotify(struct vm_area_struct *vma) |
1491 | { | 1491 | { |
1492 | vm_flags_t vm_flags = vma->vm_flags; | 1492 | vm_flags_t vm_flags = vma->vm_flags; |
1493 | const struct vm_operations_struct *vm_ops = vma->vm_ops; | ||
1493 | 1494 | ||
1494 | /* If it was private or non-writable, the write bit is already clear */ | 1495 | /* If it was private or non-writable, the write bit is already clear */ |
1495 | if ((vm_flags & (VM_WRITE|VM_SHARED)) != ((VM_WRITE|VM_SHARED))) | 1496 | if ((vm_flags & (VM_WRITE|VM_SHARED)) != ((VM_WRITE|VM_SHARED))) |
1496 | return 0; | 1497 | return 0; |
1497 | 1498 | ||
1498 | /* The backer wishes to know when pages are first written to? */ | 1499 | /* The backer wishes to know when pages are first written to? */ |
1499 | if (vma->vm_ops && vma->vm_ops->page_mkwrite) | 1500 | if (vm_ops && (vm_ops->page_mkwrite || vm_ops->pfn_mkwrite)) |
1500 | return 1; | 1501 | return 1; |
1501 | 1502 | ||
1502 | /* The open routine did something to the protections that pgprot_modify | 1503 | /* The open routine did something to the protections that pgprot_modify |