aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/libxfs/xfs_bmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/libxfs/xfs_bmap.c')
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c199
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 */
2202xfs_bmap_add_extent_unwritten_real( 2187xfs_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);
2721done: 2715done:
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;