diff mbox series

[v2,3/3] btrfs: call mapping_set_error() on btree inode with a write error

Message ID f6f2469932a07a706149353618a1f77e88706fc2.1637781110.git.josef@toxicpanda.com (mailing list archive)
State New, archived
Headers show
Series Metadata IO error fixes | expand

Commit Message

Josef Bacik Nov. 24, 2021, 7:14 p.m. UTC
generic/484 fails sometimes with compression on because the write ends
up small enough that it goes into the btree.  This means that we never
call mapping_set_error() on the inode itself, because the page gets
marked as fine when we inline it into the metadata.  When the metadata
writeback happens we see it and abort the transaction properly and mark
the fs as readonly, however we don't do the mapping_set_error() on
anything.  In syncfs() we will simply return 0 if the sb is marked
read-only, so we can't check for this in our syncfs callback.  The only
way the error gets returned if we called mapping_set_error() on
something.  Fix this by calling mapping_set_error() on the btree inode
mapping.  This allows us to properly return an error on syncfs and pass
generic/484 with compression on.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/extent_io.c | 8 ++++++++
 1 file changed, 8 insertions(+)

Comments

Nikolay Borisov Nov. 25, 2021, 9:12 a.m. UTC | #1
On 24.11.21 г. 21:14, Josef Bacik wrote:
> generic/484 fails sometimes with compression on because the write ends
> up small enough that it goes into the btree.  This means that we never
> call mapping_set_error() on the inode itself, because the page gets
> marked as fine when we inline it into the metadata.  When the metadata
> writeback happens we see it and abort the transaction properly and mark
> the fs as readonly, however we don't do the mapping_set_error() on
> anything.  In syncfs() we will simply return 0 if the sb is marked
> read-only, so we can't check for this in our syncfs callback.  The only
> way the error gets returned if we called mapping_set_error() on
> something.  Fix this by calling mapping_set_error() on the btree inode
> mapping.  This allows us to properly return an error on syncfs and pass
> generic/484 with compression on.
> 
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>

Reviewed-by: Nikolay Borisov <nborisov@suse.com>

> ---
>  fs/btrfs/extent_io.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
> index 3454cac28389..1a67f4b3986b 100644
> --- a/fs/btrfs/extent_io.c
> +++ b/fs/btrfs/extent_io.c
> @@ -4314,6 +4314,14 @@ static void set_btree_ioerr(struct page *page, struct extent_buffer *eb)
>  	 */
>  	clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
>  
> +	/*
> +	 * We need to set the mapping with the io error as well because a write
> +	 * error will flip the file system readonly, and then syncfs() will
> +	 * return a 0 because we are readonly if we don't modify the err seq for
> +	 * the superblock.
> +	 */
> +	mapping_set_error(page->mapping, -EIO);
> +
>  	/*
>  	 * If we error out, we should add back the dirty_metadata_bytes
>  	 * to make it consistent.
>
diff mbox series

Patch

diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 3454cac28389..1a67f4b3986b 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -4314,6 +4314,14 @@  static void set_btree_ioerr(struct page *page, struct extent_buffer *eb)
 	 */
 	clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
 
+	/*
+	 * We need to set the mapping with the io error as well because a write
+	 * error will flip the file system readonly, and then syncfs() will
+	 * return a 0 because we are readonly if we don't modify the err seq for
+	 * the superblock.
+	 */
+	mapping_set_error(page->mapping, -EIO);
+
 	/*
 	 * If we error out, we should add back the dirty_metadata_bytes
 	 * to make it consistent.