Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+14 −6
Original line number Diff line number Diff line
@@ -167,17 +167,25 @@ xfs_growfs_data_private(
	new = nb - mp->m_sb.sb_dblocks;
	oagcount = mp->m_sb.sb_agcount;
	if (nagcount > oagcount) {
		void *new_perag, *old_perag;

		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);
		mp->m_perag = kmem_realloc(mp->m_perag,
			sizeof(xfs_perag_t) * nagcount,
			sizeof(xfs_perag_t) * oagcount,
			KM_SLEEP);
		memset(&mp->m_perag[oagcount], 0,
			(nagcount - oagcount) * sizeof(xfs_perag_t));
		memcpy(new_perag, mp->m_perag, sizeof(xfs_perag_t) * oagcount);
		old_perag = mp->m_perag;
		mp->m_perag = new_perag;

		mp->m_flags |= XFS_MOUNT_32BITINODES;
		nagimax = xfs_initialize_perag(mp, nagcount);
		up_write(&mp->m_peraglock);

		kmem_free(old_perag);
	}
	tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS);
	tp->t_flags |= XFS_TRANS_RESERVE;