android_kernel_oneplus_msm8998/fs/xfs/libxfs
Brian Foster 55ffb6acd2 xfs: detect agfl count corruption and reset agfl
commit a27ba2607e60312554cbcd43fc660b2c7f29dc9c upstream.

The struct xfs_agfl v5 header was originally introduced with
unexpected padding that caused the AGFL to operate with one less
slot than intended. The header has since been packed, but the fix
left an incompatibility for users who upgrade from an old kernel
with the unpacked header to a newer kernel with the packed header
while the AGFL happens to wrap around the end. The newer kernel
recognizes one extra slot at the physical end of the AGFL that the
previous kernel did not. The new kernel will eventually attempt to
allocate a block from that slot, which contains invalid data, and
cause a crash.

This condition can be detected by comparing the active range of the
AGFL to the count. While this detects a padding mismatch, it can
also trigger false positives for unrelated flcount corruption. Since
we cannot distinguish a size mismatch due to padding from unrelated
corruption, we can't trust the AGFL enough to simply repopulate the
empty slot.

Instead, avoid unnecessarily complex detection logic and and use a
solution that can handle any form of flcount corruption that slips
through read verifiers: distrust the entire AGFL and reset it to an
empty state. Any valid blocks within the AGFL are intentionally
leaked. This requires xfs_repair to rectify (which was already
necessary based on the state the AGFL was found in). The reset
mitigates the side effect of the padding mismatch problem from a
filesystem crash to a free space accounting inconsistency. The
generic approach also means that this patch can be safely backported
to kernels with or without a packed struct xfs_agfl.

Check the AGF for an invalid freelist count on initial read from
disk. If detected, set a flag on the xfs_perag to indicate that a
reset is required before the AGFL can be used. In the first
transaction that attempts to use a flagged AGFL, reset it to empty,
warn the user about the inconsistency and allow the freelist fixup
code to repopulate the AGFL with new blocks. The xfs_perag flag is
cleared to eliminate the need for repeated checks on each block
allocation operation.

This allows kernels that include the packing fix commit 96f859d52bcb
("libxfs: pack the agfl header structure so XFS_AGFL_SIZE is correct")
to handle older unpacked AGFL formats without a filesystem crash.

Suggested-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by Dave Chiluk <chiluk+linuxxfs@indeed.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Dave Chiluk <chiluk+linuxxfs@indeed.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2018-06-06 16:46:20 +02:00
..
xfs_alloc.c xfs: detect agfl count corruption and reset agfl 2018-06-06 16:46:20 +02:00
xfs_alloc.h xfs: introduce BMAPI_ZERO for allocating zeroed extents 2015-11-03 12:27:22 +11:00
xfs_alloc_btree.c xfs: print name of verifier if it fails 2016-06-07 18:14:38 -07:00
xfs_alloc_btree.h libxfs: move header files 2014-06-25 14:57:36 +10:00
xfs_attr.c xfs: remove racy hasattr check from attr ops 2018-05-30 07:48:52 +02:00
xfs_attr_leaf.c xfs: print name of verifier if it fails 2016-06-07 18:14:38 -07:00
xfs_attr_leaf.h xfs: xfs_attr_inactive leaves inconsistent attr fork state behind 2015-05-29 07:40:08 +10:00
xfs_attr_remote.c xfs: print name of verifier if it fails 2016-06-07 18:14:38 -07:00
xfs_attr_remote.h libxfs: move header files 2014-06-25 14:57:36 +10:00
xfs_attr_sf.h libxfs: move header files 2014-06-25 14:57:36 +10:00
xfs_bit.c libxfs: add xfs_bit.c 2015-07-29 11:52:08 +10:00
xfs_bit.h libxfs: move header files 2014-06-25 14:57:36 +10:00
xfs_bmap.c xfs: fix incorrect extent state in xfs_bmap_add_extent_unwritten_real 2017-12-20 10:05:00 +01:00
xfs_bmap.h xfs: introduce BMAPI_ZERO for allocating zeroed extents 2015-11-03 12:27:22 +11:00
xfs_bmap_btree.c xfs: print name of verifier if it fails 2016-06-07 18:14:38 -07:00
xfs_bmap_btree.h libxfs: move header files 2014-06-25 14:57:36 +10:00
xfs_btree.c xfs: fix unaligned access in xfs_btree_visit_blocks 2017-06-07 12:06:03 +02:00
xfs_btree.h xfs: per-filesystem stats counter implementation 2015-10-12 18:21:22 +11:00
xfs_cksum.h libxfs: move header files 2014-06-25 14:57:36 +10:00
xfs_da_btree.c xfs: print name of verifier if it fails 2016-06-07 18:14:38 -07:00
xfs_da_btree.h libxfs: move header files 2014-06-25 14:57:36 +10:00
xfs_da_format.c xfs: move most of xfs_sb.h to xfs_format.h 2014-11-28 14:27:09 +11:00
xfs_da_format.h xfs: Fix xfs_attr_leafblock definition 2015-08-19 10:34:32 +10:00
xfs_dir2.c xfs: per-filesystem stats counter implementation 2015-10-12 18:21:22 +11:00
xfs_dir2.h xfs: move type conversion functions to xfs_dir.h 2014-12-04 09:43:17 +11:00
xfs_dir2_block.c xfs: print name of verifier if it fails 2016-06-07 18:14:38 -07:00
xfs_dir2_data.c xfs: print name of verifier if it fails 2016-06-07 18:14:38 -07:00
xfs_dir2_leaf.c xfs: print name of verifier if it fails 2016-06-07 18:14:38 -07:00
xfs_dir2_node.c xfs: print name of verifier if it fails 2016-06-07 18:14:38 -07:00
xfs_dir2_priv.h xfs: move type conversion functions to xfs_dir.h 2014-12-04 09:43:17 +11:00
xfs_dir2_sf.c Merge branch 'xfs-misc-fixes-for-3.19-2' into for-next 2014-12-04 09:46:17 +11:00
xfs_dquot_buf.c libxfs: clean up _calc_dquots_per_chunk 2016-11-10 16:36:32 +01:00
xfs_format.h libxfs: pack the agfl header structure so XFS_AGFL_SIZE is correct 2016-02-25 12:01:24 -08:00
xfs_fs.h xfs: prefix XATTR_LIST_MAX with XFS_ 2015-10-12 16:02:56 +11:00
xfs_ialloc.c xfs: print name of verifier if it fails 2016-06-07 18:14:38 -07:00
xfs_ialloc.h Merge branch 'xfs-misc-fixes-for-4.2-3' into for-next 2015-06-23 08:49:01 +10:00
xfs_ialloc_btree.c xfs: print name of verifier if it fails 2016-06-07 18:14:38 -07:00
xfs_ialloc_btree.h xfs: allocate sparse inode chunks on full chunk allocation failure 2015-05-29 09:18:32 +10:00
xfs_inode_buf.c xfs: don't allow di_size with high bit set 2017-03-30 09:35:18 +02:00
xfs_inode_buf.h libxfs: move header files 2014-06-25 14:57:36 +10:00
xfs_inode_fork.c xfs: merge xfs_inum.h into xfs_format.h 2014-11-28 14:27:10 +11:00
xfs_inode_fork.h libxfs: move header files 2014-06-25 14:57:36 +10:00
xfs_log_format.h xfs: merge xfs_dinode.h into xfs_format.h 2014-11-28 14:24:06 +11:00
xfs_log_recover.h libxfs: move header files 2014-06-25 14:57:36 +10:00
xfs_log_rlimit.c xfs: move most of xfs_sb.h to xfs_format.h 2014-11-28 14:27:09 +11:00
xfs_quota_defs.h xfs: handle dquot buffer readahead in log recovery correctly 2016-06-07 18:14:38 -07:00
xfs_rtbitmap.c xfs: move most of xfs_sb.h to xfs_format.h 2014-11-28 14:27:09 +11:00
xfs_sb.c xfs: fix superblock inprogress check 2016-09-15 08:27:52 +02:00
xfs_sb.h xfs: consolidate superblock logging functions 2015-01-22 09:10:31 +11:00
xfs_shared.h xfs: handle dquot buffer readahead in log recovery correctly 2016-06-07 18:14:38 -07:00
xfs_symlink_remote.c xfs: print name of verifier if it fails 2016-06-07 18:14:38 -07:00
xfs_trans_resv.c xfs: consolidate superblock logging functions 2015-01-22 09:10:31 +11:00
xfs_trans_resv.h xfs: clean up XFS_MIN_FREELIST macros 2015-06-22 10:13:30 +10:00
xfs_trans_space.h xfs: clean up XFS_MIN_FREELIST macros 2015-06-22 10:13:30 +10:00
xfs_types.h xfs: move xfs_types.h to libxfs 2015-01-09 10:46:31 +11:00