Commit 807d1fe3 authored by Matthew Wilcox (Oracle)'s avatar Matthew Wilcox (Oracle) Committed by Andrew Morton

writeback: simplify the loops in write_cache_pages()

Collapse the two nested loops into one.  This is needed as a step towards
turning this into an iterator.

Note that this drops the "index <= end" check in the previous outer loop
and just relies on filemap_get_folios_tag() to return 0 entries when index
> end.  This actually has a subtle implication when end == -1 because then
the returned index will be -1 as well and thus if there is page present on
index -1, we could be looping indefinitely.  But as the comment in
filemap_get_folios_tag documents this as already broken anyway we should
not worry about it here either.  The fix for that would probably a change
to the filemap_get_folios_tag() calling convention.

[hch@lst.de: update the commit log per Jan]
Link: https://lkml.kernel.org/r/20240215063649.2164017-10-hch@lst.deSigned-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 751e0d55
...@@ -2454,6 +2454,7 @@ int write_cache_pages(struct address_space *mapping, ...@@ -2454,6 +2454,7 @@ int write_cache_pages(struct address_space *mapping,
int error; int error;
struct folio *folio; struct folio *folio;
pgoff_t end; /* Inclusive */ pgoff_t end; /* Inclusive */
int i = 0;
if (wbc->range_cyclic) { if (wbc->range_cyclic) {
wbc->index = mapping->writeback_index; /* prev offset */ wbc->index = mapping->writeback_index; /* prev offset */
...@@ -2467,53 +2468,49 @@ int write_cache_pages(struct address_space *mapping, ...@@ -2467,53 +2468,49 @@ int write_cache_pages(struct address_space *mapping,
folio_batch_init(&wbc->fbatch); folio_batch_init(&wbc->fbatch);
while (wbc->index <= end) { for (;;) {
int i; if (i == wbc->fbatch.nr) {
writeback_get_batch(mapping, wbc);
writeback_get_batch(mapping, wbc); i = 0;
}
if (wbc->fbatch.nr == 0) if (wbc->fbatch.nr == 0)
break; break;
for (i = 0; i < wbc->fbatch.nr; i++) { folio = wbc->fbatch.folios[i++];
folio = wbc->fbatch.folios[i];
folio_lock(folio); folio_lock(folio);
if (!folio_prepare_writeback(mapping, wbc, folio)) { if (!folio_prepare_writeback(mapping, wbc, folio)) {
folio_unlock(folio); folio_unlock(folio);
continue; continue;
} }
trace_wbc_writepage(wbc, inode_to_bdi(mapping->host)); trace_wbc_writepage(wbc, inode_to_bdi(mapping->host));
error = writepage(folio, wbc, data); error = writepage(folio, wbc, data);
wbc->nr_to_write -= folio_nr_pages(folio); wbc->nr_to_write -= folio_nr_pages(folio);
if (error == AOP_WRITEPAGE_ACTIVATE) { if (error == AOP_WRITEPAGE_ACTIVATE) {
folio_unlock(folio); folio_unlock(folio);
error = 0; error = 0;
} }
/* /*
* For integrity writeback we have to keep going until * For integrity writeback we have to keep going until we have
* we have written all the folios we tagged for * written all the folios we tagged for writeback above, even if
* writeback above, even if we run past wbc->nr_to_write * we run past wbc->nr_to_write or encounter errors.
* or encounter errors. * We stash away the first error we encounter in wbc->saved_err
* We stash away the first error we encounter in * so that it can be retrieved when we're done. This is because
* wbc->saved_err so that it can be retrieved when we're * the file system may still have state to clear for each folio.
* done. This is because the file system may still have *
* state to clear for each folio. * For background writeback we exit as soon as we run past
* * wbc->nr_to_write or encounter the first error.
* For background writeback we exit as soon as we run */
* past wbc->nr_to_write or encounter the first error. if (wbc->sync_mode == WB_SYNC_ALL) {
*/ if (error && !ret)
if (wbc->sync_mode == WB_SYNC_ALL) { ret = error;
if (error && !ret) } else {
ret = error; if (error || wbc->nr_to_write <= 0)
} else { goto done;
if (error || wbc->nr_to_write <= 0)
goto done;
}
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment