Commit 0cc6eee1 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Felix Blyakher

xfs: avoid memory allocation under m_peraglock in growfs code

Allocate the memory for the larger m_perag array before taking the
per-AG lock as the per-AG lock can be taken under the i_lock which
can be taken from reclaim context.

Reported by the new reclaim context tracing in lockdep.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarFelix Blyakher <felixb@sgi.com>
Signed-off-by: default avatarFelix Blyakher <felixb@sgi.com>
parent c8a4051c
...@@ -167,17 +167,25 @@ xfs_growfs_data_private( ...@@ -167,17 +167,25 @@ xfs_growfs_data_private(
new = nb - mp->m_sb.sb_dblocks; new = nb - mp->m_sb.sb_dblocks;
oagcount = mp->m_sb.sb_agcount; oagcount = mp->m_sb.sb_agcount;
if (nagcount > oagcount) { if (nagcount > oagcount) {
void *new_perag, *old_perag;
xfs_filestream_flush(mp); xfs_filestream_flush(mp);
new_perag = kmem_zalloc(sizeof(xfs_perag_t) * nagcount,
KM_MAYFAIL);
if (!new_perag)
return XFS_ERROR(ENOMEM);
down_write(&mp->m_peraglock); down_write(&mp->m_peraglock);
mp->m_perag = kmem_realloc(mp->m_perag, memcpy(new_perag, mp->m_perag, sizeof(xfs_perag_t) * oagcount);
sizeof(xfs_perag_t) * nagcount, old_perag = mp->m_perag;
sizeof(xfs_perag_t) * oagcount, mp->m_perag = new_perag;
KM_SLEEP);
memset(&mp->m_perag[oagcount], 0,
(nagcount - oagcount) * sizeof(xfs_perag_t));
mp->m_flags |= XFS_MOUNT_32BITINODES; mp->m_flags |= XFS_MOUNT_32BITINODES;
nagimax = xfs_initialize_perag(mp, nagcount); nagimax = xfs_initialize_perag(mp, nagcount);
up_write(&mp->m_peraglock); up_write(&mp->m_peraglock);
kmem_free(old_perag);
} }
tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS); tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS);
tp->t_flags |= XFS_TRANS_RESERVE; tp->t_flags |= XFS_TRANS_RESERVE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment