Commit 1d7ea7324ae7a59f8e17e4ba76a2707c1e6f24d2
Committed by
Greg Kroah-Hartman
1 parent
9b41ea7289
Exists in
master
and in
4 other branches
[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
fs/fuse/file.c
... | ... | @@ -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 |
include/linux/mm.h
mm/swap.c
... | ... | @@ -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 |