aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2006-01-17 01:14:46 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-17 02:15:31 -0500
commitc1aa96a52e9594fb16296c0d76c2066773d62933 (patch)
treea4fce3fa93710d66f536a8333be97fb629429eed
parent361b1eb55ea84181505c7f0674ca1205da1127ab (diff)
[PATCH] fuse: use asynchronous READ requests for readpages
This patch changes fuse_readpages() to send READ requests asynchronously. This makes it possible for userspace filesystems to utilize the kernel readahead logic instead of having to implement their own (resulting in double caching). Signed-off-by: Miklos Szeredi <miklos@szeredi.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/fuse/file.c44
1 files changed, 27 insertions, 17 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 4a0b0f9a2179..a7ef5e716f3c 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -265,7 +265,7 @@ void fuse_read_fill(struct fuse_req *req, struct file *file,
265 req->file = file; 265 req->file = file;
266 req->in.numargs = 1; 266 req->in.numargs = 1;
267 req->in.args[0].size = sizeof(struct fuse_read_in); 267 req->in.args[0].size = sizeof(struct fuse_read_in);
268 req->in.args[0].value = &inarg; 268 req->in.args[0].value = inarg;
269 req->out.argpages = 1; 269 req->out.argpages = 1;
270 req->out.argvar = 1; 270 req->out.argvar = 1;
271 req->out.numargs = 1; 271 req->out.numargs = 1;
@@ -311,21 +311,33 @@ static int fuse_readpage(struct file *file, struct page *page)
311 return err; 311 return err;
312} 312}
313 313
314static int fuse_send_readpages(struct fuse_req *req, struct file *file, 314static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)
315 struct inode *inode)
316{ 315{
317 loff_t pos = page_offset(req->pages[0]); 316 int i;
318 size_t count = req->num_pages << PAGE_CACHE_SHIFT; 317
319 unsigned i; 318 fuse_invalidate_attr(req->pages[0]->mapping->host); /* atime changed */
320 req->out.page_zeroing = 1; 319
321 fuse_send_read(req, file, inode, pos, count);
322 for (i = 0; i < req->num_pages; i++) { 320 for (i = 0; i < req->num_pages; i++) {
323 struct page *page = req->pages[i]; 321 struct page *page = req->pages[i];
324 if (!req->out.h.error) 322 if (!req->out.h.error)
325 SetPageUptodate(page); 323 SetPageUptodate(page);
324 else
325 SetPageError(page);
326 unlock_page(page); 326 unlock_page(page);
327 } 327 }
328 return req->out.h.error; 328 fuse_put_request(fc, req);
329}
330
331static void fuse_send_readpages(struct fuse_req *req, struct file *file,
332 struct inode *inode)
333{
334 struct fuse_conn *fc = get_fuse_conn(inode);
335 loff_t pos = page_offset(req->pages[0]);
336 size_t count = req->num_pages << PAGE_CACHE_SHIFT;
337 req->out.page_zeroing = 1;
338 req->end = fuse_readpages_end;
339 fuse_read_fill(req, file, inode, pos, count, FUSE_READ);
340 request_send_background(fc, req);
329} 341}
330 342
331struct fuse_readpages_data { 343struct fuse_readpages_data {
@@ -345,12 +357,12 @@ static int fuse_readpages_fill(void *_data, struct page *page)
345 (req->num_pages == FUSE_MAX_PAGES_PER_REQ || 357 (req->num_pages == FUSE_MAX_PAGES_PER_REQ ||
346 (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || 358 (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read ||
347 req->pages[req->num_pages - 1]->index + 1 != page->index)) { 359 req->pages[req->num_pages - 1]->index + 1 != page->index)) {
348 int err = fuse_send_readpages(req, data->file, inode); 360 fuse_send_readpages(req, data->file, inode);
349 if (err) { 361 data->req = req = fuse_get_request(fc);
362 if (!req) {
350 unlock_page(page); 363 unlock_page(page);
351 return err; 364 return -EINTR;
352 } 365 }
353 fuse_reset_request(req);
354 } 366 }
355 req->pages[req->num_pages] = page; 367 req->pages[req->num_pages] = page;
356 req->num_pages ++; 368 req->num_pages ++;
@@ -375,10 +387,8 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
375 return -EINTR; 387 return -EINTR;
376 388
377 err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); 389 err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
378 if (!err && data.req->num_pages) 390 if (!err)
379 err = fuse_send_readpages(data.req, file, inode); 391 fuse_send_readpages(data.req, file, inode);
380 fuse_put_request(fc, data.req);
381 fuse_invalidate_attr(inode); /* atime changed */
382 return err; 392 return err;
383} 393}
384 394