[<prev] [next>] [day] [month] [year] [list]
Message-ID: <CAN2Y7hyi1HCrSiKsDT+KD8hBjQmsqzNp71Q9Z_RmBG0LLaZxCA@mail.gmail.com>
Date: Sun, 22 Jun 2025 20:32:18 +0800
From: ying chen <yc1082463@...il.com>
To: djwong@...nel.org, linux-xfs@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [PATCH] xfs: report a writeback error on a read() call
Normally, user space returns immediately after writing data to the
buffer cache. However, if an error occurs during the actual disk
write operation, data loss may ensue, and there is no way to report
this error back to user space immediately. Current kernels may report
writeback errors when fsync() is called, but frequent invocations of
fsync() can degrade performance. Therefore, a new sysctl
fs.xfs.report_writeback_error_on_read is introduced, which, when set
to 1, reports writeback errors when read() is called. This allows user
space to be notified of writeback errors more promptly.
Signed-off-by: fengchangqing <fengchangqing@...duoduo.com>
---
fs/xfs/xfs_file.c | 9 +++++++++
fs/xfs/xfs_globals.c | 1 +
fs/xfs/xfs_linux.h | 1 +
fs/xfs/xfs_sysctl.c | 9 +++++++++
fs/xfs/xfs_sysctl.h | 1 +
5 files changed, 21 insertions(+)
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 595a5bc..8bf0a83 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -288,12 +288,21 @@
struct inode *inode = file_inode(iocb->ki_filp);
struct xfs_mount *mp = XFS_I(inode)->i_mount;
ssize_t ret = 0;
+ int error = 0;
+ errseq_t since;
XFS_STATS_INC(mp, xs_read_calls);
if (xfs_is_shutdown(mp))
return -EIO;
+ if (xfs_report_writeback_error_on_read) {
+ since = READ_ONCE(iocb->ki_filp->f_wb_err);
+ error = filemap_check_wb_err(inode->i_mapping, since);
+ if (error)
+ return error;
+ }
+
if (IS_DAX(inode))
ret = xfs_file_dax_read(iocb, to);
else if (iocb->ki_flags & IOCB_DIRECT)
diff --git a/fs/xfs/xfs_globals.c b/fs/xfs/xfs_globals.c
index 4d0a98f..9983a2f 100644
--- a/fs/xfs/xfs_globals.c
+++ b/fs/xfs/xfs_globals.c
@@ -29,6 +29,7 @@
.inherit_nodfrg = { 0, 1, 1 },
.fstrm_timer = { 1, 30*100, 3600*100},
.blockgc_timer = { 1, 300, 3600*24},
+ .report_writeback_error_on_read = { 0, 0,
1},
};
struct xfs_globals xfs_globals = {
diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h
index f987802..bbe8bdb 100644
--- a/fs/xfs/xfs_linux.h
+++ b/fs/xfs/xfs_linux.h
@@ -100,6 +100,7 @@
#define xfs_inherit_nodefrag xfs_params.inherit_nodfrg.val
#define xfs_fstrm_centisecs xfs_params.fstrm_timer.val
#define xfs_blockgc_secs xfs_params.blockgc_timer.val
+#define xfs_report_writeback_error_on_read
xfs_params.report_writeback_error_on_read.val
#define current_cpu() (raw_smp_processor_id())
#define current_set_flags_nested(sp, f) \
diff --git a/fs/xfs/xfs_sysctl.c b/fs/xfs/xfs_sysctl.c
index 546a6cd..fbec214 100644
--- a/fs/xfs/xfs_sysctl.c
+++ b/fs/xfs/xfs_sysctl.c
@@ -194,6 +194,15 @@
.extra1 = &xfs_params.blockgc_timer.min,
.extra2 = &xfs_params.blockgc_timer.max,
},
+ {
+ .procname = "report_writeback_error_on_read",
+ .data =
&xfs_params.report_writeback_error_on_read.val,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = xfs_deprecated_dointvec_minmax,
+ .extra1 =
&xfs_params.report_writeback_error_on_read.min,
+ .extra2 =
&xfs_params.report_writeback_error_on_read.max,
+ },
/* please keep this the last entry */
#ifdef CONFIG_PROC_FS
{
diff --git a/fs/xfs/xfs_sysctl.h b/fs/xfs/xfs_sysctl.h
index f78ad6b..fa0688a 100644
--- a/fs/xfs/xfs_sysctl.h
+++ b/fs/xfs/xfs_sysctl.h
@@ -36,6 +36,7 @@
xfs_sysctl_val_t inherit_nodfrg;/* Inherit the "nodefrag" inode flag. */
xfs_sysctl_val_t fstrm_timer; /* Filestream dir-AG assoc'n timeout. */
xfs_sysctl_val_t blockgc_timer; /* Interval between blockgc scans */
+ xfs_sysctl_val_t report_writeback_error_on_read; /* Report a
writeback error on a read() call. */
} xfs_param_t;
/*
--
1.8.3.1
Powered by blists - more mailing lists