summaryrefslogtreecommitdiffstats
path: root/fs/ceph/addr.c
diff options
context:
space:
mode:
authorYan, Zheng <zyan@redhat.com>2016-08-23 23:33:46 -0400
committerIlya Dryomov <idryomov@gmail.com>2016-10-03 10:13:49 -0400
commit1afe478569ba7414dde8a874dda9c1ea621c0c63 (patch)
tree1a4b24ecb88e64c8cb7d4870afd2a126655cdf6c /fs/ceph/addr.c
parent0dcc685e7dd7190dcaa5435e9c14150f1d405b7b (diff)
ceph: fix error handling of start_read()
If start_page() fails to add a page to page cache or fails to send OSD request. It should cal put_page() (instead of free_page()) for relevant pages. Besides, start_page() need to cancel fscache readpage if it fails to send OSD request. Signed-off-by: Yan, Zheng <zyan@redhat.com> Reported-by: Zhi Zhang <zhang.david2011@gmail.com>
Diffstat (limited to 'fs/ceph/addr.c')
-rw-r--r--fs/ceph/addr.c19
1 files changed, 9 insertions, 10 deletions
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index d5b6f959a3c3..f410a0cb57e3 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -298,14 +298,6 @@ unlock:
298 kfree(osd_data->pages); 298 kfree(osd_data->pages);
299} 299}
300 300
301static void ceph_unlock_page_vector(struct page **pages, int num_pages)
302{
303 int i;
304
305 for (i = 0; i < num_pages; i++)
306 unlock_page(pages[i]);
307}
308
309/* 301/*
310 * start an async read(ahead) operation. return nr_pages we submitted 302 * start an async read(ahead) operation. return nr_pages we submitted
311 * a read for on success, or negative error code. 303 * a read for on success, or negative error code.
@@ -370,6 +362,10 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max)
370 dout("start_read %p add_to_page_cache failed %p\n", 362 dout("start_read %p add_to_page_cache failed %p\n",
371 inode, page); 363 inode, page);
372 nr_pages = i; 364 nr_pages = i;
365 if (nr_pages > 0) {
366 len = nr_pages << PAGE_SHIFT;
367 break;
368 }
373 goto out_pages; 369 goto out_pages;
374 } 370 }
375 pages[i] = page; 371 pages[i] = page;
@@ -386,8 +382,11 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max)
386 return nr_pages; 382 return nr_pages;
387 383
388out_pages: 384out_pages:
389 ceph_unlock_page_vector(pages, nr_pages); 385 for (i = 0; i < nr_pages; ++i) {
390 ceph_release_page_vector(pages, nr_pages); 386 ceph_fscache_readpage_cancel(inode, pages[i]);
387 unlock_page(pages[i]);
388 }
389 ceph_put_page_vector(pages, nr_pages, false);
391out: 390out:
392 ceph_osdc_put_request(req); 391 ceph_osdc_put_request(req);
393 return ret; 392 return ret;