Commit 1cb039f3dc16 ("bdi: replace BDI_CAP_STABLE_WRITES with a queue and a sb flag") introduced a regression for the raw block device use case. Capturing QUEUE_FLAG_STABLE_WRITES flag in set_bdev_super() has the effect of respecting it only when there is a filesystem mounted on top of the block device. If a filesystem is not mounted, block devices that do integrity checking return sporadic checksum errors. Additionally, this commit made the corresponding sysfs knob writeable for debugging purposes. However, because QUEUE_FLAG_STABLE_WRITES flag is captured when the filesystem is mounted and isn't consulted after that anywhere outside of swap code, changing it doesn't take immediate effect even though dumping the knob shows the new value. With no way to dump SB_I_STABLE_WRITES flag, this is needlessly confusing. Resurrect the original stable writes behavior by changing folio_wait_stable() to account for the case of a raw block device and also: - for the case of a filesystem, test QUEUE_FLAG_STABLE_WRITES flag each time instead of capturing it in the superblock so that changes are reflected immediately (thus aligning with the case of a raw block device) - retain SB_I_STABLE_WRITES flag for filesystems that need stable writes independent of the underlying block device (currently just NFS) Cc: stable@xxxxxxxxxxxxxxx Fixes: 1cb039f3dc16 ("bdi: replace BDI_CAP_STABLE_WRITES with a queue and a sb flag") Signed-off-by: Ilya Dryomov <idryomov@xxxxxxxxx> --- fs/super.c | 2 -- mm/page-writeback.c | 12 +++++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/fs/super.c b/fs/super.c index 04bc62ab7dfe..6705b3506ae8 100644 --- a/fs/super.c +++ b/fs/super.c @@ -1213,8 +1213,6 @@ static int set_bdev_super(struct super_block *s, void *data) s->s_dev = s->s_bdev->bd_dev; s->s_bdi = bdi_get(s->s_bdev->bd_disk->bdi); - if (bdev_stable_writes(s->s_bdev)) - s->s_iflags |= SB_I_STABLE_WRITES; return 0; } diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 516b1aa247e8..469bc57add8c 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -3169,7 +3169,17 @@ EXPORT_SYMBOL_GPL(folio_wait_writeback_killable); */ void folio_wait_stable(struct folio *folio) { - if (folio_inode(folio)->i_sb->s_iflags & SB_I_STABLE_WRITES) + struct inode *inode = folio_inode(folio); + struct super_block *sb = inode->i_sb; + bool stable_writes; + + if (sb_is_blkdev_sb(sb)) + stable_writes = bdev_stable_writes(I_BDEV(inode)); + else + stable_writes = bdev_stable_writes(sb->s_bdev) || + (sb->s_iflags & SB_I_STABLE_WRITES); + + if (stable_writes) folio_wait_writeback(folio); } EXPORT_SYMBOL_GPL(folio_wait_stable); -- 2.39.2