diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2006-01-17 01:14:46 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-17 02:15:31 -0500 |
commit | c1aa96a52e9594fb16296c0d76c2066773d62933 (patch) | |
tree | a4fce3fa93710d66f536a8333be97fb629429eed | |
parent | 361b1eb55ea84181505c7f0674ca1205da1127ab (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.c | 44 |
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 | ||
314 | static int fuse_send_readpages(struct fuse_req *req, struct file *file, | 314 | static 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 | |||
331 | static 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 | ||
331 | struct fuse_readpages_data { | 343 | struct 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 | ||