diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index f32be0c85f93..9f926fbb37f8 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -937,20 +937,21 @@ xfs_ialloc_next_ag(
  */
 STATIC xfs_agnumber_t
 xfs_ialloc_ag_select(
-	xfs_trans_t	*tp,		/* transaction pointer */
-	xfs_ino_t	parent,		/* parent directory inode number */
-	umode_t		mode)		/* bits set to indicate file type */
+	struct xfs_trans	*tp,
+	struct xfs_inode	*pip,
+	umode_t			mode)
 {
-	xfs_agnumber_t	agcount;	/* number of ag's in the filesystem */
-	xfs_agnumber_t	agno;		/* current ag number */
-	int		flags;		/* alloc buffer locking flags */
-	xfs_extlen_t	ineed;		/* blocks needed for inode allocation */
-	xfs_extlen_t	longest = 0;	/* longest extent available */
-	xfs_mount_t	*mp;		/* mount point structure */
-	int		needspace;	/* file mode implies space allocated */
-	xfs_perag_t	*pag;		/* per allocation group data */
-	xfs_agnumber_t	pagno;		/* parent (starting) ag number */
-	int		error;
+	struct xfs_mount	*mp;
+	struct xfs_perag	*pag;
+	xfs_ino_t		parent = pip ? pip->i_ino : 0;
+	xfs_agnumber_t		agcount;
+	xfs_agnumber_t		agno;
+	xfs_agnumber_t		pagno;
+	xfs_extlen_t		ineed;
+	xfs_extlen_t		longest = 0;	/* longest extent available */
+	int			needspace;	/* file mode implies space allocated */
+	int			flags;
+	int			error;
 
 	/*
 	 * Files of these types need at least one block if length > 0
@@ -959,9 +960,21 @@ xfs_ialloc_ag_select(
 	needspace = S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode);
 	mp = tp->t_mountp;
 	agcount = mp->m_maxagi;
-	if (S_ISDIR(mode))
+	if (pip && xfs_is_metadata_inode(pip)) {
+		/*
+		 * Try to squash all the metadata inodes into the parent's
+		 * AG, or the one with the log if the log is internal, or
+		 * AG 0 if all else fails.
+		 */
+		if (xfs_verify_ino(mp, parent))
+			pagno = XFS_INO_TO_AGNO(mp, parent);
+		else if (mp->m_sb.sb_logstart != 0)
+			pagno = XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart);
+		else
+			pagno = 0;
+	} else if (S_ISDIR(mode)) {
 		pagno = xfs_ialloc_next_ag(mp);
-	else {
+	} else {
 		pagno = XFS_INO_TO_AGNO(mp, parent);
 		if (pagno >= agcount)
 			pagno = 0;
@@ -1693,13 +1706,14 @@ xfs_dialloc_ag(
 int
 xfs_dialloc(
 	struct xfs_trans	*tp,
-	xfs_ino_t		parent,
+	struct xfs_inode	*pip,
 	umode_t			mode,
 	struct xfs_buf		**IO_agbp,
 	xfs_ino_t		*inop)
 {
 	struct xfs_mount	*mp = tp->t_mountp;
 	struct xfs_buf		*agbp;
+	xfs_ino_t		parent = pip ? pip->i_ino : 0;
 	xfs_agnumber_t		agno;
 	int			error;
 	int			ialloced;
@@ -1723,7 +1737,7 @@ xfs_dialloc(
 	 * We do not have an agbp, so select an initial allocation
 	 * group for inode allocation.
 	 */
-	start_agno = xfs_ialloc_ag_select(tp, parent, mode);
+	start_agno = xfs_ialloc_ag_select(tp, pip, mode);
 	if (start_agno == NULLAGNUMBER) {
 		*inop = NULLFSINO;
 		return 0;
diff --git a/fs/xfs/libxfs/xfs_ialloc.h b/fs/xfs/libxfs/xfs_ialloc.h
index b74fa2addd51..23a03168c240 100644
--- a/fs/xfs/libxfs/xfs_ialloc.h
+++ b/fs/xfs/libxfs/xfs_ialloc.h
@@ -66,11 +66,11 @@ xfs_make_iptr(struct xfs_mount *mp, struct xfs_buf *b, int o)
  */
 int					/* error */
 xfs_dialloc(
-	struct xfs_trans *tp,		/* transaction pointer */
-	xfs_ino_t	parent,		/* parent inode (directory) */
-	umode_t		mode,		/* mode bits for new inode */
-	struct xfs_buf	**agbp,		/* buf for a.g. inode header */
-	xfs_ino_t	*inop);		/* inode number allocated */
+	struct xfs_trans	*tp,	/* transaction pointer */
+	struct xfs_inode	*pip,	/* parent inode (directory) */
+	umode_t			mode,	/* mode bits for new inode */
+	struct xfs_buf		**agbp,	/* buf for a.g. inode header */
+	xfs_ino_t		*inop);	/* inode number allocated */
 
 /*
  * Free disk inode.  Carefully avoids touching the incore inode, all
diff --git a/fs/xfs/libxfs/xfs_inode_util.c b/fs/xfs/libxfs/xfs_inode_util.c
index 815efd73efa7..7d29b995f2dc 100644
--- a/fs/xfs/libxfs/xfs_inode_util.c
+++ b/fs/xfs/libxfs/xfs_inode_util.c
@@ -380,8 +380,7 @@ xfs_ialloc(
 	 * Call the space management code to pick
 	 * the on-disk inode to be allocated.
 	 */
-	error = xfs_dialloc(tp, pip ? pip->i_ino : 0, args->mode,
-			    ialloc_context, &ino);
+	error = xfs_dialloc(tp, pip, args->mode, ialloc_context, &ino);
 	if (error)
 		return error;
 	if (*ialloc_context || ino == NULLFSINO) {
