diff options
Diffstat (limited to 'fs/xfs/xfs_alloc.c')
-rw-r--r-- | fs/xfs/xfs_alloc.c | 96 |
1 files changed, 49 insertions, 47 deletions
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index 275b1f4f9430..94cddbfb2560 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 | } |
@@ -2175,7 +2180,7 @@ xfs_alloc_read_agf( | |||
2175 | ASSERT(agno != NULLAGNUMBER); | 2180 | ASSERT(agno != NULLAGNUMBER); |
2176 | 2181 | ||
2177 | error = xfs_read_agf(mp, tp, agno, | 2182 | error = xfs_read_agf(mp, tp, agno, |
2178 | (flags & XFS_ALLOC_FLAG_TRYLOCK) ? XFS_BUF_TRYLOCK : 0, | 2183 | (flags & XFS_ALLOC_FLAG_TRYLOCK) ? XBF_TRYLOCK : 0, |
2179 | bpp); | 2184 | bpp); |
2180 | if (error) | 2185 | if (error) |
2181 | return error; | 2186 | return error; |
@@ -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); |
@@ -2195,8 +2200,8 @@ xfs_alloc_read_agf( | |||
2195 | pag->pagf_levels[XFS_BTNUM_CNTi] = | 2200 | pag->pagf_levels[XFS_BTNUM_CNTi] = |
2196 | be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]); | 2201 | be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]); |
2197 | spin_lock_init(&pag->pagb_lock); | 2202 | spin_lock_init(&pag->pagb_lock); |
2198 | pag->pagb_list = kmem_zalloc(XFS_PAGB_NUM_SLOTS * | 2203 | pag->pagb_count = 0; |
2199 | sizeof(xfs_perag_busy_t), KM_SLEEP); | 2204 | memset(pag->pagb_list, 0, sizeof(pag->pagb_list)); |
2200 | pag->pagf_init = 1; | 2205 | pag->pagf_init = 1; |
2201 | } | 2206 | } |
2202 | #ifdef DEBUG | 2207 | #ifdef DEBUG |
@@ -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 | ||
@@ -2270,8 +2276,7 @@ xfs_alloc_vextent( | |||
2270 | * These three force us into a single a.g. | 2276 | * These three force us into a single a.g. |
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 | args->pag = xfs_perag_get(mp, args->agno); |
2274 | args->pag = &mp->m_perag[args->agno]; | ||
2275 | args->minleft = 0; | 2280 | args->minleft = 0; |
2276 | error = xfs_alloc_fix_freelist(args, 0); | 2281 | error = xfs_alloc_fix_freelist(args, 0); |
2277 | args->minleft = minleft; | 2282 | args->minleft = minleft; |
@@ -2280,14 +2285,12 @@ xfs_alloc_vextent( | |||
2280 | goto error0; | 2285 | goto error0; |
2281 | } | 2286 | } |
2282 | if (!args->agbp) { | 2287 | if (!args->agbp) { |
2283 | up_read(&mp->m_peraglock); | ||
2284 | trace_xfs_alloc_vextent_noagbp(args); | 2288 | trace_xfs_alloc_vextent_noagbp(args); |
2285 | break; | 2289 | break; |
2286 | } | 2290 | } |
2287 | args->agbno = XFS_FSB_TO_AGBNO(mp, args->fsbno); | 2291 | args->agbno = XFS_FSB_TO_AGBNO(mp, args->fsbno); |
2288 | if ((error = xfs_alloc_ag_vextent(args))) | 2292 | if ((error = xfs_alloc_ag_vextent(args))) |
2289 | goto error0; | 2293 | goto error0; |
2290 | up_read(&mp->m_peraglock); | ||
2291 | break; | 2294 | break; |
2292 | case XFS_ALLOCTYPE_START_BNO: | 2295 | case XFS_ALLOCTYPE_START_BNO: |
2293 | /* | 2296 | /* |
@@ -2339,9 +2342,8 @@ xfs_alloc_vextent( | |||
2339 | * Loop over allocation groups twice; first time with | 2342 | * Loop over allocation groups twice; first time with |
2340 | * trylock set, second time without. | 2343 | * trylock set, second time without. |
2341 | */ | 2344 | */ |
2342 | down_read(&mp->m_peraglock); | ||
2343 | for (;;) { | 2345 | for (;;) { |
2344 | args->pag = &mp->m_perag[args->agno]; | 2346 | args->pag = xfs_perag_get(mp, args->agno); |
2345 | if (no_min) args->minleft = 0; | 2347 | if (no_min) args->minleft = 0; |
2346 | error = xfs_alloc_fix_freelist(args, flags); | 2348 | error = xfs_alloc_fix_freelist(args, flags); |
2347 | args->minleft = minleft; | 2349 | args->minleft = minleft; |
@@ -2400,8 +2402,8 @@ xfs_alloc_vextent( | |||
2400 | } | 2402 | } |
2401 | } | 2403 | } |
2402 | } | 2404 | } |
2405 | xfs_perag_put(args->pag); | ||
2403 | } | 2406 | } |
2404 | up_read(&mp->m_peraglock); | ||
2405 | if (bump_rotor || (type == XFS_ALLOCTYPE_ANY_AG)) { | 2407 | if (bump_rotor || (type == XFS_ALLOCTYPE_ANY_AG)) { |
2406 | if (args->agno == sagno) | 2408 | if (args->agno == sagno) |
2407 | mp->m_agfrotor = (mp->m_agfrotor + 1) % | 2409 | mp->m_agfrotor = (mp->m_agfrotor + 1) % |
@@ -2427,9 +2429,10 @@ xfs_alloc_vextent( | |||
2427 | args->len); | 2429 | args->len); |
2428 | #endif | 2430 | #endif |
2429 | } | 2431 | } |
2432 | xfs_perag_put(args->pag); | ||
2430 | return 0; | 2433 | return 0; |
2431 | error0: | 2434 | error0: |
2432 | up_read(&mp->m_peraglock); | 2435 | xfs_perag_put(args->pag); |
2433 | return error; | 2436 | return error; |
2434 | } | 2437 | } |
2435 | 2438 | ||
@@ -2454,8 +2457,7 @@ xfs_free_extent( | |||
2454 | args.agno = XFS_FSB_TO_AGNO(args.mp, bno); | 2457 | args.agno = XFS_FSB_TO_AGNO(args.mp, bno); |
2455 | ASSERT(args.agno < args.mp->m_sb.sb_agcount); | 2458 | ASSERT(args.agno < args.mp->m_sb.sb_agcount); |
2456 | args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno); | 2459 | args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno); |
2457 | down_read(&args.mp->m_peraglock); | 2460 | args.pag = xfs_perag_get(args.mp, args.agno); |
2458 | args.pag = &args.mp->m_perag[args.agno]; | ||
2459 | if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING))) | 2461 | if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING))) |
2460 | goto error0; | 2462 | goto error0; |
2461 | #ifdef DEBUG | 2463 | #ifdef DEBUG |
@@ -2465,7 +2467,7 @@ xfs_free_extent( | |||
2465 | #endif | 2467 | #endif |
2466 | error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0); | 2468 | error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0); |
2467 | error0: | 2469 | error0: |
2468 | up_read(&args.mp->m_peraglock); | 2470 | xfs_perag_put(args.pag); |
2469 | return error; | 2471 | return error; |
2470 | } | 2472 | } |
2471 | 2473 | ||
@@ -2486,15 +2488,15 @@ xfs_alloc_mark_busy(xfs_trans_t *tp, | |||
2486 | xfs_agblock_t bno, | 2488 | xfs_agblock_t bno, |
2487 | xfs_extlen_t len) | 2489 | xfs_extlen_t len) |
2488 | { | 2490 | { |
2489 | xfs_mount_t *mp; | ||
2490 | xfs_perag_busy_t *bsy; | 2491 | xfs_perag_busy_t *bsy; |
2492 | struct xfs_perag *pag; | ||
2491 | int n; | 2493 | int n; |
2492 | 2494 | ||
2493 | mp = tp->t_mountp; | 2495 | pag = xfs_perag_get(tp->t_mountp, agno); |
2494 | spin_lock(&mp->m_perag[agno].pagb_lock); | 2496 | spin_lock(&pag->pagb_lock); |
2495 | 2497 | ||
2496 | /* search pagb_list for an open slot */ | 2498 | /* search pagb_list for an open slot */ |
2497 | for (bsy = mp->m_perag[agno].pagb_list, n = 0; | 2499 | for (bsy = pag->pagb_list, n = 0; |
2498 | n < XFS_PAGB_NUM_SLOTS; | 2500 | n < XFS_PAGB_NUM_SLOTS; |
2499 | bsy++, n++) { | 2501 | bsy++, n++) { |
2500 | if (bsy->busy_tp == NULL) { | 2502 | if (bsy->busy_tp == NULL) { |
@@ -2502,11 +2504,11 @@ xfs_alloc_mark_busy(xfs_trans_t *tp, | |||
2502 | } | 2504 | } |
2503 | } | 2505 | } |
2504 | 2506 | ||
2505 | trace_xfs_alloc_busy(mp, agno, bno, len, n); | 2507 | trace_xfs_alloc_busy(tp->t_mountp, agno, bno, len, n); |
2506 | 2508 | ||
2507 | if (n < XFS_PAGB_NUM_SLOTS) { | 2509 | if (n < XFS_PAGB_NUM_SLOTS) { |
2508 | bsy = &mp->m_perag[agno].pagb_list[n]; | 2510 | bsy = &pag->pagb_list[n]; |
2509 | mp->m_perag[agno].pagb_count++; | 2511 | pag->pagb_count++; |
2510 | bsy->busy_start = bno; | 2512 | bsy->busy_start = bno; |
2511 | bsy->busy_length = len; | 2513 | bsy->busy_length = len; |
2512 | bsy->busy_tp = tp; | 2514 | bsy->busy_tp = tp; |
@@ -2521,7 +2523,8 @@ xfs_alloc_mark_busy(xfs_trans_t *tp, | |||
2521 | xfs_trans_set_sync(tp); | 2523 | xfs_trans_set_sync(tp); |
2522 | } | 2524 | } |
2523 | 2525 | ||
2524 | spin_unlock(&mp->m_perag[agno].pagb_lock); | 2526 | spin_unlock(&pag->pagb_lock); |
2527 | xfs_perag_put(pag); | ||
2525 | } | 2528 | } |
2526 | 2529 | ||
2527 | void | 2530 | void |
@@ -2529,24 +2532,23 @@ xfs_alloc_clear_busy(xfs_trans_t *tp, | |||
2529 | xfs_agnumber_t agno, | 2532 | xfs_agnumber_t agno, |
2530 | int idx) | 2533 | int idx) |
2531 | { | 2534 | { |
2532 | xfs_mount_t *mp; | 2535 | struct xfs_perag *pag; |
2533 | xfs_perag_busy_t *list; | 2536 | xfs_perag_busy_t *list; |
2534 | 2537 | ||
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); | 2538 | ASSERT(idx < XFS_PAGB_NUM_SLOTS); |
2539 | pag = xfs_perag_get(tp->t_mountp, agno); | ||
2540 | spin_lock(&pag->pagb_lock); | ||
2541 | list = pag->pagb_list; | ||
2541 | 2542 | ||
2542 | trace_xfs_alloc_unbusy(mp, agno, idx, list[idx].busy_tp == tp); | 2543 | trace_xfs_alloc_unbusy(tp->t_mountp, agno, idx, list[idx].busy_tp == tp); |
2543 | 2544 | ||
2544 | if (list[idx].busy_tp == tp) { | 2545 | if (list[idx].busy_tp == tp) { |
2545 | list[idx].busy_tp = NULL; | 2546 | list[idx].busy_tp = NULL; |
2546 | mp->m_perag[agno].pagb_count--; | 2547 | pag->pagb_count--; |
2547 | } | 2548 | } |
2548 | 2549 | ||
2549 | spin_unlock(&mp->m_perag[agno].pagb_lock); | 2550 | spin_unlock(&pag->pagb_lock); |
2551 | xfs_perag_put(pag); | ||
2550 | } | 2552 | } |
2551 | 2553 | ||
2552 | 2554 | ||
@@ -2560,17 +2562,15 @@ xfs_alloc_search_busy(xfs_trans_t *tp, | |||
2560 | xfs_agblock_t bno, | 2562 | xfs_agblock_t bno, |
2561 | xfs_extlen_t len) | 2563 | xfs_extlen_t len) |
2562 | { | 2564 | { |
2563 | xfs_mount_t *mp; | 2565 | struct xfs_perag *pag; |
2564 | xfs_perag_busy_t *bsy; | 2566 | xfs_perag_busy_t *bsy; |
2565 | xfs_agblock_t uend, bend; | 2567 | xfs_agblock_t uend, bend; |
2566 | xfs_lsn_t lsn = 0; | 2568 | xfs_lsn_t lsn = 0; |
2567 | int cnt; | 2569 | int cnt; |
2568 | 2570 | ||
2569 | mp = tp->t_mountp; | 2571 | pag = xfs_perag_get(tp->t_mountp, agno); |
2570 | 2572 | spin_lock(&pag->pagb_lock); | |
2571 | spin_lock(&mp->m_perag[agno].pagb_lock); | 2573 | cnt = pag->pagb_count; |
2572 | |||
2573 | uend = bno + len - 1; | ||
2574 | 2574 | ||
2575 | /* | 2575 | /* |
2576 | * search pagb_list for this slot, skipping open slots. We have to | 2576 | * search pagb_list for this slot, skipping open slots. We have to |
@@ -2578,8 +2578,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 | 2578 | * we have to get the most recent LSN for the log force to push out |
2579 | * all the transactions that span the range. | 2579 | * all the transactions that span the range. |
2580 | */ | 2580 | */ |
2581 | for (cnt = 0; cnt < mp->m_perag[agno].pagb_count; cnt++) { | 2581 | uend = bno + len - 1; |
2582 | bsy = &mp->m_perag[agno].pagb_list[cnt]; | 2582 | for (cnt = 0; cnt < pag->pagb_count; cnt++) { |
2583 | bsy = &pag->pagb_list[cnt]; | ||
2583 | if (!bsy->busy_tp) | 2584 | if (!bsy->busy_tp) |
2584 | continue; | 2585 | continue; |
2585 | 2586 | ||
@@ -2591,7 +2592,8 @@ xfs_alloc_search_busy(xfs_trans_t *tp, | |||
2591 | if (XFS_LSN_CMP(bsy->busy_tp->t_commit_lsn, lsn) > 0) | 2592 | if (XFS_LSN_CMP(bsy->busy_tp->t_commit_lsn, lsn) > 0) |
2592 | lsn = bsy->busy_tp->t_commit_lsn; | 2593 | lsn = bsy->busy_tp->t_commit_lsn; |
2593 | } | 2594 | } |
2594 | spin_unlock(&mp->m_perag[agno].pagb_lock); | 2595 | spin_unlock(&pag->pagb_lock); |
2596 | xfs_perag_put(pag); | ||
2595 | trace_xfs_alloc_busysearch(tp->t_mountp, agno, bno, len, lsn); | 2597 | trace_xfs_alloc_busysearch(tp->t_mountp, agno, bno, len, lsn); |
2596 | 2598 | ||
2597 | /* | 2599 | /* |
@@ -2599,5 +2601,5 @@ xfs_alloc_search_busy(xfs_trans_t *tp, | |||
2599 | * transaction that freed the block | 2601 | * transaction that freed the block |
2600 | */ | 2602 | */ |
2601 | if (lsn) | 2603 | if (lsn) |
2602 | xfs_log_force(mp, lsn, XFS_LOG_FORCE|XFS_LOG_SYNC); | 2604 | xfs_log_force_lsn(tp->t_mountp, lsn, XFS_LOG_SYNC); |
2603 | } | 2605 | } |