aboutsummaryrefslogtreecommitdiffstats
path: root/mm/mprotect.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2006-06-23 05:03:43 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-23 10:42:51 -0400
commit9637a5efd4fbe36164c5ce7f6a0ee68b2bf22b7f (patch)
tree38b86e3e2151e78f952076e36bee4fd7d77e3baf /mm/mprotect.c
parentbd96b9eb7cfd6ab24ba244360a09980a720874d2 (diff)
[PATCH] add page_mkwrite() vm_operations method
Add a new VMA operation to notify a filesystem or other driver about the MMU generating a fault because userspace attempted to write to a page mapped through a read-only PTE. This facility permits the filesystem or driver to: (*) Implement storage allocation/reservation on attempted write, and so to deal with problems such as ENOSPC more gracefully (perhaps by generating SIGBUS). (*) Delay making the page writable until the contents have been written to a backing cache. This is useful for NFS/AFS when using FS-Cache/CacheFS. It permits the filesystem to have some guarantee about the state of the cache. (*) Account and limit number of dirty pages. This is one piece of the puzzle needed to make shared writable mapping work safely in FUSE. Needed by cachefs (Or is it cachefiles? Or fscache? <head spins>). At least four other groups have stated an interest in it or a desire to use the functionality it provides: FUSE, OCFS2, NTFS and JFFS2. Also, things like EXT3 really ought to use it to deal with the case of shared-writable mmap encountering ENOSPC before we permit the page to be dirtied. From: Peter Zijlstra <a.p.zijlstra@chello.nl> get_user_pages(.write=1, .force=1) can generate COW hits on read-only shared mappings, this patch traps those as mkpage_write candidates and fails to handle them the old way. Signed-off-by: David Howells <dhowells@redhat.com> Cc: Miklos Szeredi <miklos@szeredi.hu> Cc: Joel Becker <Joel.Becker@oracle.com> Cc: Mark Fasheh <mark.fasheh@oracle.com> Cc: Anton Altaparmakov <aia21@cantab.net> Cc: David Woodhouse <dwmw2@infradead.org> Cc: Hugh Dickins <hugh@veritas.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm/mprotect.c')
-rw-r--r--mm/mprotect.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 14f93e62270f..638edabaff71 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -123,6 +123,7 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
123 unsigned long oldflags = vma->vm_flags; 123 unsigned long oldflags = vma->vm_flags;
124 long nrpages = (end - start) >> PAGE_SHIFT; 124 long nrpages = (end - start) >> PAGE_SHIFT;
125 unsigned long charged = 0; 125 unsigned long charged = 0;
126 unsigned int mask;
126 pgprot_t newprot; 127 pgprot_t newprot;
127 pgoff_t pgoff; 128 pgoff_t pgoff;
128 int error; 129 int error;
@@ -149,8 +150,6 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
149 } 150 }
150 } 151 }
151 152
152 newprot = protection_map[newflags & 0xf];
153
154 /* 153 /*
155 * First try to merge with previous and/or next vma. 154 * First try to merge with previous and/or next vma.
156 */ 155 */
@@ -177,6 +176,14 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
177 } 176 }
178 177
179success: 178success:
179 /* Don't make the VMA automatically writable if it's shared, but the
180 * backer wishes to know when pages are first written to */
181 mask = VM_READ|VM_WRITE|VM_EXEC|VM_SHARED;
182 if (vma->vm_ops && vma->vm_ops->page_mkwrite)
183 mask &= ~VM_SHARED;
184
185 newprot = protection_map[newflags & mask];
186
180 /* 187 /*
181 * vm_flags and vm_page_prot are protected by the mmap_sem 188 * vm_flags and vm_page_prot are protected by the mmap_sem
182 * held in write mode. 189 * held in write mode.