[PATCH v15 4/4] xfs: use current->journal_info to avoid transaction reservation recursion
From: Yafang Shao <hidden>
Date: 2021-01-13 10:24:14
Also in:
linux-mm, linux-xfs
Subsystem:
filesystems (vfs and infrastructure), filesystems [iomap], the rest, xfs filesystem · Maintainers:
Alexander Viro, Christian Brauner, Linus Torvalds, Carlos Maiolino
PF_FSTRANS which is used to avoid transaction reservation recursion, is
dropped since commit 9070733b4efa ("xfs: abstract PF_FSTRANS to
PF_MEMALLOC_NOFS") and replaced by PF_MEMALLOC_NOFS which means to avoid
filesystem reclaim recursion.
As these two flags have different meanings, we'd better reintroduce
PF_FSTRANS back. To avoid wasting the space of PF_* flags in
task_struct,
we can reuse the current->journal_info to do that, per Willy. As the
check of transaction reservation recursion is used by XFS only, we can
move the check into xfs_vm_writepage(s), per Dave.
[oliver.sang@intel.com: reported a Assertion_failed in the prev version]
Cc: Darrick J. Wong <redacted>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: David Howells <dhowells@redhat.com>
Cc: Jeff Layton <redacted>
Cc: kernel test robot <redacted>
Signed-off-by: Yafang Shao <redacted>
---
fs/iomap/buffered-io.c | 7 -------
fs/xfs/xfs_aops.c | 10 ++++++++++
fs/xfs/xfs_trans.h | 22 +++++++++++++++++++---
3 files changed, 29 insertions(+), 10 deletions(-)
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 10cc7979ce38..3c53fa6ce64d 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c@@ -1458,13 +1458,6 @@ iomap_do_writepage(struct page *page, struct writeback_control *wbc, void *data) PF_MEMALLOC)) goto redirty; - /* - * Given that we do not allow direct reclaim to call us, we should - * never be called in a recursive filesystem reclaim context. - */ - if (WARN_ON_ONCE(current->flags & PF_MEMALLOC_NOFS)) - goto redirty; - /* * Is this page beyond the end of the file? *
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 2371187b7615..eed4881d4461 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c@@ -568,6 +568,12 @@ xfs_vm_writepage( { struct xfs_writepage_ctx wpc = { }; + if (WARN_ON_ONCE(xfs_trans_context_active())) { + redirty_page_for_writepage(wbc, page); + unlock_page(page); + return 0; + } + return iomap_writepage(page, wbc, &wpc.ctx, &xfs_writeback_ops); }
@@ -579,6 +585,10 @@ xfs_vm_writepages( struct xfs_writepage_ctx wpc = { }; xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED); + + if (WARN_ON_ONCE(xfs_trans_context_active())) + return 0; + return iomap_writepages(mapping, wbc, &wpc.ctx, &xfs_writeback_ops); }
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 3645fd0d74b8..e2f3251d6cce 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h@@ -268,24 +268,40 @@ xfs_trans_item_relog( return lip->li_ops->iop_relog(lip, tp); } +static inline bool +xfs_trans_context_active(void) +{ + return current->journal_info != NULL; +} + static inline void xfs_trans_context_set(struct xfs_trans *tp) { + ASSERT(!current->journal_info); + current->journal_info = tp; tp->t_pflags = memalloc_nofs_save(); } static inline void xfs_trans_context_clear(struct xfs_trans *tp) { - if (!tp->t_pflags) - memalloc_nofs_restore(tp->t_pflags); + /* + * If we handed over the context via xfs_trans_context_swap() then + * the context is no longer needed to clear. + */ + if (current->journal_info != tp) + return; + + current->journal_info = NULL; + memalloc_nofs_restore(tp->t_pflags); } static inline void xfs_trans_context_swap(struct xfs_trans *tp, struct xfs_trans *ntp) { + ASSERT(current->journal_info == tp); + current->journal_info = ntp; ntp->t_pflags = tp->t_pflags; - tp->t_pflags = -1; } #endif /* __XFS_TRANS_H__ */
--
2.17.1