]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.kabi/mm-page_mkwrite-compat.patch
Reenabled linux-xen, added patches for Xen Kernel Version 2.6.27.31,
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.kabi / mm-page_mkwrite-compat.patch
1 From: Nick Piggin <npiggin@suse.de>
2 Subject: mm: page_mkwrite kABI compat 2
3 Patch-upstream: never
4
5 Introduce a new vma flag, VM_PAGE_MKWRITE2, which signals to the mm that the
6 driver is using page_mkwrite2. Have all in-tree users set this flag because
7 they use page_mkwrite2. Introduce some fallback paths in the page fault
8 page_mkwrite callers which calls the old page_mkwrite in case this flag is not
9 set. In this way, ABI compatibility should be retained for out of tree modules.
10
11 We also now do some extra checking in the fallback case to catch page
12 invalidations and just retry the fault rather than erroneously causing a
13 SIGBUS, which was one of the failure cases of the old page_mkwrite ABI (it
14 still has other problems, but this was one of the worst).
15
16 Signed-off-by: Nick Piggin <npiggin@suse.de>
17 ---
18 drivers/video/fb_defio.c | 2 -
19 fs/ext4/file.c | 2 -
20 fs/fuse/file.c | 1
21 fs/gfs2/ops_file.c | 1
22 fs/nfs/file.c | 2 -
23 fs/ocfs2/mmap.c | 2 -
24 fs/ubifs/file.c | 1
25 fs/xfs/linux-2.6/xfs_file.c | 2 -
26 include/linux/mm.h | 1
27 mm/memory.c | 77 ++++++++++++++++++++++++++++++++------------
28 10 files changed, 66 insertions(+), 25 deletions(-)
29
30 Index: linux-2.6.27/drivers/video/fb_defio.c
31 ===================================================================
32 --- linux-2.6.27.orig/drivers/video/fb_defio.c
33 +++ linux-2.6.27/drivers/video/fb_defio.c
34 @@ -129,7 +129,7 @@ static const struct address_space_operat
35 static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
36 {
37 vma->vm_ops = &fb_deferred_io_vm_ops;
38 - vma->vm_flags |= ( VM_IO | VM_RESERVED | VM_DONTEXPAND );
39 + vma->vm_flags |= ( VM_IO | VM_RESERVED | VM_DONTEXPAND | VM_PAGE_MKWRITE2 );
40 vma->vm_private_data = info;
41 return 0;
42 }
43 Index: linux-2.6.27/fs/ext4/file.c
44 ===================================================================
45 --- linux-2.6.27.orig/fs/ext4/file.c
46 +++ linux-2.6.27/fs/ext4/file.c
47 @@ -136,7 +136,7 @@ static int ext4_file_mmap(struct file *f
48 return -ENOEXEC;
49 file_accessed(file);
50 vma->vm_ops = &ext4_file_vm_ops;
51 - vma->vm_flags |= VM_CAN_NONLINEAR;
52 + vma->vm_flags |= VM_CAN_NONLINEAR | VM_PAGE_MKWRITE2;
53 return 0;
54 }
55
56 Index: linux-2.6.27/fs/fuse/file.c
57 ===================================================================
58 --- linux-2.6.27.orig/fs/fuse/file.c
59 +++ linux-2.6.27/fs/fuse/file.c
60 @@ -1255,6 +1255,7 @@ static int fuse_file_mmap(struct file *f
61 spin_unlock(&fc->lock);
62 }
63 file_accessed(file);
64 + vma->vm_flags |= VM_PAGE_MKWRITE2;
65 vma->vm_ops = &fuse_file_vm_ops;
66 return 0;
67 }
68 Index: linux-2.6.27/fs/gfs2/ops_file.c
69 ===================================================================
70 --- linux-2.6.27.orig/fs/gfs2/ops_file.c
71 +++ linux-2.6.27/fs/gfs2/ops_file.c
72 @@ -446,6 +446,7 @@ static int gfs2_mmap(struct file *file,
73 return error;
74 }
75
76 + vma->vm_flags |= VM_PAGE_MKWRITE2;
77 vma->vm_ops = &gfs2_vm_ops;
78
79 gfs2_glock_dq_uninit(&i_gh);
80 Index: linux-2.6.27/fs/nfs/file.c
81 ===================================================================
82 --- linux-2.6.27.orig/fs/nfs/file.c
83 +++ linux-2.6.27/fs/nfs/file.c
84 @@ -304,7 +304,7 @@ nfs_file_mmap(struct file * file, struct
85 status = nfs_revalidate_mapping(inode, file->f_mapping);
86 if (!status) {
87 vma->vm_ops = &nfs_file_vm_ops;
88 - vma->vm_flags |= VM_CAN_NONLINEAR;
89 + vma->vm_flags |= VM_CAN_NONLINEAR | VM_PAGE_MKWRITE2;
90 file_accessed(file);
91 }
92 return status;
93 Index: linux-2.6.27/fs/ocfs2/mmap.c
94 ===================================================================
95 --- linux-2.6.27.orig/fs/ocfs2/mmap.c
96 +++ linux-2.6.27/fs/ocfs2/mmap.c
97 @@ -216,7 +216,7 @@ int ocfs2_mmap(struct file *file, struct
98 ocfs2_inode_unlock(file->f_dentry->d_inode, lock_level);
99 out:
100 vma->vm_ops = &ocfs2_file_vm_ops;
101 - vma->vm_flags |= VM_CAN_NONLINEAR;
102 + vma->vm_flags |= VM_CAN_NONLINEAR | VM_PAGE_MKWRITE2;
103 return 0;
104 }
105
106 Index: linux-2.6.27/fs/ubifs/file.c
107 ===================================================================
108 --- linux-2.6.27.orig/fs/ubifs/file.c
109 +++ linux-2.6.27/fs/ubifs/file.c
110 @@ -1246,6 +1246,7 @@ static int ubifs_file_mmap(struct file *
111 if (err)
112 return err;
113 vma->vm_ops = &ubifs_file_vm_ops;
114 + vma->vm_flags |= VM_PAGE_MKWRITE2;
115 return 0;
116 }
117
118 Index: linux-2.6.27/fs/xfs/linux-2.6/xfs_file.c
119 ===================================================================
120 --- linux-2.6.27.orig/fs/xfs/linux-2.6/xfs_file.c
121 +++ linux-2.6.27/fs/xfs/linux-2.6/xfs_file.c
122 @@ -370,7 +370,7 @@ xfs_file_mmap(
123 struct vm_area_struct *vma)
124 {
125 vma->vm_ops = &xfs_file_vm_ops;
126 - vma->vm_flags |= VM_CAN_NONLINEAR;
127 + vma->vm_flags |= VM_CAN_NONLINEAR | VM_PAGE_MKWRITE2;
128
129 file_accessed(filp);
130 return 0;
131 Index: linux-2.6.27/include/linux/mm.h
132 ===================================================================
133 --- linux-2.6.27.orig/include/linux/mm.h
134 +++ linux-2.6.27/include/linux/mm.h
135 @@ -113,6 +113,7 @@ extern unsigned int kobjsize(const void
136 #define VM_CAN_NONLINEAR 0x08000000 /* Has ->fault & does nonlinear pages */
137 #define VM_MIXEDMAP 0x10000000 /* Can contain "struct page" and pure PFN pages */
138 #define VM_SAO 0x20000000 /* Strong Access Ordering (powerpc) */
139 +#define VM_PAGE_MKWRITE2 0x80000000 /* Uses page_mkwrite2 rather than page_mkwrite */
140
141 #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */
142 #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
143 Index: linux-2.6.27/mm/memory.c
144 ===================================================================
145 --- linux-2.6.27.orig/mm/memory.c
146 +++ linux-2.6.27/mm/memory.c
147 @@ -1800,7 +1800,7 @@ static int do_wp_page(struct mm_struct *
148 * read-only shared pages can get COWed by
149 * get_user_pages(.write=1, .force=1).
150 */
151 - if (vma->vm_ops && vma->vm_ops->_pmkw.page_mkwrite2) {
152 + if (vma->vm_ops && vma->vm_ops->_pmkw.page_mkwrite) {
153 struct vm_fault vmf;
154 int tmp;
155
156 @@ -1821,21 +1821,42 @@ static int do_wp_page(struct mm_struct *
157 page_cache_get(old_page);
158 pte_unmap_unlock(page_table, ptl);
159
160 - tmp = vma->vm_ops->_pmkw.page_mkwrite2(vma, &vmf);
161 - if (unlikely(tmp &
162 - (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) {
163 - ret = tmp;
164 - goto unwritable_page;
165 - }
166 - if (unlikely(!(tmp & VM_FAULT_LOCKED))) {
167 + if (likely(vma->vm_flags & VM_PAGE_MKWRITE2)) {
168 + tmp = vma->vm_ops->_pmkw.page_mkwrite2(vma, &vmf);
169 + if (unlikely(tmp &
170 + (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) {
171 + ret = tmp;
172 + goto unwritable_page;
173 + }
174 + if (unlikely(!(tmp & VM_FAULT_LOCKED))) {
175 + lock_page(old_page);
176 + if (!old_page->mapping) {
177 + ret = 0; /* retry the fault */
178 + unlock_page(old_page);
179 + goto unwritable_page;
180 + }
181 + } else
182 + VM_BUG_ON(!PageLocked(old_page));
183 + } else {
184 + tmp = vma->vm_ops->_pmkw.page_mkwrite(vma, old_page);
185 lock_page(old_page);
186 if (!old_page->mapping) {
187 + /*
188 + * page_mkwrite API is broken, it returns error even
189 + * if the page was invalidated. So if it was, then
190 + * clear that error here so we don't get a SIGBUS.
191 + */
192 ret = 0; /* retry the fault */
193 unlock_page(old_page);
194 goto unwritable_page;
195 }
196 - } else
197 - VM_BUG_ON(!PageLocked(old_page));
198 + if (tmp) {
199 + /* can't distinguish OOM from SIGBUS, but oh well */
200 + ret = VM_FAULT_SIGBUS;
201 + unlock_page(old_page);
202 + goto unwritable_page;
203 + }
204 + }
205
206 /*
207 * Since we dropped the lock we need to revalidate
208 @@ -2517,26 +2538,42 @@ static int __do_fault(struct mm_struct *
209 * address space wants to know that the page is about
210 * to become writable
211 */
212 - if (vma->vm_ops->_pmkw.page_mkwrite2) {
213 + if (vma->vm_ops->_pmkw.page_mkwrite) {
214 int tmp;
215
216 unlock_page(page);
217 vmf.flags = FAULT_FLAG_WRITE|FAULT_FLAG_MKWRITE;
218 - tmp = vma->vm_ops->_pmkw.page_mkwrite2(vma, &vmf);
219 - if (unlikely(tmp &
220 - (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) {
221 - ret = tmp;
222 - goto unwritable_page;
223 - }
224 - if (unlikely(!(tmp & VM_FAULT_LOCKED))) {
225 +
226 + if (likely(vma->vm_flags & VM_PAGE_MKWRITE2)) {
227 + tmp = vma->vm_ops->_pmkw.page_mkwrite2(vma, &vmf);
228 + if (unlikely(tmp &
229 + (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) {
230 + ret = tmp;
231 + goto unwritable_page;
232 + }
233 + if (unlikely(!(tmp & VM_FAULT_LOCKED))) {
234 + lock_page(page);
235 + if (!page->mapping) {
236 + ret = 0; /* retry the fault */
237 + unlock_page(page);
238 + goto unwritable_page;
239 + }
240 + } else
241 + VM_BUG_ON(!PageLocked(page));
242 + } else {
243 + tmp = vma->vm_ops->_pmkw.page_mkwrite(vma, page);
244 lock_page(page);
245 if (!page->mapping) {
246 ret = 0; /* retry the fault */
247 unlock_page(page);
248 goto unwritable_page;
249 }
250 - } else
251 - VM_BUG_ON(!PageLocked(page));
252 + if (tmp) {
253 + ret = VM_FAULT_SIGBUS;
254 + unlock_page(page);
255 + goto unwritable_page;
256 + }
257 + }
258 page_mkwrite = 1;
259 }
260 }