aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
authorChuck Lever <cel@netapp.com>2005-11-30 18:09:02 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-01-06 14:58:49 -0500
commit40859d7ee64ed6bfad8a4e93f9bb5c1074afadff (patch)
treeed4069423c3d6551035d5b6116f50452cdac4103 /fs/nfs/write.c
parent325cfed9ae901320e9234b18c21434b783dbe342 (diff)
NFS: support large reads and writes on the wire
Most NFS server implementations allow up to 64KB reads and writes on the wire. The Solaris NFS server allows up to a megabyte, for instance. Now the Linux NFS client supports transfer sizes up to 1MB, too. This will help reduce protocol and context switch overhead on read/write intensive NFS workloads, and support larger atomic read and write operations on servers that support them. Test-plan: Connectathon and iozone on mount point with wsize=rsize>32768 over TCP. Tests with NFS over UDP to verify the maximum RPC payload size cap. Signed-off-by: Chuck Lever <cel@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r--fs/nfs/write.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 80bc4ea1b824..1ce0c200df16 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -89,18 +89,33 @@ static mempool_t *nfs_commit_mempool;
89 89
90static DECLARE_WAIT_QUEUE_HEAD(nfs_write_congestion); 90static DECLARE_WAIT_QUEUE_HEAD(nfs_write_congestion);
91 91
92static inline struct nfs_write_data *nfs_commit_alloc(void) 92static inline struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount)
93{ 93{
94 struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, SLAB_NOFS); 94 struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, SLAB_NOFS);
95
95 if (p) { 96 if (p) {
96 memset(p, 0, sizeof(*p)); 97 memset(p, 0, sizeof(*p));
97 INIT_LIST_HEAD(&p->pages); 98 INIT_LIST_HEAD(&p->pages);
99 if (pagecount < NFS_PAGEVEC_SIZE)
100 p->pagevec = &p->page_array[0];
101 else {
102 size_t size = ++pagecount * sizeof(struct page *);
103 p->pagevec = kmalloc(size, GFP_NOFS);
104 if (p->pagevec) {
105 memset(p->pagevec, 0, size);
106 } else {
107 mempool_free(p, nfs_commit_mempool);
108 p = NULL;
109 }
110 }
98 } 111 }
99 return p; 112 return p;
100} 113}
101 114
102static inline void nfs_commit_free(struct nfs_write_data *p) 115static inline void nfs_commit_free(struct nfs_write_data *p)
103{ 116{
117 if (p && (p->pagevec != &p->page_array[0]))
118 kfree(p->pagevec);
104 mempool_free(p, nfs_commit_mempool); 119 mempool_free(p, nfs_commit_mempool);
105} 120}
106 121
@@ -167,7 +182,7 @@ static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode,
167 int result, written = 0; 182 int result, written = 0;
168 struct nfs_write_data *wdata; 183 struct nfs_write_data *wdata;
169 184
170 wdata = nfs_writedata_alloc(); 185 wdata = nfs_writedata_alloc(1);
171 if (!wdata) 186 if (!wdata)
172 return -ENOMEM; 187 return -ENOMEM;
173 188
@@ -909,7 +924,7 @@ static int nfs_flush_multi(struct list_head *head, struct inode *inode, int how)
909 924
910 nbytes = req->wb_bytes; 925 nbytes = req->wb_bytes;
911 for (;;) { 926 for (;;) {
912 data = nfs_writedata_alloc(); 927 data = nfs_writedata_alloc(1);
913 if (!data) 928 if (!data)
914 goto out_bad; 929 goto out_bad;
915 list_add(&data->pages, &list); 930 list_add(&data->pages, &list);
@@ -973,7 +988,7 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how)
973 if (NFS_SERVER(inode)->wsize < PAGE_CACHE_SIZE) 988 if (NFS_SERVER(inode)->wsize < PAGE_CACHE_SIZE)
974 return nfs_flush_multi(head, inode, how); 989 return nfs_flush_multi(head, inode, how);
975 990
976 data = nfs_writedata_alloc(); 991 data = nfs_writedata_alloc(NFS_SERVER(inode)->wpages);
977 if (!data) 992 if (!data)
978 goto out_bad; 993 goto out_bad;
979 994
@@ -1241,12 +1256,12 @@ static void nfs_commit_rpcsetup(struct list_head *head,
1241 * Commit dirty pages 1256 * Commit dirty pages
1242 */ 1257 */
1243static int 1258static int
1244nfs_commit_list(struct list_head *head, int how) 1259nfs_commit_list(struct inode *inode, struct list_head *head, int how)
1245{ 1260{
1246 struct nfs_write_data *data; 1261 struct nfs_write_data *data;
1247 struct nfs_page *req; 1262 struct nfs_page *req;
1248 1263
1249 data = nfs_commit_alloc(); 1264 data = nfs_commit_alloc(NFS_SERVER(inode)->wpages);
1250 1265
1251 if (!data) 1266 if (!data)
1252 goto out_bad; 1267 goto out_bad;
@@ -1351,7 +1366,7 @@ int nfs_commit_inode(struct inode *inode, int how)
1351 res = nfs_scan_commit(inode, &head, 0, 0); 1366 res = nfs_scan_commit(inode, &head, 0, 0);
1352 spin_unlock(&nfsi->req_lock); 1367 spin_unlock(&nfsi->req_lock);
1353 if (res) { 1368 if (res) {
1354 error = nfs_commit_list(&head, how); 1369 error = nfs_commit_list(inode, &head, how);
1355 if (error < 0) 1370 if (error < 0)
1356 return error; 1371 return error;
1357 } 1372 }