]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - fs/nfs/file.c
NFS: kswapd must not block in nfs_release_page
[net-next-2.6.git] / fs / nfs / file.c
index cac96bcc91e42f6f5a1fbf818f46254c2649e5fc..f036153d9f50eaaa93bd8d8d6bc4da231a9f26d3 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/pagemap.h>
 #include <linux/aio.h>
 #include <linux/gfp.h>
+#include <linux/swap.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -53,7 +54,7 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
 static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov,
                                unsigned long nr_segs, loff_t pos);
 static int  nfs_file_flush(struct file *, fl_owner_t id);
-static int  nfs_file_fsync(struct file *, struct dentry *dentry, int datasync);
+static int  nfs_file_fsync(struct file *, int datasync);
 static int nfs_check_flags(int flags);
 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);
@@ -322,8 +323,9 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
  * whether any write errors occurred for this process.
  */
 static int
-nfs_file_fsync(struct file *file, struct dentry *dentry, int datasync)
+nfs_file_fsync(struct file *file, int datasync)
 {
+       struct dentry *dentry = file->f_path.dentry;
        struct nfs_open_context *ctx = nfs_file_open_context(file);
        struct inode *inode = dentry->d_inode;
 
@@ -492,11 +494,19 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset)
  */
 static int nfs_release_page(struct page *page, gfp_t gfp)
 {
+       struct address_space *mapping = page->mapping;
+
        dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page);
 
        /* Only do I/O if gfp is a superset of GFP_KERNEL */
-       if ((gfp & GFP_KERNEL) == GFP_KERNEL)
-               nfs_wb_page(page->mapping->host, page);
+       if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL) {
+               int how = FLUSH_SYNC;
+
+               /* Don't let kswapd deadlock waiting for OOM RPC calls */
+               if (current_is_kswapd())
+                       how = 0;
+               nfs_commit_inode(mapping->host, how);
+       }
        /* If PagePrivate() is set, then the page is not freeable */
        if (PagePrivate(page))
                return 0;