aboutsummaryrefslogtreecommitdiff
path: root/fs/xfs/libxfs/xfs_bmap.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-04 12:44:02 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-04 12:44:02 -0700
commit547c43d777968228b1060b6f1b152b96215eb7b2 (patch)
tree3e256530397ec1e751d06ed23230bfe1daf4886c /fs/xfs/libxfs/xfs_bmap.c
parent2e08edc5c50a01dc52c005fd939c24476eaf55ef (diff)
parentdc1baa715bbfbb1902da942d06497e79b40e7bc7 (diff)
Merge tag 'xfs-4.17-merge-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs updates from Darrick Wong: "Here's the first round of fixes for XFS for 4.17. The biggest new features this time around are the addition of lazytime support, further enhancement of the on-disk inode metadata verifiers, and a patch to smooth over some of the AGFL padding problems that have intermittently plagued users since 4.5. I forsee sending a second pull request next week with further bug fixes and speedups in the online scrub code and elsewhere. This series has been run through a full xfstests run over the weekend and through a quick xfstests run against this morning's master, with no major failures reported. Summary of changes for this release: - Various cleanups and code fixes - Implement lazytime as a mount option - Convert various on-disk metadata checks from asserts to -EFSCORRUPTED - Fix accounting problems with the rmap per-ag reservations - Refactorings and cleanups for xfs_log_force - Various bugfixes for the reflink code - Work around v5 AGFL padding problems to prevent fs shutdowns - Establish inode fork verifiers to inspect on-disk metadata correctness - Various online scrub fixes - Fix v5 swapext blowing up on deleted inodes" * tag 'xfs-4.17-merge-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: (49 commits) xfs: do not log/recover swapext extent owner changes for deleted inodes xfs: clean up xfs_mount allocation and dynamic initializers xfs: remove dead inode version setting code xfs: catch inode allocation state mismatch corruption xfs: xfs_scrub_iallocbt_xref_rmap_inodes should use xref_set_corrupt xfs: flag inode corruption if parent ptr doesn't get us a real inode xfs: don't accept inode buffers with suspicious unlinked chains xfs: move inode extent size hint validation to libxfs xfs: record inode buf errors as a xref error in inobt scrubber xfs: remove xfs_buf parameter from inode scrub methods xfs: inode scrubber shouldn't bother with raw checks xfs: bmap scrubber should do rmap xref with bmap for sparse files xfs: refactor inode buffer verifier error logging xfs: refactor inode verifier error logging xfs: refactor bmap record validation xfs: sanity-check the unused space before trying to use it xfs: detect agfl count corruption and reset agfl xfs: unwind the try_again loop in xfs_log_force xfs: refactor xfs_log_force_lsn xfs: minor cleanup for xfs_reflink_end_cow ...
Diffstat (limited to 'fs/xfs/libxfs/xfs_bmap.c')
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c51
1 files changed, 46 insertions, 5 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index daae00ed30c5..3b03d886df66 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -1244,8 +1244,9 @@ xfs_iread_extents(
xfs_warn(ip->i_mount,
"corrupt dinode %Lu, (btree extents).",
(unsigned long long) ip->i_ino);
- XFS_CORRUPTION_ERROR(__func__,
- XFS_ERRLEVEL_LOW, ip->i_mount, block);
+ xfs_inode_verifier_error(ip, -EFSCORRUPTED,
+ __func__, block, sizeof(*block),
+ __this_address);
error = -EFSCORRUPTED;
goto out_brelse;
}
@@ -1261,11 +1262,15 @@ xfs_iread_extents(
*/
frp = XFS_BMBT_REC_ADDR(mp, block, 1);
for (j = 0; j < num_recs; j++, frp++, i++) {
+ xfs_failaddr_t fa;
+
xfs_bmbt_disk_get_all(frp, &new);
- if (!xfs_bmbt_validate_extent(mp, whichfork, &new)) {
- XFS_ERROR_REPORT("xfs_bmap_read_extents(2)",
- XFS_ERRLEVEL_LOW, mp);
+ fa = xfs_bmap_validate_extent(ip, whichfork, &new);
+ if (fa) {
error = -EFSCORRUPTED;
+ xfs_inode_verifier_error(ip, error,
+ "xfs_iread_extents(2)",
+ frp, sizeof(*frp), fa);
goto out_brelse;
}
xfs_iext_insert(ip, &icur, &new, state);
@@ -6154,3 +6159,39 @@ xfs_bmap_finish_one(
return error;
}
+
+/* Check that an inode's extent does not have invalid flags or bad ranges. */
+xfs_failaddr_t
+xfs_bmap_validate_extent(
+ struct xfs_inode *ip,
+ int whichfork,
+ struct xfs_bmbt_irec *irec)
+{
+ struct xfs_mount *mp = ip->i_mount;
+ xfs_fsblock_t endfsb;
+ bool isrt;
+
+ isrt = XFS_IS_REALTIME_INODE(ip);
+ endfsb = irec->br_startblock + irec->br_blockcount - 1;
+ if (isrt) {
+ if (!xfs_verify_rtbno(mp, irec->br_startblock))
+ return __this_address;
+ if (!xfs_verify_rtbno(mp, endfsb))
+ return __this_address;
+ } else {
+ if (!xfs_verify_fsbno(mp, irec->br_startblock))
+ return __this_address;
+ if (!xfs_verify_fsbno(mp, endfsb))
+ return __this_address;
+ if (XFS_FSB_TO_AGNO(mp, irec->br_startblock) !=
+ XFS_FSB_TO_AGNO(mp, endfsb))
+ return __this_address;
+ }
+ if (irec->br_state != XFS_EXT_NORM) {
+ if (whichfork != XFS_DATA_FORK)
+ return __this_address;
+ if (!xfs_sb_version_hasextflgbit(&mp->m_sb))
+ return __this_address;
+ }
+ return NULL;
+}