]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/commitdiff
ceph: invalidate pages that beyond EOF in ceph_writepages_start()
authorYan, Zheng <zyan@redhat.com>
Sun, 4 Mar 2018 08:36:01 +0000 (16:36 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 2 Apr 2018 08:12:47 +0000 (10:12 +0200)
Dirty pages can be associated with different capsnap. Different capsnap
may have different EOF value. So invalidating dirty pages according to
the largest EOF value is wrong. Dirty pages beyond EOF, but associated
with other capsnap, do not get invalidated.

Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/addr.c
fs/ceph/inode.c

index 4b3cf53d564142c1b09206b249069a5cc1b15324..3376822a624e2bee77d9b3b969bc3925bf1bdfd1 100644 (file)
@@ -801,7 +801,7 @@ static int ceph_writepages_start(struct address_space *mapping,
        struct ceph_osd_request *req = NULL;
        struct ceph_writeback_ctl ceph_wbc;
        bool should_loop, range_whole = false;
-       bool stop, done = false;
+       bool done = false;
 
        dout("writepages_start %p (mode=%s)\n", inode,
             wbc->sync_mode == WB_SYNC_NONE ? "NONE" :
@@ -865,8 +865,7 @@ retry:
        ceph_put_snap_context(last_snapc);
        last_snapc = snapc;
 
-       stop = false;
-       while (!stop && index <= end) {
+       while (!done && index <= end) {
                int num_ops = 0, op_idx;
                unsigned i, pvec_pages, max_pages, locked_pages = 0;
                struct page **pages = NULL, **data_pages;
@@ -899,16 +898,26 @@ get_more_pages:
                                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 ||
+                                   page_offset(page) >= i_size_read(inode))
+                                       mapping->a_ops->invalidatepage(page,
+                                                               0, PAGE_SIZE);
+                               unlock_page(page);
+                               continue;
+                       }
+                       if (strip_unit_end && (page->index > strip_unit_end)) {
+                               dout("end of strip unit %p\n", page);
                                unlock_page(page);
                                break;
                        }
@@ -922,15 +931,6 @@ get_more_pages:
                                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);
                                unlock_page(page);
@@ -1143,7 +1143,7 @@ new_request:
                 * we tagged for writeback prior to entering this loop.
                 */
                if (wbc->nr_to_write <= 0 && wbc->sync_mode == WB_SYNC_NONE)
-                       done = stop = true;
+                       done = true;
 
 release_pvec_pages:
                dout("pagevec_release on %d pages (%p)\n", (int)pvec.nr,
index c6ec5aa461002796325e84796199dd0ed2dd0a67..be5f12d0d6372c97328892170f9c41549bb5a51f 100644 (file)
@@ -1867,20 +1867,9 @@ retry:
         * 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);
                goto retry;