diff options
| author | Alexander Zarochentsev <zam@namesys.com> | 2006-08-14 02:24:27 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-08-14 15:54:29 -0400 |
| commit | 1d7ea7324ae7a59f8e17e4ba76a2707c1e6f24d2 (patch) | |
| tree | 902b646ed70af86481a77a67582b79e67264a481 | |
| parent | 9b41ea7289a589993d3daabc61f999b4147872c4 (diff) | |
[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>
| -rw-r--r-- | fs/fuse/file.c | 10 | ||||
| -rw-r--r-- | include/linux/mm.h | 1 | ||||
| -rw-r--r-- | mm/swap.c | 20 |
3 files changed, 29 insertions, 2 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 63614ed163..5c4fcd1dbf 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
| @@ -395,14 +395,16 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
| 395 | struct fuse_readpages_data data; | 395 | struct fuse_readpages_data data; |
| 396 | int err; | 396 | int err; |
| 397 | 397 | ||
| 398 | err = -EIO; | ||
| 398 | if (is_bad_inode(inode)) | 399 | if (is_bad_inode(inode)) |
| 399 | return -EIO; | 400 | goto clean_pages_up; |
| 400 | 401 | ||
| 401 | data.file = file; | 402 | data.file = file; |
| 402 | data.inode = inode; | 403 | data.inode = inode; |
| 403 | data.req = fuse_get_req(fc); | 404 | data.req = fuse_get_req(fc); |
| 405 | err = PTR_ERR(data.req); | ||
| 404 | if (IS_ERR(data.req)) | 406 | if (IS_ERR(data.req)) |
| 405 | return PTR_ERR(data.req); | 407 | goto clean_pages_up; |
| 406 | 408 | ||
| 407 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); | 409 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); |
| 408 | if (!err) { | 410 | if (!err) { |
| @@ -412,6 +414,10 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
| 412 | fuse_put_request(fc, data.req); | 414 | fuse_put_request(fc, data.req); |
| 413 | } | 415 | } |
| 414 | return err; | 416 | return err; |
| 417 | |||
| 418 | clean_pages_up: | ||
| 419 | put_pages_list(pages); | ||
| 420 | return err; | ||
| 415 | } | 421 | } |
| 416 | 422 | ||
| 417 | static size_t fuse_send_write(struct fuse_req *req, struct file *file, | 423 | static size_t fuse_send_write(struct fuse_req *req, struct file *file, |
diff --git a/include/linux/mm.h b/include/linux/mm.h index 990957e092..f0b135cd86 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -336,6 +336,7 @@ static inline void init_page_count(struct page *page) | |||
| 336 | } | 336 | } |
| 337 | 337 | ||
| 338 | void put_page(struct page *page); | 338 | void put_page(struct page *page); |
| 339 | void put_pages_list(struct list_head *pages); | ||
| 339 | 340 | ||
| 340 | void split_page(struct page *page, unsigned int order); | 341 | void split_page(struct page *page, unsigned int order); |
| 341 | 342 | ||
| @@ -54,6 +54,26 @@ void put_page(struct page *page) | |||
| 54 | } | 54 | } |
| 55 | EXPORT_SYMBOL(put_page); | 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 | * Writeback is about to end against a page which has been marked for immediate | 78 | * Writeback is about to end against a page which has been marked for immediate |
| 59 | * reclaim. If it still appears to be reclaimable, move it to the tail of the | 79 | * reclaim. If it still appears to be reclaimable, move it to the tail of the |
