diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-05-20 10:18:27 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-05-24 10:44:20 -0400 |
commit | 7fe7f8487ae742239dd8c66596e2311c30d057d1 (patch) | |
tree | c506bd7dcacc9d5b25b3295bd1f327e534532c54 /fs/nfs/write.c | |
parent | 585a2858b970cb6e2e5ca4877eefd18b4dba8ed4 (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.c | 6 |
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; |