diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_bmap.c')
-rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 199 |
1 files changed, 112 insertions, 87 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index bfc00de5c6f1..a9c66d47757a 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c | |||
@@ -740,15 +740,9 @@ xfs_bmap_extents_to_btree( | |||
740 | * Fill in the root. | 740 | * Fill in the root. |
741 | */ | 741 | */ |
742 | block = ifp->if_broot; | 742 | block = ifp->if_broot; |
743 | if (xfs_sb_version_hascrc(&mp->m_sb)) | 743 | xfs_btree_init_block_int(mp, block, XFS_BUF_DADDR_NULL, |
744 | xfs_btree_init_block_int(mp, block, XFS_BUF_DADDR_NULL, | 744 | XFS_BTNUM_BMAP, 1, 1, ip->i_ino, |
745 | XFS_BMAP_CRC_MAGIC, 1, 1, ip->i_ino, | ||
746 | XFS_BTREE_LONG_PTRS | XFS_BTREE_CRC_BLOCKS); | ||
747 | else | ||
748 | xfs_btree_init_block_int(mp, block, XFS_BUF_DADDR_NULL, | ||
749 | XFS_BMAP_MAGIC, 1, 1, ip->i_ino, | ||
750 | XFS_BTREE_LONG_PTRS); | 745 | XFS_BTREE_LONG_PTRS); |
751 | |||
752 | /* | 746 | /* |
753 | * Need a cursor. Can't allocate until bb_level is filled in. | 747 | * Need a cursor. Can't allocate until bb_level is filled in. |
754 | */ | 748 | */ |
@@ -804,9 +798,7 @@ try_another_ag: | |||
804 | */ | 798 | */ |
805 | ASSERT(args.fsbno != NULLFSBLOCK); | 799 | ASSERT(args.fsbno != NULLFSBLOCK); |
806 | ASSERT(*firstblock == NULLFSBLOCK || | 800 | ASSERT(*firstblock == NULLFSBLOCK || |
807 | args.agno == XFS_FSB_TO_AGNO(mp, *firstblock) || | 801 | args.agno >= XFS_FSB_TO_AGNO(mp, *firstblock)); |
808 | (dfops->dop_low && | ||
809 | args.agno > XFS_FSB_TO_AGNO(mp, *firstblock))); | ||
810 | *firstblock = cur->bc_private.b.firstblock = args.fsbno; | 802 | *firstblock = cur->bc_private.b.firstblock = args.fsbno; |
811 | cur->bc_private.b.allocated++; | 803 | cur->bc_private.b.allocated++; |
812 | ip->i_d.di_nblocks++; | 804 | ip->i_d.di_nblocks++; |
@@ -817,13 +809,8 @@ try_another_ag: | |||
817 | */ | 809 | */ |
818 | abp->b_ops = &xfs_bmbt_buf_ops; | 810 | abp->b_ops = &xfs_bmbt_buf_ops; |
819 | ablock = XFS_BUF_TO_BLOCK(abp); | 811 | ablock = XFS_BUF_TO_BLOCK(abp); |
820 | if (xfs_sb_version_hascrc(&mp->m_sb)) | 812 | xfs_btree_init_block_int(mp, ablock, abp->b_bn, |
821 | xfs_btree_init_block_int(mp, ablock, abp->b_bn, | 813 | XFS_BTNUM_BMAP, 0, 0, ip->i_ino, |
822 | XFS_BMAP_CRC_MAGIC, 0, 0, ip->i_ino, | ||
823 | XFS_BTREE_LONG_PTRS | XFS_BTREE_CRC_BLOCKS); | ||
824 | else | ||
825 | xfs_btree_init_block_int(mp, ablock, abp->b_bn, | ||
826 | XFS_BMAP_MAGIC, 0, 0, ip->i_ino, | ||
827 | XFS_BTREE_LONG_PTRS); | 814 | XFS_BTREE_LONG_PTRS); |
828 | 815 | ||
829 | arp = XFS_BMBT_REC_ADDR(mp, ablock, 1); | 816 | arp = XFS_BMBT_REC_ADDR(mp, ablock, 1); |
@@ -1278,7 +1265,6 @@ xfs_bmap_read_extents( | |||
1278 | /* REFERENCED */ | 1265 | /* REFERENCED */ |
1279 | xfs_extnum_t room; /* number of entries there's room for */ | 1266 | xfs_extnum_t room; /* number of entries there's room for */ |
1280 | 1267 | ||
1281 | bno = NULLFSBLOCK; | ||
1282 | mp = ip->i_mount; | 1268 | mp = ip->i_mount; |
1283 | ifp = XFS_IFORK_PTR(ip, whichfork); | 1269 | ifp = XFS_IFORK_PTR(ip, whichfork); |
1284 | exntf = (whichfork != XFS_DATA_FORK) ? XFS_EXTFMT_NOSTATE : | 1270 | exntf = (whichfork != XFS_DATA_FORK) ? XFS_EXTFMT_NOSTATE : |
@@ -1291,9 +1277,7 @@ xfs_bmap_read_extents( | |||
1291 | ASSERT(level > 0); | 1277 | ASSERT(level > 0); |
1292 | pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes); | 1278 | pp = XFS_BMAP_BROOT_PTR_ADDR(mp, block, 1, ifp->if_broot_bytes); |
1293 | bno = be64_to_cpu(*pp); | 1279 | bno = be64_to_cpu(*pp); |
1294 | ASSERT(bno != NULLFSBLOCK); | 1280 | |
1295 | ASSERT(XFS_FSB_TO_AGNO(mp, bno) < mp->m_sb.sb_agcount); | ||
1296 | ASSERT(XFS_FSB_TO_AGBNO(mp, bno) < mp->m_sb.sb_agblocks); | ||
1297 | /* | 1281 | /* |
1298 | * Go down the tree until leaf level is reached, following the first | 1282 | * Go down the tree until leaf level is reached, following the first |
1299 | * pointer (leftmost) at each level. | 1283 | * pointer (leftmost) at each level. |
@@ -1864,6 +1848,7 @@ xfs_bmap_add_extent_delay_real( | |||
1864 | */ | 1848 | */ |
1865 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); | 1849 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
1866 | xfs_bmbt_set_startblock(ep, new->br_startblock); | 1850 | xfs_bmbt_set_startblock(ep, new->br_startblock); |
1851 | xfs_bmbt_set_state(ep, new->br_state); | ||
1867 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); | 1852 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
1868 | 1853 | ||
1869 | (*nextents)++; | 1854 | (*nextents)++; |
@@ -2202,6 +2187,7 @@ STATIC int /* error */ | |||
2202 | xfs_bmap_add_extent_unwritten_real( | 2187 | xfs_bmap_add_extent_unwritten_real( |
2203 | struct xfs_trans *tp, | 2188 | struct xfs_trans *tp, |
2204 | xfs_inode_t *ip, /* incore inode pointer */ | 2189 | xfs_inode_t *ip, /* incore inode pointer */ |
2190 | int whichfork, | ||
2205 | xfs_extnum_t *idx, /* extent number to update/insert */ | 2191 | xfs_extnum_t *idx, /* extent number to update/insert */ |
2206 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ | 2192 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ |
2207 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 2193 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ |
@@ -2221,12 +2207,14 @@ xfs_bmap_add_extent_unwritten_real( | |||
2221 | /* left is 0, right is 1, prev is 2 */ | 2207 | /* left is 0, right is 1, prev is 2 */ |
2222 | int rval=0; /* return value (logging flags) */ | 2208 | int rval=0; /* return value (logging flags) */ |
2223 | int state = 0;/* state bits, accessed thru macros */ | 2209 | int state = 0;/* state bits, accessed thru macros */ |
2224 | struct xfs_mount *mp = tp->t_mountp; | 2210 | struct xfs_mount *mp = ip->i_mount; |
2225 | 2211 | ||
2226 | *logflagsp = 0; | 2212 | *logflagsp = 0; |
2227 | 2213 | ||
2228 | cur = *curp; | 2214 | cur = *curp; |
2229 | ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); | 2215 | ifp = XFS_IFORK_PTR(ip, whichfork); |
2216 | if (whichfork == XFS_COW_FORK) | ||
2217 | state |= BMAP_COWFORK; | ||
2230 | 2218 | ||
2231 | ASSERT(*idx >= 0); | 2219 | ASSERT(*idx >= 0); |
2232 | ASSERT(*idx <= xfs_iext_count(ifp)); | 2220 | ASSERT(*idx <= xfs_iext_count(ifp)); |
@@ -2285,7 +2273,7 @@ xfs_bmap_add_extent_unwritten_real( | |||
2285 | * Don't set contiguous if the combined extent would be too large. | 2273 | * Don't set contiguous if the combined extent would be too large. |
2286 | * Also check for all-three-contiguous being too large. | 2274 | * Also check for all-three-contiguous being too large. |
2287 | */ | 2275 | */ |
2288 | if (*idx < xfs_iext_count(&ip->i_df) - 1) { | 2276 | if (*idx < xfs_iext_count(ifp) - 1) { |
2289 | state |= BMAP_RIGHT_VALID; | 2277 | state |= BMAP_RIGHT_VALID; |
2290 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx + 1), &RIGHT); | 2278 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx + 1), &RIGHT); |
2291 | if (isnullstartblock(RIGHT.br_startblock)) | 2279 | if (isnullstartblock(RIGHT.br_startblock)) |
@@ -2325,7 +2313,8 @@ xfs_bmap_add_extent_unwritten_real( | |||
2325 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 2313 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); |
2326 | 2314 | ||
2327 | xfs_iext_remove(ip, *idx + 1, 2, state); | 2315 | xfs_iext_remove(ip, *idx + 1, 2, state); |
2328 | ip->i_d.di_nextents -= 2; | 2316 | XFS_IFORK_NEXT_SET(ip, whichfork, |
2317 | XFS_IFORK_NEXTENTS(ip, whichfork) - 2); | ||
2329 | if (cur == NULL) | 2318 | if (cur == NULL) |
2330 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; | 2319 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; |
2331 | else { | 2320 | else { |
@@ -2368,7 +2357,8 @@ xfs_bmap_add_extent_unwritten_real( | |||
2368 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 2357 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); |
2369 | 2358 | ||
2370 | xfs_iext_remove(ip, *idx + 1, 1, state); | 2359 | xfs_iext_remove(ip, *idx + 1, 1, state); |
2371 | ip->i_d.di_nextents--; | 2360 | XFS_IFORK_NEXT_SET(ip, whichfork, |
2361 | XFS_IFORK_NEXTENTS(ip, whichfork) - 1); | ||
2372 | if (cur == NULL) | 2362 | if (cur == NULL) |
2373 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; | 2363 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; |
2374 | else { | 2364 | else { |
@@ -2403,7 +2393,8 @@ xfs_bmap_add_extent_unwritten_real( | |||
2403 | xfs_bmbt_set_state(ep, newext); | 2393 | xfs_bmbt_set_state(ep, newext); |
2404 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 2394 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); |
2405 | xfs_iext_remove(ip, *idx + 1, 1, state); | 2395 | xfs_iext_remove(ip, *idx + 1, 1, state); |
2406 | ip->i_d.di_nextents--; | 2396 | XFS_IFORK_NEXT_SET(ip, whichfork, |
2397 | XFS_IFORK_NEXTENTS(ip, whichfork) - 1); | ||
2407 | if (cur == NULL) | 2398 | if (cur == NULL) |
2408 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; | 2399 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; |
2409 | else { | 2400 | else { |
@@ -2515,7 +2506,8 @@ xfs_bmap_add_extent_unwritten_real( | |||
2515 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 2506 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); |
2516 | 2507 | ||
2517 | xfs_iext_insert(ip, *idx, 1, new, state); | 2508 | xfs_iext_insert(ip, *idx, 1, new, state); |
2518 | ip->i_d.di_nextents++; | 2509 | XFS_IFORK_NEXT_SET(ip, whichfork, |
2510 | XFS_IFORK_NEXTENTS(ip, whichfork) + 1); | ||
2519 | if (cur == NULL) | 2511 | if (cur == NULL) |
2520 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; | 2512 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; |
2521 | else { | 2513 | else { |
@@ -2593,7 +2585,8 @@ xfs_bmap_add_extent_unwritten_real( | |||
2593 | ++*idx; | 2585 | ++*idx; |
2594 | xfs_iext_insert(ip, *idx, 1, new, state); | 2586 | xfs_iext_insert(ip, *idx, 1, new, state); |
2595 | 2587 | ||
2596 | ip->i_d.di_nextents++; | 2588 | XFS_IFORK_NEXT_SET(ip, whichfork, |
2589 | XFS_IFORK_NEXTENTS(ip, whichfork) + 1); | ||
2597 | if (cur == NULL) | 2590 | if (cur == NULL) |
2598 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; | 2591 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; |
2599 | else { | 2592 | else { |
@@ -2641,7 +2634,8 @@ xfs_bmap_add_extent_unwritten_real( | |||
2641 | ++*idx; | 2634 | ++*idx; |
2642 | xfs_iext_insert(ip, *idx, 2, &r[0], state); | 2635 | xfs_iext_insert(ip, *idx, 2, &r[0], state); |
2643 | 2636 | ||
2644 | ip->i_d.di_nextents += 2; | 2637 | XFS_IFORK_NEXT_SET(ip, whichfork, |
2638 | XFS_IFORK_NEXTENTS(ip, whichfork) + 2); | ||
2645 | if (cur == NULL) | 2639 | if (cur == NULL) |
2646 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; | 2640 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; |
2647 | else { | 2641 | else { |
@@ -2695,17 +2689,17 @@ xfs_bmap_add_extent_unwritten_real( | |||
2695 | } | 2689 | } |
2696 | 2690 | ||
2697 | /* update reverse mappings */ | 2691 | /* update reverse mappings */ |
2698 | error = xfs_rmap_convert_extent(mp, dfops, ip, XFS_DATA_FORK, new); | 2692 | error = xfs_rmap_convert_extent(mp, dfops, ip, whichfork, new); |
2699 | if (error) | 2693 | if (error) |
2700 | goto done; | 2694 | goto done; |
2701 | 2695 | ||
2702 | /* convert to a btree if necessary */ | 2696 | /* convert to a btree if necessary */ |
2703 | if (xfs_bmap_needs_btree(ip, XFS_DATA_FORK)) { | 2697 | if (xfs_bmap_needs_btree(ip, whichfork)) { |
2704 | int tmp_logflags; /* partial log flag return val */ | 2698 | int tmp_logflags; /* partial log flag return val */ |
2705 | 2699 | ||
2706 | ASSERT(cur == NULL); | 2700 | ASSERT(cur == NULL); |
2707 | error = xfs_bmap_extents_to_btree(tp, ip, first, dfops, &cur, | 2701 | error = xfs_bmap_extents_to_btree(tp, ip, first, dfops, &cur, |
2708 | 0, &tmp_logflags, XFS_DATA_FORK); | 2702 | 0, &tmp_logflags, whichfork); |
2709 | *logflagsp |= tmp_logflags; | 2703 | *logflagsp |= tmp_logflags; |
2710 | if (error) | 2704 | if (error) |
2711 | goto done; | 2705 | goto done; |
@@ -2717,7 +2711,7 @@ xfs_bmap_add_extent_unwritten_real( | |||
2717 | *curp = cur; | 2711 | *curp = cur; |
2718 | } | 2712 | } |
2719 | 2713 | ||
2720 | xfs_bmap_check_leaf_extents(*curp, ip, XFS_DATA_FORK); | 2714 | xfs_bmap_check_leaf_extents(*curp, ip, whichfork); |
2721 | done: | 2715 | done: |
2722 | *logflagsp |= rval; | 2716 | *logflagsp |= rval; |
2723 | return error; | 2717 | return error; |
@@ -2809,7 +2803,8 @@ xfs_bmap_add_extent_hole_delay( | |||
2809 | oldlen = startblockval(left.br_startblock) + | 2803 | oldlen = startblockval(left.br_startblock) + |
2810 | startblockval(new->br_startblock) + | 2804 | startblockval(new->br_startblock) + |
2811 | startblockval(right.br_startblock); | 2805 | startblockval(right.br_startblock); |
2812 | newlen = xfs_bmap_worst_indlen(ip, temp); | 2806 | newlen = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), |
2807 | oldlen); | ||
2813 | xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, *idx), | 2808 | xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, *idx), |
2814 | nullstartblock((int)newlen)); | 2809 | nullstartblock((int)newlen)); |
2815 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 2810 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); |
@@ -2830,7 +2825,8 @@ xfs_bmap_add_extent_hole_delay( | |||
2830 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), temp); | 2825 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), temp); |
2831 | oldlen = startblockval(left.br_startblock) + | 2826 | oldlen = startblockval(left.br_startblock) + |
2832 | startblockval(new->br_startblock); | 2827 | startblockval(new->br_startblock); |
2833 | newlen = xfs_bmap_worst_indlen(ip, temp); | 2828 | newlen = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), |
2829 | oldlen); | ||
2834 | xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, *idx), | 2830 | xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, *idx), |
2835 | nullstartblock((int)newlen)); | 2831 | nullstartblock((int)newlen)); |
2836 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 2832 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); |
@@ -2846,7 +2842,8 @@ xfs_bmap_add_extent_hole_delay( | |||
2846 | temp = new->br_blockcount + right.br_blockcount; | 2842 | temp = new->br_blockcount + right.br_blockcount; |
2847 | oldlen = startblockval(new->br_startblock) + | 2843 | oldlen = startblockval(new->br_startblock) + |
2848 | startblockval(right.br_startblock); | 2844 | startblockval(right.br_startblock); |
2849 | newlen = xfs_bmap_worst_indlen(ip, temp); | 2845 | newlen = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), |
2846 | oldlen); | ||
2850 | xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, *idx), | 2847 | xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, *idx), |
2851 | new->br_startoff, | 2848 | new->br_startoff, |
2852 | nullstartblock((int)newlen), temp, right.br_state); | 2849 | nullstartblock((int)newlen), temp, right.br_state); |
@@ -2899,13 +2896,14 @@ xfs_bmap_add_extent_hole_real( | |||
2899 | ASSERT(!isnullstartblock(new->br_startblock)); | 2896 | ASSERT(!isnullstartblock(new->br_startblock)); |
2900 | ASSERT(!bma->cur || | 2897 | ASSERT(!bma->cur || |
2901 | !(bma->cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL)); | 2898 | !(bma->cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL)); |
2902 | ASSERT(whichfork != XFS_COW_FORK); | ||
2903 | 2899 | ||
2904 | XFS_STATS_INC(mp, xs_add_exlist); | 2900 | XFS_STATS_INC(mp, xs_add_exlist); |
2905 | 2901 | ||
2906 | state = 0; | 2902 | state = 0; |
2907 | if (whichfork == XFS_ATTR_FORK) | 2903 | if (whichfork == XFS_ATTR_FORK) |
2908 | state |= BMAP_ATTRFORK; | 2904 | state |= BMAP_ATTRFORK; |
2905 | if (whichfork == XFS_COW_FORK) | ||
2906 | state |= BMAP_COWFORK; | ||
2909 | 2907 | ||
2910 | /* | 2908 | /* |
2911 | * Check and set flags if this segment has a left neighbor. | 2909 | * Check and set flags if this segment has a left neighbor. |
@@ -3822,17 +3820,13 @@ xfs_bmap_btalloc( | |||
3822 | * the first block that was allocated. | 3820 | * the first block that was allocated. |
3823 | */ | 3821 | */ |
3824 | ASSERT(*ap->firstblock == NULLFSBLOCK || | 3822 | ASSERT(*ap->firstblock == NULLFSBLOCK || |
3825 | XFS_FSB_TO_AGNO(mp, *ap->firstblock) == | 3823 | XFS_FSB_TO_AGNO(mp, *ap->firstblock) <= |
3826 | XFS_FSB_TO_AGNO(mp, args.fsbno) || | 3824 | XFS_FSB_TO_AGNO(mp, args.fsbno)); |
3827 | (ap->dfops->dop_low && | ||
3828 | XFS_FSB_TO_AGNO(mp, *ap->firstblock) < | ||
3829 | XFS_FSB_TO_AGNO(mp, args.fsbno))); | ||
3830 | 3825 | ||
3831 | ap->blkno = args.fsbno; | 3826 | ap->blkno = args.fsbno; |
3832 | if (*ap->firstblock == NULLFSBLOCK) | 3827 | if (*ap->firstblock == NULLFSBLOCK) |
3833 | *ap->firstblock = args.fsbno; | 3828 | *ap->firstblock = args.fsbno; |
3834 | ASSERT(nullfb || fb_agno == args.agno || | 3829 | ASSERT(nullfb || fb_agno <= args.agno); |
3835 | (ap->dfops->dop_low && fb_agno < args.agno)); | ||
3836 | ap->length = args.len; | 3830 | ap->length = args.len; |
3837 | if (!(ap->flags & XFS_BMAPI_COWFORK)) | 3831 | if (!(ap->flags & XFS_BMAPI_COWFORK)) |
3838 | ap->ip->i_d.di_nblocks += args.len; | 3832 | ap->ip->i_d.di_nblocks += args.len; |
@@ -4368,10 +4362,16 @@ xfs_bmapi_allocate( | |||
4368 | bma->got.br_state = XFS_EXT_NORM; | 4362 | bma->got.br_state = XFS_EXT_NORM; |
4369 | 4363 | ||
4370 | /* | 4364 | /* |
4371 | * A wasdelay extent has been initialized, so shouldn't be flagged | 4365 | * In the data fork, a wasdelay extent has been initialized, so |
4372 | * as unwritten. | 4366 | * shouldn't be flagged as unwritten. |
4367 | * | ||
4368 | * For the cow fork, however, we convert delalloc reservations | ||
4369 | * (extents allocated for speculative preallocation) to | ||
4370 | * allocated unwritten extents, and only convert the unwritten | ||
4371 | * extents to real extents when we're about to write the data. | ||
4373 | */ | 4372 | */ |
4374 | if (!bma->wasdel && (bma->flags & XFS_BMAPI_PREALLOC) && | 4373 | if ((!bma->wasdel || (bma->flags & XFS_BMAPI_COWFORK)) && |
4374 | (bma->flags & XFS_BMAPI_PREALLOC) && | ||
4375 | xfs_sb_version_hasextflgbit(&mp->m_sb)) | 4375 | xfs_sb_version_hasextflgbit(&mp->m_sb)) |
4376 | bma->got.br_state = XFS_EXT_UNWRITTEN; | 4376 | bma->got.br_state = XFS_EXT_UNWRITTEN; |
4377 | 4377 | ||
@@ -4422,8 +4422,6 @@ xfs_bmapi_convert_unwritten( | |||
4422 | (XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT)) | 4422 | (XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT)) |
4423 | return 0; | 4423 | return 0; |
4424 | 4424 | ||
4425 | ASSERT(whichfork != XFS_COW_FORK); | ||
4426 | |||
4427 | /* | 4425 | /* |
4428 | * Modify (by adding) the state flag, if writing. | 4426 | * Modify (by adding) the state flag, if writing. |
4429 | */ | 4427 | */ |
@@ -4448,8 +4446,8 @@ xfs_bmapi_convert_unwritten( | |||
4448 | return error; | 4446 | return error; |
4449 | } | 4447 | } |
4450 | 4448 | ||
4451 | error = xfs_bmap_add_extent_unwritten_real(bma->tp, bma->ip, &bma->idx, | 4449 | error = xfs_bmap_add_extent_unwritten_real(bma->tp, bma->ip, whichfork, |
4452 | &bma->cur, mval, bma->firstblock, bma->dfops, | 4450 | &bma->idx, &bma->cur, mval, bma->firstblock, bma->dfops, |
4453 | &tmp_logflags); | 4451 | &tmp_logflags); |
4454 | /* | 4452 | /* |
4455 | * Log the inode core unconditionally in the unwritten extent conversion | 4453 | * Log the inode core unconditionally in the unwritten extent conversion |
@@ -4458,8 +4456,12 @@ xfs_bmapi_convert_unwritten( | |||
4458 | * in the transaction for the sake of fsync(), even if nothing has | 4456 | * in the transaction for the sake of fsync(), even if nothing has |
4459 | * changed, because fsync() will not force the log for this transaction | 4457 | * changed, because fsync() will not force the log for this transaction |
4460 | * unless it sees the inode pinned. | 4458 | * unless it sees the inode pinned. |
4459 | * | ||
4460 | * Note: If we're only converting cow fork extents, there aren't | ||
4461 | * any on-disk updates to make, so we don't need to log anything. | ||
4461 | */ | 4462 | */ |
4462 | bma->logflags |= tmp_logflags | XFS_ILOG_CORE; | 4463 | if (whichfork != XFS_COW_FORK) |
4464 | bma->logflags |= tmp_logflags | XFS_ILOG_CORE; | ||
4463 | if (error) | 4465 | if (error) |
4464 | return error; | 4466 | return error; |
4465 | 4467 | ||
@@ -4533,15 +4535,15 @@ xfs_bmapi_write( | |||
4533 | ASSERT(*nmap >= 1); | 4535 | ASSERT(*nmap >= 1); |
4534 | ASSERT(*nmap <= XFS_BMAP_MAX_NMAP); | 4536 | ASSERT(*nmap <= XFS_BMAP_MAX_NMAP); |
4535 | ASSERT(!(flags & XFS_BMAPI_IGSTATE)); | 4537 | ASSERT(!(flags & XFS_BMAPI_IGSTATE)); |
4536 | ASSERT(tp != NULL); | 4538 | ASSERT(tp != NULL || |
4539 | (flags & (XFS_BMAPI_CONVERT | XFS_BMAPI_COWFORK)) == | ||
4540 | (XFS_BMAPI_CONVERT | XFS_BMAPI_COWFORK)); | ||
4537 | ASSERT(len > 0); | 4541 | ASSERT(len > 0); |
4538 | ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL); | 4542 | ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL); |
4539 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 4543 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
4540 | ASSERT(!(flags & XFS_BMAPI_REMAP) || whichfork == XFS_DATA_FORK); | 4544 | ASSERT(!(flags & XFS_BMAPI_REMAP) || whichfork == XFS_DATA_FORK); |
4541 | ASSERT(!(flags & XFS_BMAPI_PREALLOC) || !(flags & XFS_BMAPI_REMAP)); | 4545 | ASSERT(!(flags & XFS_BMAPI_PREALLOC) || !(flags & XFS_BMAPI_REMAP)); |
4542 | ASSERT(!(flags & XFS_BMAPI_CONVERT) || !(flags & XFS_BMAPI_REMAP)); | 4546 | ASSERT(!(flags & XFS_BMAPI_CONVERT) || !(flags & XFS_BMAPI_REMAP)); |
4543 | ASSERT(!(flags & XFS_BMAPI_PREALLOC) || whichfork != XFS_COW_FORK); | ||
4544 | ASSERT(!(flags & XFS_BMAPI_CONVERT) || whichfork != XFS_COW_FORK); | ||
4545 | 4547 | ||
4546 | /* zeroing is for currently only for data extents, not metadata */ | 4548 | /* zeroing is for currently only for data extents, not metadata */ |
4547 | ASSERT((flags & (XFS_BMAPI_METADATA | XFS_BMAPI_ZERO)) != | 4549 | ASSERT((flags & (XFS_BMAPI_METADATA | XFS_BMAPI_ZERO)) != |
@@ -4746,13 +4748,9 @@ error0: | |||
4746 | if (bma.cur) { | 4748 | if (bma.cur) { |
4747 | if (!error) { | 4749 | if (!error) { |
4748 | ASSERT(*firstblock == NULLFSBLOCK || | 4750 | ASSERT(*firstblock == NULLFSBLOCK || |
4749 | XFS_FSB_TO_AGNO(mp, *firstblock) == | 4751 | XFS_FSB_TO_AGNO(mp, *firstblock) <= |
4750 | XFS_FSB_TO_AGNO(mp, | 4752 | XFS_FSB_TO_AGNO(mp, |
4751 | bma.cur->bc_private.b.firstblock) || | 4753 | bma.cur->bc_private.b.firstblock)); |
4752 | (dfops->dop_low && | ||
4753 | XFS_FSB_TO_AGNO(mp, *firstblock) < | ||
4754 | XFS_FSB_TO_AGNO(mp, | ||
4755 | bma.cur->bc_private.b.firstblock))); | ||
4756 | *firstblock = bma.cur->bc_private.b.firstblock; | 4754 | *firstblock = bma.cur->bc_private.b.firstblock; |
4757 | } | 4755 | } |
4758 | xfs_btree_del_cursor(bma.cur, | 4756 | xfs_btree_del_cursor(bma.cur, |
@@ -4787,34 +4785,59 @@ xfs_bmap_split_indlen( | |||
4787 | xfs_filblks_t len2 = *indlen2; | 4785 | xfs_filblks_t len2 = *indlen2; |
4788 | xfs_filblks_t nres = len1 + len2; /* new total res. */ | 4786 | xfs_filblks_t nres = len1 + len2; /* new total res. */ |
4789 | xfs_filblks_t stolen = 0; | 4787 | xfs_filblks_t stolen = 0; |
4788 | xfs_filblks_t resfactor; | ||
4790 | 4789 | ||
4791 | /* | 4790 | /* |
4792 | * Steal as many blocks as we can to try and satisfy the worst case | 4791 | * Steal as many blocks as we can to try and satisfy the worst case |
4793 | * indlen for both new extents. | 4792 | * indlen for both new extents. |
4794 | */ | 4793 | */ |
4795 | while (nres > ores && avail) { | 4794 | if (ores < nres && avail) |
4796 | nres--; | 4795 | stolen = XFS_FILBLKS_MIN(nres - ores, avail); |
4797 | avail--; | 4796 | ores += stolen; |
4798 | stolen++; | 4797 | |
4799 | } | 4798 | /* nothing else to do if we've satisfied the new reservation */ |
4799 | if (ores >= nres) | ||
4800 | return stolen; | ||
4801 | |||
4802 | /* | ||
4803 | * We can't meet the total required reservation for the two extents. | ||
4804 | * Calculate the percent of the overall shortage between both extents | ||
4805 | * and apply this percentage to each of the requested indlen values. | ||
4806 | * This distributes the shortage fairly and reduces the chances that one | ||
4807 | * of the two extents is left with nothing when extents are repeatedly | ||
4808 | * split. | ||
4809 | */ | ||
4810 | resfactor = (ores * 100); | ||
4811 | do_div(resfactor, nres); | ||
4812 | len1 *= resfactor; | ||
4813 | do_div(len1, 100); | ||
4814 | len2 *= resfactor; | ||
4815 | do_div(len2, 100); | ||
4816 | ASSERT(len1 + len2 <= ores); | ||
4817 | ASSERT(len1 < *indlen1 && len2 < *indlen2); | ||
4800 | 4818 | ||
4801 | /* | 4819 | /* |
4802 | * The only blocks available are those reserved for the original | 4820 | * Hand out the remainder to each extent. If one of the two reservations |
4803 | * extent and what we can steal from the extent being removed. | 4821 | * is zero, we want to make sure that one gets a block first. The loop |
4804 | * If this still isn't enough to satisfy the combined | 4822 | * below starts with len1, so hand len2 a block right off the bat if it |
4805 | * requirements for the two new extents, skim blocks off of each | 4823 | * is zero. |
4806 | * of the new reservations until they match what is available. | ||
4807 | */ | 4824 | */ |
4808 | while (nres > ores) { | 4825 | ores -= (len1 + len2); |
4809 | if (len1) { | 4826 | ASSERT((*indlen1 - len1) + (*indlen2 - len2) >= ores); |
4810 | len1--; | 4827 | if (ores && !len2 && *indlen2) { |
4811 | nres--; | 4828 | len2++; |
4829 | ores--; | ||
4830 | } | ||
4831 | while (ores) { | ||
4832 | if (len1 < *indlen1) { | ||
4833 | len1++; | ||
4834 | ores--; | ||
4812 | } | 4835 | } |
4813 | if (nres == ores) | 4836 | if (!ores) |
4814 | break; | 4837 | break; |
4815 | if (len2) { | 4838 | if (len2 < *indlen2) { |
4816 | len2--; | 4839 | len2++; |
4817 | nres--; | 4840 | ores--; |
4818 | } | 4841 | } |
4819 | } | 4842 | } |
4820 | 4843 | ||
@@ -5556,8 +5579,8 @@ __xfs_bunmapi( | |||
5556 | } | 5579 | } |
5557 | del.br_state = XFS_EXT_UNWRITTEN; | 5580 | del.br_state = XFS_EXT_UNWRITTEN; |
5558 | error = xfs_bmap_add_extent_unwritten_real(tp, ip, | 5581 | error = xfs_bmap_add_extent_unwritten_real(tp, ip, |
5559 | &lastx, &cur, &del, firstblock, dfops, | 5582 | whichfork, &lastx, &cur, &del, |
5560 | &logflags); | 5583 | firstblock, dfops, &logflags); |
5561 | if (error) | 5584 | if (error) |
5562 | goto error0; | 5585 | goto error0; |
5563 | goto nodelete; | 5586 | goto nodelete; |
@@ -5610,8 +5633,9 @@ __xfs_bunmapi( | |||
5610 | prev.br_state = XFS_EXT_UNWRITTEN; | 5633 | prev.br_state = XFS_EXT_UNWRITTEN; |
5611 | lastx--; | 5634 | lastx--; |
5612 | error = xfs_bmap_add_extent_unwritten_real(tp, | 5635 | error = xfs_bmap_add_extent_unwritten_real(tp, |
5613 | ip, &lastx, &cur, &prev, | 5636 | ip, whichfork, &lastx, &cur, |
5614 | firstblock, dfops, &logflags); | 5637 | &prev, firstblock, dfops, |
5638 | &logflags); | ||
5615 | if (error) | 5639 | if (error) |
5616 | goto error0; | 5640 | goto error0; |
5617 | goto nodelete; | 5641 | goto nodelete; |
@@ -5619,8 +5643,9 @@ __xfs_bunmapi( | |||
5619 | ASSERT(del.br_state == XFS_EXT_NORM); | 5643 | ASSERT(del.br_state == XFS_EXT_NORM); |
5620 | del.br_state = XFS_EXT_UNWRITTEN; | 5644 | del.br_state = XFS_EXT_UNWRITTEN; |
5621 | error = xfs_bmap_add_extent_unwritten_real(tp, | 5645 | error = xfs_bmap_add_extent_unwritten_real(tp, |
5622 | ip, &lastx, &cur, &del, | 5646 | ip, whichfork, &lastx, &cur, |
5623 | firstblock, dfops, &logflags); | 5647 | &del, firstblock, dfops, |
5648 | &logflags); | ||
5624 | if (error) | 5649 | if (error) |
5625 | goto error0; | 5650 | goto error0; |
5626 | goto nodelete; | 5651 | goto nodelete; |