diff options
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r-- | fs/xfs/xfs_bmap.c | 85 |
1 files changed, 60 insertions, 25 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 4111cd3966c7..fa00788de2f5 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) |
@@ -2348,6 +2365,13 @@ xfs_bmap_rtalloc( | |||
2348 | */ | 2365 | */ |
2349 | if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN) | 2366 | if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN) |
2350 | ralen = MAXEXTLEN / mp->m_sb.sb_rextsize; | 2367 | ralen = MAXEXTLEN / mp->m_sb.sb_rextsize; |
2368 | |||
2369 | /* | ||
2370 | * Lock out other modifications to the RT bitmap inode. | ||
2371 | */ | ||
2372 | xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); | ||
2373 | xfs_trans_ijoin_ref(ap->tp, mp->m_rbmip, XFS_ILOCK_EXCL); | ||
2374 | |||
2351 | /* | 2375 | /* |
2352 | * If it's an allocation to an empty file at offset 0, | 2376 | * If it's an allocation to an empty file at offset 0, |
2353 | * pick an extent that will space things out in the rt area. | 2377 | * pick an extent that will space things out in the rt area. |
@@ -2430,7 +2454,7 @@ xfs_bmap_btalloc_nullfb( | |||
2430 | startag = ag = 0; | 2454 | startag = ag = 0; |
2431 | 2455 | ||
2432 | pag = xfs_perag_get(mp, ag); | 2456 | pag = xfs_perag_get(mp, ag); |
2433 | while (*blen < ap->alen) { | 2457 | while (*blen < args->maxlen) { |
2434 | if (!pag->pagf_init) { | 2458 | if (!pag->pagf_init) { |
2435 | error = xfs_alloc_pagf_init(mp, args->tp, ag, | 2459 | error = xfs_alloc_pagf_init(mp, args->tp, ag, |
2436 | XFS_ALLOC_FLAG_TRYLOCK); | 2460 | XFS_ALLOC_FLAG_TRYLOCK); |
@@ -2452,7 +2476,7 @@ xfs_bmap_btalloc_nullfb( | |||
2452 | notinit = 1; | 2476 | notinit = 1; |
2453 | 2477 | ||
2454 | if (xfs_inode_is_filestream(ap->ip)) { | 2478 | if (xfs_inode_is_filestream(ap->ip)) { |
2455 | if (*blen >= ap->alen) | 2479 | if (*blen >= args->maxlen) |
2456 | break; | 2480 | break; |
2457 | 2481 | ||
2458 | if (ap->userdata) { | 2482 | if (ap->userdata) { |
@@ -2498,14 +2522,14 @@ xfs_bmap_btalloc_nullfb( | |||
2498 | * If the best seen length is less than the request | 2522 | * If the best seen length is less than the request |
2499 | * length, use the best as the minimum. | 2523 | * length, use the best as the minimum. |
2500 | */ | 2524 | */ |
2501 | else if (*blen < ap->alen) | 2525 | else if (*blen < args->maxlen) |
2502 | args->minlen = *blen; | 2526 | args->minlen = *blen; |
2503 | /* | 2527 | /* |
2504 | * Otherwise we've seen an extent as big as alen, | 2528 | * Otherwise we've seen an extent as big as maxlen, |
2505 | * use that as the minimum. | 2529 | * use that as the minimum. |
2506 | */ | 2530 | */ |
2507 | else | 2531 | else |
2508 | args->minlen = ap->alen; | 2532 | args->minlen = args->maxlen; |
2509 | 2533 | ||
2510 | /* | 2534 | /* |
2511 | * set the failure fallback case to look in the selected | 2535 | * set the failure fallback case to look in the selected |
@@ -2573,7 +2597,9 @@ xfs_bmap_btalloc( | |||
2573 | args.tp = ap->tp; | 2597 | args.tp = ap->tp; |
2574 | args.mp = mp; | 2598 | args.mp = mp; |
2575 | args.fsbno = ap->rval; | 2599 | args.fsbno = ap->rval; |
2576 | args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks); | 2600 | |
2601 | /* Trim the allocation back to the maximum an AG can fit. */ | ||
2602 | args.maxlen = MIN(ap->alen, XFS_ALLOC_AG_MAX_USABLE(mp)); | ||
2577 | args.firstblock = ap->firstblock; | 2603 | args.firstblock = ap->firstblock; |
2578 | blen = 0; | 2604 | blen = 0; |
2579 | if (nullfb) { | 2605 | if (nullfb) { |
@@ -2621,7 +2647,7 @@ xfs_bmap_btalloc( | |||
2621 | /* | 2647 | /* |
2622 | * Adjust for alignment | 2648 | * Adjust for alignment |
2623 | */ | 2649 | */ |
2624 | if (blen > args.alignment && blen <= ap->alen) | 2650 | if (blen > args.alignment && blen <= args.maxlen) |
2625 | args.minlen = blen - args.alignment; | 2651 | args.minlen = blen - args.alignment; |
2626 | args.minalignslop = 0; | 2652 | args.minalignslop = 0; |
2627 | } else { | 2653 | } else { |
@@ -2640,7 +2666,7 @@ xfs_bmap_btalloc( | |||
2640 | * of minlen+alignment+slop doesn't go up | 2666 | * of minlen+alignment+slop doesn't go up |
2641 | * between the calls. | 2667 | * between the calls. |
2642 | */ | 2668 | */ |
2643 | if (blen > mp->m_dalign && blen <= ap->alen) | 2669 | if (blen > mp->m_dalign && blen <= args.maxlen) |
2644 | nextminlen = blen - mp->m_dalign; | 2670 | nextminlen = blen - mp->m_dalign; |
2645 | else | 2671 | else |
2646 | nextminlen = args.minlen; | 2672 | nextminlen = args.minlen; |
@@ -3500,7 +3526,7 @@ xfs_bmap_search_extents( | |||
3500 | 3526 | ||
3501 | if (unlikely(!(gotp->br_startblock) && (*lastxp != NULLEXTNUM) && | 3527 | if (unlikely(!(gotp->br_startblock) && (*lastxp != NULLEXTNUM) && |
3502 | !(XFS_IS_REALTIME_INODE(ip) && fork == XFS_DATA_FORK))) { | 3528 | !(XFS_IS_REALTIME_INODE(ip) && fork == XFS_DATA_FORK))) { |
3503 | xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount, | 3529 | xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO, |
3504 | "Access to block zero in inode %llu " | 3530 | "Access to block zero in inode %llu " |
3505 | "start_block: %llx start_off: %llx " | 3531 | "start_block: %llx start_off: %llx " |
3506 | "blkcnt: %llx extent-state: %x lastx: %x\n", | 3532 | "blkcnt: %llx extent-state: %x lastx: %x\n", |
@@ -4174,12 +4200,11 @@ xfs_bmap_read_extents( | |||
4174 | num_recs = xfs_btree_get_numrecs(block); | 4200 | num_recs = xfs_btree_get_numrecs(block); |
4175 | if (unlikely(i + num_recs > room)) { | 4201 | if (unlikely(i + num_recs > room)) { |
4176 | ASSERT(i + num_recs <= room); | 4202 | ASSERT(i + num_recs <= room); |
4177 | xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, | 4203 | xfs_warn(ip->i_mount, |
4178 | "corrupt dinode %Lu, (btree extents).", | 4204 | "corrupt dinode %Lu, (btree extents).", |
4179 | (unsigned long long) ip->i_ino); | 4205 | (unsigned long long) ip->i_ino); |
4180 | XFS_ERROR_REPORT("xfs_bmap_read_extents(1)", | 4206 | XFS_CORRUPTION_ERROR("xfs_bmap_read_extents(1)", |
4181 | XFS_ERRLEVEL_LOW, | 4207 | XFS_ERRLEVEL_LOW, ip->i_mount, block); |
4182 | ip->i_mount); | ||
4183 | goto error0; | 4208 | goto error0; |
4184 | } | 4209 | } |
4185 | XFS_WANT_CORRUPTED_GOTO( | 4210 | XFS_WANT_CORRUPTED_GOTO( |
@@ -4485,6 +4510,16 @@ xfs_bmapi( | |||
4485 | /* Figure out the extent size, adjust alen */ | 4510 | /* Figure out the extent size, adjust alen */ |
4486 | extsz = xfs_get_extsz_hint(ip); | 4511 | extsz = xfs_get_extsz_hint(ip); |
4487 | if (extsz) { | 4512 | if (extsz) { |
4513 | /* | ||
4514 | * make sure we don't exceed a single | ||
4515 | * extent length when we align the | ||
4516 | * extent by reducing length we are | ||
4517 | * going to allocate by the maximum | ||
4518 | * amount extent size aligment may | ||
4519 | * require. | ||
4520 | */ | ||
4521 | alen = XFS_FILBLKS_MIN(len, | ||
4522 | MAXEXTLEN - (2 * extsz - 1)); | ||
4488 | error = xfs_bmap_extsize_align(mp, | 4523 | error = xfs_bmap_extsize_align(mp, |
4489 | &got, &prev, extsz, | 4524 | &got, &prev, extsz, |
4490 | rt, eof, | 4525 | rt, eof, |
@@ -5743,7 +5778,7 @@ xfs_check_block( | |||
5743 | else | 5778 | else |
5744 | thispa = XFS_BMBT_PTR_ADDR(mp, block, j, dmxr); | 5779 | thispa = XFS_BMBT_PTR_ADDR(mp, block, j, dmxr); |
5745 | if (*thispa == *pp) { | 5780 | if (*thispa == *pp) { |
5746 | cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld", | 5781 | xfs_warn(mp, "%s: thispa(%d) == pp(%d) %Ld", |
5747 | __func__, j, i, | 5782 | __func__, j, i, |
5748 | (unsigned long long)be64_to_cpu(*thispa)); | 5783 | (unsigned long long)be64_to_cpu(*thispa)); |
5749 | panic("%s: ptrs are equal in node\n", | 5784 | panic("%s: ptrs are equal in node\n", |
@@ -5908,11 +5943,11 @@ xfs_bmap_check_leaf_extents( | |||
5908 | return; | 5943 | return; |
5909 | 5944 | ||
5910 | error0: | 5945 | error0: |
5911 | cmn_err(CE_WARN, "%s: at error0", __func__); | 5946 | xfs_warn(mp, "%s: at error0", __func__); |
5912 | if (bp_release) | 5947 | if (bp_release) |
5913 | xfs_trans_brelse(NULL, bp); | 5948 | xfs_trans_brelse(NULL, bp); |
5914 | error_norelse: | 5949 | error_norelse: |
5915 | cmn_err(CE_WARN, "%s: BAD after btree leaves for %d extents", | 5950 | xfs_warn(mp, "%s: BAD after btree leaves for %d extents", |
5916 | __func__, i); | 5951 | __func__, i); |
5917 | panic("%s: CORRUPTED BTREE OR SOMETHING", __func__); | 5952 | panic("%s: CORRUPTED BTREE OR SOMETHING", __func__); |
5918 | return; | 5953 | return; |
@@ -6115,7 +6150,7 @@ xfs_bmap_punch_delalloc_range( | |||
6115 | if (error) { | 6150 | if (error) { |
6116 | /* something screwed, just bail */ | 6151 | /* something screwed, just bail */ |
6117 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { | 6152 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { |
6118 | xfs_fs_cmn_err(CE_ALERT, ip->i_mount, | 6153 | xfs_alert(ip->i_mount, |
6119 | "Failed delalloc mapping lookup ino %lld fsb %lld.", | 6154 | "Failed delalloc mapping lookup ino %lld fsb %lld.", |
6120 | ip->i_ino, start_fsb); | 6155 | ip->i_ino, start_fsb); |
6121 | } | 6156 | } |