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@xxxxxxxxxx> --- fs/ceph/addr.c | 32 +++++++++++++++++++------------- fs/ceph/inode.c | 14 +------------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index e57e9d37bf2d..938acb15b4d3 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -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); diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 8100f8a1a12d..e3515f759998 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -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; } -- 2.13.6 -- To unsubscribe from this list: send the line "unsubscribe ceph-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html