提交 80641dc6 编写于 作者: C Christoph Hellwig 提交者: Alex Elder

xfs: I/O completion handlers must use NOFS allocations

When completing I/O requests we must not allow the memory allocator to
recurse into the filesystem, as we might deadlock on waiting for the
I/O completion otherwise.  The only thing currently allocating normal
GFP_KERNEL memory is the allocation of the transaction structure for
the unwritten extent conversion.  Add a memflags argument to
_xfs_trans_alloc to allow controlling the allocator behaviour.
Signed-off-by: NChristoph Hellwig <hch@lst.de>
Reported-by: NThomas Neumann <tneumann@users.sourceforge.net>
Tested-by: NThomas Neumann <tneumann@users.sourceforge.net>
Reviewed-by: NAlex Elder <aelder@sgi.com>
Signed-off-by: NAlex Elder <aelder@sgi.com>
上级 c56c9631
...@@ -611,7 +611,7 @@ xfs_fs_log_dummy( ...@@ -611,7 +611,7 @@ xfs_fs_log_dummy(
xfs_inode_t *ip; xfs_inode_t *ip;
int error; int error;
tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1); tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1, KM_SLEEP);
error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0); error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0);
if (error) { if (error) {
xfs_trans_cancel(tp, 0); xfs_trans_cancel(tp, 0);
......
...@@ -860,8 +860,15 @@ xfs_iomap_write_unwritten( ...@@ -860,8 +860,15 @@ xfs_iomap_write_unwritten(
* set up a transaction to convert the range of extents * set up a transaction to convert the range of extents
* from unwritten to real. Do allocations in a loop until * from unwritten to real. Do allocations in a loop until
* we have covered the range passed in. * we have covered the range passed in.
*
* Note that we open code the transaction allocation here
* to pass KM_NOFS--we can't risk to recursing back into
* the filesystem here as we might be asked to write out
* the same inode that we complete here and might deadlock
* on the iolock.
*/ */
tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); xfs_wait_for_freeze(mp, SB_FREEZE_TRANS);
tp = _xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE, KM_NOFS);
tp->t_flags |= XFS_TRANS_RESERVE; tp->t_flags |= XFS_TRANS_RESERVE;
error = xfs_trans_reserve(tp, resblks, error = xfs_trans_reserve(tp, resblks,
XFS_WRITE_LOG_RES(mp), 0, XFS_WRITE_LOG_RES(mp), 0,
......
...@@ -1471,7 +1471,7 @@ xfs_log_sbcount( ...@@ -1471,7 +1471,7 @@ xfs_log_sbcount(
if (!xfs_sb_version_haslazysbcount(&mp->m_sb)) if (!xfs_sb_version_haslazysbcount(&mp->m_sb))
return 0; return 0;
tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_COUNT); tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_COUNT, KM_SLEEP);
error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0, error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
XFS_DEFAULT_LOG_COUNT); XFS_DEFAULT_LOG_COUNT);
if (error) { if (error) {
......
...@@ -236,19 +236,20 @@ xfs_trans_alloc( ...@@ -236,19 +236,20 @@ xfs_trans_alloc(
uint type) uint type)
{ {
xfs_wait_for_freeze(mp, SB_FREEZE_TRANS); xfs_wait_for_freeze(mp, SB_FREEZE_TRANS);
return _xfs_trans_alloc(mp, type); return _xfs_trans_alloc(mp, type, KM_SLEEP);
} }
xfs_trans_t * xfs_trans_t *
_xfs_trans_alloc( _xfs_trans_alloc(
xfs_mount_t *mp, xfs_mount_t *mp,
uint type) uint type,
uint memflags)
{ {
xfs_trans_t *tp; xfs_trans_t *tp;
atomic_inc(&mp->m_active_trans); atomic_inc(&mp->m_active_trans);
tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP); tp = kmem_zone_zalloc(xfs_trans_zone, memflags);
tp->t_magic = XFS_TRANS_MAGIC; tp->t_magic = XFS_TRANS_MAGIC;
tp->t_type = type; tp->t_type = type;
tp->t_mountp = mp; tp->t_mountp = mp;
......
...@@ -924,7 +924,7 @@ typedef struct xfs_trans { ...@@ -924,7 +924,7 @@ typedef struct xfs_trans {
* XFS transaction mechanism exported interfaces. * XFS transaction mechanism exported interfaces.
*/ */
xfs_trans_t *xfs_trans_alloc(struct xfs_mount *, uint); xfs_trans_t *xfs_trans_alloc(struct xfs_mount *, uint);
xfs_trans_t *_xfs_trans_alloc(struct xfs_mount *, uint); xfs_trans_t *_xfs_trans_alloc(struct xfs_mount *, uint, uint);
xfs_trans_t *xfs_trans_dup(xfs_trans_t *); xfs_trans_t *xfs_trans_dup(xfs_trans_t *);
int xfs_trans_reserve(xfs_trans_t *, uint, uint, uint, int xfs_trans_reserve(xfs_trans_t *, uint, uint, uint,
uint, uint); uint, uint);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册