aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-04-02 19:29:52 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-05-01 01:17:06 -0400
commitc63c7b051395368573779c8309aa5c990dcf2f96 (patch)
treedb54090eef99349d15b95fcd8c2620a2403d8db8 /include/linux
parent8b09bee3083897e375bd0bf9d60f48daedfab3e0 (diff)
NFS: Fix a race when doing NFS write coalescing
Currently we do write coalescing in a very inefficient manner: one pass in generic_writepages() in order to lock the pages for writing, then one pass in nfs_flush_mapping() and/or nfs_sync_mapping_wait() in order to gather the locked pages for coalescing into RPC requests of size "wsize". In fact, it turns out there is actually a deadlock possible here since we only start I/O on the second pass. If the user signals the process while we're in nfs_sync_mapping_wait(), for instance, then we may exit before starting I/O on all the requests that have been queued up. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/nfs_page.h8
-rw-r--r--include/linux/writeback.h2
2 files changed, 3 insertions, 7 deletions
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index b8b7bca3bac8..e556e57ef7ad 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -21,8 +21,7 @@
21/* 21/*
22 * Valid flags for the radix tree 22 * Valid flags for the radix tree
23 */ 23 */
24#define NFS_PAGE_TAG_DIRTY 0 24#define NFS_PAGE_TAG_WRITEBACK 0
25#define NFS_PAGE_TAG_WRITEBACK 1
26 25
27/* 26/*
28 * Valid flags for a dirty buffer 27 * Valid flags for a dirty buffer
@@ -72,9 +71,6 @@ extern void nfs_clear_request(struct nfs_page *req);
72extern void nfs_release_request(struct nfs_page *req); 71extern void nfs_release_request(struct nfs_page *req);
73 72
74 73
75extern long nfs_scan_dirty(struct address_space *mapping,
76 struct writeback_control *wbc,
77 struct list_head *dst);
78extern int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head, struct list_head *dst, 74extern int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head, struct list_head *dst,
79 unsigned long idx_start, unsigned int npages); 75 unsigned long idx_start, unsigned int npages);
80extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc, 76extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
@@ -84,8 +80,6 @@ extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
84 int how); 80 int how);
85extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *, 81extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *,
86 struct nfs_page *); 82 struct nfs_page *);
87extern void nfs_pageio_add_list(struct nfs_pageio_descriptor *,
88 struct list_head *);
89extern void nfs_pageio_complete(struct nfs_pageio_descriptor *desc); 83extern void nfs_pageio_complete(struct nfs_pageio_descriptor *desc);
90extern int nfs_wait_on_request(struct nfs_page *); 84extern int nfs_wait_on_request(struct nfs_page *);
91extern void nfs_unlock_request(struct nfs_page *req); 85extern void nfs_unlock_request(struct nfs_page *req);
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 0c78f7f4a976..daa6c125f66e 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -59,6 +59,8 @@ struct writeback_control {
59 unsigned for_reclaim:1; /* Invoked from the page allocator */ 59 unsigned for_reclaim:1; /* Invoked from the page allocator */
60 unsigned for_writepages:1; /* This is a writepages() call */ 60 unsigned for_writepages:1; /* This is a writepages() call */
61 unsigned range_cyclic:1; /* range_start is cyclic */ 61 unsigned range_cyclic:1; /* range_start is cyclic */
62
63 void *fs_private; /* For use by ->writepages() */
62}; 64};
63 65
64/* 66/*