|
@@ -1164,33 +1164,37 @@ trans_cancel:
|
|
*/
|
|
*/
|
|
|
|
|
|
/*
|
|
/*
|
|
- * Read in the extents to if_extents.
|
|
|
|
- * All inode fields are set up by caller, we just traverse the btree
|
|
|
|
- * and copy the records in. If the file system cannot contain unwritten
|
|
|
|
- * extents, the records are checked for no "state" flags.
|
|
|
|
|
|
+ * Read in extents from a btree-format inode.
|
|
*/
|
|
*/
|
|
-int /* error */
|
|
|
|
-xfs_bmap_read_extents(
|
|
|
|
- xfs_trans_t *tp, /* transaction pointer */
|
|
|
|
- xfs_inode_t *ip, /* incore inode */
|
|
|
|
- int whichfork) /* data or attr fork */
|
|
|
|
|
|
+int
|
|
|
|
+xfs_iread_extents(
|
|
|
|
+ struct xfs_trans *tp,
|
|
|
|
+ struct xfs_inode *ip,
|
|
|
|
+ int whichfork)
|
|
{
|
|
{
|
|
- struct xfs_btree_block *block; /* current btree block */
|
|
|
|
- xfs_fsblock_t bno; /* block # of "block" */
|
|
|
|
- xfs_buf_t *bp; /* buffer for "block" */
|
|
|
|
- int error; /* error return value */
|
|
|
|
- xfs_extnum_t i, j; /* index into the extents list */
|
|
|
|
- xfs_ifork_t *ifp; /* fork structure */
|
|
|
|
- int level; /* btree level, for checking */
|
|
|
|
- xfs_mount_t *mp; /* file system mount structure */
|
|
|
|
- __be64 *pp; /* pointer to block address */
|
|
|
|
- /* REFERENCED */
|
|
|
|
- xfs_extnum_t room; /* number of entries there's room for */
|
|
|
|
|
|
+ struct xfs_mount *mp = ip->i_mount;
|
|
int state = xfs_bmap_fork_to_state(whichfork);
|
|
int state = xfs_bmap_fork_to_state(whichfork);
|
|
|
|
+ struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
|
|
|
|
+ xfs_extnum_t nextents = XFS_IFORK_NEXTENTS(ip, whichfork);
|
|
|
|
+ struct xfs_btree_block *block = ifp->if_broot;
|
|
|
|
+ xfs_fsblock_t bno;
|
|
|
|
+ struct xfs_buf *bp;
|
|
|
|
+ xfs_extnum_t i, j;
|
|
|
|
+ int level;
|
|
|
|
+ __be64 *pp;
|
|
|
|
+ int error;
|
|
|
|
+
|
|
|
|
+ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
|
|
|
|
+
|
|
|
|
+ if (unlikely(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) {
|
|
|
|
+ XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
|
|
|
|
+ return -EFSCORRUPTED;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ifp->if_bytes = 0;
|
|
|
|
+ ifp->if_real_bytes = 0;
|
|
|
|
+ xfs_iext_add(ifp, 0, nextents);
|
|
|
|
|
|
- mp = ip->i_mount;
|
|
|
|
- ifp = XFS_IFORK_PTR(ip, whichfork);
|
|
|
|
- block = ifp->if_broot;
|
|
|
|
/*
|
|
/*
|
|
* Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
|
|
* Root level must use BMAP_BROOT_PTR_ADDR macro to get ptr out.
|
|
*/
|
|
*/
|
|
@@ -1207,21 +1211,22 @@ xfs_bmap_read_extents(
|
|
error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
|
|
error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
|
|
XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops);
|
|
XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops);
|
|
if (error)
|
|
if (error)
|
|
- return error;
|
|
|
|
|
|
+ goto out;
|
|
block = XFS_BUF_TO_BLOCK(bp);
|
|
block = XFS_BUF_TO_BLOCK(bp);
|
|
if (level == 0)
|
|
if (level == 0)
|
|
break;
|
|
break;
|
|
pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
|
|
pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
|
|
bno = be64_to_cpu(*pp);
|
|
bno = be64_to_cpu(*pp);
|
|
XFS_WANT_CORRUPTED_GOTO(mp,
|
|
XFS_WANT_CORRUPTED_GOTO(mp,
|
|
- XFS_FSB_SANITY_CHECK(mp, bno), error0);
|
|
|
|
|
|
+ XFS_FSB_SANITY_CHECK(mp, bno), out_brelse);
|
|
xfs_trans_brelse(tp, bp);
|
|
xfs_trans_brelse(tp, bp);
|
|
}
|
|
}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Here with bp and block set to the leftmost leaf node in the tree.
|
|
* Here with bp and block set to the leftmost leaf node in the tree.
|
|
*/
|
|
*/
|
|
- room = xfs_iext_count(ifp);
|
|
|
|
i = 0;
|
|
i = 0;
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Loop over all leaf nodes. Copy information to the extent records.
|
|
* Loop over all leaf nodes. Copy information to the extent records.
|
|
*/
|
|
*/
|
|
@@ -1231,14 +1236,15 @@ xfs_bmap_read_extents(
|
|
xfs_extnum_t num_recs;
|
|
xfs_extnum_t num_recs;
|
|
|
|
|
|
num_recs = xfs_btree_get_numrecs(block);
|
|
num_recs = xfs_btree_get_numrecs(block);
|
|
- if (unlikely(i + num_recs > room)) {
|
|
|
|
- ASSERT(i + num_recs <= room);
|
|
|
|
|
|
+ if (unlikely(i + num_recs > nextents)) {
|
|
|
|
+ ASSERT(i + num_recs <= nextents);
|
|
xfs_warn(ip->i_mount,
|
|
xfs_warn(ip->i_mount,
|
|
"corrupt dinode %Lu, (btree extents).",
|
|
"corrupt dinode %Lu, (btree extents).",
|
|
(unsigned long long) ip->i_ino);
|
|
(unsigned long long) ip->i_ino);
|
|
- XFS_CORRUPTION_ERROR("xfs_bmap_read_extents(1)",
|
|
|
|
|
|
+ XFS_CORRUPTION_ERROR(__func__,
|
|
XFS_ERRLEVEL_LOW, ip->i_mount, block);
|
|
XFS_ERRLEVEL_LOW, ip->i_mount, block);
|
|
- goto error0;
|
|
|
|
|
|
+ error = -EFSCORRUPTED;
|
|
|
|
+ goto out_brelse;
|
|
}
|
|
}
|
|
/*
|
|
/*
|
|
* Read-ahead the next leaf block, if any.
|
|
* Read-ahead the next leaf block, if any.
|
|
@@ -1258,7 +1264,8 @@ xfs_bmap_read_extents(
|
|
if (!xfs_bmbt_validate_extent(mp, whichfork, trp)) {
|
|
if (!xfs_bmbt_validate_extent(mp, whichfork, trp)) {
|
|
XFS_ERROR_REPORT("xfs_bmap_read_extents(2)",
|
|
XFS_ERROR_REPORT("xfs_bmap_read_extents(2)",
|
|
XFS_ERRLEVEL_LOW, mp);
|
|
XFS_ERRLEVEL_LOW, mp);
|
|
- goto error0;
|
|
|
|
|
|
+ error = -EFSCORRUPTED;
|
|
|
|
+ goto out_brelse;
|
|
}
|
|
}
|
|
trace_xfs_read_extent(ip, i, state, _THIS_IP_);
|
|
trace_xfs_read_extent(ip, i, state, _THIS_IP_);
|
|
}
|
|
}
|
|
@@ -1272,16 +1279,24 @@ xfs_bmap_read_extents(
|
|
error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
|
|
error = xfs_btree_read_bufl(mp, tp, bno, 0, &bp,
|
|
XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops);
|
|
XFS_BMAP_BTREE_REF, &xfs_bmbt_buf_ops);
|
|
if (error)
|
|
if (error)
|
|
- return error;
|
|
|
|
|
|
+ goto out;
|
|
block = XFS_BUF_TO_BLOCK(bp);
|
|
block = XFS_BUF_TO_BLOCK(bp);
|
|
}
|
|
}
|
|
- if (i != XFS_IFORK_NEXTENTS(ip, whichfork))
|
|
|
|
- return -EFSCORRUPTED;
|
|
|
|
|
|
+
|
|
|
|
+ if (i != XFS_IFORK_NEXTENTS(ip, whichfork)) {
|
|
|
|
+ error = -EFSCORRUPTED;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
ASSERT(i == xfs_iext_count(ifp));
|
|
ASSERT(i == xfs_iext_count(ifp));
|
|
|
|
+
|
|
|
|
+ ifp->if_flags |= XFS_IFEXTENTS;
|
|
return 0;
|
|
return 0;
|
|
-error0:
|
|
|
|
|
|
+
|
|
|
|
+out_brelse:
|
|
xfs_trans_brelse(tp, bp);
|
|
xfs_trans_brelse(tp, bp);
|
|
- return -EFSCORRUPTED;
|
|
|
|
|
|
+out:
|
|
|
|
+ xfs_iext_destroy(ifp);
|
|
|
|
+ return error;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|