Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

btrfs: remove the nr_ret parameter from __extent_writepage_io()

The parameter @nr_ret is used to tell the caller how many sectors have
been submitted for IO.

Then callers check @nr_ret value to determine if we need to manually
clear the PAGECACHE_TAG_DIRTY, as if we submitted no sector (e.g. all
sectors are beyond i_size) there is no folio_start_writeback() called thus
PAGECACHE_TAG_DIRTY tag will not be cleared.

Remove this parameter by:

- Moving the btrfs_folio_clear_writeback() call into
__extent_writepage_io()
So that if we didn't submit any IO, then manually call
btrfs_folio_set_writeback() to clear PAGECACHE_TAG_DIRTY when
the page is no longer dirty.

- Use a bool to record if we have submitted any sector
Instead of an int.

- Use subpage compatible helpers to end folio writeback.
This brings no change to the behavior, just for the sake of consistency.

As for the call site inside __extent_writepage(), we're always called
for the whole page, so the existing full page helper
folio_(start|end)_writeback() is totally fine.

For the call site inside extent_write_locked_range(), although we can
have subpage range, folio_start_writeback() will only clear
PAGECACHE_TAG_DIRTY if the page is no longer dirty, and the full folio
will still be dirty if there is any subpage dirty range.
Only when the last dirty subpage sector is cleared, the
folio_start_writeback() will clear PAGECACHE_TAG_DIRTY.

So no matter if we call the full page or subpage helper, the result
is still the same, then just use the subpage helpers for consistency.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>

authored by

Qu Wenruo and committed by
David Sterba
2c70fe16 e39ba5df

+17 -25
+17 -25
fs/btrfs/extent_io.c
··· 1409 1409 struct folio *folio, 1410 1410 u64 start, u32 len, 1411 1411 struct btrfs_bio_ctrl *bio_ctrl, 1412 - loff_t i_size, int *nr_ret) 1412 + loff_t i_size) 1413 1413 { 1414 1414 struct btrfs_fs_info *fs_info = inode->root->fs_info; 1415 1415 unsigned long range_bitmap = 0; ··· 1422 1422 */ 1423 1423 unsigned long dirty_bitmap = 1; 1424 1424 unsigned int bitmap_size = 1; 1425 + bool submitted_io = false; 1425 1426 const u64 folio_start = folio_pos(folio); 1426 1427 u64 cur; 1427 1428 int bit; 1428 1429 int ret = 0; 1429 - int nr = 0; 1430 1430 1431 1431 ASSERT(start >= folio_start && 1432 1432 start + len <= folio_start + folio_size(folio)); ··· 1470 1470 } 1471 1471 ret = submit_one_sector(inode, folio, cur, bio_ctrl, i_size); 1472 1472 if (ret < 0) 1473 - goto out_error; 1474 - nr++; 1473 + goto out; 1474 + submitted_io = true; 1475 1475 } 1476 1476 1477 1477 btrfs_folio_assert_not_dirty(fs_info, folio, start, len); 1478 - *nr_ret = nr; 1479 - return 0; 1480 - 1481 - out_error: 1478 + out: 1482 1479 /* 1483 - * If we finish without problem, we should not only clear folio dirty, 1484 - * but also empty subpage dirty bits 1480 + * If we didn't submitted any sector (>= i_size), folio dirty get 1481 + * cleared but PAGECACHE_TAG_DIRTY is not cleared (only cleared 1482 + * by folio_start_writeback() if the folio is not dirty). 1483 + * 1484 + * Here we set writeback and clear for the range. If the full folio 1485 + * is no longer dirty then we clear the PAGECACHE_TAG_DIRTY tag. 1485 1486 */ 1486 - *nr_ret = nr; 1487 + if (!submitted_io) { 1488 + btrfs_folio_set_writeback(fs_info, folio, start, len); 1489 + btrfs_folio_clear_writeback(fs_info, folio, start, len); 1490 + } 1487 1491 return ret; 1488 1492 } 1489 1493 ··· 1505 1501 struct inode *inode = folio->mapping->host; 1506 1502 const u64 page_start = folio_pos(folio); 1507 1503 int ret; 1508 - int nr = 0; 1509 1504 size_t pg_offset; 1510 1505 loff_t i_size = i_size_read(inode); 1511 1506 unsigned long end_index = i_size >> PAGE_SHIFT; ··· 1535 1532 goto done; 1536 1533 1537 1534 ret = __extent_writepage_io(BTRFS_I(inode), folio, folio_pos(folio), 1538 - PAGE_SIZE, bio_ctrl, i_size, &nr); 1535 + PAGE_SIZE, bio_ctrl, i_size); 1539 1536 if (ret == 1) 1540 1537 return 0; 1541 1538 1542 1539 bio_ctrl->wbc->nr_to_write--; 1543 1540 1544 1541 done: 1545 - if (nr == 0) { 1546 - /* make sure the mapping tag for page dirty gets cleared */ 1547 - folio_start_writeback(folio); 1548 - folio_end_writeback(folio); 1549 - } 1550 1542 if (ret) { 1551 1543 btrfs_mark_ordered_io_finished(BTRFS_I(inode), folio, 1552 1544 page_start, PAGE_SIZE, !ret); ··· 2274 2276 u64 cur_end = min(round_down(cur, PAGE_SIZE) + PAGE_SIZE - 1, end); 2275 2277 u32 cur_len = cur_end + 1 - cur; 2276 2278 struct folio *folio; 2277 - int nr = 0; 2278 2279 2279 2280 folio = __filemap_get_folio(mapping, cur >> PAGE_SHIFT, 0, 0); 2280 2281 ··· 2294 2297 ASSERT(folio_test_dirty(folio)); 2295 2298 2296 2299 ret = __extent_writepage_io(BTRFS_I(inode), folio, cur, cur_len, 2297 - &bio_ctrl, i_size, &nr); 2300 + &bio_ctrl, i_size); 2298 2301 if (ret == 1) 2299 2302 goto next_page; 2300 2303 2301 - /* Make sure the mapping tag for page dirty gets cleared. */ 2302 - if (nr == 0) { 2303 - btrfs_folio_set_writeback(fs_info, folio, cur, cur_len); 2304 - btrfs_folio_clear_writeback(fs_info, folio, cur, cur_len); 2305 - } 2306 2304 if (ret) { 2307 2305 btrfs_mark_ordered_io_finished(BTRFS_I(inode), folio, 2308 2306 cur, cur_len, !ret);