X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=fs%2Fnfs%2Ffile.c;h=ef57a5ae5904663d4ab20c974e920e711f921436;hb=19e66a67e9b25874cd5e184e7d381ce1b955df11;hp=c664bb9214255eccdcba34e987a33f1deb1cbe10;hpb=f2e1d89f9b349b3cd914b7c6ec6368632f4ad048;p=linux-2.6 diff --git a/fs/nfs/file.c b/fs/nfs/file.c index c664bb9214..ef57a5ae59 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -131,7 +131,7 @@ nfs_file_release(struct inode *inode, struct file *filp) { /* Ensure that dirty pages are flushed out with the right creds */ if (filp->f_mode & FMODE_WRITE) - filemap_fdatawrite(filp->f_mapping); + nfs_wb_all(filp->f_path.dentry->d_inode); nfs_inc_stats(inode, NFSIOS_VFSRELEASE); return NFS_PROTO(inode)->file_release(inode, filp); } @@ -306,27 +306,52 @@ nfs_fsync(struct file *file, struct dentry *dentry, int datasync) } /* - * This does the "real" work of the write. The generic routine has - * allocated the page, locked it, done all the page alignment stuff - * calculations etc. Now we should just copy the data from user - * space and write it back to the real medium.. + * This does the "real" work of the write. We must allocate and lock the + * page to be sent back to the generic routine, which then copies the + * data from user space. * * If the writer ends up delaying the write, the writer needs to * increment the page use counts until he is done with the page. */ -static int nfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) +static int nfs_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned flags, + struct page **pagep, void **fsdata) { - return nfs_flush_incompatible(file, page); + int ret; + pgoff_t index; + struct page *page; + index = pos >> PAGE_CACHE_SHIFT; + + page = __grab_cache_page(mapping, index); + if (!page) + return -ENOMEM; + *pagep = page; + + ret = nfs_flush_incompatible(file, page); + if (ret) { + unlock_page(page); + page_cache_release(page); + } + return ret; } -static int nfs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to) +static int nfs_write_end(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned copied, + struct page *page, void *fsdata) { - long status; + unsigned offset = pos & (PAGE_CACHE_SIZE - 1); + int status; lock_kernel(); - status = nfs_updatepage(file, page, offset, to-offset); + status = nfs_updatepage(file, page, offset, copied); unlock_kernel(); - return status; + + unlock_page(page); + page_cache_release(page); + + if (status < 0) + return status; + return copied; } static void nfs_invalidate_page(struct page *page, unsigned long offset) @@ -354,8 +379,8 @@ const struct address_space_operations nfs_file_aops = { .set_page_dirty = __set_page_dirty_nobuffers, .writepage = nfs_writepage, .writepages = nfs_writepages, - .prepare_write = nfs_prepare_write, - .commit_write = nfs_commit_write, + .write_begin = nfs_write_begin, + .write_end = nfs_write_end, .invalidatepage = nfs_invalidate_page, .releasepage = nfs_release_page, #ifdef CONFIG_NFS_DIRECTIO @@ -369,16 +394,25 @@ 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; + struct address_space *mapping; lock_page(page); - if (page->mapping != vma->vm_file->f_path.dentry->d_inode->i_mapping) + mapping = page->mapping; + if (mapping != vma->vm_file->f_path.dentry->d_inode->i_mapping) goto out_unlock; + + ret = 0; 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); + + ret = nfs_flush_incompatible(filp, page); + if (ret != 0) + goto out_unlock; + + ret = nfs_updatepage(filp, page, 0, pagelen); + if (ret == 0) + ret = pagelen; out_unlock: unlock_page(page); return ret; @@ -577,8 +611,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) nfs_inc_stats(inode, NFSIOS_VFSLOCK); /* No mandatory locks over NFS */ - if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID && - fl->fl_type != F_UNLCK) + if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) return -ENOLCK; if (IS_GETLK(cmd))