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.c554
1 files changed, 397 insertions, 157 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 61ec015dca16..aeffeaaac0ec 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -244,30 +244,6 @@ xfs_bmap_forkoff_reset(
244 } 244 }
245} 245}
246 246
247/*
248 * Debug/sanity checking code
249 */
250
251STATIC int
252xfs_bmap_sanity_check(
253 struct xfs_mount *mp,
254 struct xfs_buf *bp,
255 int level)
256{
257 struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
258
259 if (block->bb_magic != cpu_to_be32(XFS_BMAP_CRC_MAGIC) &&
260 block->bb_magic != cpu_to_be32(XFS_BMAP_MAGIC))
261 return 0;
262
263 if (be16_to_cpu(block->bb_level) != level ||
264 be16_to_cpu(block->bb_numrecs) == 0 ||
265 be16_to_cpu(block->bb_numrecs) > mp->m_bmap_dmxr[level != 0])
266 return 0;
267
268 return 1;
269}
270
271#ifdef DEBUG 247#ifdef DEBUG
272STATIC struct xfs_buf * 248STATIC struct xfs_buf *
273xfs_bmap_get_bp( 249xfs_bmap_get_bp(
@@ -410,9 +386,6 @@ xfs_bmap_check_leaf_extents(
410 goto error_norelse; 386 goto error_norelse;
411 } 387 }
412 block = XFS_BUF_TO_BLOCK(bp); 388 block = XFS_BUF_TO_BLOCK(bp);
413 XFS_WANT_CORRUPTED_GOTO(
414 xfs_bmap_sanity_check(mp, bp, level),
415 error0);
416 if (level == 0) 389 if (level == 0)
417 break; 390 break;
418 391
@@ -424,7 +397,8 @@ xfs_bmap_check_leaf_extents(
424 xfs_check_block(block, mp, 0, 0); 397 xfs_check_block(block, mp, 0, 0);
425 pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]); 398 pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
426 bno = be64_to_cpu(*pp); 399 bno = be64_to_cpu(*pp);
427 XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0); 400 XFS_WANT_CORRUPTED_GOTO(mp,
401 XFS_FSB_SANITY_CHECK(mp, bno), error0);
428 if (bp_release) { 402 if (bp_release) {
429 bp_release = 0; 403 bp_release = 0;
430 xfs_trans_brelse(NULL, bp); 404 xfs_trans_brelse(NULL, bp);
@@ -1029,7 +1003,7 @@ xfs_bmap_add_attrfork_btree(
1029 if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat))) 1003 if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat)))
1030 goto error0; 1004 goto error0;
1031 /* must be at least one entry */ 1005 /* must be at least one entry */
1032 XFS_WANT_CORRUPTED_GOTO(stat == 1, error0); 1006 XFS_WANT_CORRUPTED_GOTO(mp, stat == 1, error0);
1033 if ((error = xfs_btree_new_iroot(cur, flags, &stat))) 1007 if ((error = xfs_btree_new_iroot(cur, flags, &stat)))
1034 goto error0; 1008 goto error0;
1035 if (stat == 0) { 1009 if (stat == 0) {
@@ -1311,14 +1285,12 @@ xfs_bmap_read_extents(
1311 if (error) 1285 if (error)
1312 return error; 1286 return error;
1313 block = XFS_BUF_TO_BLOCK(bp); 1287 block = XFS_BUF_TO_BLOCK(bp);
1314 XFS_WANT_CORRUPTED_GOTO(
1315 xfs_bmap_sanity_check(mp, bp, level),
1316 error0);
1317 if (level == 0) 1288 if (level == 0)
1318 break; 1289 break;
1319 pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]); 1290 pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
1320 bno = be64_to_cpu(*pp); 1291 bno = be64_to_cpu(*pp);
1321 XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0); 1292 XFS_WANT_CORRUPTED_GOTO(mp,
1293 XFS_FSB_SANITY_CHECK(mp, bno), error0);
1322 xfs_trans_brelse(tp, bp); 1294 xfs_trans_brelse(tp, bp);
1323 } 1295 }
1324 /* 1296 /*
@@ -1345,9 +1317,6 @@ xfs_bmap_read_extents(
1345 XFS_ERRLEVEL_LOW, ip->i_mount, block); 1317 XFS_ERRLEVEL_LOW, ip->i_mount, block);
1346 goto error0; 1318 goto error0;
1347 } 1319 }
1348 XFS_WANT_CORRUPTED_GOTO(
1349 xfs_bmap_sanity_check(mp, bp, 0),
1350 error0);
1351 /* 1320 /*
1352 * Read-ahead the next leaf block, if any. 1321 * Read-ahead the next leaf block, if any.
1353 */ 1322 */
@@ -1755,7 +1724,9 @@ xfs_bmap_add_extent_delay_real(
1755 xfs_filblks_t temp=0; /* value for da_new calculations */ 1724 xfs_filblks_t temp=0; /* value for da_new calculations */
1756 xfs_filblks_t temp2=0;/* value for da_new calculations */ 1725 xfs_filblks_t temp2=0;/* value for da_new calculations */
1757 int tmp_rval; /* partial logging flags */ 1726 int tmp_rval; /* partial logging flags */
1727 struct xfs_mount *mp;
1758 1728
1729 mp = bma->tp ? bma->tp->t_mountp : NULL;
1759 ifp = XFS_IFORK_PTR(bma->ip, XFS_DATA_FORK); 1730 ifp = XFS_IFORK_PTR(bma->ip, XFS_DATA_FORK);
1760 1731
1761 ASSERT(bma->idx >= 0); 1732 ASSERT(bma->idx >= 0);
@@ -1866,15 +1837,15 @@ xfs_bmap_add_extent_delay_real(
1866 RIGHT.br_blockcount, &i); 1837 RIGHT.br_blockcount, &i);
1867 if (error) 1838 if (error)
1868 goto done; 1839 goto done;
1869 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 1840 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1870 error = xfs_btree_delete(bma->cur, &i); 1841 error = xfs_btree_delete(bma->cur, &i);
1871 if (error) 1842 if (error)
1872 goto done; 1843 goto done;
1873 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 1844 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1874 error = xfs_btree_decrement(bma->cur, 0, &i); 1845 error = xfs_btree_decrement(bma->cur, 0, &i);
1875 if (error) 1846 if (error)
1876 goto done; 1847 goto done;
1877 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 1848 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1878 error = xfs_bmbt_update(bma->cur, LEFT.br_startoff, 1849 error = xfs_bmbt_update(bma->cur, LEFT.br_startoff,
1879 LEFT.br_startblock, 1850 LEFT.br_startblock,
1880 LEFT.br_blockcount + 1851 LEFT.br_blockcount +
@@ -1907,7 +1878,7 @@ xfs_bmap_add_extent_delay_real(
1907 &i); 1878 &i);
1908 if (error) 1879 if (error)
1909 goto done; 1880 goto done;
1910 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 1881 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1911 error = xfs_bmbt_update(bma->cur, LEFT.br_startoff, 1882 error = xfs_bmbt_update(bma->cur, LEFT.br_startoff,
1912 LEFT.br_startblock, 1883 LEFT.br_startblock,
1913 LEFT.br_blockcount + 1884 LEFT.br_blockcount +
@@ -1938,7 +1909,7 @@ xfs_bmap_add_extent_delay_real(
1938 RIGHT.br_blockcount, &i); 1909 RIGHT.br_blockcount, &i);
1939 if (error) 1910 if (error)
1940 goto done; 1911 goto done;
1941 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 1912 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1942 error = xfs_bmbt_update(bma->cur, PREV.br_startoff, 1913 error = xfs_bmbt_update(bma->cur, PREV.br_startoff,
1943 new->br_startblock, 1914 new->br_startblock,
1944 PREV.br_blockcount + 1915 PREV.br_blockcount +
@@ -1968,12 +1939,12 @@ xfs_bmap_add_extent_delay_real(
1968 &i); 1939 &i);
1969 if (error) 1940 if (error)
1970 goto done; 1941 goto done;
1971 XFS_WANT_CORRUPTED_GOTO(i == 0, done); 1942 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1972 bma->cur->bc_rec.b.br_state = XFS_EXT_NORM; 1943 bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
1973 error = xfs_btree_insert(bma->cur, &i); 1944 error = xfs_btree_insert(bma->cur, &i);
1974 if (error) 1945 if (error)
1975 goto done; 1946 goto done;
1976 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 1947 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1977 } 1948 }
1978 break; 1949 break;
1979 1950
@@ -2001,7 +1972,7 @@ xfs_bmap_add_extent_delay_real(
2001 &i); 1972 &i);
2002 if (error) 1973 if (error)
2003 goto done; 1974 goto done;
2004 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 1975 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2005 error = xfs_bmbt_update(bma->cur, LEFT.br_startoff, 1976 error = xfs_bmbt_update(bma->cur, LEFT.br_startoff,
2006 LEFT.br_startblock, 1977 LEFT.br_startblock,
2007 LEFT.br_blockcount + 1978 LEFT.br_blockcount +
@@ -2038,12 +2009,12 @@ xfs_bmap_add_extent_delay_real(
2038 &i); 2009 &i);
2039 if (error) 2010 if (error)
2040 goto done; 2011 goto done;
2041 XFS_WANT_CORRUPTED_GOTO(i == 0, done); 2012 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
2042 bma->cur->bc_rec.b.br_state = XFS_EXT_NORM; 2013 bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
2043 error = xfs_btree_insert(bma->cur, &i); 2014 error = xfs_btree_insert(bma->cur, &i);
2044 if (error) 2015 if (error)
2045 goto done; 2016 goto done;
2046 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2017 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2047 } 2018 }
2048 2019
2049 if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) { 2020 if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
@@ -2084,7 +2055,7 @@ xfs_bmap_add_extent_delay_real(
2084 RIGHT.br_blockcount, &i); 2055 RIGHT.br_blockcount, &i);
2085 if (error) 2056 if (error)
2086 goto done; 2057 goto done;
2087 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2058 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2088 error = xfs_bmbt_update(bma->cur, new->br_startoff, 2059 error = xfs_bmbt_update(bma->cur, new->br_startoff,
2089 new->br_startblock, 2060 new->br_startblock,
2090 new->br_blockcount + 2061 new->br_blockcount +
@@ -2122,12 +2093,12 @@ xfs_bmap_add_extent_delay_real(
2122 &i); 2093 &i);
2123 if (error) 2094 if (error)
2124 goto done; 2095 goto done;
2125 XFS_WANT_CORRUPTED_GOTO(i == 0, done); 2096 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
2126 bma->cur->bc_rec.b.br_state = XFS_EXT_NORM; 2097 bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
2127 error = xfs_btree_insert(bma->cur, &i); 2098 error = xfs_btree_insert(bma->cur, &i);
2128 if (error) 2099 if (error)
2129 goto done; 2100 goto done;
2130 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2101 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2131 } 2102 }
2132 2103
2133 if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) { 2104 if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
@@ -2191,12 +2162,12 @@ xfs_bmap_add_extent_delay_real(
2191 &i); 2162 &i);
2192 if (error) 2163 if (error)
2193 goto done; 2164 goto done;
2194 XFS_WANT_CORRUPTED_GOTO(i == 0, done); 2165 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
2195 bma->cur->bc_rec.b.br_state = XFS_EXT_NORM; 2166 bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
2196 error = xfs_btree_insert(bma->cur, &i); 2167 error = xfs_btree_insert(bma->cur, &i);
2197 if (error) 2168 if (error)
2198 goto done; 2169 goto done;
2199 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2170 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2200 } 2171 }
2201 2172
2202 if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) { 2173 if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
@@ -2212,9 +2183,8 @@ xfs_bmap_add_extent_delay_real(
2212 diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) - 2183 diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) -
2213 (bma->cur ? bma->cur->bc_private.b.allocated : 0)); 2184 (bma->cur ? bma->cur->bc_private.b.allocated : 0));
2214 if (diff > 0) { 2185 if (diff > 0) {
2215 error = xfs_icsb_modify_counters(bma->ip->i_mount, 2186 error = xfs_mod_fdblocks(bma->ip->i_mount,
2216 XFS_SBS_FDBLOCKS, 2187 -((int64_t)diff), false);
2217 -((int64_t)diff), 0);
2218 ASSERT(!error); 2188 ASSERT(!error);
2219 if (error) 2189 if (error)
2220 goto done; 2190 goto done;
@@ -2265,9 +2235,8 @@ xfs_bmap_add_extent_delay_real(
2265 temp += bma->cur->bc_private.b.allocated; 2235 temp += bma->cur->bc_private.b.allocated;
2266 ASSERT(temp <= da_old); 2236 ASSERT(temp <= da_old);
2267 if (temp < da_old) 2237 if (temp < da_old)
2268 xfs_icsb_modify_counters(bma->ip->i_mount, 2238 xfs_mod_fdblocks(bma->ip->i_mount,
2269 XFS_SBS_FDBLOCKS, 2239 (int64_t)(da_old - temp), false);
2270 (int64_t)(da_old - temp), 0);
2271 } 2240 }
2272 2241
2273 /* clear out the allocated field, done with it now in any case. */ 2242 /* clear out the allocated field, done with it now in any case. */
@@ -2309,6 +2278,7 @@ xfs_bmap_add_extent_unwritten_real(
2309 /* left is 0, right is 1, prev is 2 */ 2278 /* left is 0, right is 1, prev is 2 */
2310 int rval=0; /* return value (logging flags) */ 2279 int rval=0; /* return value (logging flags) */
2311 int state = 0;/* state bits, accessed thru macros */ 2280 int state = 0;/* state bits, accessed thru macros */
2281 struct xfs_mount *mp = tp->t_mountp;
2312 2282
2313 *logflagsp = 0; 2283 *logflagsp = 0;
2314 2284
@@ -2421,19 +2391,19 @@ xfs_bmap_add_extent_unwritten_real(
2421 RIGHT.br_startblock, 2391 RIGHT.br_startblock,
2422 RIGHT.br_blockcount, &i))) 2392 RIGHT.br_blockcount, &i)))
2423 goto done; 2393 goto done;
2424 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2394 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2425 if ((error = xfs_btree_delete(cur, &i))) 2395 if ((error = xfs_btree_delete(cur, &i)))
2426 goto done; 2396 goto done;
2427 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2397 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2428 if ((error = xfs_btree_decrement(cur, 0, &i))) 2398 if ((error = xfs_btree_decrement(cur, 0, &i)))
2429 goto done; 2399 goto done;
2430 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2400 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2431 if ((error = xfs_btree_delete(cur, &i))) 2401 if ((error = xfs_btree_delete(cur, &i)))
2432 goto done; 2402 goto done;
2433 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2403 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2434 if ((error = xfs_btree_decrement(cur, 0, &i))) 2404 if ((error = xfs_btree_decrement(cur, 0, &i)))
2435 goto done; 2405 goto done;
2436 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2406 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2437 if ((error = xfs_bmbt_update(cur, LEFT.br_startoff, 2407 if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
2438 LEFT.br_startblock, 2408 LEFT.br_startblock,
2439 LEFT.br_blockcount + PREV.br_blockcount + 2409 LEFT.br_blockcount + PREV.br_blockcount +
@@ -2464,13 +2434,13 @@ xfs_bmap_add_extent_unwritten_real(
2464 PREV.br_startblock, PREV.br_blockcount, 2434 PREV.br_startblock, PREV.br_blockcount,
2465 &i))) 2435 &i)))
2466 goto done; 2436 goto done;
2467 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2437 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2468 if ((error = xfs_btree_delete(cur, &i))) 2438 if ((error = xfs_btree_delete(cur, &i)))
2469 goto done; 2439 goto done;
2470 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2440 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2471 if ((error = xfs_btree_decrement(cur, 0, &i))) 2441 if ((error = xfs_btree_decrement(cur, 0, &i)))
2472 goto done; 2442 goto done;
2473 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2443 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2474 if ((error = xfs_bmbt_update(cur, LEFT.br_startoff, 2444 if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
2475 LEFT.br_startblock, 2445 LEFT.br_startblock,
2476 LEFT.br_blockcount + PREV.br_blockcount, 2446 LEFT.br_blockcount + PREV.br_blockcount,
@@ -2499,13 +2469,13 @@ xfs_bmap_add_extent_unwritten_real(
2499 RIGHT.br_startblock, 2469 RIGHT.br_startblock,
2500 RIGHT.br_blockcount, &i))) 2470 RIGHT.br_blockcount, &i)))
2501 goto done; 2471 goto done;
2502 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2472 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2503 if ((error = xfs_btree_delete(cur, &i))) 2473 if ((error = xfs_btree_delete(cur, &i)))
2504 goto done; 2474 goto done;
2505 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2475 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2506 if ((error = xfs_btree_decrement(cur, 0, &i))) 2476 if ((error = xfs_btree_decrement(cur, 0, &i)))
2507 goto done; 2477 goto done;
2508 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2478 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2509 if ((error = xfs_bmbt_update(cur, new->br_startoff, 2479 if ((error = xfs_bmbt_update(cur, new->br_startoff,
2510 new->br_startblock, 2480 new->br_startblock,
2511 new->br_blockcount + RIGHT.br_blockcount, 2481 new->br_blockcount + RIGHT.br_blockcount,
@@ -2532,7 +2502,7 @@ xfs_bmap_add_extent_unwritten_real(
2532 new->br_startblock, new->br_blockcount, 2502 new->br_startblock, new->br_blockcount,
2533 &i))) 2503 &i)))
2534 goto done; 2504 goto done;
2535 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2505 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2536 if ((error = xfs_bmbt_update(cur, new->br_startoff, 2506 if ((error = xfs_bmbt_update(cur, new->br_startoff,
2537 new->br_startblock, new->br_blockcount, 2507 new->br_startblock, new->br_blockcount,
2538 newext))) 2508 newext)))
@@ -2569,7 +2539,7 @@ xfs_bmap_add_extent_unwritten_real(
2569 PREV.br_startblock, PREV.br_blockcount, 2539 PREV.br_startblock, PREV.br_blockcount,
2570 &i))) 2540 &i)))
2571 goto done; 2541 goto done;
2572 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2542 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2573 if ((error = xfs_bmbt_update(cur, 2543 if ((error = xfs_bmbt_update(cur,
2574 PREV.br_startoff + new->br_blockcount, 2544 PREV.br_startoff + new->br_blockcount,
2575 PREV.br_startblock + new->br_blockcount, 2545 PREV.br_startblock + new->br_blockcount,
@@ -2611,7 +2581,7 @@ xfs_bmap_add_extent_unwritten_real(
2611 PREV.br_startblock, PREV.br_blockcount, 2581 PREV.br_startblock, PREV.br_blockcount,
2612 &i))) 2582 &i)))
2613 goto done; 2583 goto done;
2614 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2584 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2615 if ((error = xfs_bmbt_update(cur, 2585 if ((error = xfs_bmbt_update(cur,
2616 PREV.br_startoff + new->br_blockcount, 2586 PREV.br_startoff + new->br_blockcount,
2617 PREV.br_startblock + new->br_blockcount, 2587 PREV.br_startblock + new->br_blockcount,
@@ -2621,7 +2591,7 @@ xfs_bmap_add_extent_unwritten_real(
2621 cur->bc_rec.b = *new; 2591 cur->bc_rec.b = *new;
2622 if ((error = xfs_btree_insert(cur, &i))) 2592 if ((error = xfs_btree_insert(cur, &i)))
2623 goto done; 2593 goto done;
2624 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2594 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2625 } 2595 }
2626 break; 2596 break;
2627 2597
@@ -2651,7 +2621,7 @@ xfs_bmap_add_extent_unwritten_real(
2651 PREV.br_startblock, 2621 PREV.br_startblock,
2652 PREV.br_blockcount, &i))) 2622 PREV.br_blockcount, &i)))
2653 goto done; 2623 goto done;
2654 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2624 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2655 if ((error = xfs_bmbt_update(cur, PREV.br_startoff, 2625 if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
2656 PREV.br_startblock, 2626 PREV.br_startblock,
2657 PREV.br_blockcount - new->br_blockcount, 2627 PREV.br_blockcount - new->br_blockcount,
@@ -2689,7 +2659,7 @@ xfs_bmap_add_extent_unwritten_real(
2689 PREV.br_startblock, PREV.br_blockcount, 2659 PREV.br_startblock, PREV.br_blockcount,
2690 &i))) 2660 &i)))
2691 goto done; 2661 goto done;
2692 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2662 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2693 if ((error = xfs_bmbt_update(cur, PREV.br_startoff, 2663 if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
2694 PREV.br_startblock, 2664 PREV.br_startblock,
2695 PREV.br_blockcount - new->br_blockcount, 2665 PREV.br_blockcount - new->br_blockcount,
@@ -2699,11 +2669,11 @@ xfs_bmap_add_extent_unwritten_real(
2699 new->br_startblock, new->br_blockcount, 2669 new->br_startblock, new->br_blockcount,
2700 &i))) 2670 &i)))
2701 goto done; 2671 goto done;
2702 XFS_WANT_CORRUPTED_GOTO(i == 0, done); 2672 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
2703 cur->bc_rec.b.br_state = XFS_EXT_NORM; 2673 cur->bc_rec.b.br_state = XFS_EXT_NORM;
2704 if ((error = xfs_btree_insert(cur, &i))) 2674 if ((error = xfs_btree_insert(cur, &i)))
2705 goto done; 2675 goto done;
2706 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2676 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2707 } 2677 }
2708 break; 2678 break;
2709 2679
@@ -2737,7 +2707,7 @@ xfs_bmap_add_extent_unwritten_real(
2737 PREV.br_startblock, PREV.br_blockcount, 2707 PREV.br_startblock, PREV.br_blockcount,
2738 &i))) 2708 &i)))
2739 goto done; 2709 goto done;
2740 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2710 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2741 /* new right extent - oldext */ 2711 /* new right extent - oldext */
2742 if ((error = xfs_bmbt_update(cur, r[1].br_startoff, 2712 if ((error = xfs_bmbt_update(cur, r[1].br_startoff,
2743 r[1].br_startblock, r[1].br_blockcount, 2713 r[1].br_startblock, r[1].br_blockcount,
@@ -2749,7 +2719,7 @@ xfs_bmap_add_extent_unwritten_real(
2749 new->br_startoff - PREV.br_startoff; 2719 new->br_startoff - PREV.br_startoff;
2750 if ((error = xfs_btree_insert(cur, &i))) 2720 if ((error = xfs_btree_insert(cur, &i)))
2751 goto done; 2721 goto done;
2752 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2722 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2753 /* 2723 /*
2754 * Reset the cursor to the position of the new extent 2724 * Reset the cursor to the position of the new extent
2755 * we are about to insert as we can't trust it after 2725 * we are about to insert as we can't trust it after
@@ -2759,12 +2729,12 @@ xfs_bmap_add_extent_unwritten_real(
2759 new->br_startblock, new->br_blockcount, 2729 new->br_startblock, new->br_blockcount,
2760 &i))) 2730 &i)))
2761 goto done; 2731 goto done;
2762 XFS_WANT_CORRUPTED_GOTO(i == 0, done); 2732 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
2763 /* new middle extent - newext */ 2733 /* new middle extent - newext */
2764 cur->bc_rec.b.br_state = new->br_state; 2734 cur->bc_rec.b.br_state = new->br_state;
2765 if ((error = xfs_btree_insert(cur, &i))) 2735 if ((error = xfs_btree_insert(cur, &i)))
2766 goto done; 2736 goto done;
2767 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 2737 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
2768 } 2738 }
2769 break; 2739 break;
2770 2740
@@ -2944,8 +2914,8 @@ xfs_bmap_add_extent_hole_delay(
2944 } 2914 }
2945 if (oldlen != newlen) { 2915 if (oldlen != newlen) {
2946 ASSERT(oldlen > newlen); 2916 ASSERT(oldlen > newlen);
2947 xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS, 2917 xfs_mod_fdblocks(ip->i_mount, (int64_t)(oldlen - newlen),
2948 (int64_t)(oldlen - newlen), 0); 2918 false);
2949 /* 2919 /*
2950 * Nothing to do for disk quota accounting here. 2920 * Nothing to do for disk quota accounting here.
2951 */ 2921 */
@@ -2968,7 +2938,9 @@ xfs_bmap_add_extent_hole_real(
2968 xfs_bmbt_irec_t right; /* right neighbor extent entry */ 2938 xfs_bmbt_irec_t right; /* right neighbor extent entry */
2969 int rval=0; /* return value (logging flags) */ 2939 int rval=0; /* return value (logging flags) */
2970 int state; /* state bits, accessed thru macros */ 2940 int state; /* state bits, accessed thru macros */
2941 struct xfs_mount *mp;
2971 2942
2943 mp = bma->tp ? bma->tp->t_mountp : NULL;
2972 ifp = XFS_IFORK_PTR(bma->ip, whichfork); 2944 ifp = XFS_IFORK_PTR(bma->ip, whichfork);
2973 2945
2974 ASSERT(bma->idx >= 0); 2946 ASSERT(bma->idx >= 0);
@@ -3056,15 +3028,15 @@ xfs_bmap_add_extent_hole_real(
3056 &i); 3028 &i);
3057 if (error) 3029 if (error)
3058 goto done; 3030 goto done;
3059 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 3031 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
3060 error = xfs_btree_delete(bma->cur, &i); 3032 error = xfs_btree_delete(bma->cur, &i);
3061 if (error) 3033 if (error)
3062 goto done; 3034 goto done;
3063 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 3035 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
3064 error = xfs_btree_decrement(bma->cur, 0, &i); 3036 error = xfs_btree_decrement(bma->cur, 0, &i);
3065 if (error) 3037 if (error)
3066 goto done; 3038 goto done;
3067 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 3039 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
3068 error = xfs_bmbt_update(bma->cur, left.br_startoff, 3040 error = xfs_bmbt_update(bma->cur, left.br_startoff,
3069 left.br_startblock, 3041 left.br_startblock,
3070 left.br_blockcount + 3042 left.br_blockcount +
@@ -3097,7 +3069,7 @@ xfs_bmap_add_extent_hole_real(
3097 &i); 3069 &i);
3098 if (error) 3070 if (error)
3099 goto done; 3071 goto done;
3100 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 3072 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
3101 error = xfs_bmbt_update(bma->cur, left.br_startoff, 3073 error = xfs_bmbt_update(bma->cur, left.br_startoff,
3102 left.br_startblock, 3074 left.br_startblock,
3103 left.br_blockcount + 3075 left.br_blockcount +
@@ -3131,7 +3103,7 @@ xfs_bmap_add_extent_hole_real(
3131 right.br_blockcount, &i); 3103 right.br_blockcount, &i);
3132 if (error) 3104 if (error)
3133 goto done; 3105 goto done;
3134 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 3106 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
3135 error = xfs_bmbt_update(bma->cur, new->br_startoff, 3107 error = xfs_bmbt_update(bma->cur, new->br_startoff,
3136 new->br_startblock, 3108 new->br_startblock,
3137 new->br_blockcount + 3109 new->br_blockcount +
@@ -3161,12 +3133,12 @@ xfs_bmap_add_extent_hole_real(
3161 new->br_blockcount, &i); 3133 new->br_blockcount, &i);
3162 if (error) 3134 if (error)
3163 goto done; 3135 goto done;
3164 XFS_WANT_CORRUPTED_GOTO(i == 0, done); 3136 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
3165 bma->cur->bc_rec.b.br_state = new->br_state; 3137 bma->cur->bc_rec.b.br_state = new->br_state;
3166 error = xfs_btree_insert(bma->cur, &i); 3138 error = xfs_btree_insert(bma->cur, &i);
3167 if (error) 3139 if (error)
3168 goto done; 3140 goto done;
3169 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 3141 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
3170 } 3142 }
3171 break; 3143 break;
3172 } 3144 }
@@ -4160,18 +4132,15 @@ xfs_bmapi_reserve_delalloc(
4160 ASSERT(indlen > 0); 4132 ASSERT(indlen > 0);
4161 4133
4162 if (rt) { 4134 if (rt) {
4163 error = xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, 4135 error = xfs_mod_frextents(mp, -((int64_t)extsz));
4164 -((int64_t)extsz), 0);
4165 } else { 4136 } else {
4166 error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, 4137 error = xfs_mod_fdblocks(mp, -((int64_t)alen), false);
4167 -((int64_t)alen), 0);
4168 } 4138 }
4169 4139
4170 if (error) 4140 if (error)
4171 goto out_unreserve_quota; 4141 goto out_unreserve_quota;
4172 4142
4173 error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, 4143 error = xfs_mod_fdblocks(mp, -((int64_t)indlen), false);
4174 -((int64_t)indlen), 0);
4175 if (error) 4144 if (error)
4176 goto out_unreserve_blocks; 4145 goto out_unreserve_blocks;
4177 4146
@@ -4198,9 +4167,9 @@ xfs_bmapi_reserve_delalloc(
4198 4167
4199out_unreserve_blocks: 4168out_unreserve_blocks:
4200 if (rt) 4169 if (rt)
4201 xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, extsz, 0); 4170 xfs_mod_frextents(mp, extsz);
4202 else 4171 else
4203 xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, alen, 0); 4172 xfs_mod_fdblocks(mp, alen, false);
4204out_unreserve_quota: 4173out_unreserve_quota:
4205 if (XFS_IS_QUOTA_ON(mp)) 4174 if (XFS_IS_QUOTA_ON(mp))
4206 xfs_trans_unreserve_quota_nblks(NULL, ip, (long)alen, 0, rt ? 4175 xfs_trans_unreserve_quota_nblks(NULL, ip, (long)alen, 0, rt ?
@@ -4801,7 +4770,7 @@ xfs_bmap_del_extent(
4801 got.br_startblock, got.br_blockcount, 4770 got.br_startblock, got.br_blockcount,
4802 &i))) 4771 &i)))
4803 goto done; 4772 goto done;
4804 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 4773 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
4805 } 4774 }
4806 da_old = da_new = 0; 4775 da_old = da_new = 0;
4807 } else { 4776 } else {
@@ -4835,7 +4804,7 @@ xfs_bmap_del_extent(
4835 } 4804 }
4836 if ((error = xfs_btree_delete(cur, &i))) 4805 if ((error = xfs_btree_delete(cur, &i)))
4837 goto done; 4806 goto done;
4838 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 4807 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
4839 break; 4808 break;
4840 4809
4841 case 2: 4810 case 2:
@@ -4935,7 +4904,8 @@ xfs_bmap_del_extent(
4935 got.br_startblock, 4904 got.br_startblock,
4936 temp, &i))) 4905 temp, &i)))
4937 goto done; 4906 goto done;
4938 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 4907 XFS_WANT_CORRUPTED_GOTO(mp,
4908 i == 1, done);
4939 /* 4909 /*
4940 * Update the btree record back 4910 * Update the btree record back
4941 * to the original value. 4911 * to the original value.
@@ -4956,7 +4926,7 @@ xfs_bmap_del_extent(
4956 error = -ENOSPC; 4926 error = -ENOSPC;
4957 goto done; 4927 goto done;
4958 } 4928 }
4959 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 4929 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
4960 } else 4930 } else
4961 flags |= xfs_ilog_fext(whichfork); 4931 flags |= xfs_ilog_fext(whichfork);
4962 XFS_IFORK_NEXT_SET(ip, whichfork, 4932 XFS_IFORK_NEXT_SET(ip, whichfork,
@@ -5012,10 +4982,8 @@ xfs_bmap_del_extent(
5012 * Nothing to do for disk quota accounting here. 4982 * Nothing to do for disk quota accounting here.
5013 */ 4983 */
5014 ASSERT(da_old >= da_new); 4984 ASSERT(da_old >= da_new);
5015 if (da_old > da_new) { 4985 if (da_old > da_new)
5016 xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, 4986 xfs_mod_fdblocks(mp, (int64_t)(da_old - da_new), false);
5017 (int64_t)(da_old - da_new), 0);
5018 }
5019done: 4987done:
5020 *logflagsp = flags; 4988 *logflagsp = flags;
5021 return error; 4989 return error;
@@ -5284,14 +5252,13 @@ xfs_bunmapi(
5284 5252
5285 rtexts = XFS_FSB_TO_B(mp, del.br_blockcount); 5253 rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
5286 do_div(rtexts, mp->m_sb.sb_rextsize); 5254 do_div(rtexts, mp->m_sb.sb_rextsize);
5287 xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, 5255 xfs_mod_frextents(mp, (int64_t)rtexts);
5288 (int64_t)rtexts, 0);
5289 (void)xfs_trans_reserve_quota_nblks(NULL, 5256 (void)xfs_trans_reserve_quota_nblks(NULL,
5290 ip, -((long)del.br_blockcount), 0, 5257 ip, -((long)del.br_blockcount), 0,
5291 XFS_QMOPT_RES_RTBLKS); 5258 XFS_QMOPT_RES_RTBLKS);
5292 } else { 5259 } else {
5293 xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, 5260 xfs_mod_fdblocks(mp, (int64_t)del.br_blockcount,
5294 (int64_t)del.br_blockcount, 0); 5261 false);
5295 (void)xfs_trans_reserve_quota_nblks(NULL, 5262 (void)xfs_trans_reserve_quota_nblks(NULL,
5296 ip, -((long)del.br_blockcount), 0, 5263 ip, -((long)del.br_blockcount), 0,
5297 XFS_QMOPT_RES_REGBLKS); 5264 XFS_QMOPT_RES_REGBLKS);
@@ -5453,6 +5420,7 @@ xfs_bmse_merge(
5453 struct xfs_bmbt_irec left; 5420 struct xfs_bmbt_irec left;
5454 xfs_filblks_t blockcount; 5421 xfs_filblks_t blockcount;
5455 int error, i; 5422 int error, i;
5423 struct xfs_mount *mp = ip->i_mount;
5456 5424
5457 xfs_bmbt_get_all(gotp, &got); 5425 xfs_bmbt_get_all(gotp, &got);
5458 xfs_bmbt_get_all(leftp, &left); 5426 xfs_bmbt_get_all(leftp, &left);
@@ -5487,19 +5455,19 @@ xfs_bmse_merge(
5487 got.br_blockcount, &i); 5455 got.br_blockcount, &i);
5488 if (error) 5456 if (error)
5489 return error; 5457 return error;
5490 XFS_WANT_CORRUPTED_RETURN(i == 1); 5458 XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
5491 5459
5492 error = xfs_btree_delete(cur, &i); 5460 error = xfs_btree_delete(cur, &i);
5493 if (error) 5461 if (error)
5494 return error; 5462 return error;
5495 XFS_WANT_CORRUPTED_RETURN(i == 1); 5463 XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
5496 5464
5497 /* lookup and update size of the previous extent */ 5465 /* lookup and update size of the previous extent */
5498 error = xfs_bmbt_lookup_eq(cur, left.br_startoff, left.br_startblock, 5466 error = xfs_bmbt_lookup_eq(cur, left.br_startoff, left.br_startblock,
5499 left.br_blockcount, &i); 5467 left.br_blockcount, &i);
5500 if (error) 5468 if (error)
5501 return error; 5469 return error;
5502 XFS_WANT_CORRUPTED_RETURN(i == 1); 5470 XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
5503 5471
5504 left.br_blockcount = blockcount; 5472 left.br_blockcount = blockcount;
5505 5473
@@ -5518,50 +5486,92 @@ xfs_bmse_shift_one(
5518 int *current_ext, 5486 int *current_ext,
5519 struct xfs_bmbt_rec_host *gotp, 5487 struct xfs_bmbt_rec_host *gotp,
5520 struct xfs_btree_cur *cur, 5488 struct xfs_btree_cur *cur,
5521 int *logflags) 5489 int *logflags,
5490 enum shift_direction direction)
5522{ 5491{
5523 struct xfs_ifork *ifp; 5492 struct xfs_ifork *ifp;
5493 struct xfs_mount *mp;
5524 xfs_fileoff_t startoff; 5494 xfs_fileoff_t startoff;
5525 struct xfs_bmbt_rec_host *leftp; 5495 struct xfs_bmbt_rec_host *adj_irecp;
5526 struct xfs_bmbt_irec got; 5496 struct xfs_bmbt_irec got;
5527 struct xfs_bmbt_irec left; 5497 struct xfs_bmbt_irec adj_irec;
5528 int error; 5498 int error;
5529 int i; 5499 int i;
5500 int total_extents;
5530 5501
5502 mp = ip->i_mount;
5531 ifp = XFS_IFORK_PTR(ip, whichfork); 5503 ifp = XFS_IFORK_PTR(ip, whichfork);
5504 total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
5532 5505
5533 xfs_bmbt_get_all(gotp, &got); 5506 xfs_bmbt_get_all(gotp, &got);
5534 startoff = got.br_startoff - offset_shift_fsb;
5535 5507
5536 /* delalloc extents should be prevented by caller */ 5508 /* delalloc extents should be prevented by caller */
5537 XFS_WANT_CORRUPTED_RETURN(!isnullstartblock(got.br_startblock)); 5509 XFS_WANT_CORRUPTED_RETURN(mp, !isnullstartblock(got.br_startblock));
5538 5510
5539 /* 5511 if (direction == SHIFT_LEFT) {
5540 * Check for merge if we've got an extent to the left, otherwise make 5512 startoff = got.br_startoff - offset_shift_fsb;
5541 * sure there's enough room at the start of the file for the shift. 5513
5542 */ 5514 /*
5543 if (*current_ext) { 5515 * Check for merge if we've got an extent to the left,
5544 /* grab the left extent and check for a large enough hole */ 5516 * otherwise make sure there's enough room at the start
5545 leftp = xfs_iext_get_ext(ifp, *current_ext - 1); 5517 * of the file for the shift.
5546 xfs_bmbt_get_all(leftp, &left); 5518 */
5519 if (!*current_ext) {
5520 if (got.br_startoff < offset_shift_fsb)
5521 return -EINVAL;
5522 goto update_current_ext;
5523 }
5524 /*
5525 * grab the left extent and check for a large
5526 * enough hole.
5527 */
5528 adj_irecp = xfs_iext_get_ext(ifp, *current_ext - 1);
5529 xfs_bmbt_get_all(adj_irecp, &adj_irec);
5547 5530
5548 if (startoff < left.br_startoff + left.br_blockcount) 5531 if (startoff <
5532 adj_irec.br_startoff + adj_irec.br_blockcount)
5549 return -EINVAL; 5533 return -EINVAL;
5550 5534
5551 /* check whether to merge the extent or shift it down */ 5535 /* check whether to merge the extent or shift it down */
5552 if (xfs_bmse_can_merge(&left, &got, offset_shift_fsb)) { 5536 if (xfs_bmse_can_merge(&adj_irec, &got,
5537 offset_shift_fsb)) {
5553 return xfs_bmse_merge(ip, whichfork, offset_shift_fsb, 5538 return xfs_bmse_merge(ip, whichfork, offset_shift_fsb,
5554 *current_ext, gotp, leftp, cur, 5539 *current_ext, gotp, adj_irecp,
5555 logflags); 5540 cur, logflags);
5556 } 5541 }
5557 } else if (got.br_startoff < offset_shift_fsb) 5542 } else {
5558 return -EINVAL; 5543 startoff = got.br_startoff + offset_shift_fsb;
5559 5544 /* nothing to move if this is the last extent */
5545 if (*current_ext >= (total_extents - 1))
5546 goto update_current_ext;
5547 /*
5548 * If this is not the last extent in the file, make sure there
5549 * is enough room between current extent and next extent for
5550 * accommodating the shift.
5551 */
5552 adj_irecp = xfs_iext_get_ext(ifp, *current_ext + 1);
5553 xfs_bmbt_get_all(adj_irecp, &adj_irec);
5554 if (startoff + got.br_blockcount > adj_irec.br_startoff)
5555 return -EINVAL;
5556 /*
5557 * Unlike a left shift (which involves a hole punch),
5558 * a right shift does not modify extent neighbors
5559 * in any way. We should never find mergeable extents
5560 * in this scenario. Check anyways and warn if we
5561 * encounter two extents that could be one.
5562 */
5563 if (xfs_bmse_can_merge(&got, &adj_irec, offset_shift_fsb))
5564 WARN_ON_ONCE(1);
5565 }
5560 /* 5566 /*
5561 * Increment the extent index for the next iteration, update the start 5567 * Increment the extent index for the next iteration, update the start
5562 * offset of the in-core extent and update the btree if applicable. 5568 * offset of the in-core extent and update the btree if applicable.
5563 */ 5569 */
5564 (*current_ext)++; 5570update_current_ext:
5571 if (direction == SHIFT_LEFT)
5572 (*current_ext)++;
5573 else
5574 (*current_ext)--;
5565 xfs_bmbt_set_startoff(gotp, startoff); 5575 xfs_bmbt_set_startoff(gotp, startoff);
5566 *logflags |= XFS_ILOG_CORE; 5576 *logflags |= XFS_ILOG_CORE;
5567 if (!cur) { 5577 if (!cur) {
@@ -5573,18 +5583,18 @@ xfs_bmse_shift_one(
5573 got.br_blockcount, &i); 5583 got.br_blockcount, &i);
5574 if (error) 5584 if (error)
5575 return error; 5585 return error;
5576 XFS_WANT_CORRUPTED_RETURN(i == 1); 5586 XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
5577 5587
5578 got.br_startoff = startoff; 5588 got.br_startoff = startoff;
5579 return xfs_bmbt_update(cur, got.br_startoff, got.br_startblock, 5589 return xfs_bmbt_update(cur, got.br_startoff, got.br_startblock,
5580 got.br_blockcount, got.br_state); 5590 got.br_blockcount, got.br_state);
5581} 5591}
5582 5592
5583/* 5593/*
5584 * Shift extent records to the left to cover a hole. 5594 * Shift extent records to the left/right to cover/create a hole.
5585 * 5595 *
5586 * The maximum number of extents to be shifted in a single operation is 5596 * The maximum number of extents to be shifted in a single operation is
5587 * @num_exts. @start_fsb specifies the file offset to start the shift and the 5597 * @num_exts. @stop_fsb specifies the file offset at which to stop shift and the
5588 * file offset where we've left off is returned in @next_fsb. @offset_shift_fsb 5598 * file offset where we've left off is returned in @next_fsb. @offset_shift_fsb
5589 * is the length by which each extent is shifted. If there is no hole to shift 5599 * is the length by which each extent is shifted. If there is no hole to shift
5590 * the extents into, this will be considered invalid operation and we abort 5600 * the extents into, this will be considered invalid operation and we abort
@@ -5594,12 +5604,13 @@ int
5594xfs_bmap_shift_extents( 5604xfs_bmap_shift_extents(
5595 struct xfs_trans *tp, 5605 struct xfs_trans *tp,
5596 struct xfs_inode *ip, 5606 struct xfs_inode *ip,
5597 xfs_fileoff_t start_fsb, 5607 xfs_fileoff_t *next_fsb,
5598 xfs_fileoff_t offset_shift_fsb, 5608 xfs_fileoff_t offset_shift_fsb,
5599 int *done, 5609 int *done,
5600 xfs_fileoff_t *next_fsb, 5610 xfs_fileoff_t stop_fsb,
5601 xfs_fsblock_t *firstblock, 5611 xfs_fsblock_t *firstblock,
5602 struct xfs_bmap_free *flist, 5612 struct xfs_bmap_free *flist,
5613 enum shift_direction direction,
5603 int num_exts) 5614 int num_exts)
5604{ 5615{
5605 struct xfs_btree_cur *cur = NULL; 5616 struct xfs_btree_cur *cur = NULL;
@@ -5609,10 +5620,11 @@ xfs_bmap_shift_extents(
5609 struct xfs_ifork *ifp; 5620 struct xfs_ifork *ifp;
5610 xfs_extnum_t nexts = 0; 5621 xfs_extnum_t nexts = 0;
5611 xfs_extnum_t current_ext; 5622 xfs_extnum_t current_ext;
5623 xfs_extnum_t total_extents;
5624 xfs_extnum_t stop_extent;
5612 int error = 0; 5625 int error = 0;
5613 int whichfork = XFS_DATA_FORK; 5626 int whichfork = XFS_DATA_FORK;
5614 int logflags = 0; 5627 int logflags = 0;
5615 int total_extents;
5616 5628
5617 if (unlikely(XFS_TEST_ERROR( 5629 if (unlikely(XFS_TEST_ERROR(
5618 (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && 5630 (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
@@ -5628,6 +5640,8 @@ xfs_bmap_shift_extents(
5628 5640
5629 ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); 5641 ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
5630 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 5642 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
5643 ASSERT(direction == SHIFT_LEFT || direction == SHIFT_RIGHT);
5644 ASSERT(*next_fsb != NULLFSBLOCK || direction == SHIFT_RIGHT);
5631 5645
5632 ifp = XFS_IFORK_PTR(ip, whichfork); 5646 ifp = XFS_IFORK_PTR(ip, whichfork);
5633 if (!(ifp->if_flags & XFS_IFEXTENTS)) { 5647 if (!(ifp->if_flags & XFS_IFEXTENTS)) {
@@ -5645,43 +5659,83 @@ xfs_bmap_shift_extents(
5645 } 5659 }
5646 5660
5647 /* 5661 /*
5662 * There may be delalloc extents in the data fork before the range we
5663 * are collapsing out, so we cannot use the count of real extents here.
5664 * Instead we have to calculate it from the incore fork.
5665 */
5666 total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
5667 if (total_extents == 0) {
5668 *done = 1;
5669 goto del_cursor;
5670 }
5671
5672 /*
5673 * In case of first right shift, we need to initialize next_fsb
5674 */
5675 if (*next_fsb == NULLFSBLOCK) {
5676 gotp = xfs_iext_get_ext(ifp, total_extents - 1);
5677 xfs_bmbt_get_all(gotp, &got);
5678 *next_fsb = got.br_startoff;
5679 if (stop_fsb > *next_fsb) {
5680 *done = 1;
5681 goto del_cursor;
5682 }
5683 }
5684
5685 /* Lookup the extent index at which we have to stop */
5686 if (direction == SHIFT_RIGHT) {
5687 gotp = xfs_iext_bno_to_ext(ifp, stop_fsb, &stop_extent);
5688 /* Make stop_extent exclusive of shift range */
5689 stop_extent--;
5690 } else
5691 stop_extent = total_extents;
5692
5693 /*
5648 * Look up the extent index for the fsb where we start shifting. We can 5694 * Look up the extent index for the fsb where we start shifting. We can
5649 * henceforth iterate with current_ext as extent list changes are locked 5695 * henceforth iterate with current_ext as extent list changes are locked
5650 * out via ilock. 5696 * out via ilock.
5651 * 5697 *
5652 * gotp can be null in 2 cases: 1) if there are no extents or 2) 5698 * gotp can be null in 2 cases: 1) if there are no extents or 2)
5653 * start_fsb lies in a hole beyond which there are no extents. Either 5699 * *next_fsb lies in a hole beyond which there are no extents. Either
5654 * way, we are done. 5700 * way, we are done.
5655 */ 5701 */
5656 gotp = xfs_iext_bno_to_ext(ifp, start_fsb, &current_ext); 5702 gotp = xfs_iext_bno_to_ext(ifp, *next_fsb, &current_ext);
5657 if (!gotp) { 5703 if (!gotp) {
5658 *done = 1; 5704 *done = 1;
5659 goto del_cursor; 5705 goto del_cursor;
5660 } 5706 }
5661 5707
5662 /* 5708 /* some sanity checking before we finally start shifting extents */
5663 * There may be delalloc extents in the data fork before the range we 5709 if ((direction == SHIFT_LEFT && current_ext >= stop_extent) ||
5664 * are collapsing out, so we cannot use the count of real extents here. 5710 (direction == SHIFT_RIGHT && current_ext <= stop_extent)) {
5665 * Instead we have to calculate it from the incore fork. 5711 error = -EIO;
5666 */ 5712 goto del_cursor;
5667 total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); 5713 }
5668 while (nexts++ < num_exts && current_ext < total_extents) { 5714
5715 while (nexts++ < num_exts) {
5669 error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb, 5716 error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb,
5670 &current_ext, gotp, cur, &logflags); 5717 &current_ext, gotp, cur, &logflags,
5718 direction);
5671 if (error) 5719 if (error)
5672 goto del_cursor; 5720 goto del_cursor;
5721 /*
5722 * If there was an extent merge during the shift, the extent
5723 * count can change. Update the total and grade the next record.
5724 */
5725 if (direction == SHIFT_LEFT) {
5726 total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
5727 stop_extent = total_extents;
5728 }
5673 5729
5674 /* update total extent count and grab the next record */ 5730 if (current_ext == stop_extent) {
5675 total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); 5731 *done = 1;
5676 if (current_ext >= total_extents) 5732 *next_fsb = NULLFSBLOCK;
5677 break; 5733 break;
5734 }
5678 gotp = xfs_iext_get_ext(ifp, current_ext); 5735 gotp = xfs_iext_get_ext(ifp, current_ext);
5679 } 5736 }
5680 5737
5681 /* Check if we are done */ 5738 if (!*done) {
5682 if (current_ext == total_extents) {
5683 *done = 1;
5684 } else if (next_fsb) {
5685 xfs_bmbt_get_all(gotp, &got); 5739 xfs_bmbt_get_all(gotp, &got);
5686 *next_fsb = got.br_startoff; 5740 *next_fsb = got.br_startoff;
5687 } 5741 }
@@ -5696,3 +5750,189 @@ del_cursor:
5696 5750
5697 return error; 5751 return error;
5698} 5752}
5753
5754/*
5755 * Splits an extent into two extents at split_fsb block such that it is
5756 * the first block of the current_ext. @current_ext is a target extent
5757 * to be split. @split_fsb is a block where the extents is split.
5758 * If split_fsb lies in a hole or the first block of extents, just return 0.
5759 */
5760STATIC int
5761xfs_bmap_split_extent_at(
5762 struct xfs_trans *tp,
5763 struct xfs_inode *ip,
5764 xfs_fileoff_t split_fsb,
5765 xfs_fsblock_t *firstfsb,
5766 struct xfs_bmap_free *free_list)
5767{
5768 int whichfork = XFS_DATA_FORK;
5769 struct xfs_btree_cur *cur = NULL;
5770 struct xfs_bmbt_rec_host *gotp;
5771 struct xfs_bmbt_irec got;
5772 struct xfs_bmbt_irec new; /* split extent */
5773 struct xfs_mount *mp = ip->i_mount;
5774 struct xfs_ifork *ifp;
5775 xfs_fsblock_t gotblkcnt; /* new block count for got */
5776 xfs_extnum_t current_ext;
5777 int error = 0;
5778 int logflags = 0;
5779 int i = 0;
5780
5781 if (unlikely(XFS_TEST_ERROR(
5782 (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
5783 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
5784 mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
5785 XFS_ERROR_REPORT("xfs_bmap_split_extent_at",
5786 XFS_ERRLEVEL_LOW, mp);
5787 return -EFSCORRUPTED;
5788 }
5789
5790 if (XFS_FORCED_SHUTDOWN(mp))
5791 return -EIO;
5792
5793 ifp = XFS_IFORK_PTR(ip, whichfork);
5794 if (!(ifp->if_flags & XFS_IFEXTENTS)) {
5795 /* Read in all the extents */
5796 error = xfs_iread_extents(tp, ip, whichfork);
5797 if (error)
5798 return error;
5799 }
5800
5801 /*
5802 * gotp can be null in 2 cases: 1) if there are no extents
5803 * or 2) split_fsb lies in a hole beyond which there are
5804 * no extents. Either way, we are done.
5805 */
5806 gotp = xfs_iext_bno_to_ext(ifp, split_fsb, &current_ext);
5807 if (!gotp)
5808 return 0;
5809
5810 xfs_bmbt_get_all(gotp, &got);
5811
5812 /*
5813 * Check split_fsb lies in a hole or the start boundary offset
5814 * of the extent.
5815 */
5816 if (got.br_startoff >= split_fsb)
5817 return 0;
5818
5819 gotblkcnt = split_fsb - got.br_startoff;
5820 new.br_startoff = split_fsb;
5821 new.br_startblock = got.br_startblock + gotblkcnt;
5822 new.br_blockcount = got.br_blockcount - gotblkcnt;
5823 new.br_state = got.br_state;
5824
5825 if (ifp->if_flags & XFS_IFBROOT) {
5826 cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
5827 cur->bc_private.b.firstblock = *firstfsb;
5828 cur->bc_private.b.flist = free_list;
5829 cur->bc_private.b.flags = 0;
5830 error = xfs_bmbt_lookup_eq(cur, got.br_startoff,
5831 got.br_startblock,
5832 got.br_blockcount,
5833 &i);
5834 if (error)
5835 goto del_cursor;
5836 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, del_cursor);
5837 }
5838
5839 xfs_bmbt_set_blockcount(gotp, gotblkcnt);
5840 got.br_blockcount = gotblkcnt;
5841
5842 logflags = XFS_ILOG_CORE;
5843 if (cur) {
5844 error = xfs_bmbt_update(cur, got.br_startoff,
5845 got.br_startblock,
5846 got.br_blockcount,
5847 got.br_state);
5848 if (error)
5849 goto del_cursor;
5850 } else
5851 logflags |= XFS_ILOG_DEXT;
5852
5853 /* Add new extent */
5854 current_ext++;
5855 xfs_iext_insert(ip, current_ext, 1, &new, 0);
5856 XFS_IFORK_NEXT_SET(ip, whichfork,
5857 XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
5858
5859 if (cur) {
5860 error = xfs_bmbt_lookup_eq(cur, new.br_startoff,
5861 new.br_startblock, new.br_blockcount,
5862 &i);
5863 if (error)
5864 goto del_cursor;
5865 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, del_cursor);
5866 cur->bc_rec.b.br_state = new.br_state;
5867
5868 error = xfs_btree_insert(cur, &i);
5869 if (error)
5870 goto del_cursor;
5871 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, del_cursor);
5872 }
5873
5874 /*
5875 * Convert to a btree if necessary.
5876 */
5877 if (xfs_bmap_needs_btree(ip, whichfork)) {
5878 int tmp_logflags; /* partial log flag return val */
5879
5880 ASSERT(cur == NULL);
5881 error = xfs_bmap_extents_to_btree(tp, ip, firstfsb, free_list,
5882 &cur, 0, &tmp_logflags, whichfork);
5883 logflags |= tmp_logflags;
5884 }
5885
5886del_cursor:
5887 if (cur) {
5888 cur->bc_private.b.allocated = 0;
5889 xfs_btree_del_cursor(cur,
5890 error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
5891 }
5892
5893 if (logflags)
5894 xfs_trans_log_inode(tp, ip, logflags);
5895 return error;
5896}
5897
5898int
5899xfs_bmap_split_extent(
5900 struct xfs_inode *ip,
5901 xfs_fileoff_t split_fsb)
5902{
5903 struct xfs_mount *mp = ip->i_mount;
5904 struct xfs_trans *tp;
5905 struct xfs_bmap_free free_list;
5906 xfs_fsblock_t firstfsb;
5907 int committed;
5908 int error;
5909
5910 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
5911 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write,
5912 XFS_DIOSTRAT_SPACE_RES(mp, 0), 0);
5913 if (error) {
5914 xfs_trans_cancel(tp, 0);
5915 return error;
5916 }
5917
5918 xfs_ilock(ip, XFS_ILOCK_EXCL);
5919 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
5920
5921 xfs_bmap_init(&free_list, &firstfsb);
5922
5923 error = xfs_bmap_split_extent_at(tp, ip, split_fsb,
5924 &firstfsb, &free_list);
5925 if (error)
5926 goto out;
5927
5928 error = xfs_bmap_finish(&tp, &free_list, &committed);
5929 if (error)
5930 goto out;
5931
5932 return xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
5933
5934
5935out:
5936 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
5937 return error;
5938}