aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-05-20 10:18:27 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-05-24 10:44:20 -0400
commit7fe7f8487ae742239dd8c66596e2311c30d057d1 (patch)
treec506bd7dcacc9d5b25b3295bd1f327e534532c54 /fs/nfs/write.c
parent585a2858b970cb6e2e5ca4877eefd18b4dba8ed4 (diff)
NFS: Avoid a deadlock situation on write
When processes are allowed to attempt to lock a non-contiguous range of nfs write requests, it is possible for generic_writepages to 'wrap round' the address space, and call writepage() on a request that is already locked by the same process. We avoid the deadlock by checking if the page index is contiguous with the list of nfs write requests that is already held in our nfs_pageio_descriptor prior to attempting to lock a new request. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r--fs/nfs/write.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index b084c03ce493..af344a158e01 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -273,8 +273,6 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
273 * request as dirty (in which case we don't care). 273 * request as dirty (in which case we don't care).
274 */ 274 */
275 spin_unlock(req_lock); 275 spin_unlock(req_lock);
276 /* Prevent deadlock! */
277 nfs_pageio_complete(pgio);
278 ret = nfs_wait_on_request(req); 276 ret = nfs_wait_on_request(req);
279 nfs_release_request(req); 277 nfs_release_request(req);
280 if (ret != 0) 278 if (ret != 0)
@@ -321,6 +319,8 @@ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc
321 pgio = &mypgio; 319 pgio = &mypgio;
322 } 320 }
323 321
322 nfs_pageio_cond_complete(pgio, page->index);
323
324 err = nfs_page_async_flush(pgio, page); 324 err = nfs_page_async_flush(pgio, page);
325 if (err <= 0) 325 if (err <= 0)
326 goto out; 326 goto out;
@@ -329,6 +329,8 @@ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc
329 if (!offset) 329 if (!offset)
330 goto out; 330 goto out;
331 331
332 nfs_pageio_cond_complete(pgio, page->index);
333
332 ctx = nfs_find_open_context(inode, NULL, FMODE_WRITE); 334 ctx = nfs_find_open_context(inode, NULL, FMODE_WRITE);
333 if (ctx == NULL) { 335 if (ctx == NULL) {
334 err = -EBADF; 336 err = -EBADF;