diff options
author | Yan, Zheng <zyan@redhat.com> | 2017-08-31 16:55:48 +0800 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2017-09-06 19:56:56 +0200 |
commit | 0713e5f24b7deb88579dc312cf818b1a0809f02e (patch) | |
tree | 3f6ac060be135724eba021fdd5de551fe1306f2e /fs/ceph | |
parent | 05455e1177f76849e0a6450e8710dcb2c361f337 (diff) | |
download | linux-stable-0713e5f24b7deb88579dc312cf818b1a0809f02e.tar.gz linux-stable-0713e5f24b7deb88579dc312cf818b1a0809f02e.tar.bz2 linux-stable-0713e5f24b7deb88579dc312cf818b1a0809f02e.zip |
ceph: optimize pagevec iterating in ceph_writepages_start()
ceph_writepages_start() supports writing non-continuous pages.
If it encounters a non-dirty or non-writeable page in pagevec,
it can continue to check the rest pages in pagevec.
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/ceph')
-rw-r--r-- | fs/ceph/addr.c | 54 |
1 files changed, 25 insertions, 29 deletions
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 8526359c08b2..5ca887bb5cae 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -851,7 +851,6 @@ retry: while (!done && index <= end) { unsigned i; - int first; pgoff_t strip_unit_end = 0; int num_ops = 0, op_idx; int pvec_pages, locked_pages = 0; @@ -864,7 +863,6 @@ retry: max_pages = max_pages_ever; get_more_pages: - first = -1; want = min(end - index, min((pgoff_t)PAGEVEC_SIZE, max_pages - (pgoff_t)locked_pages) - 1) @@ -888,7 +886,7 @@ get_more_pages: unlikely(page->mapping != mapping)) { dout("!dirty or !mapping %p\n", page); unlock_page(page); - break; + continue; } if (!wbc->range_cyclic && page->index > end) { dout("end of range %p\n", page); @@ -901,10 +899,6 @@ get_more_pages: unlock_page(page); break; } - if (wbc->sync_mode != WB_SYNC_NONE) { - dout("waiting on writeback %p\n", page); - wait_on_page_writeback(page); - } if (page_offset(page) >= ceph_wbc.i_size) { dout("%p page eof %llu\n", page, ceph_wbc.i_size); @@ -913,9 +907,13 @@ get_more_pages: break; } if (PageWriteback(page)) { - dout("%p under writeback\n", page); - unlock_page(page); - break; + if (wbc->sync_mode == WB_SYNC_NONE) { + dout("%p under writeback\n", page); + unlock_page(page); + continue; + } + dout("waiting on writeback %p\n", page); + wait_on_page_writeback(page); } /* only if matching snap context */ @@ -924,15 +922,13 @@ get_more_pages: dout("page snapc %p %lld > oldest %p %lld\n", pgsnapc, pgsnapc->seq, snapc, snapc->seq); unlock_page(page); - if (!locked_pages) - continue; /* keep looking for snap */ - break; + continue; } if (!clear_page_dirty_for_io(page)) { dout("%p !clear_page_dirty_for_io\n", page); unlock_page(page); - break; + continue; } /* @@ -988,8 +984,6 @@ get_more_pages: } /* note position of first page in pvec */ - if (first < 0) - first = i; dout("%p will write page %p idx %lu\n", inode, page, page->index); @@ -1000,8 +994,10 @@ get_more_pages: BLK_RW_ASYNC); } - pages[locked_pages] = page; - locked_pages++; + + pages[locked_pages++] = page; + pvec.pages[i] = NULL; + len += PAGE_SIZE; } @@ -1009,23 +1005,23 @@ get_more_pages: if (!locked_pages) goto release_pvec_pages; if (i) { - int j; - BUG_ON(!locked_pages || first < 0); + unsigned j, n = 0; + /* shift unused page to beginning of pvec */ + for (j = 0; j < pvec_pages; j++) { + if (!pvec.pages[j]) + continue; + if (n < j) + pvec.pages[n] = pvec.pages[j]; + n++; + } + pvec.nr = n; if (pvec_pages && i == pvec_pages && locked_pages < max_pages) { dout("reached end pvec, trying for more\n"); - pagevec_reinit(&pvec); + pagevec_release(&pvec); goto get_more_pages; } - - /* shift unused pages over in the pvec... we - * will need to release them below. */ - for (j = i; j < pvec_pages; j++) { - dout(" pvec leftover page %p\n", pvec.pages[j]); - pvec.pages[j-i+first] = pvec.pages[j]; - } - pvec.nr -= i-first; } new_request: |