Skip to content

Commit

Permalink
ceph: fix error handling of start_read()
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
ukernel authored and idryomov committed Sep 5, 2016
1 parent 52f51f2 commit ea482ac
Showing 1 changed file with 9 additions and 10 deletions.
19 changes: 9 additions & 10 deletions fs/ceph/addr.c
Expand Up @@ -298,14 +298,6 @@ static void finish_read(struct ceph_osd_request *req)
kfree(osd_data->pages);
}

static void ceph_unlock_page_vector(struct page **pages, int num_pages)
{
int i;

for (i = 0; i < num_pages; i++)
unlock_page(pages[i]);
}

/*
* start an async read(ahead) operation. return nr_pages we submitted
* a read for on success, or negative error code.
Expand Down Expand Up @@ -370,6 +362,10 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max)
dout("start_read %p add_to_page_cache failed %p\n",
inode, page);
nr_pages = i;
if (nr_pages > 0) {
len = nr_pages << PAGE_SHIFT;
break;
}
goto out_pages;
}
pages[i] = page;
Expand All @@ -386,8 +382,11 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max)
return nr_pages;

out_pages:
ceph_unlock_page_vector(pages, nr_pages);
ceph_release_page_vector(pages, nr_pages);
for (i = 0; i < nr_pages; ++i) {
ceph_fscache_readpage_cancel(inode, pages[i]);
unlock_page(pages[i]);
}
ceph_put_page_vector(pages, nr_pages, false);
out:
ceph_osdc_put_request(req);
return ret;
Expand Down

0 comments on commit ea482ac

Please sign in to comment.