diff options
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 579cf8a7d4a7..f2270fff4962 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <asm/system.h> | 33 | #include <asm/system.h> |
34 | 34 | ||
35 | #include "delegation.h" | 35 | #include "delegation.h" |
36 | #include "internal.h" | ||
36 | #include "iostat.h" | 37 | #include "iostat.h" |
37 | 38 | ||
38 | #define NFSDBG_FACILITY NFSDBG_FILE | 39 | #define NFSDBG_FACILITY NFSDBG_FILE |
@@ -55,6 +56,8 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); | |||
55 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); | 56 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); |
56 | static int nfs_setlease(struct file *file, long arg, struct file_lock **fl); | 57 | static int nfs_setlease(struct file *file, long arg, struct file_lock **fl); |
57 | 58 | ||
59 | static struct vm_operations_struct nfs_file_vm_ops; | ||
60 | |||
58 | const struct file_operations nfs_file_operations = { | 61 | const struct file_operations nfs_file_operations = { |
59 | .llseek = nfs_file_llseek, | 62 | .llseek = nfs_file_llseek, |
60 | .read = do_sync_read, | 63 | .read = do_sync_read, |
@@ -257,8 +260,11 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) | |||
257 | dentry->d_parent->d_name.name, dentry->d_name.name); | 260 | dentry->d_parent->d_name.name, dentry->d_name.name); |
258 | 261 | ||
259 | status = nfs_revalidate_mapping(inode, file->f_mapping); | 262 | status = nfs_revalidate_mapping(inode, file->f_mapping); |
260 | if (!status) | 263 | if (!status) { |
261 | status = generic_file_mmap(file, vma); | 264 | vma->vm_ops = &nfs_file_vm_ops; |
265 | vma->vm_flags |= VM_CAN_NONLINEAR; | ||
266 | file_accessed(file); | ||
267 | } | ||
262 | return status; | 268 | return status; |
263 | } | 269 | } |
264 | 270 | ||
@@ -346,6 +352,31 @@ const struct address_space_operations nfs_file_aops = { | |||
346 | .launder_page = nfs_launder_page, | 352 | .launder_page = nfs_launder_page, |
347 | }; | 353 | }; |
348 | 354 | ||
355 | static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page) | ||
356 | { | ||
357 | struct file *filp = vma->vm_file; | ||
358 | unsigned pagelen; | ||
359 | int ret = -EINVAL; | ||
360 | |||
361 | lock_page(page); | ||
362 | if (page->mapping != vma->vm_file->f_path.dentry->d_inode->i_mapping) | ||
363 | goto out_unlock; | ||
364 | pagelen = nfs_page_length(page); | ||
365 | if (pagelen == 0) | ||
366 | goto out_unlock; | ||
367 | ret = nfs_prepare_write(filp, page, 0, pagelen); | ||
368 | if (!ret) | ||
369 | ret = nfs_commit_write(filp, page, 0, pagelen); | ||
370 | out_unlock: | ||
371 | unlock_page(page); | ||
372 | return ret; | ||
373 | } | ||
374 | |||
375 | static struct vm_operations_struct nfs_file_vm_ops = { | ||
376 | .fault = filemap_fault, | ||
377 | .page_mkwrite = nfs_vm_page_mkwrite, | ||
378 | }; | ||
379 | |||
349 | static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, | 380 | static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, |
350 | unsigned long nr_segs, loff_t pos) | 381 | unsigned long nr_segs, loff_t pos) |
351 | { | 382 | { |