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: Christoph Hellwig <hch@lst.de>
Reviewed-by: Felix Blyakher <felixb@sgi.com>
Signed-off-by: Felix Blyakher <felixb@sgi.com>

authored by Christoph Hellwig and committed by Felix Blyakher 0cc6eee1 c8a4051c

+14 -6
+14 -6
fs/xfs/xfs_fsops.c
··· 167 new = nb - mp->m_sb.sb_dblocks; 168 oagcount = mp->m_sb.sb_agcount; 169 if (nagcount > oagcount) { 170 xfs_filestream_flush(mp); 171 down_write(&mp->m_peraglock); 172 - mp->m_perag = kmem_realloc(mp->m_perag, 173 - sizeof(xfs_perag_t) * nagcount, 174 - sizeof(xfs_perag_t) * oagcount, 175 - KM_SLEEP); 176 - memset(&mp->m_perag[oagcount], 0, 177 - (nagcount - oagcount) * sizeof(xfs_perag_t)); 178 mp->m_flags |= XFS_MOUNT_32BITINODES; 179 nagimax = xfs_initialize_perag(mp, nagcount); 180 up_write(&mp->m_peraglock); 181 } 182 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS); 183 tp->t_flags |= XFS_TRANS_RESERVE;
··· 167 new = nb - mp->m_sb.sb_dblocks; 168 oagcount = mp->m_sb.sb_agcount; 169 if (nagcount > oagcount) { 170 + void *new_perag, *old_perag; 171 + 172 xfs_filestream_flush(mp); 173 + 174 + new_perag = kmem_zalloc(sizeof(xfs_perag_t) * nagcount, 175 + KM_MAYFAIL); 176 + if (!new_perag) 177 + return XFS_ERROR(ENOMEM); 178 + 179 down_write(&mp->m_peraglock); 180 + memcpy(new_perag, mp->m_perag, sizeof(xfs_perag_t) * oagcount); 181 + old_perag = mp->m_perag; 182 + mp->m_perag = new_perag; 183 + 184 mp->m_flags |= XFS_MOUNT_32BITINODES; 185 nagimax = xfs_initialize_perag(mp, nagcount); 186 up_write(&mp->m_peraglock); 187 + 188 + kmem_free(old_perag); 189 } 190 tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS); 191 tp->t_flags |= XFS_TRANS_RESERVE;