diff options
author | Christoph Hellwig <hch@infradead.org> | 2011-01-25 04:06:19 -0500 |
---|---|---|
committer | Alex Elder <aelder@sgi.com> | 2011-02-07 14:29:06 -0500 |
commit | 04e99455ea5bb17ea7c2e7bb0970168efb736242 (patch) | |
tree | 6990228f08cf4ffdfe454bd3d4e88f42b23f9cf8 /fs/xfs | |
parent | 24446fc66fdebbdd8baca0f44fd2a47ad77ba580 (diff) |
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>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_bmap.c | 11 | ||||
-rw-r--r-- | fs/xfs/xfs_rtalloc.c | 34 |
2 files changed, 24 insertions, 21 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index dc3afd7739ff..2f89af25996f 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -2333,6 +2333,7 @@ xfs_bmap_rtalloc( | |||
2333 | xfs_extlen_t prod = 0; /* product factor for allocators */ | 2333 | xfs_extlen_t prod = 0; /* product factor for allocators */ |
2334 | xfs_extlen_t ralen = 0; /* realtime allocation length */ | 2334 | xfs_extlen_t ralen = 0; /* realtime allocation length */ |
2335 | xfs_extlen_t align; /* minimum allocation alignment */ | 2335 | xfs_extlen_t align; /* minimum allocation alignment */ |
2336 | xfs_inode_t *ip; /* bitmap incore inode */ | ||
2336 | xfs_rtblock_t rtb; | 2337 | xfs_rtblock_t rtb; |
2337 | 2338 | ||
2338 | mp = ap->ip->i_mount; | 2339 | mp = ap->ip->i_mount; |
@@ -2365,6 +2366,16 @@ xfs_bmap_rtalloc( | |||
2365 | */ | 2366 | */ |
2366 | if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN) | 2367 | if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN) |
2367 | ralen = MAXEXTLEN / mp->m_sb.sb_rextsize; | 2368 | ralen = MAXEXTLEN / mp->m_sb.sb_rextsize; |
2369 | |||
2370 | /* | ||
2371 | * Lock out other modifications to the RT bitmap inode. | ||
2372 | */ | ||
2373 | error = xfs_trans_iget(mp, ap->tp, mp->m_sb.sb_rbmino, 0, | ||
2374 | XFS_ILOCK_EXCL, &ip); | ||
2375 | if (error) | ||
2376 | return error; | ||
2377 | ASSERT(ip == mp->m_rbmip); | ||
2378 | |||
2368 | /* | 2379 | /* |
2369 | * If it's an allocation to an empty file at offset 0, | 2380 | * If it's an allocation to an empty file at offset 0, |
2370 | * pick an extent that will space things out in the rt area. | 2381 | * pick an extent that will space things out in the rt area. |
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 12a191385310..037fab140242 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c | |||
@@ -2075,15 +2075,15 @@ xfs_rtallocate_extent( | |||
2075 | xfs_extlen_t prod, /* extent product factor */ | 2075 | xfs_extlen_t prod, /* extent product factor */ |
2076 | xfs_rtblock_t *rtblock) /* out: start block allocated */ | 2076 | xfs_rtblock_t *rtblock) /* out: start block allocated */ |
2077 | { | 2077 | { |
2078 | xfs_mount_t *mp = tp->t_mountp; | ||
2078 | int error; /* error value */ | 2079 | int error; /* error value */ |
2079 | xfs_inode_t *ip; /* inode for bitmap file */ | ||
2080 | xfs_mount_t *mp; /* file system mount structure */ | ||
2081 | xfs_rtblock_t r; /* result allocated block */ | 2080 | xfs_rtblock_t r; /* result allocated block */ |
2082 | xfs_fsblock_t sb; /* summary file block number */ | 2081 | xfs_fsblock_t sb; /* summary file block number */ |
2083 | xfs_buf_t *sumbp; /* summary file block buffer */ | 2082 | xfs_buf_t *sumbp; /* summary file block buffer */ |
2084 | 2083 | ||
2084 | ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); | ||
2085 | ASSERT(minlen > 0 && minlen <= maxlen); | 2085 | ASSERT(minlen > 0 && minlen <= maxlen); |
2086 | mp = tp->t_mountp; | 2086 | |
2087 | /* | 2087 | /* |
2088 | * If prod is set then figure out what to do to minlen and maxlen. | 2088 | * If prod is set then figure out what to do to minlen and maxlen. |
2089 | */ | 2089 | */ |
@@ -2099,12 +2099,7 @@ xfs_rtallocate_extent( | |||
2099 | return 0; | 2099 | return 0; |
2100 | } | 2100 | } |
2101 | } | 2101 | } |
2102 | /* | 2102 | |
2103 | * Lock out other callers by grabbing the bitmap inode lock. | ||
2104 | */ | ||
2105 | if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, | ||
2106 | XFS_ILOCK_EXCL, &ip))) | ||
2107 | return error; | ||
2108 | sumbp = NULL; | 2103 | sumbp = NULL; |
2109 | /* | 2104 | /* |
2110 | * Allocate by size, or near another block, or exactly at some block. | 2105 | * Allocate by size, or near another block, or exactly at some block. |
@@ -2123,11 +2118,12 @@ xfs_rtallocate_extent( | |||
2123 | len, &sumbp, &sb, prod, &r); | 2118 | len, &sumbp, &sb, prod, &r); |
2124 | break; | 2119 | break; |
2125 | default: | 2120 | default: |
2121 | error = EIO; | ||
2126 | ASSERT(0); | 2122 | ASSERT(0); |
2127 | } | 2123 | } |
2128 | if (error) { | 2124 | if (error) |
2129 | return error; | 2125 | return error; |
2130 | } | 2126 | |
2131 | /* | 2127 | /* |
2132 | * If it worked, update the superblock. | 2128 | * If it worked, update the superblock. |
2133 | */ | 2129 | */ |
@@ -2306,20 +2302,16 @@ xfs_rtpick_extent( | |||
2306 | xfs_rtblock_t *pick) /* result rt extent */ | 2302 | xfs_rtblock_t *pick) /* result rt extent */ |
2307 | { | 2303 | { |
2308 | xfs_rtblock_t b; /* result block */ | 2304 | xfs_rtblock_t b; /* result block */ |
2309 | int error; /* error return value */ | ||
2310 | xfs_inode_t *ip; /* bitmap incore inode */ | ||
2311 | int log2; /* log of sequence number */ | 2305 | int log2; /* log of sequence number */ |
2312 | __uint64_t resid; /* residual after log removed */ | 2306 | __uint64_t resid; /* residual after log removed */ |
2313 | __uint64_t seq; /* sequence number of file creation */ | 2307 | __uint64_t seq; /* sequence number of file creation */ |
2314 | __uint64_t *seqp; /* pointer to seqno in inode */ | 2308 | __uint64_t *seqp; /* pointer to seqno in inode */ |
2315 | 2309 | ||
2316 | if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, | 2310 | ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); |
2317 | XFS_ILOCK_EXCL, &ip))) | 2311 | |
2318 | return error; | 2312 | seqp = (__uint64_t *)&mp->m_rbmip->i_d.di_atime; |
2319 | ASSERT(ip == mp->m_rbmip); | 2313 | if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) { |
2320 | seqp = (__uint64_t *)&ip->i_d.di_atime; | 2314 | mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; |
2321 | if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) { | ||
2322 | ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; | ||
2323 | *seqp = 0; | 2315 | *seqp = 0; |
2324 | } | 2316 | } |
2325 | seq = *seqp; | 2317 | seq = *seqp; |
@@ -2335,7 +2327,7 @@ xfs_rtpick_extent( | |||
2335 | b = mp->m_sb.sb_rextents - len; | 2327 | b = mp->m_sb.sb_rextents - len; |
2336 | } | 2328 | } |
2337 | *seqp = seq + 1; | 2329 | *seqp = seq + 1; |
2338 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 2330 | xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); |
2339 | *pick = b; | 2331 | *pick = b; |
2340 | return 0; | 2332 | return 0; |
2341 | } | 2333 | } |