aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/aops.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/aops.c')
-rw-r--r--fs/gfs2/aops.c132
1 files changed, 96 insertions, 36 deletions
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 49436fa7cd4f..ce62dcac90b6 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -21,6 +21,7 @@
21#include <linux/gfs2_ondisk.h> 21#include <linux/gfs2_ondisk.h>
22#include <linux/backing-dev.h> 22#include <linux/backing-dev.h>
23#include <linux/aio.h> 23#include <linux/aio.h>
24#include <trace/events/writeback.h>
24 25
25#include "gfs2.h" 26#include "gfs2.h"
26#include "incore.h" 27#include "incore.h"
@@ -230,13 +231,11 @@ static int gfs2_writepages(struct address_space *mapping,
230static int gfs2_write_jdata_pagevec(struct address_space *mapping, 231static int gfs2_write_jdata_pagevec(struct address_space *mapping,
231 struct writeback_control *wbc, 232 struct writeback_control *wbc,
232 struct pagevec *pvec, 233 struct pagevec *pvec,
233 int nr_pages, pgoff_t end) 234 int nr_pages, pgoff_t end,
235 pgoff_t *done_index)
234{ 236{
235 struct inode *inode = mapping->host; 237 struct inode *inode = mapping->host;
236 struct gfs2_sbd *sdp = GFS2_SB(inode); 238 struct gfs2_sbd *sdp = GFS2_SB(inode);
237 loff_t i_size = i_size_read(inode);
238 pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
239 unsigned offset = i_size & (PAGE_CACHE_SIZE-1);
240 unsigned nrblocks = nr_pages * (PAGE_CACHE_SIZE/inode->i_sb->s_blocksize); 239 unsigned nrblocks = nr_pages * (PAGE_CACHE_SIZE/inode->i_sb->s_blocksize);
241 int i; 240 int i;
242 int ret; 241 int ret;
@@ -248,40 +247,83 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping,
248 for(i = 0; i < nr_pages; i++) { 247 for(i = 0; i < nr_pages; i++) {
249 struct page *page = pvec->pages[i]; 248 struct page *page = pvec->pages[i];
250 249
250 /*
251 * At this point, the page may be truncated or
252 * invalidated (changing page->mapping to NULL), or
253 * even swizzled back from swapper_space to tmpfs file
254 * mapping. However, page->index will not change
255 * because we have a reference on the page.
256 */
257 if (page->index > end) {
258 /*
259 * can't be range_cyclic (1st pass) because
260 * end == -1 in that case.
261 */
262 ret = 1;
263 break;
264 }
265
266 *done_index = page->index;
267
251 lock_page(page); 268 lock_page(page);
252 269
253 if (unlikely(page->mapping != mapping)) { 270 if (unlikely(page->mapping != mapping)) {
271continue_unlock:
254 unlock_page(page); 272 unlock_page(page);
255 continue; 273 continue;
256 } 274 }
257 275
258 if (!wbc->range_cyclic && page->index > end) { 276 if (!PageDirty(page)) {
259 ret = 1; 277 /* someone wrote it for us */
260 unlock_page(page); 278 goto continue_unlock;
261 continue;
262 } 279 }
263 280
264 if (wbc->sync_mode != WB_SYNC_NONE) 281 if (PageWriteback(page)) {
265 wait_on_page_writeback(page); 282 if (wbc->sync_mode != WB_SYNC_NONE)
266 283 wait_on_page_writeback(page);
267 if (PageWriteback(page) || 284 else
268 !clear_page_dirty_for_io(page)) { 285 goto continue_unlock;
269 unlock_page(page);
270 continue;
271 } 286 }
272 287
273 /* Is the page fully outside i_size? (truncate in progress) */ 288 BUG_ON(PageWriteback(page));
274 if (page->index > end_index || (page->index == end_index && !offset)) { 289 if (!clear_page_dirty_for_io(page))
275 page->mapping->a_ops->invalidatepage(page, 0, 290 goto continue_unlock;
276 PAGE_CACHE_SIZE); 291
277 unlock_page(page); 292 trace_wbc_writepage(wbc, mapping->backing_dev_info);
278 continue;
279 }
280 293
281 ret = __gfs2_jdata_writepage(page, wbc); 294 ret = __gfs2_jdata_writepage(page, wbc);
295 if (unlikely(ret)) {
296 if (ret == AOP_WRITEPAGE_ACTIVATE) {
297 unlock_page(page);
298 ret = 0;
299 } else {
300
301 /*
302 * done_index is set past this page,
303 * so media errors will not choke
304 * background writeout for the entire
305 * file. This has consequences for
306 * range_cyclic semantics (ie. it may
307 * not be suitable for data integrity
308 * writeout).
309 */
310 *done_index = page->index + 1;
311 ret = 1;
312 break;
313 }
314 }
282 315
283 if (ret || (--(wbc->nr_to_write) <= 0)) 316 /*
317 * We stop writing back only if we are not doing
318 * integrity sync. In case of integrity sync we have to
319 * keep going until we have written all the pages
320 * we tagged for writeback prior to entering this loop.
321 */
322 if (--wbc->nr_to_write <= 0 && wbc->sync_mode == WB_SYNC_NONE) {
284 ret = 1; 323 ret = 1;
324 break;
325 }
326
285 } 327 }
286 gfs2_trans_end(sdp); 328 gfs2_trans_end(sdp);
287 return ret; 329 return ret;
@@ -306,51 +348,69 @@ static int gfs2_write_cache_jdata(struct address_space *mapping,
306 int done = 0; 348 int done = 0;
307 struct pagevec pvec; 349 struct pagevec pvec;
308 int nr_pages; 350 int nr_pages;
351 pgoff_t uninitialized_var(writeback_index);
309 pgoff_t index; 352 pgoff_t index;
310 pgoff_t end; 353 pgoff_t end;
311 int scanned = 0; 354 pgoff_t done_index;
355 int cycled;
312 int range_whole = 0; 356 int range_whole = 0;
357 int tag;
313 358
314 pagevec_init(&pvec, 0); 359 pagevec_init(&pvec, 0);
315 if (wbc->range_cyclic) { 360 if (wbc->range_cyclic) {
316 index = mapping->writeback_index; /* Start from prev offset */ 361 writeback_index = mapping->writeback_index; /* prev offset */
362 index = writeback_index;
363 if (index == 0)
364 cycled = 1;
365 else
366 cycled = 0;
317 end = -1; 367 end = -1;
318 } else { 368 } else {
319 index = wbc->range_start >> PAGE_CACHE_SHIFT; 369 index = wbc->range_start >> PAGE_CACHE_SHIFT;
320 end = wbc->range_end >> PAGE_CACHE_SHIFT; 370 end = wbc->range_end >> PAGE_CACHE_SHIFT;
321 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) 371 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
322 range_whole = 1; 372 range_whole = 1;
323 scanned = 1; 373 cycled = 1; /* ignore range_cyclic tests */
324 } 374 }
375 if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
376 tag = PAGECACHE_TAG_TOWRITE;
377 else
378 tag = PAGECACHE_TAG_DIRTY;
325 379
326retry: 380retry:
327 while (!done && (index <= end) && 381 if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
328 (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, 382 tag_pages_for_writeback(mapping, index, end);
329 PAGECACHE_TAG_DIRTY, 383 done_index = index;
330 min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) { 384 while (!done && (index <= end)) {
331 scanned = 1; 385 nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, tag,
332 ret = gfs2_write_jdata_pagevec(mapping, wbc, &pvec, nr_pages, end); 386 min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
387 if (nr_pages == 0)
388 break;
389
390 ret = gfs2_write_jdata_pagevec(mapping, wbc, &pvec, nr_pages, end, &done_index);
333 if (ret) 391 if (ret)
334 done = 1; 392 done = 1;
335 if (ret > 0) 393 if (ret > 0)
336 ret = 0; 394 ret = 0;
337
338 pagevec_release(&pvec); 395 pagevec_release(&pvec);
339 cond_resched(); 396 cond_resched();
340 } 397 }
341 398
342 if (!scanned && !done) { 399 if (!cycled && !done) {
343 /* 400 /*
401 * range_cyclic:
344 * We hit the last page and there is more work to be done: wrap 402 * We hit the last page and there is more work to be done: wrap
345 * back to the start of the file 403 * back to the start of the file
346 */ 404 */
347 scanned = 1; 405 cycled = 1;
348 index = 0; 406 index = 0;
407 end = writeback_index - 1;
349 goto retry; 408 goto retry;
350 } 409 }
351 410
352 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) 411 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
353 mapping->writeback_index = index; 412 mapping->writeback_index = done_index;
413
354 return ret; 414 return ret;
355} 415}
356 416