aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/pagelist.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/pagelist.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/pagelist.c')
-rw-r--r--fs/nfs/pagelist.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index cbdd1c6aaa94..c5bb51a29e80 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -355,6 +355,26 @@ void nfs_pageio_complete(struct nfs_pageio_descriptor *desc)
355 nfs_pageio_doio(desc); 355 nfs_pageio_doio(desc);
356} 356}
357 357
358/**
359 * nfs_pageio_cond_complete - Conditional I/O completion
360 * @desc: pointer to io descriptor
361 * @index: page index
362 *
363 * It is important to ensure that processes don't try to take locks
364 * on non-contiguous ranges of pages as that might deadlock. This
365 * function should be called before attempting to wait on a locked
366 * nfs_page. It will complete the I/O if the page index 'index'
367 * is not contiguous with the existing list of pages in 'desc'.
368 */
369void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *desc, pgoff_t index)
370{
371 if (!list_empty(&desc->pg_list)) {
372 struct nfs_page *prev = nfs_list_entry(desc->pg_list.prev);
373 if (index != prev->wb_index + 1)
374 nfs_pageio_doio(desc);
375 }
376}
377
358#define NFS_SCAN_MAXENTRIES 16 378#define NFS_SCAN_MAXENTRIES 16
359/** 379/**
360 * nfs_scan_list - Scan a list for matching requests 380 * nfs_scan_list - Scan a list for matching requests