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.c280
1 files changed, 136 insertions, 144 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index c09c16b1ad3b..459f4b4f08fe 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -579,7 +579,7 @@ xfs_bmap_validate_ret(
#else
#define xfs_bmap_check_leaf_extents(cur, ip, whichfork) do { } while (0)
-#define xfs_bmap_validate_ret(bno,len,flags,mval,onmap,nmap)
+#define xfs_bmap_validate_ret(bno,len,flags,mval,onmap,nmap) do { } while (0)
#endif /* DEBUG */
/*
@@ -880,7 +880,7 @@ xfs_bmap_local_to_extents(
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_alloc_arg_t args; /* allocation arguments */
xfs_buf_t *bp; /* buffer for extent block */
- xfs_bmbt_rec_host_t *ep; /* extent record pointer */
+ struct xfs_bmbt_irec rec;
/*
* We don't want to deal with the case of keeping inode data inline yet.
@@ -943,9 +943,12 @@ xfs_bmap_local_to_extents(
xfs_bmap_local_to_extents_empty(ip, whichfork);
flags |= XFS_ILOG_CORE;
- xfs_iext_add(ifp, 0, 1);
- ep = xfs_iext_get_ext(ifp, 0);
- xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM);
+ rec.br_startoff = 0;
+ rec.br_startblock = args.fsbno;
+ rec.br_blockcount = 1;
+ rec.br_state = XFS_EXT_NORM;
+ xfs_iext_insert(ip, 0, 1, &rec, 0);
+
trace_xfs_bmap_post_update(ip, 0,
whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0,
_THIS_IP_);
@@ -1196,7 +1199,7 @@ xfs_bmap_add_attrfork(
xfs_log_sb(tp);
}
- error = xfs_defer_finish(&tp, &dfops, NULL);
+ error = xfs_defer_finish(&tp, &dfops);
if (error)
goto bmap_cancel;
error = xfs_trans_commit(tp);
@@ -1356,7 +1359,6 @@ xfs_bmap_first_unused(
xfs_fileoff_t lastaddr; /* last block number seen */
xfs_fileoff_t lowest; /* lowest useful block */
xfs_fileoff_t max; /* starting useful block */
- xfs_fileoff_t off; /* offset for this block */
xfs_extnum_t nextents; /* number of extent entries */
ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE ||
@@ -1373,16 +1375,19 @@ xfs_bmap_first_unused(
lowest = *first_unused;
nextents = xfs_iext_count(ifp);
for (idx = 0, lastaddr = 0, max = lowest; idx < nextents; idx++) {
- xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx);
- off = xfs_bmbt_get_startoff(ep);
+ struct xfs_bmbt_irec got;
+
+ xfs_iext_get_extent(ifp, idx, &got);
+
/*
* See if the hole before this extent will work.
*/
- if (off >= lowest + len && off - max >= len) {
+ if (got.br_startoff >= lowest + len &&
+ got.br_startoff - max >= len) {
*first_unused = max;
return 0;
}
- lastaddr = off + xfs_bmbt_get_blockcount(ep);
+ lastaddr = got.br_startoff + got.br_blockcount;
max = XFS_FILEOFF_MAX(lastaddr, lowest);
}
*first_unused = max;
@@ -4918,7 +4923,7 @@ xfs_bmap_del_extent_delay(
da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip,
got->br_blockcount), da_old);
got->br_startblock = nullstartblock((int)da_new);
- xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got);
+ xfs_iext_update_extent(ifp, *idx, got);
trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
break;
case BMAP_RIGHT_CONTIG:
@@ -4930,7 +4935,7 @@ xfs_bmap_del_extent_delay(
da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip,
got->br_blockcount), da_old);
got->br_startblock = nullstartblock((int)da_new);
- xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got);
+ xfs_iext_update_extent(ifp, *idx, got);
trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
break;
case 0:
@@ -4956,7 +4961,7 @@ xfs_bmap_del_extent_delay(
del->br_blockcount);
got->br_startblock = nullstartblock((int)got_indlen);
- xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got);
+ xfs_iext_update_extent(ifp, *idx, got);
trace_xfs_bmap_post_update(ip, *idx, 0, _THIS_IP_);
new.br_startoff = del_endoff;
@@ -5026,7 +5031,7 @@ xfs_bmap_del_extent_cow(
got->br_startoff = del_endoff;
got->br_blockcount -= del->br_blockcount;
got->br_startblock = del->br_startblock + del->br_blockcount;
- xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got);
+ xfs_iext_update_extent(ifp, *idx, got);
trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
break;
case BMAP_RIGHT_CONTIG:
@@ -5035,7 +5040,7 @@ xfs_bmap_del_extent_cow(
*/
trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
got->br_blockcount -= del->br_blockcount;
- xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got);
+ xfs_iext_update_extent(ifp, *idx, got);
trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
break;
case 0:
@@ -5044,7 +5049,7 @@ xfs_bmap_del_extent_cow(
*/
trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
got->br_blockcount = del->br_startoff - got->br_startoff;
- xfs_bmbt_set_all(xfs_iext_get_ext(ifp, *idx), got);
+ xfs_iext_update_extent(ifp, *idx, got);
trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
new.br_startoff = del_endoff;
@@ -5876,32 +5881,26 @@ xfs_bmse_merge(
int whichfork,
xfs_fileoff_t shift, /* shift fsb */
int current_ext, /* idx of gotp */
- struct xfs_bmbt_rec_host *gotp, /* extent to shift */
- struct xfs_bmbt_rec_host *leftp, /* preceding extent */
+ struct xfs_bmbt_irec *got, /* extent to shift */
+ struct xfs_bmbt_irec *left, /* preceding extent */
struct xfs_btree_cur *cur,
- int *logflags) /* output */
+ int *logflags, /* output */
+ struct xfs_defer_ops *dfops)
{
- struct xfs_bmbt_irec got;
- struct xfs_bmbt_irec left;
+ struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
+ struct xfs_bmbt_irec new;
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);
- blockcount = left.br_blockcount + got.br_blockcount;
+ blockcount = left->br_blockcount + got->br_blockcount;
ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
- ASSERT(xfs_bmse_can_merge(&left, &got, shift));
+ ASSERT(xfs_bmse_can_merge(left, got, shift));
- /*
- * Merge the in-core extents. Note that the host record pointers and
- * current_ext index are invalid once the extent has been removed via
- * xfs_iext_remove().
- */
- xfs_bmbt_set_blockcount(leftp, blockcount);
- xfs_iext_remove(ip, current_ext, 1, 0);
+ new = *left;
+ new.br_blockcount = blockcount;
/*
* Update the on-disk extent count, the btree if necessary and log the
@@ -5912,12 +5911,12 @@ xfs_bmse_merge(
*logflags |= XFS_ILOG_CORE;
if (!cur) {
*logflags |= XFS_ILOG_DEXT;
- return 0;
+ goto done;
}
/* lookup and remove the extent to merge */
- error = xfs_bmbt_lookup_eq(cur, got.br_startoff, got.br_startblock,
- got.br_blockcount, &i);
+ error = xfs_bmbt_lookup_eq(cur, got->br_startoff, got->br_startblock,
+ got->br_blockcount, &i);
if (error)
return error;
XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
@@ -5928,16 +5927,28 @@ xfs_bmse_merge(
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);
+ error = xfs_bmbt_lookup_eq(cur, left->br_startoff, left->br_startblock,
+ left->br_blockcount, &i);
if (error)
return error;
XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
- left.br_blockcount = blockcount;
+ error = xfs_bmbt_update(cur, new.br_startoff, new.br_startblock,
+ new.br_blockcount, new.br_state);
+ if (error)
+ return error;
+
+done:
+ xfs_iext_update_extent(ifp, current_ext - 1, &new);
+ xfs_iext_remove(ip, current_ext, 1, 0);
- return xfs_bmbt_update(cur, left.br_startoff, left.br_startblock,
- left.br_blockcount, left.br_state);
+ /* update reverse mapping. rmap functions merge the rmaps for us */
+ error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, got);
+ if (error)
+ return error;
+ memcpy(&new, got, sizeof(new));
+ new.br_startoff = left->br_startoff + left->br_blockcount;
+ return xfs_rmap_map_extent(mp, dfops, ip, whichfork, &new);
}
/*
@@ -5949,7 +5960,7 @@ xfs_bmse_shift_one(
int whichfork,
xfs_fileoff_t offset_shift_fsb,
int *current_ext,
- struct xfs_bmbt_rec_host *gotp,
+ struct xfs_bmbt_irec *got,
struct xfs_btree_cur *cur,
int *logflags,
enum shift_direction direction,
@@ -5958,9 +5969,7 @@ xfs_bmse_shift_one(
struct xfs_ifork *ifp;
struct xfs_mount *mp;
xfs_fileoff_t startoff;
- struct xfs_bmbt_rec_host *adj_irecp;
- struct xfs_bmbt_irec got;
- struct xfs_bmbt_irec adj_irec;
+ struct xfs_bmbt_irec adj_irec, new;
int error;
int i;
int total_extents;
@@ -5969,13 +5978,11 @@ xfs_bmse_shift_one(
ifp = XFS_IFORK_PTR(ip, whichfork);
total_extents = xfs_iext_count(ifp);
- xfs_bmbt_get_all(gotp, &got);
-
/* delalloc extents should be prevented by caller */
- XFS_WANT_CORRUPTED_RETURN(mp, !isnullstartblock(got.br_startblock));
+ XFS_WANT_CORRUPTED_RETURN(mp, !isnullstartblock(got->br_startblock));
if (direction == SHIFT_LEFT) {
- startoff = got.br_startoff - offset_shift_fsb;
+ startoff = got->br_startoff - offset_shift_fsb;
/*
* Check for merge if we've got an extent to the left,
@@ -5983,46 +5990,39 @@ xfs_bmse_shift_one(
* of the file for the shift.
*/
if (!*current_ext) {
- if (got.br_startoff < offset_shift_fsb)
+ if (got->br_startoff < offset_shift_fsb)
return -EINVAL;
goto update_current_ext;
}
+
/*
- * grab the left extent and check for a large
- * enough hole.
+ * 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 <
- adj_irec.br_startoff + adj_irec.br_blockcount)
+ xfs_iext_get_extent(ifp, *current_ext - 1, &adj_irec);
+ 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(&adj_irec, &got,
- offset_shift_fsb)) {
- error = xfs_bmse_merge(ip, whichfork, offset_shift_fsb,
- *current_ext, gotp, adj_irecp,
- cur, logflags);
- if (error)
- return error;
- adj_irec = got;
- goto update_rmap;
+ if (xfs_bmse_can_merge(&adj_irec, got, offset_shift_fsb)) {
+ return xfs_bmse_merge(ip, whichfork, offset_shift_fsb,
+ *current_ext, got, &adj_irec,
+ cur, logflags, dfops);
}
} else {
- startoff = got.br_startoff + offset_shift_fsb;
+ 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)
+ xfs_iext_get_extent(ifp, *current_ext + 1, &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
@@ -6030,45 +6030,48 @@ xfs_bmse_shift_one(
* 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))
+ 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.
*/
update_current_ext:
- if (direction == SHIFT_LEFT)
- (*current_ext)++;
- else
- (*current_ext)--;
- xfs_bmbt_set_startoff(gotp, startoff);
*logflags |= XFS_ILOG_CORE;
- adj_irec = got;
- if (!cur) {
+
+ new = *got;
+ new.br_startoff = startoff;
+
+ if (cur) {
+ error = xfs_bmbt_lookup_eq(cur, got->br_startoff,
+ got->br_startblock, got->br_blockcount, &i);
+ if (error)
+ return error;
+ XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
+
+ error = xfs_bmbt_update(cur, new.br_startoff,
+ new.br_startblock, new.br_blockcount,
+ new.br_state);
+ if (error)
+ return error;
+ } else {
*logflags |= XFS_ILOG_DEXT;
- goto update_rmap;
}
- error = xfs_bmbt_lookup_eq(cur, got.br_startoff, got.br_startblock,
- got.br_blockcount, &i);
- if (error)
- return error;
- XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
+ xfs_iext_update_extent(ifp, *current_ext, &new);
- got.br_startoff = startoff;
- error = xfs_bmbt_update(cur, got.br_startoff, got.br_startblock,
- got.br_blockcount, got.br_state);
- if (error)
- return error;
+ if (direction == SHIFT_LEFT)
+ (*current_ext)++;
+ else
+ (*current_ext)--;
-update_rmap:
/* update reverse mapping */
- error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, &adj_irec);
+ error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, got);
if (error)
return error;
- adj_irec.br_startoff = startoff;
- return xfs_rmap_map_extent(mp, dfops, ip, whichfork, &adj_irec);
+ return xfs_rmap_map_extent(mp, dfops, ip, whichfork, &new);
}
/*
@@ -6095,7 +6098,6 @@ xfs_bmap_shift_extents(
int num_exts)
{
struct xfs_btree_cur *cur = NULL;
- struct xfs_bmbt_rec_host *gotp;
struct xfs_bmbt_irec got;
struct xfs_mount *mp = ip->i_mount;
struct xfs_ifork *ifp;
@@ -6122,7 +6124,6 @@ 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)) {
@@ -6154,10 +6155,26 @@ xfs_bmap_shift_extents(
* 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);
+ ASSERT(direction == SHIFT_RIGHT);
+
+ current_ext = total_extents - 1;
+ xfs_iext_get_extent(ifp, current_ext, &got);
+ if (stop_fsb > got.br_startoff) {
+ *done = 1;
+ goto del_cursor;
+ }
*next_fsb = got.br_startoff;
- if (stop_fsb > *next_fsb) {
+ } else {
+ /*
+ * 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.
+ *
+ * If next_fsb lies in a hole beyond which there are no extents we are
+ * done.
+ */
+ if (!xfs_iext_lookup_extent(ip, ifp, *next_fsb, &current_ext,
+ &got)) {
*done = 1;
goto del_cursor;
}
@@ -6165,37 +6182,26 @@ xfs_bmap_shift_extents(
/* 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);
+ struct xfs_bmbt_irec s;
+
+ xfs_iext_lookup_extent(ip, ifp, stop_fsb, &stop_extent, &s);
/* Make stop_extent exclusive of shift range */
stop_extent--;
- } else
+ if (current_ext <= stop_extent) {
+ error = -EIO;
+ goto del_cursor;
+ }
+ } 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)
- * *next_fsb lies in a hole beyond which there are no extents. Either
- * way, we are done.
- */
- gotp = xfs_iext_bno_to_ext(ifp, *next_fsb, &current_ext);
- if (!gotp) {
- *done = 1;
- goto del_cursor;
- }
-
- /* 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;
+ if (current_ext >= stop_extent) {
+ error = -EIO;
+ goto del_cursor;
+ }
}
while (nexts++ < num_exts) {
error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb,
- &current_ext, gotp, cur, &logflags,
+ &current_ext, &got, cur, &logflags,
direction, dfops);
if (error)
goto del_cursor;
@@ -6213,13 +6219,11 @@ xfs_bmap_shift_extents(
*next_fsb = NULLFSBLOCK;
break;
}
- gotp = xfs_iext_get_ext(ifp, current_ext);
+ xfs_iext_get_extent(ifp, current_ext, &got);
}
- if (!*done) {
- xfs_bmbt_get_all(gotp, &got);
+ if (!*done)
*next_fsb = got.br_startoff;
- }
del_cursor:
if (cur)
@@ -6248,7 +6252,6 @@ xfs_bmap_split_extent_at(
{
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;
@@ -6280,21 +6283,10 @@ xfs_bmap_split_extent_at(
}
/*
- * 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, &current_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 there are not extents, or split_fsb lies in a hole we are done.
*/
- if (got.br_startoff >= split_fsb)
+ if (!xfs_iext_lookup_extent(ip, ifp, split_fsb, &current_ext, &got) ||
+ got.br_startoff >= split_fsb)
return 0;
gotblkcnt = split_fsb - got.br_startoff;
@@ -6317,8 +6309,8 @@ xfs_bmap_split_extent_at(
XFS_WANT_CORRUPTED_GOTO(mp, i == 1, del_cursor);
}
- xfs_bmbt_set_blockcount(gotp, gotblkcnt);
got.br_blockcount = gotblkcnt;
+ xfs_iext_update_extent(ifp, current_ext, &got);
logflags = XFS_ILOG_CORE;
if (cur) {
@@ -6402,7 +6394,7 @@ xfs_bmap_split_extent(
if (error)
goto out;
- error = xfs_defer_finish(&tp, &dfops, NULL);
+ error = xfs_defer_finish(&tp, &dfops);
if (error)
goto out;
@@ -6452,7 +6444,7 @@ __xfs_bmap_add(
bi->bi_whichfork = whichfork;
bi->bi_bmap = *bmap;
- error = xfs_defer_join(dfops, bi->bi_owner);
+ error = xfs_defer_ijoin(dfops, bi->bi_owner);
if (error) {
kmem_free(bi);
return error;