aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/read.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-04-02 18:48:28 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-05-01 01:17:04 -0400
commitbcb71bba7e64f0442d0ca339d7d3117a7060589f (patch)
tree072e9a28395eee87e539a48553b20fa9cb768e94 /fs/nfs/read.c
parentd8a5ad75cc4d577987964e37a4c43b1c648c201e (diff)
NFS: Another cleanup of the read/write request coalescing code
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/read.c')
-rw-r--r--fs/nfs/read.c62
1 files changed, 27 insertions, 35 deletions
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 97f0f42e136d..0effa74992df 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -27,7 +27,8 @@
27 27
28#define NFSDBG_FACILITY NFSDBG_PAGECACHE 28#define NFSDBG_FACILITY NFSDBG_PAGECACHE
29 29
30static int nfs_pagein_one(struct list_head *, struct inode *); 30static int nfs_pagein_multi(struct inode *, struct list_head *, size_t, int);
31static int nfs_pagein_one(struct inode *, struct list_head *, size_t, int);
31static const struct rpc_call_ops nfs_read_partial_ops; 32static const struct rpc_call_ops nfs_read_partial_ops;
32static const struct rpc_call_ops nfs_read_full_ops; 33static const struct rpc_call_ops nfs_read_full_ops;
33 34
@@ -133,7 +134,10 @@ static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
133 memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len); 134 memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len);
134 135
135 nfs_list_add_request(new, &one_request); 136 nfs_list_add_request(new, &one_request);
136 nfs_pagein_one(&one_request, inode); 137 if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE)
138 nfs_pagein_multi(inode, &one_request, len, 0);
139 else
140 nfs_pagein_one(inode, &one_request, len, 0);
137 return 0; 141 return 0;
138} 142}
139 143
@@ -230,7 +234,7 @@ static void nfs_execute_read(struct nfs_read_data *data)
230 * won't see the new data until our attribute cache is updated. This is more 234 * won't see the new data until our attribute cache is updated. This is more
231 * or less conventional NFS client behavior. 235 * or less conventional NFS client behavior.
232 */ 236 */
233static int nfs_pagein_multi(struct list_head *head, struct inode *inode) 237static int nfs_pagein_multi(struct inode *inode, struct list_head *head, size_t count, int flags)
234{ 238{
235 struct nfs_page *req = nfs_list_entry(head->next); 239 struct nfs_page *req = nfs_list_entry(head->next);
236 struct page *page = req->wb_page; 240 struct page *page = req->wb_page;
@@ -242,7 +246,7 @@ static int nfs_pagein_multi(struct list_head *head, struct inode *inode)
242 246
243 nfs_list_remove_request(req); 247 nfs_list_remove_request(req);
244 248
245 nbytes = req->wb_bytes; 249 nbytes = count;
246 do { 250 do {
247 size_t len = min(nbytes,rsize); 251 size_t len = min(nbytes,rsize);
248 252
@@ -258,23 +262,19 @@ static int nfs_pagein_multi(struct list_head *head, struct inode *inode)
258 262
259 ClearPageError(page); 263 ClearPageError(page);
260 offset = 0; 264 offset = 0;
261 nbytes = req->wb_bytes; 265 nbytes = count;
262 do { 266 do {
263 data = list_entry(list.next, struct nfs_read_data, pages); 267 data = list_entry(list.next, struct nfs_read_data, pages);
264 list_del_init(&data->pages); 268 list_del_init(&data->pages);
265 269
266 data->pagevec[0] = page; 270 data->pagevec[0] = page;
267 271
268 if (nbytes > rsize) { 272 if (nbytes < rsize)
269 nfs_read_rpcsetup(req, data, &nfs_read_partial_ops, 273 rsize = nbytes;
270 rsize, offset); 274 nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
271 offset += rsize; 275 rsize, offset);
272 nbytes -= rsize; 276 offset += rsize;
273 } else { 277 nbytes -= rsize;
274 nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
275 nbytes, offset);
276 nbytes = 0;
277 }
278 nfs_execute_read(data); 278 nfs_execute_read(data);
279 } while (nbytes != 0); 279 } while (nbytes != 0);
280 280
@@ -291,30 +291,24 @@ out_bad:
291 return -ENOMEM; 291 return -ENOMEM;
292} 292}
293 293
294static int nfs_pagein_one(struct list_head *head, struct inode *inode) 294static int nfs_pagein_one(struct inode *inode, struct list_head *head, size_t count, int flags)
295{ 295{
296 struct nfs_page *req; 296 struct nfs_page *req;
297 struct page **pages; 297 struct page **pages;
298 struct nfs_read_data *data; 298 struct nfs_read_data *data;
299 unsigned int count;
300
301 if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE)
302 return nfs_pagein_multi(head, inode);
303 299
304 data = nfs_readdata_alloc(NFS_SERVER(inode)->rsize); 300 data = nfs_readdata_alloc(count);
305 if (!data) 301 if (!data)
306 goto out_bad; 302 goto out_bad;
307 303
308 INIT_LIST_HEAD(&data->pages); 304 INIT_LIST_HEAD(&data->pages);
309 pages = data->pagevec; 305 pages = data->pagevec;
310 count = 0;
311 while (!list_empty(head)) { 306 while (!list_empty(head)) {
312 req = nfs_list_entry(head->next); 307 req = nfs_list_entry(head->next);
313 nfs_list_remove_request(req); 308 nfs_list_remove_request(req);
314 nfs_list_add_request(req, &data->pages); 309 nfs_list_add_request(req, &data->pages);
315 ClearPageError(req->wb_page); 310 ClearPageError(req->wb_page);
316 *pages++ = req->wb_page; 311 *pages++ = req->wb_page;
317 count += req->wb_bytes;
318 } 312 }
319 req = nfs_list_entry(data->pages.next); 313 req = nfs_list_entry(data->pages.next);
320 314
@@ -328,22 +322,20 @@ out_bad:
328} 322}
329 323
330static int 324static int
331nfs_pagein_list(struct list_head *head, unsigned int rsize) 325nfs_pagein_list(struct inode *inode, struct list_head *head, unsigned int rsize)
332{ 326{
333 struct nfs_pageio_descriptor desc; 327 struct nfs_pageio_descriptor desc;
334 struct nfs_page *req;
335 unsigned int pages = 0; 328 unsigned int pages = 0;
336 int error = 0; 329 int error = 0;
337 330
338 while (!list_empty(head)) { 331 if (rsize < PAGE_CACHE_SIZE)
339 nfs_pageio_init(&desc, rsize); 332 nfs_pageio_init(&desc, inode, nfs_pagein_multi, rsize, 0);
340 nfs_pageio_add_list(&desc, head); 333 else
341 req = nfs_list_entry(desc.pg_list.next); 334 nfs_pageio_init(&desc, inode, nfs_pagein_one, rsize, 0);
342 error = nfs_pagein_one(&desc.pg_list, req->wb_context->dentry->d_inode); 335
343 if (error < 0) 336 nfs_pageio_add_list(&desc, head);
344 break; 337 nfs_pageio_complete(&desc);
345 pages += (desc.pg_count + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; 338 pages += (desc.pg_bytes_written + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
346 }
347 339
348 nfs_async_read_error(head); 340 nfs_async_read_error(head);
349 if (error >= 0) 341 if (error >= 0)
@@ -597,7 +589,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
597 filp->private_data); 589 filp->private_data);
598 ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc); 590 ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);
599 if (!list_empty(&head)) { 591 if (!list_empty(&head)) {
600 int err = nfs_pagein_list(&head, server->rsize); 592 int err = nfs_pagein_list(inode, &head, server->rsize);
601 if (!ret) 593 if (!ret)
602 nfs_add_stats(inode, NFSIOS_READPAGES, err); 594 nfs_add_stats(inode, NFSIOS_READPAGES, err);
603 ret = err; 595 ret = err;