summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Brauner <brauner@kernel.org>2026-02-19 09:12:13 +0100
committerChristian Brauner <brauner@kernel.org>2026-02-19 09:12:13 +0100
commit768f4dc4cc318a547303f3ec984e5b366566950b (patch)
tree5b7dbed01f79a55a6291542c9ff3cfaf84e54950
parent6c4b2243cb6c0755159bd567130d5e12e7b10d9f (diff)
parent294f54f849d846f4643a67db9b41b63867dc8bfe (diff)
Merge patch series "fserror: bug fixes"
This contains two fixes for the new fserror infrastructure. * patches from https://patch.msgid.link/177148129514.716249.10889194125495783768.stgit@frogsfrogsfrogs: fserror: fix lockdep complaint when igrabbing inode fsnotify: drop unused helper Link: https://patch.msgid.link/177148129514.716249.10889194125495783768.stgit@frogsfrogsfrogs Signed-off-by: Christian Brauner <brauner@kernel.org>
-rw-r--r--fs/iomap/ioend.c46
-rw-r--r--include/linux/fsnotify.h13
2 files changed, 46 insertions, 13 deletions
diff --git a/fs/iomap/ioend.c b/fs/iomap/ioend.c
index e4d57cb969f1..4d1ef8a2cee9 100644
--- a/fs/iomap/ioend.c
+++ b/fs/iomap/ioend.c
@@ -69,11 +69,57 @@ static u32 iomap_finish_ioend_buffered(struct iomap_ioend *ioend)
return folio_count;
}
+static DEFINE_SPINLOCK(failed_ioend_lock);
+static LIST_HEAD(failed_ioend_list);
+
+static void
+iomap_fail_ioends(
+ struct work_struct *work)
+{
+ struct iomap_ioend *ioend;
+ struct list_head tmp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&failed_ioend_lock, flags);
+ list_replace_init(&failed_ioend_list, &tmp);
+ spin_unlock_irqrestore(&failed_ioend_lock, flags);
+
+ while ((ioend = list_first_entry_or_null(&tmp, struct iomap_ioend,
+ io_list))) {
+ list_del_init(&ioend->io_list);
+ iomap_finish_ioend_buffered(ioend);
+ cond_resched();
+ }
+}
+
+static DECLARE_WORK(failed_ioend_work, iomap_fail_ioends);
+
+static void iomap_fail_ioend_buffered(struct iomap_ioend *ioend)
+{
+ unsigned long flags;
+
+ /*
+ * Bounce I/O errors to a workqueue to avoid nested i_lock acquisitions
+ * in the fserror code. The caller no longer owns the ioend reference
+ * after the spinlock drops.
+ */
+ spin_lock_irqsave(&failed_ioend_lock, flags);
+ if (list_empty(&failed_ioend_list))
+ WARN_ON_ONCE(!schedule_work(&failed_ioend_work));
+ list_add_tail(&ioend->io_list, &failed_ioend_list);
+ spin_unlock_irqrestore(&failed_ioend_lock, flags);
+}
+
static void ioend_writeback_end_bio(struct bio *bio)
{
struct iomap_ioend *ioend = iomap_ioend_from_bio(bio);
ioend->io_error = blk_status_to_errno(bio->bi_status);
+ if (ioend->io_error) {
+ iomap_fail_ioend_buffered(ioend);
+ return;
+ }
+
iomap_finish_ioend_buffered(ioend);
}
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 28a9cb13fbfa..079c18bcdbde 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -495,19 +495,6 @@ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
fsnotify_dentry(dentry, mask);
}
-static inline int fsnotify_sb_error(struct super_block *sb, struct inode *inode,
- int error)
-{
- struct fs_error_report report = {
- .error = error,
- .inode = inode,
- .sb = sb,
- };
-
- return fsnotify(FS_ERROR, &report, FSNOTIFY_EVENT_ERROR,
- NULL, NULL, NULL, 0);
-}
-
static inline void fsnotify_mnt_attach(struct mnt_namespace *ns, struct vfsmount *mnt)
{
fsnotify_mnt(FS_MNT_ATTACH, ns, mnt);