diff options
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r-- | fs/xfs/xfs_bmap.c | 61 |
1 files changed, 45 insertions, 16 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 4111cd3966c7..dc3afd7739ff 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -1038,17 +1038,34 @@ xfs_bmap_add_extent_delay_real( | |||
1038 | * Filling in the middle part of a previous delayed allocation. | 1038 | * Filling in the middle part of a previous delayed allocation. |
1039 | * Contiguity is impossible here. | 1039 | * Contiguity is impossible here. |
1040 | * This case is avoided almost all the time. | 1040 | * This case is avoided almost all the time. |
1041 | * | ||
1042 | * We start with a delayed allocation: | ||
1043 | * | ||
1044 | * +ddddddddddddddddddddddddddddddddddddddddddddddddddddddd+ | ||
1045 | * PREV @ idx | ||
1046 | * | ||
1047 | * and we are allocating: | ||
1048 | * +rrrrrrrrrrrrrrrrr+ | ||
1049 | * new | ||
1050 | * | ||
1051 | * and we set it up for insertion as: | ||
1052 | * +ddddddddddddddddddd+rrrrrrrrrrrrrrrrr+ddddddddddddddddd+ | ||
1053 | * new | ||
1054 | * PREV @ idx LEFT RIGHT | ||
1055 | * inserted at idx + 1 | ||
1041 | */ | 1056 | */ |
1042 | temp = new->br_startoff - PREV.br_startoff; | 1057 | temp = new->br_startoff - PREV.br_startoff; |
1043 | trace_xfs_bmap_pre_update(ip, idx, 0, _THIS_IP_); | ||
1044 | xfs_bmbt_set_blockcount(ep, temp); | ||
1045 | r[0] = *new; | ||
1046 | r[1].br_state = PREV.br_state; | ||
1047 | r[1].br_startblock = 0; | ||
1048 | r[1].br_startoff = new_endoff; | ||
1049 | temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff; | 1058 | temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff; |
1050 | r[1].br_blockcount = temp2; | 1059 | trace_xfs_bmap_pre_update(ip, idx, 0, _THIS_IP_); |
1051 | xfs_iext_insert(ip, idx + 1, 2, &r[0], state); | 1060 | xfs_bmbt_set_blockcount(ep, temp); /* truncate PREV */ |
1061 | LEFT = *new; | ||
1062 | RIGHT.br_state = PREV.br_state; | ||
1063 | RIGHT.br_startblock = nullstartblock( | ||
1064 | (int)xfs_bmap_worst_indlen(ip, temp2)); | ||
1065 | RIGHT.br_startoff = new_endoff; | ||
1066 | RIGHT.br_blockcount = temp2; | ||
1067 | /* insert LEFT (r[0]) and RIGHT (r[1]) at the same time */ | ||
1068 | xfs_iext_insert(ip, idx + 1, 2, &LEFT, state); | ||
1052 | ip->i_df.if_lastex = idx + 1; | 1069 | ip->i_df.if_lastex = idx + 1; |
1053 | ip->i_d.di_nextents++; | 1070 | ip->i_d.di_nextents++; |
1054 | if (cur == NULL) | 1071 | if (cur == NULL) |
@@ -2430,7 +2447,7 @@ xfs_bmap_btalloc_nullfb( | |||
2430 | startag = ag = 0; | 2447 | startag = ag = 0; |
2431 | 2448 | ||
2432 | pag = xfs_perag_get(mp, ag); | 2449 | pag = xfs_perag_get(mp, ag); |
2433 | while (*blen < ap->alen) { | 2450 | while (*blen < args->maxlen) { |
2434 | if (!pag->pagf_init) { | 2451 | if (!pag->pagf_init) { |
2435 | error = xfs_alloc_pagf_init(mp, args->tp, ag, | 2452 | error = xfs_alloc_pagf_init(mp, args->tp, ag, |
2436 | XFS_ALLOC_FLAG_TRYLOCK); | 2453 | XFS_ALLOC_FLAG_TRYLOCK); |
@@ -2452,7 +2469,7 @@ xfs_bmap_btalloc_nullfb( | |||
2452 | notinit = 1; | 2469 | notinit = 1; |
2453 | 2470 | ||
2454 | if (xfs_inode_is_filestream(ap->ip)) { | 2471 | if (xfs_inode_is_filestream(ap->ip)) { |
2455 | if (*blen >= ap->alen) | 2472 | if (*blen >= args->maxlen) |
2456 | break; | 2473 | break; |
2457 | 2474 | ||
2458 | if (ap->userdata) { | 2475 | if (ap->userdata) { |
@@ -2498,14 +2515,14 @@ xfs_bmap_btalloc_nullfb( | |||
2498 | * If the best seen length is less than the request | 2515 | * If the best seen length is less than the request |
2499 | * length, use the best as the minimum. | 2516 | * length, use the best as the minimum. |
2500 | */ | 2517 | */ |
2501 | else if (*blen < ap->alen) | 2518 | else if (*blen < args->maxlen) |
2502 | args->minlen = *blen; | 2519 | args->minlen = *blen; |
2503 | /* | 2520 | /* |
2504 | * Otherwise we've seen an extent as big as alen, | 2521 | * Otherwise we've seen an extent as big as maxlen, |
2505 | * use that as the minimum. | 2522 | * use that as the minimum. |
2506 | */ | 2523 | */ |
2507 | else | 2524 | else |
2508 | args->minlen = ap->alen; | 2525 | args->minlen = args->maxlen; |
2509 | 2526 | ||
2510 | /* | 2527 | /* |
2511 | * set the failure fallback case to look in the selected | 2528 | * set the failure fallback case to look in the selected |
@@ -2573,7 +2590,9 @@ xfs_bmap_btalloc( | |||
2573 | args.tp = ap->tp; | 2590 | args.tp = ap->tp; |
2574 | args.mp = mp; | 2591 | args.mp = mp; |
2575 | args.fsbno = ap->rval; | 2592 | args.fsbno = ap->rval; |
2576 | args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks); | 2593 | |
2594 | /* Trim the allocation back to the maximum an AG can fit. */ | ||
2595 | args.maxlen = MIN(ap->alen, XFS_ALLOC_AG_MAX_USABLE(mp)); | ||
2577 | args.firstblock = ap->firstblock; | 2596 | args.firstblock = ap->firstblock; |
2578 | blen = 0; | 2597 | blen = 0; |
2579 | if (nullfb) { | 2598 | if (nullfb) { |
@@ -2621,7 +2640,7 @@ xfs_bmap_btalloc( | |||
2621 | /* | 2640 | /* |
2622 | * Adjust for alignment | 2641 | * Adjust for alignment |
2623 | */ | 2642 | */ |
2624 | if (blen > args.alignment && blen <= ap->alen) | 2643 | if (blen > args.alignment && blen <= args.maxlen) |
2625 | args.minlen = blen - args.alignment; | 2644 | args.minlen = blen - args.alignment; |
2626 | args.minalignslop = 0; | 2645 | args.minalignslop = 0; |
2627 | } else { | 2646 | } else { |
@@ -2640,7 +2659,7 @@ xfs_bmap_btalloc( | |||
2640 | * of minlen+alignment+slop doesn't go up | 2659 | * of minlen+alignment+slop doesn't go up |
2641 | * between the calls. | 2660 | * between the calls. |
2642 | */ | 2661 | */ |
2643 | if (blen > mp->m_dalign && blen <= ap->alen) | 2662 | if (blen > mp->m_dalign && blen <= args.maxlen) |
2644 | nextminlen = blen - mp->m_dalign; | 2663 | nextminlen = blen - mp->m_dalign; |
2645 | else | 2664 | else |
2646 | nextminlen = args.minlen; | 2665 | nextminlen = args.minlen; |
@@ -4485,6 +4504,16 @@ xfs_bmapi( | |||
4485 | /* Figure out the extent size, adjust alen */ | 4504 | /* Figure out the extent size, adjust alen */ |
4486 | extsz = xfs_get_extsz_hint(ip); | 4505 | extsz = xfs_get_extsz_hint(ip); |
4487 | if (extsz) { | 4506 | if (extsz) { |
4507 | /* | ||
4508 | * make sure we don't exceed a single | ||
4509 | * extent length when we align the | ||
4510 | * extent by reducing length we are | ||
4511 | * going to allocate by the maximum | ||
4512 | * amount extent size aligment may | ||
4513 | * require. | ||
4514 | */ | ||
4515 | alen = XFS_FILBLKS_MIN(len, | ||
4516 | MAXEXTLEN - (2 * extsz - 1)); | ||
4488 | error = xfs_bmap_extsize_align(mp, | 4517 | error = xfs_bmap_extsize_align(mp, |
4489 | &got, &prev, extsz, | 4518 | &got, &prev, extsz, |
4490 | rt, eof, | 4519 | rt, eof, |