@@ -892,16 +892,30 @@ static int ceph_writepages_start(struct address_space *mapping,
unlock_page(page);
continue;
}
- if (strip_unit_end && (page->index > strip_unit_end)) {
- dout("end of strip unit %p\n", page);
+ /* only if matching snap context */
+ pgsnapc = page_snap_context(page);
+ if (pgsnapc != snapc) {
+ dout("page snapc %p %lld != oldest %p %lld\n",
+ pgsnapc, pgsnapc->seq, snapc, snapc->seq);
unlock_page(page);
- break;
+ continue;
}
if (page_offset(page) >= ceph_wbc.i_size) {
dout("%p page eof %llu\n",
page, ceph_wbc.i_size);
- /* not done if range_cyclic */
- stop = true;
+ if (ceph_wbc.size_stable) {
+ mapping->a_ops->invalidatepage(page,
+ 0, PAGE_SIZE);
+ } else {
+ stop = true;
+ }
+ unlock_page(page);
+ if (stop)
+ break;
+ continue;
+ }
+ if (strip_unit_end && (page->index > strip_unit_end)) {
+ dout("end of strip unit %p\n", page);
unlock_page(page);
break;
}
@@ -915,14 +929,6 @@ static int ceph_writepages_start(struct address_space *mapping,
wait_on_page_writeback(page);
}
- /* only if matching snap context */
- pgsnapc = page_snap_context(page);
- if (pgsnapc != snapc) {
- dout("page snapc %p %lld != oldest %p %lld\n",
- pgsnapc, pgsnapc->seq, snapc, snapc->seq);
- unlock_page(page);
- continue;
- }
if (!clear_page_dirty_for_io(page)) {
dout("%p !clear_page_dirty_for_io\n", page);
@@ -1838,22 +1838,10 @@ void __ceph_do_pending_vmtruncate(struct inode *inode)
* possibly truncate them.. so write AND block!
*/
if (ci->i_wrbuffer_ref_head < ci->i_wrbuffer_ref) {
- struct ceph_cap_snap *capsnap;
- to = ci->i_truncate_size;
- list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) {
- // MDS should have revoked Frw caps
- WARN_ON_ONCE(capsnap->writing);
- if (capsnap->dirty_pages && capsnap->size > to)
- to = capsnap->size;
- }
spin_unlock(&ci->i_ceph_lock);
dout("__do_pending_vmtruncate %p flushing snaps first\n",
inode);
-
- truncate_pagecache(inode, to);
-
- filemap_write_and_wait_range(&inode->i_data, 0,
- inode->i_sb->s_maxbytes);
+ filemap_write_and_wait_range(&inode->i_data, 0, LLONG_MAX);
goto retry;
}
It's possible there are several pending ceph_cap_snap, and they have different i_size. For a given dirty page, value of EOF depends on which snap context it's associated. calling truncate_pagecache() in __ceph_do_pending_vmtruncate() can not handle such complex situation. Signed-off-by: "Yan, Zheng" <zyan@redhat.com> --- fs/ceph/addr.c | 32 +++++++++++++++++++------------- fs/ceph/inode.c | 14 +------------- 2 files changed, 20 insertions(+), 26 deletions(-)