Commit b1793929 authored by Matthew Wilcox (Oracle)'s avatar Matthew Wilcox (Oracle) Committed by Andrew Morton
Browse files

writeback: factor folio_prepare_writeback() out of write_cache_pages()

Reduce write_cache_pages() by about 30 lines; much of it is commentary,
but it all bundles nicely into an obvious function.

[hch@lst.de: rename should_writeback_folio to folio_prepare_writeback per Jan]
Link: https://lkml.kernel.org/r/20240215063649.2164017-8-hch@lst.de


Signed-off-by: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Acked-by: default avatarDave Chinner <dchinner@redhat.com>
Cc: Christian Brauner <brauner@kernel.org>
Cc: David Howells <dhowells@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent f946e0d2
Loading
Loading
Loading
Loading
+34 −27
Original line number Diff line number Diff line
@@ -2360,6 +2360,38 @@ void tag_pages_for_writeback(struct address_space *mapping,
}
EXPORT_SYMBOL(tag_pages_for_writeback);

static bool folio_prepare_writeback(struct address_space *mapping,
		struct writeback_control *wbc, struct folio *folio)
{
	/*
	 * Folio truncated or invalidated. We can freely skip it then,
	 * even for data integrity operations: the folio has disappeared
	 * concurrently, so there could be no real expectation of this
	 * data integrity operation even if there is now a new, dirty
	 * folio at the same pagecache index.
	 */
	if (unlikely(folio->mapping != mapping))
		return false;

	/*
	 * Did somebody else write it for us?
	 */
	if (!folio_test_dirty(folio))
		return false;

	if (folio_test_writeback(folio)) {
		if (wbc->sync_mode == WB_SYNC_NONE)
			return false;
		folio_wait_writeback(folio);
	}
	BUG_ON(folio_test_writeback(folio));

	if (!folio_clear_dirty_for_io(folio))
		return false;

	return true;
}

/**
 * write_cache_pages - walk the list of dirty pages of the given address space and write all of them.
 * @mapping: address space structure to write
@@ -2430,38 +2462,13 @@ int write_cache_pages(struct address_space *mapping,
		for (i = 0; i < nr_folios; i++) {
			folio = fbatch.folios[i];
			folio_lock(folio);

			/*
			 * Page truncated or invalidated. We can freely skip it
			 * then, even for data integrity operations: the page
			 * has disappeared concurrently, so there could be no
			 * real expectation of this data integrity operation
			 * even if there is now a new, dirty page at the same
			 * pagecache address.
			 */
			if (unlikely(folio->mapping != mapping)) {
continue_unlock:
			if (!folio_prepare_writeback(mapping, wbc, folio)) {
				folio_unlock(folio);
				continue;
			}

			if (!folio_test_dirty(folio)) {
				/* someone wrote it for us */
				goto continue_unlock;
			}

			if (folio_test_writeback(folio)) {
				if (wbc->sync_mode != WB_SYNC_NONE)
					folio_wait_writeback(folio);
				else
					goto continue_unlock;
			}

			BUG_ON(folio_test_writeback(folio));
			if (!folio_clear_dirty_for_io(folio))
				goto continue_unlock;

			trace_wbc_writepage(wbc, inode_to_bdi(mapping->host));

			error = writepage(folio, wbc, data);
			wbc->nr_to_write -= folio_nr_pages(folio);