Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8b1f9ee5 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

NFS: Optimise nfs_vm_page_mkwrite()



The current model locks the page twice for no good reason. Optimise by
inlining the parts of nfs_write_begin()/nfs_write_end() that we care about.

Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 77f11192
Loading
Loading
Loading
Loading
+14 −22
Original line number Diff line number Diff line
@@ -392,35 +392,27 @@ 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;
	void *fsdata;
	struct address_space *mapping;
	loff_t offset;

	lock_page(page);
	mapping = page->mapping;
	if (mapping != vma->vm_file->f_path.dentry->d_inode->i_mapping) {
		unlock_page(page);
		return -EINVAL;
	}
	if (mapping != vma->vm_file->f_path.dentry->d_inode->i_mapping)
		goto out_unlock;

	ret = 0;
	pagelen = nfs_page_length(page);
	offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
	unlock_page(page);
	if (pagelen == 0)
		goto out_unlock;

	/*
	 * we can use mapping after releasing the page lock, because:
	 * we hold mmap_sem on the fault path, which should pin the vma
	 * which should pin the file, which pins the dentry which should
	 * hold a reference on inode.
	 */
	ret = nfs_flush_incompatible(filp, page);
	if (ret != 0)
		goto out_unlock;

	if (pagelen) {
		struct page *page2 = NULL;
		ret = nfs_write_begin(filp, mapping, offset, pagelen,
			       	0, &page2, &fsdata);
		if (!ret)
			ret = nfs_write_end(filp, mapping, offset, pagelen,
				       	pagelen, page2, fsdata);
	}
	ret = nfs_updatepage(filp, page, 0, pagelen);
	if (ret == 0)
		ret = pagelen;
out_unlock:
	unlock_page(page);
	return ret;
}