|
@@ -244,30 +244,6 @@ xfs_bmap_forkoff_reset(
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Debug/sanity checking code
|
|
|
- */
|
|
|
-
|
|
|
-STATIC int
|
|
|
-xfs_bmap_sanity_check(
|
|
|
- struct xfs_mount *mp,
|
|
|
- struct xfs_buf *bp,
|
|
|
- int level)
|
|
|
-{
|
|
|
- struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
|
|
|
-
|
|
|
- if (block->bb_magic != cpu_to_be32(XFS_BMAP_CRC_MAGIC) &&
|
|
|
- block->bb_magic != cpu_to_be32(XFS_BMAP_MAGIC))
|
|
|
- return 0;
|
|
|
-
|
|
|
- if (be16_to_cpu(block->bb_level) != level ||
|
|
|
- be16_to_cpu(block->bb_numrecs) == 0 ||
|
|
|
- be16_to_cpu(block->bb_numrecs) > mp->m_bmap_dmxr[level != 0])
|
|
|
- return 0;
|
|
|
-
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
#ifdef DEBUG
|
|
|
STATIC struct xfs_buf *
|
|
|
xfs_bmap_get_bp(
|
|
@@ -410,9 +386,6 @@ xfs_bmap_check_leaf_extents(
|
|
|
goto error_norelse;
|
|
|
}
|
|
|
block = XFS_BUF_TO_BLOCK(bp);
|
|
|
- XFS_WANT_CORRUPTED_GOTO(
|
|
|
- xfs_bmap_sanity_check(mp, bp, level),
|
|
|
- error0);
|
|
|
if (level == 0)
|
|
|
break;
|
|
|
|
|
@@ -424,7 +397,8 @@ xfs_bmap_check_leaf_extents(
|
|
|
xfs_check_block(block, mp, 0, 0);
|
|
|
pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
|
|
|
bno = be64_to_cpu(*pp);
|
|
|
- XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp,
|
|
|
+ XFS_FSB_SANITY_CHECK(mp, bno), error0);
|
|
|
if (bp_release) {
|
|
|
bp_release = 0;
|
|
|
xfs_trans_brelse(NULL, bp);
|
|
@@ -1029,7 +1003,7 @@ xfs_bmap_add_attrfork_btree(
|
|
|
if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat)))
|
|
|
goto error0;
|
|
|
/* must be at least one entry */
|
|
|
- XFS_WANT_CORRUPTED_GOTO(stat == 1, error0);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, stat == 1, error0);
|
|
|
if ((error = xfs_btree_new_iroot(cur, flags, &stat)))
|
|
|
goto error0;
|
|
|
if (stat == 0) {
|
|
@@ -1311,14 +1285,12 @@ xfs_bmap_read_extents(
|
|
|
if (error)
|
|
|
return error;
|
|
|
block = XFS_BUF_TO_BLOCK(bp);
|
|
|
- XFS_WANT_CORRUPTED_GOTO(
|
|
|
- xfs_bmap_sanity_check(mp, bp, level),
|
|
|
- error0);
|
|
|
if (level == 0)
|
|
|
break;
|
|
|
pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
|
|
|
bno = be64_to_cpu(*pp);
|
|
|
- XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp,
|
|
|
+ XFS_FSB_SANITY_CHECK(mp, bno), error0);
|
|
|
xfs_trans_brelse(tp, bp);
|
|
|
}
|
|
|
/*
|
|
@@ -1345,9 +1317,6 @@ xfs_bmap_read_extents(
|
|
|
XFS_ERRLEVEL_LOW, ip->i_mount, block);
|
|
|
goto error0;
|
|
|
}
|
|
|
- XFS_WANT_CORRUPTED_GOTO(
|
|
|
- xfs_bmap_sanity_check(mp, bp, 0),
|
|
|
- error0);
|
|
|
/*
|
|
|
* Read-ahead the next leaf block, if any.
|
|
|
*/
|
|
@@ -1755,7 +1724,9 @@ xfs_bmap_add_extent_delay_real(
|
|
|
xfs_filblks_t temp=0; /* value for da_new calculations */
|
|
|
xfs_filblks_t temp2=0;/* value for da_new calculations */
|
|
|
int tmp_rval; /* partial logging flags */
|
|
|
+ struct xfs_mount *mp;
|
|
|
|
|
|
+ mp = bma->tp ? bma->tp->t_mountp : NULL;
|
|
|
ifp = XFS_IFORK_PTR(bma->ip, XFS_DATA_FORK);
|
|
|
|
|
|
ASSERT(bma->idx >= 0);
|
|
@@ -1866,15 +1837,15 @@ xfs_bmap_add_extent_delay_real(
|
|
|
RIGHT.br_blockcount, &i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
error = xfs_btree_delete(bma->cur, &i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
error = xfs_btree_decrement(bma->cur, 0, &i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
error = xfs_bmbt_update(bma->cur, LEFT.br_startoff,
|
|
|
LEFT.br_startblock,
|
|
|
LEFT.br_blockcount +
|
|
@@ -1907,7 +1878,7 @@ xfs_bmap_add_extent_delay_real(
|
|
|
&i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
error = xfs_bmbt_update(bma->cur, LEFT.br_startoff,
|
|
|
LEFT.br_startblock,
|
|
|
LEFT.br_blockcount +
|
|
@@ -1938,7 +1909,7 @@ xfs_bmap_add_extent_delay_real(
|
|
|
RIGHT.br_blockcount, &i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
error = xfs_bmbt_update(bma->cur, PREV.br_startoff,
|
|
|
new->br_startblock,
|
|
|
PREV.br_blockcount +
|
|
@@ -1968,12 +1939,12 @@ xfs_bmap_add_extent_delay_real(
|
|
|
&i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 0, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
|
|
|
bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
|
|
|
error = xfs_btree_insert(bma->cur, &i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
}
|
|
|
break;
|
|
|
|
|
@@ -2001,7 +1972,7 @@ xfs_bmap_add_extent_delay_real(
|
|
|
&i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
error = xfs_bmbt_update(bma->cur, LEFT.br_startoff,
|
|
|
LEFT.br_startblock,
|
|
|
LEFT.br_blockcount +
|
|
@@ -2038,12 +2009,12 @@ xfs_bmap_add_extent_delay_real(
|
|
|
&i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 0, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
|
|
|
bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
|
|
|
error = xfs_btree_insert(bma->cur, &i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
}
|
|
|
|
|
|
if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
|
|
@@ -2084,7 +2055,7 @@ xfs_bmap_add_extent_delay_real(
|
|
|
RIGHT.br_blockcount, &i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
error = xfs_bmbt_update(bma->cur, new->br_startoff,
|
|
|
new->br_startblock,
|
|
|
new->br_blockcount +
|
|
@@ -2122,12 +2093,12 @@ xfs_bmap_add_extent_delay_real(
|
|
|
&i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 0, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
|
|
|
bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
|
|
|
error = xfs_btree_insert(bma->cur, &i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
}
|
|
|
|
|
|
if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
|
|
@@ -2191,12 +2162,12 @@ xfs_bmap_add_extent_delay_real(
|
|
|
&i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 0, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
|
|
|
bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
|
|
|
error = xfs_btree_insert(bma->cur, &i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
}
|
|
|
|
|
|
if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
|
|
@@ -2212,9 +2183,8 @@ xfs_bmap_add_extent_delay_real(
|
|
|
diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) -
|
|
|
(bma->cur ? bma->cur->bc_private.b.allocated : 0));
|
|
|
if (diff > 0) {
|
|
|
- error = xfs_icsb_modify_counters(bma->ip->i_mount,
|
|
|
- XFS_SBS_FDBLOCKS,
|
|
|
- -((int64_t)diff), 0);
|
|
|
+ error = xfs_mod_fdblocks(bma->ip->i_mount,
|
|
|
+ -((int64_t)diff), false);
|
|
|
ASSERT(!error);
|
|
|
if (error)
|
|
|
goto done;
|
|
@@ -2265,9 +2235,8 @@ xfs_bmap_add_extent_delay_real(
|
|
|
temp += bma->cur->bc_private.b.allocated;
|
|
|
ASSERT(temp <= da_old);
|
|
|
if (temp < da_old)
|
|
|
- xfs_icsb_modify_counters(bma->ip->i_mount,
|
|
|
- XFS_SBS_FDBLOCKS,
|
|
|
- (int64_t)(da_old - temp), 0);
|
|
|
+ xfs_mod_fdblocks(bma->ip->i_mount,
|
|
|
+ (int64_t)(da_old - temp), false);
|
|
|
}
|
|
|
|
|
|
/* clear out the allocated field, done with it now in any case. */
|
|
@@ -2309,6 +2278,7 @@ xfs_bmap_add_extent_unwritten_real(
|
|
|
/* left is 0, right is 1, prev is 2 */
|
|
|
int rval=0; /* return value (logging flags) */
|
|
|
int state = 0;/* state bits, accessed thru macros */
|
|
|
+ struct xfs_mount *mp = tp->t_mountp;
|
|
|
|
|
|
*logflagsp = 0;
|
|
|
|
|
@@ -2421,19 +2391,19 @@ xfs_bmap_add_extent_unwritten_real(
|
|
|
RIGHT.br_startblock,
|
|
|
RIGHT.br_blockcount, &i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
if ((error = xfs_btree_delete(cur, &i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
if ((error = xfs_btree_decrement(cur, 0, &i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
if ((error = xfs_btree_delete(cur, &i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
if ((error = xfs_btree_decrement(cur, 0, &i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
|
|
|
LEFT.br_startblock,
|
|
|
LEFT.br_blockcount + PREV.br_blockcount +
|
|
@@ -2464,13 +2434,13 @@ xfs_bmap_add_extent_unwritten_real(
|
|
|
PREV.br_startblock, PREV.br_blockcount,
|
|
|
&i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
if ((error = xfs_btree_delete(cur, &i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
if ((error = xfs_btree_decrement(cur, 0, &i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
|
|
|
LEFT.br_startblock,
|
|
|
LEFT.br_blockcount + PREV.br_blockcount,
|
|
@@ -2499,13 +2469,13 @@ xfs_bmap_add_extent_unwritten_real(
|
|
|
RIGHT.br_startblock,
|
|
|
RIGHT.br_blockcount, &i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
if ((error = xfs_btree_delete(cur, &i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
if ((error = xfs_btree_decrement(cur, 0, &i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
if ((error = xfs_bmbt_update(cur, new->br_startoff,
|
|
|
new->br_startblock,
|
|
|
new->br_blockcount + RIGHT.br_blockcount,
|
|
@@ -2532,7 +2502,7 @@ xfs_bmap_add_extent_unwritten_real(
|
|
|
new->br_startblock, new->br_blockcount,
|
|
|
&i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
if ((error = xfs_bmbt_update(cur, new->br_startoff,
|
|
|
new->br_startblock, new->br_blockcount,
|
|
|
newext)))
|
|
@@ -2569,7 +2539,7 @@ xfs_bmap_add_extent_unwritten_real(
|
|
|
PREV.br_startblock, PREV.br_blockcount,
|
|
|
&i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
if ((error = xfs_bmbt_update(cur,
|
|
|
PREV.br_startoff + new->br_blockcount,
|
|
|
PREV.br_startblock + new->br_blockcount,
|
|
@@ -2611,7 +2581,7 @@ xfs_bmap_add_extent_unwritten_real(
|
|
|
PREV.br_startblock, PREV.br_blockcount,
|
|
|
&i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
if ((error = xfs_bmbt_update(cur,
|
|
|
PREV.br_startoff + new->br_blockcount,
|
|
|
PREV.br_startblock + new->br_blockcount,
|
|
@@ -2621,7 +2591,7 @@ xfs_bmap_add_extent_unwritten_real(
|
|
|
cur->bc_rec.b = *new;
|
|
|
if ((error = xfs_btree_insert(cur, &i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
}
|
|
|
break;
|
|
|
|
|
@@ -2651,7 +2621,7 @@ xfs_bmap_add_extent_unwritten_real(
|
|
|
PREV.br_startblock,
|
|
|
PREV.br_blockcount, &i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
|
|
|
PREV.br_startblock,
|
|
|
PREV.br_blockcount - new->br_blockcount,
|
|
@@ -2689,7 +2659,7 @@ xfs_bmap_add_extent_unwritten_real(
|
|
|
PREV.br_startblock, PREV.br_blockcount,
|
|
|
&i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
|
|
|
PREV.br_startblock,
|
|
|
PREV.br_blockcount - new->br_blockcount,
|
|
@@ -2699,11 +2669,11 @@ xfs_bmap_add_extent_unwritten_real(
|
|
|
new->br_startblock, new->br_blockcount,
|
|
|
&i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 0, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
|
|
|
cur->bc_rec.b.br_state = XFS_EXT_NORM;
|
|
|
if ((error = xfs_btree_insert(cur, &i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
}
|
|
|
break;
|
|
|
|
|
@@ -2737,7 +2707,7 @@ xfs_bmap_add_extent_unwritten_real(
|
|
|
PREV.br_startblock, PREV.br_blockcount,
|
|
|
&i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
/* new right extent - oldext */
|
|
|
if ((error = xfs_bmbt_update(cur, r[1].br_startoff,
|
|
|
r[1].br_startblock, r[1].br_blockcount,
|
|
@@ -2749,7 +2719,7 @@ xfs_bmap_add_extent_unwritten_real(
|
|
|
new->br_startoff - PREV.br_startoff;
|
|
|
if ((error = xfs_btree_insert(cur, &i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
/*
|
|
|
* Reset the cursor to the position of the new extent
|
|
|
* we are about to insert as we can't trust it after
|
|
@@ -2759,12 +2729,12 @@ xfs_bmap_add_extent_unwritten_real(
|
|
|
new->br_startblock, new->br_blockcount,
|
|
|
&i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 0, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
|
|
|
/* new middle extent - newext */
|
|
|
cur->bc_rec.b.br_state = new->br_state;
|
|
|
if ((error = xfs_btree_insert(cur, &i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
}
|
|
|
break;
|
|
|
|
|
@@ -2944,8 +2914,8 @@ xfs_bmap_add_extent_hole_delay(
|
|
|
}
|
|
|
if (oldlen != newlen) {
|
|
|
ASSERT(oldlen > newlen);
|
|
|
- xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS,
|
|
|
- (int64_t)(oldlen - newlen), 0);
|
|
|
+ xfs_mod_fdblocks(ip->i_mount, (int64_t)(oldlen - newlen),
|
|
|
+ false);
|
|
|
/*
|
|
|
* Nothing to do for disk quota accounting here.
|
|
|
*/
|
|
@@ -2968,7 +2938,9 @@ xfs_bmap_add_extent_hole_real(
|
|
|
xfs_bmbt_irec_t right; /* right neighbor extent entry */
|
|
|
int rval=0; /* return value (logging flags) */
|
|
|
int state; /* state bits, accessed thru macros */
|
|
|
+ struct xfs_mount *mp;
|
|
|
|
|
|
+ mp = bma->tp ? bma->tp->t_mountp : NULL;
|
|
|
ifp = XFS_IFORK_PTR(bma->ip, whichfork);
|
|
|
|
|
|
ASSERT(bma->idx >= 0);
|
|
@@ -3056,15 +3028,15 @@ xfs_bmap_add_extent_hole_real(
|
|
|
&i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
error = xfs_btree_delete(bma->cur, &i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
error = xfs_btree_decrement(bma->cur, 0, &i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
error = xfs_bmbt_update(bma->cur, left.br_startoff,
|
|
|
left.br_startblock,
|
|
|
left.br_blockcount +
|
|
@@ -3097,7 +3069,7 @@ xfs_bmap_add_extent_hole_real(
|
|
|
&i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
error = xfs_bmbt_update(bma->cur, left.br_startoff,
|
|
|
left.br_startblock,
|
|
|
left.br_blockcount +
|
|
@@ -3131,7 +3103,7 @@ xfs_bmap_add_extent_hole_real(
|
|
|
right.br_blockcount, &i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
error = xfs_bmbt_update(bma->cur, new->br_startoff,
|
|
|
new->br_startblock,
|
|
|
new->br_blockcount +
|
|
@@ -3161,12 +3133,12 @@ xfs_bmap_add_extent_hole_real(
|
|
|
new->br_blockcount, &i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 0, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
|
|
|
bma->cur->bc_rec.b.br_state = new->br_state;
|
|
|
error = xfs_btree_insert(bma->cur, &i);
|
|
|
if (error)
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
@@ -4160,18 +4132,15 @@ xfs_bmapi_reserve_delalloc(
|
|
|
ASSERT(indlen > 0);
|
|
|
|
|
|
if (rt) {
|
|
|
- error = xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
|
|
|
- -((int64_t)extsz), 0);
|
|
|
+ error = xfs_mod_frextents(mp, -((int64_t)extsz));
|
|
|
} else {
|
|
|
- error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
|
|
|
- -((int64_t)alen), 0);
|
|
|
+ error = xfs_mod_fdblocks(mp, -((int64_t)alen), false);
|
|
|
}
|
|
|
|
|
|
if (error)
|
|
|
goto out_unreserve_quota;
|
|
|
|
|
|
- error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
|
|
|
- -((int64_t)indlen), 0);
|
|
|
+ error = xfs_mod_fdblocks(mp, -((int64_t)indlen), false);
|
|
|
if (error)
|
|
|
goto out_unreserve_blocks;
|
|
|
|
|
@@ -4198,9 +4167,9 @@ xfs_bmapi_reserve_delalloc(
|
|
|
|
|
|
out_unreserve_blocks:
|
|
|
if (rt)
|
|
|
- xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, extsz, 0);
|
|
|
+ xfs_mod_frextents(mp, extsz);
|
|
|
else
|
|
|
- xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, alen, 0);
|
|
|
+ xfs_mod_fdblocks(mp, alen, false);
|
|
|
out_unreserve_quota:
|
|
|
if (XFS_IS_QUOTA_ON(mp))
|
|
|
xfs_trans_unreserve_quota_nblks(NULL, ip, (long)alen, 0, rt ?
|
|
@@ -4801,7 +4770,7 @@ xfs_bmap_del_extent(
|
|
|
got.br_startblock, got.br_blockcount,
|
|
|
&i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
}
|
|
|
da_old = da_new = 0;
|
|
|
} else {
|
|
@@ -4835,7 +4804,7 @@ xfs_bmap_del_extent(
|
|
|
}
|
|
|
if ((error = xfs_btree_delete(cur, &i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
break;
|
|
|
|
|
|
case 2:
|
|
@@ -4935,7 +4904,8 @@ xfs_bmap_del_extent(
|
|
|
got.br_startblock,
|
|
|
temp, &i)))
|
|
|
goto done;
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp,
|
|
|
+ i == 1, done);
|
|
|
/*
|
|
|
* Update the btree record back
|
|
|
* to the original value.
|
|
@@ -4956,7 +4926,7 @@ xfs_bmap_del_extent(
|
|
|
error = -ENOSPC;
|
|
|
goto done;
|
|
|
}
|
|
|
- XFS_WANT_CORRUPTED_GOTO(i == 1, done);
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
|
|
|
} else
|
|
|
flags |= xfs_ilog_fext(whichfork);
|
|
|
XFS_IFORK_NEXT_SET(ip, whichfork,
|
|
@@ -5012,10 +4982,8 @@ xfs_bmap_del_extent(
|
|
|
* Nothing to do for disk quota accounting here.
|
|
|
*/
|
|
|
ASSERT(da_old >= da_new);
|
|
|
- if (da_old > da_new) {
|
|
|
- xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
|
|
|
- (int64_t)(da_old - da_new), 0);
|
|
|
- }
|
|
|
+ if (da_old > da_new)
|
|
|
+ xfs_mod_fdblocks(mp, (int64_t)(da_old - da_new), false);
|
|
|
done:
|
|
|
*logflagsp = flags;
|
|
|
return error;
|
|
@@ -5284,14 +5252,13 @@ xfs_bunmapi(
|
|
|
|
|
|
rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
|
|
|
do_div(rtexts, mp->m_sb.sb_rextsize);
|
|
|
- xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
|
|
|
- (int64_t)rtexts, 0);
|
|
|
+ xfs_mod_frextents(mp, (int64_t)rtexts);
|
|
|
(void)xfs_trans_reserve_quota_nblks(NULL,
|
|
|
ip, -((long)del.br_blockcount), 0,
|
|
|
XFS_QMOPT_RES_RTBLKS);
|
|
|
} else {
|
|
|
- xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
|
|
|
- (int64_t)del.br_blockcount, 0);
|
|
|
+ xfs_mod_fdblocks(mp, (int64_t)del.br_blockcount,
|
|
|
+ false);
|
|
|
(void)xfs_trans_reserve_quota_nblks(NULL,
|
|
|
ip, -((long)del.br_blockcount), 0,
|
|
|
XFS_QMOPT_RES_REGBLKS);
|
|
@@ -5453,6 +5420,7 @@ xfs_bmse_merge(
|
|
|
struct xfs_bmbt_irec left;
|
|
|
xfs_filblks_t blockcount;
|
|
|
int error, i;
|
|
|
+ struct xfs_mount *mp = ip->i_mount;
|
|
|
|
|
|
xfs_bmbt_get_all(gotp, &got);
|
|
|
xfs_bmbt_get_all(leftp, &left);
|
|
@@ -5487,19 +5455,19 @@ xfs_bmse_merge(
|
|
|
got.br_blockcount, &i);
|
|
|
if (error)
|
|
|
return error;
|
|
|
- XFS_WANT_CORRUPTED_RETURN(i == 1);
|
|
|
+ XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
|
|
|
|
|
|
error = xfs_btree_delete(cur, &i);
|
|
|
if (error)
|
|
|
return error;
|
|
|
- XFS_WANT_CORRUPTED_RETURN(i == 1);
|
|
|
+ XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
|
|
|
|
|
|
/* lookup and update size of the previous extent */
|
|
|
error = xfs_bmbt_lookup_eq(cur, left.br_startoff, left.br_startblock,
|
|
|
left.br_blockcount, &i);
|
|
|
if (error)
|
|
|
return error;
|
|
|
- XFS_WANT_CORRUPTED_RETURN(i == 1);
|
|
|
+ XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
|
|
|
|
|
|
left.br_blockcount = blockcount;
|
|
|
|
|
@@ -5518,50 +5486,92 @@ xfs_bmse_shift_one(
|
|
|
int *current_ext,
|
|
|
struct xfs_bmbt_rec_host *gotp,
|
|
|
struct xfs_btree_cur *cur,
|
|
|
- int *logflags)
|
|
|
+ int *logflags,
|
|
|
+ enum shift_direction direction)
|
|
|
{
|
|
|
struct xfs_ifork *ifp;
|
|
|
+ struct xfs_mount *mp;
|
|
|
xfs_fileoff_t startoff;
|
|
|
- struct xfs_bmbt_rec_host *leftp;
|
|
|
+ struct xfs_bmbt_rec_host *adj_irecp;
|
|
|
struct xfs_bmbt_irec got;
|
|
|
- struct xfs_bmbt_irec left;
|
|
|
+ struct xfs_bmbt_irec adj_irec;
|
|
|
int error;
|
|
|
int i;
|
|
|
+ int total_extents;
|
|
|
|
|
|
+ mp = ip->i_mount;
|
|
|
ifp = XFS_IFORK_PTR(ip, whichfork);
|
|
|
+ total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
|
|
|
|
|
|
xfs_bmbt_get_all(gotp, &got);
|
|
|
- startoff = got.br_startoff - offset_shift_fsb;
|
|
|
|
|
|
/* delalloc extents should be prevented by caller */
|
|
|
- XFS_WANT_CORRUPTED_RETURN(!isnullstartblock(got.br_startblock));
|
|
|
+ XFS_WANT_CORRUPTED_RETURN(mp, !isnullstartblock(got.br_startblock));
|
|
|
|
|
|
- /*
|
|
|
- * Check for merge if we've got an extent to the left, otherwise make
|
|
|
- * sure there's enough room at the start of the file for the shift.
|
|
|
- */
|
|
|
- if (*current_ext) {
|
|
|
- /* grab the left extent and check for a large enough hole */
|
|
|
- leftp = xfs_iext_get_ext(ifp, *current_ext - 1);
|
|
|
- xfs_bmbt_get_all(leftp, &left);
|
|
|
+ if (direction == SHIFT_LEFT) {
|
|
|
+ startoff = got.br_startoff - offset_shift_fsb;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Check for merge if we've got an extent to the left,
|
|
|
+ * otherwise make sure there's enough room at the start
|
|
|
+ * of the file for the shift.
|
|
|
+ */
|
|
|
+ if (!*current_ext) {
|
|
|
+ if (got.br_startoff < offset_shift_fsb)
|
|
|
+ return -EINVAL;
|
|
|
+ goto update_current_ext;
|
|
|
+ }
|
|
|
+ /*
|
|
|
+ * grab the left extent and check for a large
|
|
|
+ * enough hole.
|
|
|
+ */
|
|
|
+ adj_irecp = xfs_iext_get_ext(ifp, *current_ext - 1);
|
|
|
+ xfs_bmbt_get_all(adj_irecp, &adj_irec);
|
|
|
|
|
|
- if (startoff < left.br_startoff + left.br_blockcount)
|
|
|
+ if (startoff <
|
|
|
+ adj_irec.br_startoff + adj_irec.br_blockcount)
|
|
|
return -EINVAL;
|
|
|
|
|
|
/* check whether to merge the extent or shift it down */
|
|
|
- if (xfs_bmse_can_merge(&left, &got, offset_shift_fsb)) {
|
|
|
+ if (xfs_bmse_can_merge(&adj_irec, &got,
|
|
|
+ offset_shift_fsb)) {
|
|
|
return xfs_bmse_merge(ip, whichfork, offset_shift_fsb,
|
|
|
- *current_ext, gotp, leftp, cur,
|
|
|
- logflags);
|
|
|
+ *current_ext, gotp, adj_irecp,
|
|
|
+ cur, logflags);
|
|
|
}
|
|
|
- } else if (got.br_startoff < offset_shift_fsb)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
+ } else {
|
|
|
+ startoff = got.br_startoff + offset_shift_fsb;
|
|
|
+ /* nothing to move if this is the last extent */
|
|
|
+ if (*current_ext >= (total_extents - 1))
|
|
|
+ goto update_current_ext;
|
|
|
+ /*
|
|
|
+ * If this is not the last extent in the file, make sure there
|
|
|
+ * is enough room between current extent and next extent for
|
|
|
+ * accommodating the shift.
|
|
|
+ */
|
|
|
+ adj_irecp = xfs_iext_get_ext(ifp, *current_ext + 1);
|
|
|
+ xfs_bmbt_get_all(adj_irecp, &adj_irec);
|
|
|
+ if (startoff + got.br_blockcount > adj_irec.br_startoff)
|
|
|
+ return -EINVAL;
|
|
|
+ /*
|
|
|
+ * Unlike a left shift (which involves a hole punch),
|
|
|
+ * a right shift does not modify extent neighbors
|
|
|
+ * in any way. We should never find mergeable extents
|
|
|
+ * in this scenario. Check anyways and warn if we
|
|
|
+ * encounter two extents that could be one.
|
|
|
+ */
|
|
|
+ if (xfs_bmse_can_merge(&got, &adj_irec, offset_shift_fsb))
|
|
|
+ WARN_ON_ONCE(1);
|
|
|
+ }
|
|
|
/*
|
|
|
* Increment the extent index for the next iteration, update the start
|
|
|
* offset of the in-core extent and update the btree if applicable.
|
|
|
*/
|
|
|
- (*current_ext)++;
|
|
|
+update_current_ext:
|
|
|
+ if (direction == SHIFT_LEFT)
|
|
|
+ (*current_ext)++;
|
|
|
+ else
|
|
|
+ (*current_ext)--;
|
|
|
xfs_bmbt_set_startoff(gotp, startoff);
|
|
|
*logflags |= XFS_ILOG_CORE;
|
|
|
if (!cur) {
|
|
@@ -5573,18 +5583,18 @@ xfs_bmse_shift_one(
|
|
|
got.br_blockcount, &i);
|
|
|
if (error)
|
|
|
return error;
|
|
|
- XFS_WANT_CORRUPTED_RETURN(i == 1);
|
|
|
+ XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
|
|
|
|
|
|
got.br_startoff = startoff;
|
|
|
return xfs_bmbt_update(cur, got.br_startoff, got.br_startblock,
|
|
|
- got.br_blockcount, got.br_state);
|
|
|
+ got.br_blockcount, got.br_state);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * Shift extent records to the left to cover a hole.
|
|
|
+ * Shift extent records to the left/right to cover/create a hole.
|
|
|
*
|
|
|
* The maximum number of extents to be shifted in a single operation is
|
|
|
- * @num_exts. @start_fsb specifies the file offset to start the shift and the
|
|
|
+ * @num_exts. @stop_fsb specifies the file offset at which to stop shift and the
|
|
|
* file offset where we've left off is returned in @next_fsb. @offset_shift_fsb
|
|
|
* is the length by which each extent is shifted. If there is no hole to shift
|
|
|
* the extents into, this will be considered invalid operation and we abort
|
|
@@ -5594,12 +5604,13 @@ int
|
|
|
xfs_bmap_shift_extents(
|
|
|
struct xfs_trans *tp,
|
|
|
struct xfs_inode *ip,
|
|
|
- xfs_fileoff_t start_fsb,
|
|
|
+ xfs_fileoff_t *next_fsb,
|
|
|
xfs_fileoff_t offset_shift_fsb,
|
|
|
int *done,
|
|
|
- xfs_fileoff_t *next_fsb,
|
|
|
+ xfs_fileoff_t stop_fsb,
|
|
|
xfs_fsblock_t *firstblock,
|
|
|
struct xfs_bmap_free *flist,
|
|
|
+ enum shift_direction direction,
|
|
|
int num_exts)
|
|
|
{
|
|
|
struct xfs_btree_cur *cur = NULL;
|
|
@@ -5609,10 +5620,11 @@ xfs_bmap_shift_extents(
|
|
|
struct xfs_ifork *ifp;
|
|
|
xfs_extnum_t nexts = 0;
|
|
|
xfs_extnum_t current_ext;
|
|
|
+ xfs_extnum_t total_extents;
|
|
|
+ xfs_extnum_t stop_extent;
|
|
|
int error = 0;
|
|
|
int whichfork = XFS_DATA_FORK;
|
|
|
int logflags = 0;
|
|
|
- int total_extents;
|
|
|
|
|
|
if (unlikely(XFS_TEST_ERROR(
|
|
|
(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
|
|
@@ -5628,6 +5640,8 @@ xfs_bmap_shift_extents(
|
|
|
|
|
|
ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
|
|
|
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
|
|
|
+ ASSERT(direction == SHIFT_LEFT || direction == SHIFT_RIGHT);
|
|
|
+ ASSERT(*next_fsb != NULLFSBLOCK || direction == SHIFT_RIGHT);
|
|
|
|
|
|
ifp = XFS_IFORK_PTR(ip, whichfork);
|
|
|
if (!(ifp->if_flags & XFS_IFEXTENTS)) {
|
|
@@ -5644,44 +5658,84 @@ xfs_bmap_shift_extents(
|
|
|
cur->bc_private.b.flags = 0;
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * There may be delalloc extents in the data fork before the range we
|
|
|
+ * are collapsing out, so we cannot use the count of real extents here.
|
|
|
+ * Instead we have to calculate it from the incore fork.
|
|
|
+ */
|
|
|
+ total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
|
|
|
+ if (total_extents == 0) {
|
|
|
+ *done = 1;
|
|
|
+ goto del_cursor;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * In case of first right shift, we need to initialize next_fsb
|
|
|
+ */
|
|
|
+ if (*next_fsb == NULLFSBLOCK) {
|
|
|
+ gotp = xfs_iext_get_ext(ifp, total_extents - 1);
|
|
|
+ xfs_bmbt_get_all(gotp, &got);
|
|
|
+ *next_fsb = got.br_startoff;
|
|
|
+ if (stop_fsb > *next_fsb) {
|
|
|
+ *done = 1;
|
|
|
+ goto del_cursor;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Lookup the extent index at which we have to stop */
|
|
|
+ if (direction == SHIFT_RIGHT) {
|
|
|
+ gotp = xfs_iext_bno_to_ext(ifp, stop_fsb, &stop_extent);
|
|
|
+ /* Make stop_extent exclusive of shift range */
|
|
|
+ stop_extent--;
|
|
|
+ } else
|
|
|
+ stop_extent = total_extents;
|
|
|
+
|
|
|
/*
|
|
|
* Look up the extent index for the fsb where we start shifting. We can
|
|
|
* henceforth iterate with current_ext as extent list changes are locked
|
|
|
* out via ilock.
|
|
|
*
|
|
|
* gotp can be null in 2 cases: 1) if there are no extents or 2)
|
|
|
- * start_fsb lies in a hole beyond which there are no extents. Either
|
|
|
+ * *next_fsb lies in a hole beyond which there are no extents. Either
|
|
|
* way, we are done.
|
|
|
*/
|
|
|
- gotp = xfs_iext_bno_to_ext(ifp, start_fsb, ¤t_ext);
|
|
|
+ gotp = xfs_iext_bno_to_ext(ifp, *next_fsb, ¤t_ext);
|
|
|
if (!gotp) {
|
|
|
*done = 1;
|
|
|
goto del_cursor;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * There may be delalloc extents in the data fork before the range we
|
|
|
- * are collapsing out, so we cannot use the count of real extents here.
|
|
|
- * Instead we have to calculate it from the incore fork.
|
|
|
- */
|
|
|
- total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
|
|
|
- while (nexts++ < num_exts && current_ext < total_extents) {
|
|
|
+ /* some sanity checking before we finally start shifting extents */
|
|
|
+ if ((direction == SHIFT_LEFT && current_ext >= stop_extent) ||
|
|
|
+ (direction == SHIFT_RIGHT && current_ext <= stop_extent)) {
|
|
|
+ error = -EIO;
|
|
|
+ goto del_cursor;
|
|
|
+ }
|
|
|
+
|
|
|
+ while (nexts++ < num_exts) {
|
|
|
error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb,
|
|
|
- ¤t_ext, gotp, cur, &logflags);
|
|
|
+ ¤t_ext, gotp, cur, &logflags,
|
|
|
+ direction);
|
|
|
if (error)
|
|
|
goto del_cursor;
|
|
|
+ /*
|
|
|
+ * If there was an extent merge during the shift, the extent
|
|
|
+ * count can change. Update the total and grade the next record.
|
|
|
+ */
|
|
|
+ if (direction == SHIFT_LEFT) {
|
|
|
+ total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
|
|
|
+ stop_extent = total_extents;
|
|
|
+ }
|
|
|
|
|
|
- /* update total extent count and grab the next record */
|
|
|
- total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
|
|
|
- if (current_ext >= total_extents)
|
|
|
+ if (current_ext == stop_extent) {
|
|
|
+ *done = 1;
|
|
|
+ *next_fsb = NULLFSBLOCK;
|
|
|
break;
|
|
|
+ }
|
|
|
gotp = xfs_iext_get_ext(ifp, current_ext);
|
|
|
}
|
|
|
|
|
|
- /* Check if we are done */
|
|
|
- if (current_ext == total_extents) {
|
|
|
- *done = 1;
|
|
|
- } else if (next_fsb) {
|
|
|
+ if (!*done) {
|
|
|
xfs_bmbt_get_all(gotp, &got);
|
|
|
*next_fsb = got.br_startoff;
|
|
|
}
|
|
@@ -5696,3 +5750,189 @@ del_cursor:
|
|
|
|
|
|
return error;
|
|
|
}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Splits an extent into two extents at split_fsb block such that it is
|
|
|
+ * the first block of the current_ext. @current_ext is a target extent
|
|
|
+ * to be split. @split_fsb is a block where the extents is split.
|
|
|
+ * If split_fsb lies in a hole or the first block of extents, just return 0.
|
|
|
+ */
|
|
|
+STATIC int
|
|
|
+xfs_bmap_split_extent_at(
|
|
|
+ struct xfs_trans *tp,
|
|
|
+ struct xfs_inode *ip,
|
|
|
+ xfs_fileoff_t split_fsb,
|
|
|
+ xfs_fsblock_t *firstfsb,
|
|
|
+ struct xfs_bmap_free *free_list)
|
|
|
+{
|
|
|
+ int whichfork = XFS_DATA_FORK;
|
|
|
+ struct xfs_btree_cur *cur = NULL;
|
|
|
+ struct xfs_bmbt_rec_host *gotp;
|
|
|
+ struct xfs_bmbt_irec got;
|
|
|
+ struct xfs_bmbt_irec new; /* split extent */
|
|
|
+ struct xfs_mount *mp = ip->i_mount;
|
|
|
+ struct xfs_ifork *ifp;
|
|
|
+ xfs_fsblock_t gotblkcnt; /* new block count for got */
|
|
|
+ xfs_extnum_t current_ext;
|
|
|
+ int error = 0;
|
|
|
+ int logflags = 0;
|
|
|
+ int i = 0;
|
|
|
+
|
|
|
+ if (unlikely(XFS_TEST_ERROR(
|
|
|
+ (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
|
|
|
+ XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
|
|
|
+ mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
|
|
|
+ XFS_ERROR_REPORT("xfs_bmap_split_extent_at",
|
|
|
+ XFS_ERRLEVEL_LOW, mp);
|
|
|
+ return -EFSCORRUPTED;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (XFS_FORCED_SHUTDOWN(mp))
|
|
|
+ return -EIO;
|
|
|
+
|
|
|
+ ifp = XFS_IFORK_PTR(ip, whichfork);
|
|
|
+ if (!(ifp->if_flags & XFS_IFEXTENTS)) {
|
|
|
+ /* Read in all the extents */
|
|
|
+ error = xfs_iread_extents(tp, ip, whichfork);
|
|
|
+ if (error)
|
|
|
+ return error;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * gotp can be null in 2 cases: 1) if there are no extents
|
|
|
+ * or 2) split_fsb lies in a hole beyond which there are
|
|
|
+ * no extents. Either way, we are done.
|
|
|
+ */
|
|
|
+ gotp = xfs_iext_bno_to_ext(ifp, split_fsb, ¤t_ext);
|
|
|
+ if (!gotp)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ xfs_bmbt_get_all(gotp, &got);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Check split_fsb lies in a hole or the start boundary offset
|
|
|
+ * of the extent.
|
|
|
+ */
|
|
|
+ if (got.br_startoff >= split_fsb)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ gotblkcnt = split_fsb - got.br_startoff;
|
|
|
+ new.br_startoff = split_fsb;
|
|
|
+ new.br_startblock = got.br_startblock + gotblkcnt;
|
|
|
+ new.br_blockcount = got.br_blockcount - gotblkcnt;
|
|
|
+ new.br_state = got.br_state;
|
|
|
+
|
|
|
+ if (ifp->if_flags & XFS_IFBROOT) {
|
|
|
+ cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
|
|
|
+ cur->bc_private.b.firstblock = *firstfsb;
|
|
|
+ cur->bc_private.b.flist = free_list;
|
|
|
+ cur->bc_private.b.flags = 0;
|
|
|
+ error = xfs_bmbt_lookup_eq(cur, got.br_startoff,
|
|
|
+ got.br_startblock,
|
|
|
+ got.br_blockcount,
|
|
|
+ &i);
|
|
|
+ if (error)
|
|
|
+ goto del_cursor;
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, del_cursor);
|
|
|
+ }
|
|
|
+
|
|
|
+ xfs_bmbt_set_blockcount(gotp, gotblkcnt);
|
|
|
+ got.br_blockcount = gotblkcnt;
|
|
|
+
|
|
|
+ logflags = XFS_ILOG_CORE;
|
|
|
+ if (cur) {
|
|
|
+ error = xfs_bmbt_update(cur, got.br_startoff,
|
|
|
+ got.br_startblock,
|
|
|
+ got.br_blockcount,
|
|
|
+ got.br_state);
|
|
|
+ if (error)
|
|
|
+ goto del_cursor;
|
|
|
+ } else
|
|
|
+ logflags |= XFS_ILOG_DEXT;
|
|
|
+
|
|
|
+ /* Add new extent */
|
|
|
+ current_ext++;
|
|
|
+ xfs_iext_insert(ip, current_ext, 1, &new, 0);
|
|
|
+ XFS_IFORK_NEXT_SET(ip, whichfork,
|
|
|
+ XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
|
|
|
+
|
|
|
+ if (cur) {
|
|
|
+ error = xfs_bmbt_lookup_eq(cur, new.br_startoff,
|
|
|
+ new.br_startblock, new.br_blockcount,
|
|
|
+ &i);
|
|
|
+ if (error)
|
|
|
+ goto del_cursor;
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 0, del_cursor);
|
|
|
+ cur->bc_rec.b.br_state = new.br_state;
|
|
|
+
|
|
|
+ error = xfs_btree_insert(cur, &i);
|
|
|
+ if (error)
|
|
|
+ goto del_cursor;
|
|
|
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, del_cursor);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Convert to a btree if necessary.
|
|
|
+ */
|
|
|
+ if (xfs_bmap_needs_btree(ip, whichfork)) {
|
|
|
+ int tmp_logflags; /* partial log flag return val */
|
|
|
+
|
|
|
+ ASSERT(cur == NULL);
|
|
|
+ error = xfs_bmap_extents_to_btree(tp, ip, firstfsb, free_list,
|
|
|
+ &cur, 0, &tmp_logflags, whichfork);
|
|
|
+ logflags |= tmp_logflags;
|
|
|
+ }
|
|
|
+
|
|
|
+del_cursor:
|
|
|
+ if (cur) {
|
|
|
+ cur->bc_private.b.allocated = 0;
|
|
|
+ xfs_btree_del_cursor(cur,
|
|
|
+ error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (logflags)
|
|
|
+ xfs_trans_log_inode(tp, ip, logflags);
|
|
|
+ return error;
|
|
|
+}
|
|
|
+
|
|
|
+int
|
|
|
+xfs_bmap_split_extent(
|
|
|
+ struct xfs_inode *ip,
|
|
|
+ xfs_fileoff_t split_fsb)
|
|
|
+{
|
|
|
+ struct xfs_mount *mp = ip->i_mount;
|
|
|
+ struct xfs_trans *tp;
|
|
|
+ struct xfs_bmap_free free_list;
|
|
|
+ xfs_fsblock_t firstfsb;
|
|
|
+ int committed;
|
|
|
+ int error;
|
|
|
+
|
|
|
+ tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
|
|
|
+ error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write,
|
|
|
+ XFS_DIOSTRAT_SPACE_RES(mp, 0), 0);
|
|
|
+ if (error) {
|
|
|
+ xfs_trans_cancel(tp, 0);
|
|
|
+ return error;
|
|
|
+ }
|
|
|
+
|
|
|
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
|
|
|
+ xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
|
|
+
|
|
|
+ xfs_bmap_init(&free_list, &firstfsb);
|
|
|
+
|
|
|
+ error = xfs_bmap_split_extent_at(tp, ip, split_fsb,
|
|
|
+ &firstfsb, &free_list);
|
|
|
+ if (error)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ error = xfs_bmap_finish(&tp, &free_list, &committed);
|
|
|
+ if (error)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ return xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
|
|
|
+
|
|
|
+
|
|
|
+out:
|
|
|
+ xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
|
|
|
+ return error;
|
|
|
+}
|