ceph: wait on writeback after writing snapshot data

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>

authored by

Yan, Zheng and committed by
Ilya Dryomov
f275635e 7e1ee54a

+24
+24
fs/ceph/addr.c
··· 1165 1165 /* more to do; loop back to beginning of file */ 1166 1166 dout("writepages looping back to beginning of file\n"); 1167 1167 end = start_index - 1; /* OK even when start_index == 0 */ 1168 + 1169 + /* to write dirty pages associated with next snapc, 1170 + * we need to wait until current writes complete */ 1171 + if (wbc->sync_mode != WB_SYNC_NONE && 1172 + start_index == 0 && /* all dirty pages were checked */ 1173 + !ceph_wbc.head_snapc) { 1174 + struct page *page; 1175 + unsigned i, nr; 1176 + index = 0; 1177 + while ((index <= end) && 1178 + (nr = pagevec_lookup_tag(&pvec, mapping, &index, 1179 + PAGECACHE_TAG_WRITEBACK, 1180 + PAGEVEC_SIZE))) { 1181 + for (i = 0; i < nr; i++) { 1182 + page = pvec.pages[i]; 1183 + if (page_snap_context(page) != snapc) 1184 + continue; 1185 + wait_on_page_writeback(page); 1186 + } 1187 + pagevec_release(&pvec); 1188 + cond_resched(); 1189 + } 1190 + } 1191 + 1168 1192 start_index = 0; 1169 1193 index = 0; 1170 1194 goto retry;