lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <r2gurwreel7vcr3pkyq3axn7qotvz32qnwcrm4rrhkkqg3xtrl@qjldvkhr4epo>
Date: Mon, 22 Dec 2025 16:30:19 +0100
From: Jan Kara <jack@...e.cz>
To: "Darrick J. Wong" <djwong@...nel.org>
Cc: brauner@...nel.org, linux-ext4@...r.kernel.org, jack@...e.cz, 
	linux-xfs@...r.kernel.org, linux-fsdevel@...r.kernel.org, gabriel@...sman.be, hch@....de, 
	amir73il@...il.com
Subject: Re: [PATCH 3/6] iomap: report file I/O errors to the VFS

On Wed 17-12-25 18:03:27, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@...nel.org>
> 
> Wire up iomap so that it reports all file read and write errors to the
> VFS (and hence fsnotify) via the new fserror mechanism.
> 
> Signed-off-by: "Darrick J. Wong" <djwong@...nel.org>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack@...e.cz>

								Honza

> ---
>  fs/iomap/buffered-io.c |   23 ++++++++++++++++++++++-
>  fs/iomap/direct-io.c   |   12 ++++++++++++
>  fs/iomap/ioend.c       |    6 ++++++
>  3 files changed, 40 insertions(+), 1 deletion(-)
> 
> 
> diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
> index e5c1ca440d93bd..b21e989b9fa5e6 100644
> --- a/fs/iomap/buffered-io.c
> +++ b/fs/iomap/buffered-io.c
> @@ -8,6 +8,7 @@
>  #include <linux/writeback.h>
>  #include <linux/swap.h>
>  #include <linux/migrate.h>
> +#include <linux/fserror.h>
>  #include "internal.h"
>  #include "trace.h"
>  
> @@ -371,8 +372,11 @@ static int iomap_read_inline_data(const struct iomap_iter *iter,
>  	if (folio_test_uptodate(folio))
>  		return 0;
>  
> -	if (WARN_ON_ONCE(size > iomap->length))
> +	if (WARN_ON_ONCE(size > iomap->length)) {
> +		fserror_report_io(iter->inode, FSERR_BUFFERED_READ,
> +				  iomap->offset, size, -EIO, GFP_NOFS);
>  		return -EIO;
> +	}
>  	if (offset > 0)
>  		ifs_alloc(iter->inode, folio, iter->flags);
>  
> @@ -399,6 +403,11 @@ void iomap_finish_folio_read(struct folio *folio, size_t off, size_t len,
>  		spin_unlock_irqrestore(&ifs->state_lock, flags);
>  	}
>  
> +	if (error)
> +		fserror_report_io(folio->mapping->host, FSERR_BUFFERED_READ,
> +				  folio_pos(folio) + off, len, error,
> +				  GFP_ATOMIC);
> +
>  	if (finished)
>  		folio_end_read(folio, uptodate);
>  }
> @@ -540,6 +549,10 @@ static int iomap_read_folio_iter(struct iomap_iter *iter,
>  			if (!*bytes_submitted)
>  				iomap_read_init(folio);
>  			ret = ctx->ops->read_folio_range(iter, ctx, plen);
> +			if (ret < 0)
> +				fserror_report_io(iter->inode,
> +						  FSERR_BUFFERED_READ, pos,
> +						  plen, ret, GFP_NOFS);
>  			if (ret)
>  				return ret;
>  			*bytes_submitted += plen;
> @@ -815,6 +828,10 @@ static int __iomap_write_begin(const struct iomap_iter *iter,
>  			else
>  				status = iomap_bio_read_folio_range_sync(iter,
>  						folio, block_start, plen);
> +			if (status < 0)
> +				fserror_report_io(iter->inode,
> +						  FSERR_BUFFERED_READ, pos,
> +						  len, status, GFP_NOFS);
>  			if (status)
>  				return status;
>  		}
> @@ -1805,6 +1822,7 @@ int iomap_writeback_folio(struct iomap_writepage_ctx *wpc, struct folio *folio)
>  	u64 pos = folio_pos(folio);
>  	u64 end_pos = pos + folio_size(folio);
>  	u64 end_aligned = 0;
> +	loff_t orig_pos = pos;
>  	size_t bytes_submitted = 0;
>  	int error = 0;
>  	u32 rlen;
> @@ -1848,6 +1866,9 @@ int iomap_writeback_folio(struct iomap_writepage_ctx *wpc, struct folio *folio)
>  
>  	if (bytes_submitted)
>  		wpc->nr_folios++;
> +	if (error && pos > orig_pos)
> +		fserror_report_io(inode, FSERR_BUFFERED_WRITE, orig_pos, 0,
> +				  error, GFP_NOFS);
>  
>  	/*
>  	 * We can have dirty bits set past end of file in page_mkwrite path
> diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c
> index 8e273408453a9c..a06c73eaa8901b 100644
> --- a/fs/iomap/direct-io.c
> +++ b/fs/iomap/direct-io.c
> @@ -7,6 +7,7 @@
>  #include <linux/pagemap.h>
>  #include <linux/iomap.h>
>  #include <linux/task_io_accounting_ops.h>
> +#include <linux/fserror.h>
>  #include "internal.h"
>  #include "trace.h"
>  
> @@ -78,6 +79,13 @@ static void iomap_dio_submit_bio(const struct iomap_iter *iter,
>  	}
>  }
>  
> +static inline enum fserror_type iomap_dio_err_type(const struct iomap_dio *dio)
> +{
> +	if (dio->flags & IOMAP_DIO_WRITE)
> +		return FSERR_DIRECTIO_WRITE;
> +	return FSERR_DIRECTIO_READ;
> +}
> +
>  ssize_t iomap_dio_complete(struct iomap_dio *dio)
>  {
>  	const struct iomap_dio_ops *dops = dio->dops;
> @@ -87,6 +95,10 @@ ssize_t iomap_dio_complete(struct iomap_dio *dio)
>  
>  	if (dops && dops->end_io)
>  		ret = dops->end_io(iocb, dio->size, ret, dio->flags);
> +	if (dio->error)
> +		fserror_report_io(file_inode(iocb->ki_filp),
> +				  iomap_dio_err_type(dio), offset, dio->size,
> +				  dio->error, GFP_NOFS);
>  
>  	if (likely(!ret)) {
>  		ret = dio->size;
> diff --git a/fs/iomap/ioend.c b/fs/iomap/ioend.c
> index 86f44922ed3b6a..5b27ee98896707 100644
> --- a/fs/iomap/ioend.c
> +++ b/fs/iomap/ioend.c
> @@ -6,6 +6,7 @@
>  #include <linux/list_sort.h>
>  #include <linux/pagemap.h>
>  #include <linux/writeback.h>
> +#include <linux/fserror.h>
>  #include "internal.h"
>  #include "trace.h"
>  
> @@ -55,6 +56,11 @@ static u32 iomap_finish_ioend_buffered(struct iomap_ioend *ioend)
>  
>  	/* walk all folios in bio, ending page IO on them */
>  	bio_for_each_folio_all(fi, bio) {
> +		if (ioend->io_error)
> +			fserror_report_io(inode, FSERR_BUFFERED_WRITE,
> +					  folio_pos(fi.folio) + fi.offset,
> +					  fi.length, ioend->io_error,
> +					  GFP_ATOMIC);
>  		iomap_finish_folio_write(inode, fi.folio, fi.length);
>  		folio_count++;
>  	}
> 
-- 
Jan Kara <jack@...e.com>
SUSE Labs, CR

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ