ceph: wait on writeback after writing snapshot data
authorYan, Zheng <zyan@redhat.com>
Fri, 1 Sep 2017 09:03:16 +0000 (17:03 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Wed, 6 Sep 2017 17:57:00 +0000 (19:57 +0200)
In sync mode, writepages() needs to write all dirty pages. But
it can only write dirty pages associated with the oldest snapc.
To write dirty pages associated with next snapc, it needs to wait
until current writes complete.

Without this wait, writepages() keeps looking up dirty pages, but
the found dirty pages are not writeable. It wastes CPU time.

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

index 1ffdb903eb799bee7952e732b4f97e6680f05998..b3e3edc09d80382c72a1d2d42515ad67ea51bdb3 100644 (file)
@@ -1165,6 +1165,30 @@ release_pvec_pages:
                /* more to do; loop back to beginning of file */
                dout("writepages looping back to beginning of file\n");
                end = start_index - 1; /* OK even when start_index == 0 */
+
+               /* to write dirty pages associated with next snapc,
+                * we need to wait until current writes complete */
+               if (wbc->sync_mode != WB_SYNC_NONE &&
+                   start_index == 0 && /* all dirty pages were checked */
+                   !ceph_wbc.head_snapc) {
+                       struct page *page;
+                       unsigned i, nr;
+                       index = 0;
+                       while ((index <= end) &&
+                              (nr = pagevec_lookup_tag(&pvec, mapping, &index,
+                                                       PAGECACHE_TAG_WRITEBACK,
+                                                       PAGEVEC_SIZE))) {
+                               for (i = 0; i < nr; i++) {
+                                       page = pvec.pages[i];
+                                       if (page_snap_context(page) != snapc)
+                                               continue;
+                                       wait_on_page_writeback(page);
+                               }
+                               pagevec_release(&pvec);
+                               cond_resched();
+                       }
+               }
+
                start_index = 0;
                index = 0;
                goto retry;