]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/nfs/file.c
NFSv4: Add socket proto argument to setclientid
[linux-2.6-omap-h63xx.git] / fs / nfs / file.c
index c664bb9214255eccdcba34e987a33f1deb1cbe10..4560fc2ddb4afd29c33ed44b26ffd30811bb7f7d 100644 (file)
@@ -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,50 @@ 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);
+
+       return status < 0 ? status : copied;
 }
 
 static void nfs_invalidate_page(struct page *page, unsigned long offset)
@@ -354,8 +377,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 +392,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 +609,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))