aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2007-07-19 04:47:03 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:41 -0400
commitd0217ac04ca6591841e5665f518e38064f4e65bd (patch)
treed3309094bb734d34773f97d642593e298a5cfcfc /fs
parented2f2f9b3ff8debdf512f7687b232c3c1d7d60d7 (diff)
mm: fault feedback #1
Change ->fault prototype. We now return an int, which contains VM_FAULT_xxx code in the low byte, and FAULT_RET_xxx code in the next byte. FAULT_RET_ code tells the VM whether a page was found, whether it has been locked, and potentially other things. This is not quite the way he wanted it yet, but that's changed in the next patch (which requires changes to arch code). This means we no longer set VM_CAN_INVALIDATE in the vma in order to say that a page is locked which requires filemap_nopage to go away (because we can no longer remain backward compatible without that flag), but we were going to do that anyway. struct fault_data is renamed to struct vm_fault as Linus asked. address is now a void __user * that we should firmly encourage drivers not to use without really good reason. The page is now returned via a page pointer in the vm_fault struct. Signed-off-by: Nick Piggin <npiggin@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/gfs2/ops_file.c2
-rw-r--r--fs/gfs2/ops_vm.c47
-rw-r--r--fs/ncpfs/mmap.c38
-rw-r--r--fs/ocfs2/mmap.c30
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c14
5 files changed, 62 insertions, 69 deletions
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index 581ac11b2656..1a5e8e893d75 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -364,8 +364,6 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
364 else 364 else
365 vma->vm_ops = &gfs2_vm_ops_private; 365 vma->vm_ops = &gfs2_vm_ops_private;
366 366
367 vma->vm_flags |= VM_CAN_INVALIDATE|VM_CAN_NONLINEAR;
368
369 gfs2_glock_dq_uninit(&i_gh); 367 gfs2_glock_dq_uninit(&i_gh);
370 368
371 return error; 369 return error;
diff --git a/fs/gfs2/ops_vm.c b/fs/gfs2/ops_vm.c
index e9fe6eb74e75..dc287d2e3a66 100644
--- a/fs/gfs2/ops_vm.c
+++ b/fs/gfs2/ops_vm.c
@@ -27,13 +27,12 @@
27#include "trans.h" 27#include "trans.h"
28#include "util.h" 28#include "util.h"
29 29
30static struct page *gfs2_private_fault(struct vm_area_struct *vma, 30static int gfs2_private_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
31 struct fault_data *fdata)
32{ 31{
33 struct gfs2_inode *ip = GFS2_I(vma->vm_file->f_mapping->host); 32 struct gfs2_inode *ip = GFS2_I(vma->vm_file->f_mapping->host);
34 33
35 set_bit(GIF_PAGED, &ip->i_flags); 34 set_bit(GIF_PAGED, &ip->i_flags);
36 return filemap_fault(vma, fdata); 35 return filemap_fault(vma, vmf);
37} 36}
38 37
39static int alloc_page_backing(struct gfs2_inode *ip, struct page *page) 38static int alloc_page_backing(struct gfs2_inode *ip, struct page *page)
@@ -104,55 +103,55 @@ out:
104 return error; 103 return error;
105} 104}
106 105
107static struct page *gfs2_sharewrite_fault(struct vm_area_struct *vma, 106static int gfs2_sharewrite_fault(struct vm_area_struct *vma,
108 struct fault_data *fdata) 107 struct vm_fault *vmf)
109{ 108{
110 struct file *file = vma->vm_file; 109 struct file *file = vma->vm_file;
111 struct gfs2_file *gf = file->private_data; 110 struct gfs2_file *gf = file->private_data;
112 struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); 111 struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
113 struct gfs2_holder i_gh; 112 struct gfs2_holder i_gh;
114 struct page *result = NULL;
115 int alloc_required; 113 int alloc_required;
116 int error; 114 int error;
115 int ret = VM_FAULT_MINOR;
117 116
118 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); 117 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
119 if (error) 118 if (error)
120 return NULL; 119 goto out;
121 120
122 set_bit(GIF_PAGED, &ip->i_flags); 121 set_bit(GIF_PAGED, &ip->i_flags);
123 set_bit(GIF_SW_PAGED, &ip->i_flags); 122 set_bit(GIF_SW_PAGED, &ip->i_flags);
124 123
125 error = gfs2_write_alloc_required(ip, 124 error = gfs2_write_alloc_required(ip,
126 (u64)fdata->pgoff << PAGE_CACHE_SHIFT, 125 (u64)vmf->pgoff << PAGE_CACHE_SHIFT,
127 PAGE_CACHE_SIZE, &alloc_required); 126 PAGE_CACHE_SIZE, &alloc_required);
128 if (error) { 127 if (error) {
129 fdata->type = VM_FAULT_OOM; /* XXX: are these right? */ 128 ret = VM_FAULT_OOM; /* XXX: are these right? */
130 goto out; 129 goto out_unlock;
131 } 130 }
132 131
133 set_bit(GFF_EXLOCK, &gf->f_flags); 132 set_bit(GFF_EXLOCK, &gf->f_flags);
134 result = filemap_fault(vma, fdata); 133 ret = filemap_fault(vma, vmf);
135 clear_bit(GFF_EXLOCK, &gf->f_flags); 134 clear_bit(GFF_EXLOCK, &gf->f_flags);
136 if (!result) 135 if (ret & (VM_FAULT_ERROR | FAULT_RET_NOPAGE))
137 goto out; 136 goto out_unlock;
138 137
139 if (alloc_required) { 138 if (alloc_required) {
140 error = alloc_page_backing(ip, result); 139 /* XXX: do we need to drop page lock around alloc_page_backing?*/
140 error = alloc_page_backing(ip, vmf->page);
141 if (error) { 141 if (error) {
142 if (vma->vm_flags & VM_CAN_INVALIDATE) 142 if (ret & FAULT_RET_LOCKED)
143 unlock_page(result); 143 unlock_page(vmf->page);
144 page_cache_release(result); 144 page_cache_release(vmf->page);
145 fdata->type = VM_FAULT_OOM; 145 ret = VM_FAULT_OOM;
146 result = NULL; 146 goto out_unlock;
147 goto out;
148 } 147 }
149 set_page_dirty(result); 148 set_page_dirty(vmf->page);
150 } 149 }
151 150
152out: 151out_unlock:
153 gfs2_glock_dq_uninit(&i_gh); 152 gfs2_glock_dq_uninit(&i_gh);
154 153out:
155 return result; 154 return ret;
156} 155}
157 156
158struct vm_operations_struct gfs2_vm_ops_private = { 157struct vm_operations_struct gfs2_vm_ops_private = {
diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c
index af48b792ca04..a94473d3072c 100644
--- a/fs/ncpfs/mmap.c
+++ b/fs/ncpfs/mmap.c
@@ -24,33 +24,35 @@
24 24
25/* 25/*
26 * Fill in the supplied page for mmap 26 * Fill in the supplied page for mmap
27 * XXX: how are we excluding truncate/invalidate here? Maybe need to lock
28 * page?
27 */ 29 */
28static struct page* ncp_file_mmap_fault(struct vm_area_struct *area, 30static int ncp_file_mmap_fault(struct vm_area_struct *area,
29 struct fault_data *fdata) 31 struct vm_fault *vmf)
30{ 32{
31 struct file *file = area->vm_file; 33 struct file *file = area->vm_file;
32 struct dentry *dentry = file->f_path.dentry; 34 struct dentry *dentry = file->f_path.dentry;
33 struct inode *inode = dentry->d_inode; 35 struct inode *inode = dentry->d_inode;
34 struct page* page;
35 char *pg_addr; 36 char *pg_addr;
36 unsigned int already_read; 37 unsigned int already_read;
37 unsigned int count; 38 unsigned int count;
38 int bufsize; 39 int bufsize;
39 int pos; 40 int pos; /* XXX: loff_t ? */
40 41
41 page = alloc_page(GFP_HIGHUSER); /* ncpfs has nothing against high pages 42 /*
42 as long as recvmsg and memset works on it */ 43 * ncpfs has nothing against high pages as long
43 if (!page) { 44 * as recvmsg and memset works on it
44 fdata->type = VM_FAULT_OOM; 45 */
45 return NULL; 46 vmf->page = alloc_page(GFP_HIGHUSER);
46 } 47 if (!vmf->page)
47 pg_addr = kmap(page); 48 return VM_FAULT_OOM;
48 pos = fdata->pgoff << PAGE_SHIFT; 49 pg_addr = kmap(vmf->page);
50 pos = vmf->pgoff << PAGE_SHIFT;
49 51
50 count = PAGE_SIZE; 52 count = PAGE_SIZE;
51 if (fdata->address + PAGE_SIZE > area->vm_end) { 53 if ((unsigned long)vmf->virtual_address + PAGE_SIZE > area->vm_end) {
52 WARN_ON(1); /* shouldn't happen? */ 54 WARN_ON(1); /* shouldn't happen? */
53 count = area->vm_end - fdata->address; 55 count = area->vm_end - (unsigned long)vmf->virtual_address;
54 } 56 }
55 /* what we can read in one go */ 57 /* what we can read in one go */
56 bufsize = NCP_SERVER(inode)->buffer_size; 58 bufsize = NCP_SERVER(inode)->buffer_size;
@@ -85,17 +87,16 @@ static struct page* ncp_file_mmap_fault(struct vm_area_struct *area,
85 87
86 if (already_read < PAGE_SIZE) 88 if (already_read < PAGE_SIZE)
87 memset(pg_addr + already_read, 0, PAGE_SIZE - already_read); 89 memset(pg_addr + already_read, 0, PAGE_SIZE - already_read);
88 flush_dcache_page(page); 90 flush_dcache_page(vmf->page);
89 kunmap(page); 91 kunmap(vmf->page);
90 92
91 /* 93 /*
92 * If I understand ncp_read_kernel() properly, the above always 94 * If I understand ncp_read_kernel() properly, the above always
93 * fetches from the network, here the analogue of disk. 95 * fetches from the network, here the analogue of disk.
94 * -- wli 96 * -- wli
95 */ 97 */
96 fdata->type = VM_FAULT_MAJOR;
97 count_vm_event(PGMAJFAULT); 98 count_vm_event(PGMAJFAULT);
98 return page; 99 return VM_FAULT_MAJOR;
99} 100}
100 101
101static struct vm_operations_struct ncp_file_mmap = 102static struct vm_operations_struct ncp_file_mmap =
@@ -124,7 +125,6 @@ int ncp_mmap(struct file *file, struct vm_area_struct *vma)
124 return -EFBIG; 125 return -EFBIG;
125 126
126 vma->vm_ops = &ncp_file_mmap; 127 vma->vm_ops = &ncp_file_mmap;
127 vma->vm_flags |= VM_CAN_INVALIDATE;
128 file_accessed(file); 128 file_accessed(file);
129 return 0; 129 return 0;
130} 130}
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c
index cd75508b1c8a..ee64749e2eeb 100644
--- a/fs/ocfs2/mmap.c
+++ b/fs/ocfs2/mmap.c
@@ -60,30 +60,28 @@ static inline int ocfs2_vm_op_unblock_sigs(sigset_t *oldset)
60 return sigprocmask(SIG_SETMASK, oldset, NULL); 60 return sigprocmask(SIG_SETMASK, oldset, NULL);
61} 61}
62 62
63static struct page *ocfs2_fault(struct vm_area_struct *area, 63static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf)
64 struct fault_data *fdata)
65{ 64{
66 struct page *page = NULL;
67 sigset_t blocked, oldset; 65 sigset_t blocked, oldset;
68 int ret; 66 int error, ret;
69 67
70 mlog_entry("(area=%p, page offset=%lu)\n", area, fdata->pgoff); 68 mlog_entry("(area=%p, page offset=%lu)\n", area, vmf->pgoff);
71 69
72 ret = ocfs2_vm_op_block_sigs(&blocked, &oldset); 70 error = ocfs2_vm_op_block_sigs(&blocked, &oldset);
73 if (ret < 0) { 71 if (error < 0) {
74 fdata->type = VM_FAULT_SIGBUS; 72 mlog_errno(error);
75 mlog_errno(ret); 73 ret = VM_FAULT_SIGBUS;
76 goto out; 74 goto out;
77 } 75 }
78 76
79 page = filemap_fault(area, fdata); 77 ret = filemap_fault(area, vmf);
80 78
81 ret = ocfs2_vm_op_unblock_sigs(&oldset); 79 error = ocfs2_vm_op_unblock_sigs(&oldset);
82 if (ret < 0) 80 if (error < 0)
83 mlog_errno(ret); 81 mlog_errno(error);
84out: 82out:
85 mlog_exit_ptr(page); 83 mlog_exit_ptr(vmf->page);
86 return page; 84 return ret;
87} 85}
88 86
89static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh, 87static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh,
@@ -225,7 +223,7 @@ int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
225 ocfs2_meta_unlock(file->f_dentry->d_inode, lock_level); 223 ocfs2_meta_unlock(file->f_dentry->d_inode, lock_level);
226out: 224out:
227 vma->vm_ops = &ocfs2_file_vm_ops; 225 vma->vm_ops = &ocfs2_file_vm_ops;
228 vma->vm_flags |= VM_CAN_INVALIDATE | VM_CAN_NONLINEAR; 226 vma->vm_flags |= VM_CAN_NONLINEAR;
229 return 0; 227 return 0;
230} 228}
231 229
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index f12e80a69c68..2d4be2f247b2 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -212,20 +212,18 @@ xfs_file_fsync(
212} 212}
213 213
214#ifdef CONFIG_XFS_DMAPI 214#ifdef CONFIG_XFS_DMAPI
215STATIC struct page * 215STATIC int
216xfs_vm_fault( 216xfs_vm_fault(
217 struct vm_area_struct *vma, 217 struct vm_area_struct *vma,
218 struct fault_data *fdata) 218 struct vm_fault *vmf)
219{ 219{
220 struct inode *inode = vma->vm_file->f_path.dentry->d_inode; 220 struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
221 bhv_vnode_t *vp = vn_from_inode(inode); 221 bhv_vnode_t *vp = vn_from_inode(inode);
222 222
223 ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI); 223 ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI);
224 if (XFS_SEND_MMAP(XFS_VFSTOM(vp->v_vfsp), vma, 0)) { 224 if (XFS_SEND_MMAP(XFS_VFSTOM(vp->v_vfsp), vma, 0))
225 fdata->type = VM_FAULT_SIGBUS; 225 return VM_FAULT_SIGBUS;
226 return NULL; 226 return filemap_fault(vma, vmf);
227 }
228 return filemap_fault(vma, fdata);
229} 227}
230#endif /* CONFIG_XFS_DMAPI */ 228#endif /* CONFIG_XFS_DMAPI */
231 229
@@ -311,7 +309,7 @@ xfs_file_mmap(
311 struct vm_area_struct *vma) 309 struct vm_area_struct *vma)
312{ 310{
313 vma->vm_ops = &xfs_file_vm_ops; 311 vma->vm_ops = &xfs_file_vm_ops;
314 vma->vm_flags |= VM_CAN_INVALIDATE | VM_CAN_NONLINEAR; 312 vma->vm_flags |= VM_CAN_NONLINEAR;
315 313
316#ifdef CONFIG_XFS_DMAPI 314#ifdef CONFIG_XFS_DMAPI
317 if (vn_from_inode(filp->f_path.dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI) 315 if (vn_from_inode(filp->f_path.dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI)