diff options
author | Andreas Gruenbacher <agruenba@redhat.com> | 2023-01-19 20:14:42 +0100 |
---|---|---|
committer | Andreas Gruenbacher <agruenba@redhat.com> | 2023-01-22 09:46:14 +0100 |
commit | 95ecbd0f162fc06ef4c4045a66f653f47b62a2d3 (patch) | |
tree | b9f25c38265bb65d0ca8493c1d8741a69c1c2982 | |
parent | 5dc4c995db9eb45f6373a956eb1f69460e69e6d4 (diff) | |
download | linux-stable-95ecbd0f162fc06ef4c4045a66f653f47b62a2d3.tar.gz linux-stable-95ecbd0f162fc06ef4c4045a66f653f47b62a2d3.tar.bz2 linux-stable-95ecbd0f162fc06ef4c4045a66f653f47b62a2d3.zip |
Revert "gfs2: stop using generic_writepages in gfs2_ail1_start_one"
Commit b2b0a5e97855 switched from generic_writepages() to
filemap_fdatawrite_wbc() in gfs2_ail1_start_one() on the path to
replacing ->writepage() with ->writepages() and eventually eliminating
the former. Function gfs2_ail1_start_one() is called from
gfs2_log_flush(), our main function for flushing the filesystem log.
Unfortunately, at least as implemented today, ->writepage() and
->writepages() are entirely different operations for journaled data
inodes: while the former creates and submits transactions covering the
data to be written, the latter flushes dirty buffers out to disk.
With gfs2_ail1_start_one() now calling ->writepages(), we end up
creating filesystem transactions while we are in the course of a log
flush, which immediately deadlocks on the sdp->sd_log_flush_lock
semaphore.
Work around that by going back to how things used to work before commit
b2b0a5e97855 for now; figuring out a superior solution will take time we
don't have available right now. However ...
Since the removal of generic_writepages() is imminent, open-code it
here. We're already inside a blk_start_plug() ... blk_finish_plug()
section here, so skip that part of the original generic_writepages().
This reverts commit b2b0a5e978552e348f85ad9c7568b630a5ede659.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Acked-by: Christoph Hellwig <hch@lst.de>
-rw-r--r-- | fs/gfs2/log.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 723639376ae2..61323deb80bc 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -80,6 +80,15 @@ void gfs2_remove_from_ail(struct gfs2_bufdata *bd) brelse(bd->bd_bh); } +static int __gfs2_writepage(struct page *page, struct writeback_control *wbc, + void *data) +{ + struct address_space *mapping = data; + int ret = mapping->a_ops->writepage(page, wbc); + mapping_set_error(mapping, ret); + return ret; +} + /** * gfs2_ail1_start_one - Start I/O on a transaction * @sdp: The superblock @@ -131,7 +140,7 @@ __acquires(&sdp->sd_ail_lock) if (!mapping) continue; spin_unlock(&sdp->sd_ail_lock); - ret = filemap_fdatawrite_wbc(mapping, wbc); + ret = write_cache_pages(mapping, wbc, __gfs2_writepage, mapping); if (need_resched()) { blk_finish_plug(plug); cond_resched(); |