Commit b85934f2 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] nfs: Fix a possible client deadlock

From: Trond Myklebust <trond.myklebust@fys.uio.no>

Fix a bug in the NFS write code whereby writepage() may end up deadlocking
on clear_inode().
parent 7aebcc3f
......@@ -228,8 +228,19 @@ nfs_writepage(struct page *page, struct writeback_control *wbc)
unsigned long end_index;
unsigned offset = PAGE_CACHE_SIZE;
loff_t i_size = i_size_read(inode);
int inode_referenced = 0;
int err;
/*
* Note: We need to ensure that we have a reference to the inode
* if we are to do asynchronous writes. If not, waiting
* in nfs_wait_on_request() may deadlock with clear_inode().
*
* If igrab() fails here, then it is in any case safe to
* call nfs_wb_page(), since there will be no pending writes.
*/
if (igrab(inode) != 0)
inode_referenced = 1;
end_index = i_size >> PAGE_CACHE_SHIFT;
/* Ensure we've flushed out any previous writes */
......@@ -247,7 +258,8 @@ nfs_writepage(struct page *page, struct writeback_control *wbc)
goto out;
do_it:
lock_kernel();
if (NFS_SERVER(inode)->wsize >= PAGE_CACHE_SIZE && !IS_SYNC(inode)) {
if (NFS_SERVER(inode)->wsize >= PAGE_CACHE_SIZE && !IS_SYNC(inode) &&
inode_referenced) {
err = nfs_writepage_async(NULL, inode, page, 0, offset);
if (err >= 0)
err = 0;
......@@ -259,6 +271,8 @@ nfs_writepage(struct page *page, struct writeback_control *wbc)
unlock_kernel();
out:
unlock_page(page);
if (inode_referenced)
iput(inode);
return err;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment