aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <david@fromorbit.com>2010-01-11 06:47:41 -0500
committerAlex Elder <aelder@sgi.com>2010-01-15 16:33:12 -0500
commita862e0fdcb8862aab2538ec2fc2f0dc07a625c59 (patch)
tree41e83f478c9414e3376e99aa8565c67cc9930764
parent5017e97d52628fb8ae56e434e86ac2e72ddaac2b (diff)
xfs: Don't directly reference m_perag in allocation code
Start abstracting the perag references so that the indexing of the structures is not directly coded into all the places that uses the perag structures. This will allow us to separate the use of the perag structure and the way it is indexed and hence avoid the known deadlocks related to growing a busy filesystem. Signed-off-by: Dave Chinner <david@fromorbit.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
-rw-r--r--fs/xfs/xfs_alloc.c82
-rw-r--r--fs/xfs/xfs_alloc_btree.c9
2 files changed, 53 insertions, 38 deletions
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 275b1f4f9430..84070f2e0ba4 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -1662,11 +1662,13 @@ xfs_free_ag_extent(
1662 xfs_agf_t *agf; 1662 xfs_agf_t *agf;
1663 xfs_perag_t *pag; /* per allocation group data */ 1663 xfs_perag_t *pag; /* per allocation group data */
1664 1664
1665 pag = xfs_perag_get(mp, agno);
1666 pag->pagf_freeblks += len;
1667 xfs_perag_put(pag);
1668
1665 agf = XFS_BUF_TO_AGF(agbp); 1669 agf = XFS_BUF_TO_AGF(agbp);
1666 pag = &mp->m_perag[agno];
1667 be32_add_cpu(&agf->agf_freeblks, len); 1670 be32_add_cpu(&agf->agf_freeblks, len);
1668 xfs_trans_agblocks_delta(tp, len); 1671 xfs_trans_agblocks_delta(tp, len);
1669 pag->pagf_freeblks += len;
1670 XFS_WANT_CORRUPTED_GOTO( 1672 XFS_WANT_CORRUPTED_GOTO(
1671 be32_to_cpu(agf->agf_freeblks) <= 1673 be32_to_cpu(agf->agf_freeblks) <=
1672 be32_to_cpu(agf->agf_length), 1674 be32_to_cpu(agf->agf_length),
@@ -1969,10 +1971,12 @@ xfs_alloc_get_freelist(
1969 xfs_trans_brelse(tp, agflbp); 1971 xfs_trans_brelse(tp, agflbp);
1970 if (be32_to_cpu(agf->agf_flfirst) == XFS_AGFL_SIZE(mp)) 1972 if (be32_to_cpu(agf->agf_flfirst) == XFS_AGFL_SIZE(mp))
1971 agf->agf_flfirst = 0; 1973 agf->agf_flfirst = 0;
1972 pag = &mp->m_perag[be32_to_cpu(agf->agf_seqno)]; 1974
1975 pag = xfs_perag_get(mp, be32_to_cpu(agf->agf_seqno));
1973 be32_add_cpu(&agf->agf_flcount, -1); 1976 be32_add_cpu(&agf->agf_flcount, -1);
1974 xfs_trans_agflist_delta(tp, -1); 1977 xfs_trans_agflist_delta(tp, -1);
1975 pag->pagf_flcount--; 1978 pag->pagf_flcount--;
1979 xfs_perag_put(pag);
1976 1980
1977 logflags = XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT; 1981 logflags = XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT;
1978 if (btreeblk) { 1982 if (btreeblk) {
@@ -2078,7 +2082,8 @@ xfs_alloc_put_freelist(
2078 be32_add_cpu(&agf->agf_fllast, 1); 2082 be32_add_cpu(&agf->agf_fllast, 1);
2079 if (be32_to_cpu(agf->agf_fllast) == XFS_AGFL_SIZE(mp)) 2083 if (be32_to_cpu(agf->agf_fllast) == XFS_AGFL_SIZE(mp))
2080 agf->agf_fllast = 0; 2084 agf->agf_fllast = 0;
2081 pag = &mp->m_perag[be32_to_cpu(agf->agf_seqno)]; 2085
2086 pag = xfs_perag_get(mp, be32_to_cpu(agf->agf_seqno));
2082 be32_add_cpu(&agf->agf_flcount, 1); 2087 be32_add_cpu(&agf->agf_flcount, 1);
2083 xfs_trans_agflist_delta(tp, 1); 2088 xfs_trans_agflist_delta(tp, 1);
2084 pag->pagf_flcount++; 2089 pag->pagf_flcount++;
@@ -2089,6 +2094,7 @@ xfs_alloc_put_freelist(
2089 pag->pagf_btreeblks--; 2094 pag->pagf_btreeblks--;
2090 logflags |= XFS_AGF_BTREEBLKS; 2095 logflags |= XFS_AGF_BTREEBLKS;
2091 } 2096 }
2097 xfs_perag_put(pag);
2092 2098
2093 xfs_alloc_log_agf(tp, agbp, logflags); 2099 xfs_alloc_log_agf(tp, agbp, logflags);
2094 2100
@@ -2152,7 +2158,6 @@ xfs_read_agf(
2152 xfs_trans_brelse(tp, *bpp); 2158 xfs_trans_brelse(tp, *bpp);
2153 return XFS_ERROR(EFSCORRUPTED); 2159 return XFS_ERROR(EFSCORRUPTED);
2154 } 2160 }
2155
2156 XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_AGF, XFS_AGF_REF); 2161 XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_AGF, XFS_AGF_REF);
2157 return 0; 2162 return 0;
2158} 2163}
@@ -2184,7 +2189,7 @@ xfs_alloc_read_agf(
2184 ASSERT(!XFS_BUF_GETERROR(*bpp)); 2189 ASSERT(!XFS_BUF_GETERROR(*bpp));
2185 2190
2186 agf = XFS_BUF_TO_AGF(*bpp); 2191 agf = XFS_BUF_TO_AGF(*bpp);
2187 pag = &mp->m_perag[agno]; 2192 pag = xfs_perag_get(mp, agno);
2188 if (!pag->pagf_init) { 2193 if (!pag->pagf_init) {
2189 pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks); 2194 pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks);
2190 pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks); 2195 pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks);
@@ -2211,6 +2216,7 @@ xfs_alloc_read_agf(
2211 be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi])); 2216 be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]));
2212 } 2217 }
2213#endif 2218#endif
2219 xfs_perag_put(pag);
2214 return 0; 2220 return 0;
2215} 2221}
2216 2222
@@ -2271,7 +2277,7 @@ xfs_alloc_vextent(
2271 */ 2277 */
2272 args->agno = XFS_FSB_TO_AGNO(mp, args->fsbno); 2278 args->agno = XFS_FSB_TO_AGNO(mp, args->fsbno);
2273 down_read(&mp->m_peraglock); 2279 down_read(&mp->m_peraglock);
2274 args->pag = &mp->m_perag[args->agno]; 2280 args->pag = xfs_perag_get(mp, args->agno);
2275 args->minleft = 0; 2281 args->minleft = 0;
2276 error = xfs_alloc_fix_freelist(args, 0); 2282 error = xfs_alloc_fix_freelist(args, 0);
2277 args->minleft = minleft; 2283 args->minleft = minleft;
@@ -2341,7 +2347,7 @@ xfs_alloc_vextent(
2341 */ 2347 */
2342 down_read(&mp->m_peraglock); 2348 down_read(&mp->m_peraglock);
2343 for (;;) { 2349 for (;;) {
2344 args->pag = &mp->m_perag[args->agno]; 2350 args->pag = xfs_perag_get(mp, args->agno);
2345 if (no_min) args->minleft = 0; 2351 if (no_min) args->minleft = 0;
2346 error = xfs_alloc_fix_freelist(args, flags); 2352 error = xfs_alloc_fix_freelist(args, flags);
2347 args->minleft = minleft; 2353 args->minleft = minleft;
@@ -2400,6 +2406,7 @@ xfs_alloc_vextent(
2400 } 2406 }
2401 } 2407 }
2402 } 2408 }
2409 xfs_perag_put(args->pag);
2403 } 2410 }
2404 up_read(&mp->m_peraglock); 2411 up_read(&mp->m_peraglock);
2405 if (bump_rotor || (type == XFS_ALLOCTYPE_ANY_AG)) { 2412 if (bump_rotor || (type == XFS_ALLOCTYPE_ANY_AG)) {
@@ -2427,8 +2434,10 @@ xfs_alloc_vextent(
2427 args->len); 2434 args->len);
2428#endif 2435#endif
2429 } 2436 }
2437 xfs_perag_put(args->pag);
2430 return 0; 2438 return 0;
2431error0: 2439error0:
2440 xfs_perag_put(args->pag);
2432 up_read(&mp->m_peraglock); 2441 up_read(&mp->m_peraglock);
2433 return error; 2442 return error;
2434} 2443}
@@ -2455,7 +2464,7 @@ xfs_free_extent(
2455 ASSERT(args.agno < args.mp->m_sb.sb_agcount); 2464 ASSERT(args.agno < args.mp->m_sb.sb_agcount);
2456 args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno); 2465 args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno);
2457 down_read(&args.mp->m_peraglock); 2466 down_read(&args.mp->m_peraglock);
2458 args.pag = &args.mp->m_perag[args.agno]; 2467 args.pag = xfs_perag_get(args.mp, args.agno);
2459 if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING))) 2468 if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING)))
2460 goto error0; 2469 goto error0;
2461#ifdef DEBUG 2470#ifdef DEBUG
@@ -2465,6 +2474,7 @@ xfs_free_extent(
2465#endif 2474#endif
2466 error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0); 2475 error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0);
2467error0: 2476error0:
2477 xfs_perag_put(args.pag);
2468 up_read(&args.mp->m_peraglock); 2478 up_read(&args.mp->m_peraglock);
2469 return error; 2479 return error;
2470} 2480}
@@ -2486,15 +2496,15 @@ xfs_alloc_mark_busy(xfs_trans_t *tp,
2486 xfs_agblock_t bno, 2496 xfs_agblock_t bno,
2487 xfs_extlen_t len) 2497 xfs_extlen_t len)
2488{ 2498{
2489 xfs_mount_t *mp;
2490 xfs_perag_busy_t *bsy; 2499 xfs_perag_busy_t *bsy;
2500 struct xfs_perag *pag;
2491 int n; 2501 int n;
2492 2502
2493 mp = tp->t_mountp; 2503 pag = xfs_perag_get(tp->t_mountp, agno);
2494 spin_lock(&mp->m_perag[agno].pagb_lock); 2504 spin_lock(&pag->pagb_lock);
2495 2505
2496 /* search pagb_list for an open slot */ 2506 /* search pagb_list for an open slot */
2497 for (bsy = mp->m_perag[agno].pagb_list, n = 0; 2507 for (bsy = pag->pagb_list, n = 0;
2498 n < XFS_PAGB_NUM_SLOTS; 2508 n < XFS_PAGB_NUM_SLOTS;
2499 bsy++, n++) { 2509 bsy++, n++) {
2500 if (bsy->busy_tp == NULL) { 2510 if (bsy->busy_tp == NULL) {
@@ -2502,11 +2512,11 @@ xfs_alloc_mark_busy(xfs_trans_t *tp,
2502 } 2512 }
2503 } 2513 }
2504 2514
2505 trace_xfs_alloc_busy(mp, agno, bno, len, n); 2515 trace_xfs_alloc_busy(tp->t_mountp, agno, bno, len, n);
2506 2516
2507 if (n < XFS_PAGB_NUM_SLOTS) { 2517 if (n < XFS_PAGB_NUM_SLOTS) {
2508 bsy = &mp->m_perag[agno].pagb_list[n]; 2518 bsy = &pag->pagb_list[n];
2509 mp->m_perag[agno].pagb_count++; 2519 pag->pagb_count++;
2510 bsy->busy_start = bno; 2520 bsy->busy_start = bno;
2511 bsy->busy_length = len; 2521 bsy->busy_length = len;
2512 bsy->busy_tp = tp; 2522 bsy->busy_tp = tp;
@@ -2521,7 +2531,8 @@ xfs_alloc_mark_busy(xfs_trans_t *tp,
2521 xfs_trans_set_sync(tp); 2531 xfs_trans_set_sync(tp);
2522 } 2532 }
2523 2533
2524 spin_unlock(&mp->m_perag[agno].pagb_lock); 2534 spin_unlock(&pag->pagb_lock);
2535 xfs_perag_put(pag);
2525} 2536}
2526 2537
2527void 2538void
@@ -2529,24 +2540,23 @@ xfs_alloc_clear_busy(xfs_trans_t *tp,
2529 xfs_agnumber_t agno, 2540 xfs_agnumber_t agno,
2530 int idx) 2541 int idx)
2531{ 2542{
2532 xfs_mount_t *mp; 2543 struct xfs_perag *pag;
2533 xfs_perag_busy_t *list; 2544 xfs_perag_busy_t *list;
2534 2545
2535 mp = tp->t_mountp;
2536
2537 spin_lock(&mp->m_perag[agno].pagb_lock);
2538 list = mp->m_perag[agno].pagb_list;
2539
2540 ASSERT(idx < XFS_PAGB_NUM_SLOTS); 2546 ASSERT(idx < XFS_PAGB_NUM_SLOTS);
2547 pag = xfs_perag_get(tp->t_mountp, agno);
2548 spin_lock(&pag->pagb_lock);
2549 list = pag->pagb_list;
2541 2550
2542 trace_xfs_alloc_unbusy(mp, agno, idx, list[idx].busy_tp == tp); 2551 trace_xfs_alloc_unbusy(tp->t_mountp, agno, idx, list[idx].busy_tp == tp);
2543 2552
2544 if (list[idx].busy_tp == tp) { 2553 if (list[idx].busy_tp == tp) {
2545 list[idx].busy_tp = NULL; 2554 list[idx].busy_tp = NULL;
2546 mp->m_perag[agno].pagb_count--; 2555 pag->pagb_count--;
2547 } 2556 }
2548 2557
2549 spin_unlock(&mp->m_perag[agno].pagb_lock); 2558 spin_unlock(&pag->pagb_lock);
2559 xfs_perag_put(pag);
2550} 2560}
2551 2561
2552 2562
@@ -2560,17 +2570,15 @@ xfs_alloc_search_busy(xfs_trans_t *tp,
2560 xfs_agblock_t bno, 2570 xfs_agblock_t bno,
2561 xfs_extlen_t len) 2571 xfs_extlen_t len)
2562{ 2572{
2563 xfs_mount_t *mp; 2573 struct xfs_perag *pag;
2564 xfs_perag_busy_t *bsy; 2574 xfs_perag_busy_t *bsy;
2565 xfs_agblock_t uend, bend; 2575 xfs_agblock_t uend, bend;
2566 xfs_lsn_t lsn = 0; 2576 xfs_lsn_t lsn = 0;
2567 int cnt; 2577 int cnt;
2568 2578
2569 mp = tp->t_mountp; 2579 pag = xfs_perag_get(tp->t_mountp, agno);
2570 2580 spin_lock(&pag->pagb_lock);
2571 spin_lock(&mp->m_perag[agno].pagb_lock); 2581 cnt = pag->pagb_count;
2572
2573 uend = bno + len - 1;
2574 2582
2575 /* 2583 /*
2576 * search pagb_list for this slot, skipping open slots. We have to 2584 * search pagb_list for this slot, skipping open slots. We have to
@@ -2578,8 +2586,9 @@ xfs_alloc_search_busy(xfs_trans_t *tp,
2578 * we have to get the most recent LSN for the log force to push out 2586 * we have to get the most recent LSN for the log force to push out
2579 * all the transactions that span the range. 2587 * all the transactions that span the range.
2580 */ 2588 */
2581 for (cnt = 0; cnt < mp->m_perag[agno].pagb_count; cnt++) { 2589 uend = bno + len - 1;
2582 bsy = &mp->m_perag[agno].pagb_list[cnt]; 2590 for (cnt = 0; cnt < pag->pagb_count; cnt++) {
2591 bsy = &pag->pagb_list[cnt];
2583 if (!bsy->busy_tp) 2592 if (!bsy->busy_tp)
2584 continue; 2593 continue;
2585 2594
@@ -2591,7 +2600,8 @@ xfs_alloc_search_busy(xfs_trans_t *tp,
2591 if (XFS_LSN_CMP(bsy->busy_tp->t_commit_lsn, lsn) > 0) 2600 if (XFS_LSN_CMP(bsy->busy_tp->t_commit_lsn, lsn) > 0)
2592 lsn = bsy->busy_tp->t_commit_lsn; 2601 lsn = bsy->busy_tp->t_commit_lsn;
2593 } 2602 }
2594 spin_unlock(&mp->m_perag[agno].pagb_lock); 2603 spin_unlock(&pag->pagb_lock);
2604 xfs_perag_put(pag);
2595 trace_xfs_alloc_busysearch(tp->t_mountp, agno, bno, len, lsn); 2605 trace_xfs_alloc_busysearch(tp->t_mountp, agno, bno, len, lsn);
2596 2606
2597 /* 2607 /*
@@ -2599,5 +2609,5 @@ xfs_alloc_search_busy(xfs_trans_t *tp,
2599 * transaction that freed the block 2609 * transaction that freed the block
2600 */ 2610 */
2601 if (lsn) 2611 if (lsn)
2602 xfs_log_force(mp, lsn, XFS_LOG_FORCE|XFS_LOG_SYNC); 2612 xfs_log_force(tp->t_mountp, lsn, XFS_LOG_FORCE|XFS_LOG_SYNC);
2603} 2613}
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
index adbd9141aea1..b726e10d2c1c 100644
--- a/fs/xfs/xfs_alloc_btree.c
+++ b/fs/xfs/xfs_alloc_btree.c
@@ -61,12 +61,14 @@ xfs_allocbt_set_root(
61 struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); 61 struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp);
62 xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); 62 xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno);
63 int btnum = cur->bc_btnum; 63 int btnum = cur->bc_btnum;
64 struct xfs_perag *pag = xfs_perag_get(cur->bc_mp, seqno);
64 65
65 ASSERT(ptr->s != 0); 66 ASSERT(ptr->s != 0);
66 67
67 agf->agf_roots[btnum] = ptr->s; 68 agf->agf_roots[btnum] = ptr->s;
68 be32_add_cpu(&agf->agf_levels[btnum], inc); 69 be32_add_cpu(&agf->agf_levels[btnum], inc);
69 cur->bc_mp->m_perag[seqno].pagf_levels[btnum] += inc; 70 pag->pagf_levels[btnum] += inc;
71 xfs_perag_put(pag);
70 72
71 xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS); 73 xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS);
72} 74}
@@ -150,6 +152,7 @@ xfs_allocbt_update_lastrec(
150{ 152{
151 struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); 153 struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
152 xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); 154 xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno);
155 struct xfs_perag *pag;
153 __be32 len; 156 __be32 len;
154 int numrecs; 157 int numrecs;
155 158
@@ -193,7 +196,9 @@ xfs_allocbt_update_lastrec(
193 } 196 }
194 197
195 agf->agf_longest = len; 198 agf->agf_longest = len;
196 cur->bc_mp->m_perag[seqno].pagf_longest = be32_to_cpu(len); 199 pag = xfs_perag_get(cur->bc_mp, seqno);
200 pag->pagf_longest = be32_to_cpu(len);
201 xfs_perag_put(pag);
197 xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, XFS_AGF_LONGEST); 202 xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, XFS_AGF_LONGEST);
198} 203}
199 204