summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-07-22 17:09:05 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-10-09 17:15:08 -0400
commit94387fb1aa16ee853d00f959373132a181b0196b (patch)
treee41d802c5f6aa8f1d9077b6e15337e2d143098e6 /fs
parentbbf25010f1a6b761914430f5fca081ec8c7accd1 (diff)
NFS: Add the helper nfs_vm_page_mkwrite
This is needed in order to set up a proper nfs_page request for mmapped files. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/file.c35
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 @@
#include <asm/system.h>
#include "delegation.h"
+#include "internal.h"
#include "iostat.h"
#define NFSDBG_FACILITY NFSDBG_FILE
@@ -55,6 +56,8 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
static int nfs_setlease(struct file *file, long arg, struct file_lock **fl);
+static struct vm_operations_struct nfs_file_vm_ops;
+
const struct file_operations nfs_file_operations = {
.llseek = nfs_file_llseek,
.read = do_sync_read,
@@ -257,8 +260,11 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
dentry->d_parent->d_name.name, dentry->d_name.name);
status = nfs_revalidate_mapping(inode, file->f_mapping);
- if (!status)
- status = generic_file_mmap(file, vma);
+ if (!status) {
+ vma->vm_ops = &nfs_file_vm_ops;
+ vma->vm_flags |= VM_CAN_NONLINEAR;
+ file_accessed(file);
+ }
return status;
}
@@ -346,6 +352,31 @@ const struct address_space_operations nfs_file_aops = {
.launder_page = nfs_launder_page,
};
+static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page)
+{
+ struct file *filp = vma->vm_file;
+ unsigned pagelen;
+ int ret = -EINVAL;
+
+ lock_page(page);
+ if (page->mapping != vma->vm_file->f_path.dentry->d_inode->i_mapping)
+ goto out_unlock;
+ pagelen = nfs_page_length(page);
+ if (pagelen == 0)
+ goto out_unlock;
+ ret = nfs_prepare_write(filp, page, 0, pagelen);
+ if (!ret)
+ ret = nfs_commit_write(filp, page, 0, pagelen);
+out_unlock:
+ unlock_page(page);
+ return ret;
+}
+
+static struct vm_operations_struct nfs_file_vm_ops = {
+ .fault = filemap_fault,
+ .page_mkwrite = nfs_vm_page_mkwrite,
+};
+
static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{