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: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
This commit is contained in:
Родитель
24446fc66f
Коммит
04e99455ea
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче