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

Commit 04e99455 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Alex Elder
Browse files

xfs: only lock the rt bitmap inode once per allocation



Currently both xfs_rtpick_extent and xfs_rtallocate_extent call
xfs_trans_iget to grab and lock the rt bitmap inode, which results in a
deadlock since the removal of the lock recursion counters in commit

	"xfs: simplify inode to transaction joining"

Fix this by acquiring and locking the inode in xfs_bmap_rtalloc before
calling into xfs_rtpick_extent and xfs_rtallocate_extent.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAlex Elder <aelder@sgi.com>
parent 24446fc6
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
@@ -2333,6 +2333,7 @@ xfs_bmap_rtalloc(
	xfs_extlen_t	prod = 0;	/* product factor for allocators */
	xfs_extlen_t	prod = 0;	/* product factor for allocators */
	xfs_extlen_t	ralen = 0;	/* realtime allocation length */
	xfs_extlen_t	ralen = 0;	/* realtime allocation length */
	xfs_extlen_t	align;		/* minimum allocation alignment */
	xfs_extlen_t	align;		/* minimum allocation alignment */
	xfs_inode_t	*ip;		/* bitmap incore inode */
	xfs_rtblock_t	rtb;
	xfs_rtblock_t	rtb;


	mp = ap->ip->i_mount;
	mp = ap->ip->i_mount;
@@ -2365,6 +2366,16 @@ xfs_bmap_rtalloc(
	 */
	 */
	if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN)
	if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN)
		ralen = MAXEXTLEN / mp->m_sb.sb_rextsize;
		ralen = MAXEXTLEN / mp->m_sb.sb_rextsize;

	/*
	 * Lock out other modifications to the RT bitmap inode.
	 */
	error = xfs_trans_iget(mp, ap->tp, mp->m_sb.sb_rbmino, 0,
			       XFS_ILOCK_EXCL, &ip);
	if (error)
		return error;
	ASSERT(ip == mp->m_rbmip);

	/*
	/*
	 * If it's an allocation to an empty file at offset 0,
	 * If it's an allocation to an empty file at offset 0,
	 * pick an extent that will space things out in the rt area.
	 * pick an extent that will space things out in the rt area.
+13 −21
Original line number Original line Diff line number Diff line
@@ -2075,15 +2075,15 @@ xfs_rtallocate_extent(
	xfs_extlen_t	prod,		/* extent product factor */
	xfs_extlen_t	prod,		/* extent product factor */
	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
{
{
	xfs_mount_t	*mp = tp->t_mountp;
	int		error;		/* error value */
	int		error;		/* error value */
	xfs_inode_t	*ip;		/* inode for bitmap file */
	xfs_mount_t	*mp;		/* file system mount structure */
	xfs_rtblock_t	r;		/* result allocated block */
	xfs_rtblock_t	r;		/* result allocated block */
	xfs_fsblock_t	sb;		/* summary file block number */
	xfs_fsblock_t	sb;		/* summary file block number */
	xfs_buf_t	*sumbp;		/* summary file block buffer */
	xfs_buf_t	*sumbp;		/* summary file block buffer */


	ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
	ASSERT(minlen > 0 && minlen <= maxlen);
	ASSERT(minlen > 0 && minlen <= maxlen);
	mp = tp->t_mountp;

	/*
	/*
	 * If prod is set then figure out what to do to minlen and maxlen.
	 * If prod is set then figure out what to do to minlen and maxlen.
	 */
	 */
@@ -2099,12 +2099,7 @@ xfs_rtallocate_extent(
			return 0;
			return 0;
		}
		}
	}
	}
	/*

	 * Lock out other callers by grabbing the bitmap inode lock.
	 */
	if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
					XFS_ILOCK_EXCL, &ip)))
		return error;
	sumbp = NULL;
	sumbp = NULL;
	/*
	/*
	 * Allocate by size, or near another block, or exactly at some block.
	 * Allocate by size, or near another block, or exactly at some block.
@@ -2123,11 +2118,12 @@ xfs_rtallocate_extent(
				len, &sumbp, &sb, prod, &r);
				len, &sumbp, &sb, prod, &r);
		break;
		break;
	default:
	default:
		error = EIO;
		ASSERT(0);
		ASSERT(0);
	}
	}
	if (error) {
	if (error)
		return error;
		return error;
	}

	/*
	/*
	 * If it worked, update the superblock.
	 * If it worked, update the superblock.
	 */
	 */
@@ -2306,20 +2302,16 @@ xfs_rtpick_extent(
	xfs_rtblock_t	*pick)		/* result rt extent */
	xfs_rtblock_t	*pick)		/* result rt extent */
{
{
	xfs_rtblock_t	b;		/* result block */
	xfs_rtblock_t	b;		/* result block */
	int		error;		/* error return value */
	xfs_inode_t	*ip;		/* bitmap incore inode */
	int		log2;		/* log of sequence number */
	int		log2;		/* log of sequence number */
	__uint64_t	resid;		/* residual after log removed */
	__uint64_t	resid;		/* residual after log removed */
	__uint64_t	seq;		/* sequence number of file creation */
	__uint64_t	seq;		/* sequence number of file creation */
	__uint64_t	*seqp;		/* pointer to seqno in inode */
	__uint64_t	*seqp;		/* pointer to seqno in inode */


	if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
	ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
					XFS_ILOCK_EXCL, &ip)))

		return error;
	seqp = (__uint64_t *)&mp->m_rbmip->i_d.di_atime;
	ASSERT(ip == mp->m_rbmip);
	if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) {
	seqp = (__uint64_t *)&ip->i_d.di_atime;
		mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
	if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) {
		ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
		*seqp = 0;
		*seqp = 0;
	}
	}
	seq = *seqp;
	seq = *seqp;
@@ -2335,7 +2327,7 @@ xfs_rtpick_extent(
			b = mp->m_sb.sb_rextents - len;
			b = mp->m_sb.sb_rextents - len;
	}
	}
	*seqp = seq + 1;
	*seqp = seq + 1;
	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
	xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
	*pick = b;
	*pick = b;
	return 0;
	return 0;
}
}