Commit 1d7ea7324ae7a59f8e17e4ba76a2707c1e6f24d2

Authored by Alexander Zarochentsev
Committed by Greg Kroah-Hartman
1 parent 9b41ea7289

[PATCH] fuse: fix error case in fuse_readpages

Don't let fuse_readpages leave the @pages list not empty when exiting
on error.

[akpm@osdl.org: kernel-doc fixes]
Signed-off-by: Alexander Zarochentsev <zam@namesys.com>
Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 3 changed files with 29 additions and 2 deletions Side-by-side Diff

... ... @@ -395,14 +395,16 @@
395 395 struct fuse_readpages_data data;
396 396 int err;
397 397  
  398 + err = -EIO;
398 399 if (is_bad_inode(inode))
399   - return -EIO;
  400 + goto clean_pages_up;
400 401  
401 402 data.file = file;
402 403 data.inode = inode;
403 404 data.req = fuse_get_req(fc);
  405 + err = PTR_ERR(data.req);
404 406 if (IS_ERR(data.req))
405   - return PTR_ERR(data.req);
  407 + goto clean_pages_up;
406 408  
407 409 err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
408 410 if (!err) {
... ... @@ -411,6 +413,10 @@
411 413 else
412 414 fuse_put_request(fc, data.req);
413 415 }
  416 + return err;
  417 +
  418 +clean_pages_up:
  419 + put_pages_list(pages);
414 420 return err;
415 421 }
416 422  
... ... @@ -336,6 +336,7 @@
336 336 }
337 337  
338 338 void put_page(struct page *page);
  339 +void put_pages_list(struct list_head *pages);
339 340  
340 341 void split_page(struct page *page, unsigned int order);
341 342  
... ... @@ -54,6 +54,26 @@
54 54 }
55 55 EXPORT_SYMBOL(put_page);
56 56  
  57 +/**
  58 + * put_pages_list(): release a list of pages
  59 + *
  60 + * Release a list of pages which are strung together on page.lru. Currently
  61 + * used by read_cache_pages() and related error recovery code.
  62 + *
  63 + * @pages: list of pages threaded on page->lru
  64 + */
  65 +void put_pages_list(struct list_head *pages)
  66 +{
  67 + while (!list_empty(pages)) {
  68 + struct page *victim;
  69 +
  70 + victim = list_entry(pages->prev, struct page, lru);
  71 + list_del(&victim->lru);
  72 + page_cache_release(victim);
  73 + }
  74 +}
  75 +EXPORT_SYMBOL(put_pages_list);
  76 +
57 77 /*
58 78 * Writeback is about to end against a page which has been marked for immediate
59 79 * reclaim. If it still appears to be reclaimable, move it to the tail of the