提交 590e9d98 编写于 作者: Y Yan, Zheng 提交者: Ilya Dryomov

ceph: fix "range cyclic" mode writepages

In range cyclic mode, writepages() should first write dirty pages
in range [writeback_index, (pgoff_t)-1], then write pages in range
[0, writeback_index -1]. Besides, if writepages() encounters a page
that beyond EOF, it should restart from the beginning.
Signed-off-by: N"Yan, Zheng" <zyan@redhat.com>
Signed-off-by: NIlya Dryomov <idryomov@gmail.com>
上级 0e5ecac7
...@@ -781,16 +781,15 @@ static int ceph_writepages_start(struct address_space *mapping, ...@@ -781,16 +781,15 @@ static int ceph_writepages_start(struct address_space *mapping,
struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_fs_client *fsc = ceph_inode_to_client(inode); struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
struct ceph_vino vino = ceph_vino(inode); struct ceph_vino vino = ceph_vino(inode);
pgoff_t index, start, end; pgoff_t index, start_index, end;
int range_whole = 0;
int should_loop = 1;
struct ceph_snap_context *snapc = NULL, *last_snapc = NULL, *pgsnapc; struct ceph_snap_context *snapc = NULL, *last_snapc = NULL, *pgsnapc;
struct pagevec pvec; struct pagevec pvec;
int done = 0;
int rc = 0; int rc = 0;
unsigned int wsize = i_blocksize(inode); unsigned int wsize = i_blocksize(inode);
struct ceph_osd_request *req = NULL; struct ceph_osd_request *req = NULL;
struct ceph_writeback_ctl ceph_wbc; struct ceph_writeback_ctl ceph_wbc;
bool should_loop, range_whole = false;
bool stop, done = false;
dout("writepages_start %p (mode=%s)\n", inode, dout("writepages_start %p (mode=%s)\n", inode,
wbc->sync_mode == WB_SYNC_NONE ? "NONE" : wbc->sync_mode == WB_SYNC_NONE ? "NONE" :
...@@ -810,20 +809,22 @@ static int ceph_writepages_start(struct address_space *mapping, ...@@ -810,20 +809,22 @@ static int ceph_writepages_start(struct address_space *mapping,
pagevec_init(&pvec, 0); pagevec_init(&pvec, 0);
start_index = wbc->range_cyclic ? mapping->writeback_index : 0;
/* where to start/end? */ /* where to start/end? */
if (wbc->range_cyclic) { if (wbc->range_cyclic) {
start = mapping->writeback_index; /* Start from prev offset */ index = start_index;
end = -1; end = -1;
dout(" cyclic, start at %lu\n", start); should_loop = (index > 0);
dout(" cyclic, start at %lu\n", index);
} else { } else {
start = wbc->range_start >> PAGE_SHIFT; index = wbc->range_start >> PAGE_SHIFT;
end = wbc->range_end >> PAGE_SHIFT; end = wbc->range_end >> PAGE_SHIFT;
if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
range_whole = 1; range_whole = true;
should_loop = 0; should_loop = false;
dout(" not cyclic, %lu to %lu\n", start, end); dout(" not cyclic, %lu to %lu\n", index, end);
} }
index = start;
retry: retry:
/* find oldest snap context with dirty data */ /* find oldest snap context with dirty data */
...@@ -847,7 +848,8 @@ static int ceph_writepages_start(struct address_space *mapping, ...@@ -847,7 +848,8 @@ static int ceph_writepages_start(struct address_space *mapping,
} }
last_snapc = snapc; last_snapc = snapc;
while (!done && index <= end) { stop = false;
while (!stop && index <= end) {
int num_ops = 0, op_idx; int num_ops = 0, op_idx;
unsigned i, pvec_pages, max_pages, locked_pages = 0; unsigned i, pvec_pages, max_pages, locked_pages = 0;
struct page **pages = NULL, **data_pages; struct page **pages = NULL, **data_pages;
...@@ -885,9 +887,11 @@ static int ceph_writepages_start(struct address_space *mapping, ...@@ -885,9 +887,11 @@ static int ceph_writepages_start(struct address_space *mapping,
unlock_page(page); unlock_page(page);
continue; continue;
} }
if (!wbc->range_cyclic && page->index > end) { if (page->index > end) {
dout("end of range %p\n", page); dout("end of range %p\n", page);
done = 1; /* can't be range_cyclic (1st pass) because
* end == -1 in that case. */
stop = done = true;
unlock_page(page); unlock_page(page);
break; break;
} }
...@@ -899,7 +903,8 @@ static int ceph_writepages_start(struct address_space *mapping, ...@@ -899,7 +903,8 @@ static int ceph_writepages_start(struct address_space *mapping,
if (page_offset(page) >= ceph_wbc.i_size) { if (page_offset(page) >= ceph_wbc.i_size) {
dout("%p page eof %llu\n", dout("%p page eof %llu\n",
page, ceph_wbc.i_size); page, ceph_wbc.i_size);
done = 1; /* not done if range_cyclic */
stop = true;
unlock_page(page); unlock_page(page);
break; break;
} }
...@@ -1132,7 +1137,7 @@ static int ceph_writepages_start(struct address_space *mapping, ...@@ -1132,7 +1137,7 @@ static int ceph_writepages_start(struct address_space *mapping,
goto new_request; goto new_request;
if (wbc->nr_to_write <= 0) if (wbc->nr_to_write <= 0)
done = 1; stop = done = true;
release_pvec_pages: release_pvec_pages:
dout("pagevec_release on %d pages (%p)\n", (int)pvec.nr, dout("pagevec_release on %d pages (%p)\n", (int)pvec.nr,
...@@ -1146,7 +1151,9 @@ static int ceph_writepages_start(struct address_space *mapping, ...@@ -1146,7 +1151,9 @@ static int ceph_writepages_start(struct address_space *mapping,
if (should_loop && !done) { if (should_loop && !done) {
/* more to do; loop back to beginning of file */ /* more to do; loop back to beginning of file */
dout("writepages looping back to beginning of file\n"); dout("writepages looping back to beginning of file\n");
should_loop = 0; should_loop = false;
end = start_index - 1;
index = 0; index = 0;
goto retry; goto retry;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册