iomap: support partial page discard on writeback block mapping failure
authorBrian Foster <bfoster@redhat.com>
Thu, 29 Oct 2020 21:30:48 +0000 (14:30 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Wed, 4 Nov 2020 16:52:46 +0000 (08:52 -0800)
commit763e4cdc0f6d5cea45c896fef67f7be4bdefcca7
treed25be46ce7b766d673986ac041d80a7c33bb34d3
parent869ae85dae64b5540e4362d7fe4cd520e10ec05c
iomap: support partial page discard on writeback block mapping failure

iomap writeback mapping failure only calls into ->discard_page() if
the current page has not been added to the ioend. Accordingly, the
XFS callback assumes a full page discard and invalidation. This is
problematic for sub-page block size filesystems where some portion
of a page might have been mapped successfully before a failure to
map a delalloc block occurs. ->discard_page() is not called in that
error scenario and the bio is explicitly failed by iomap via the
error return from ->prepare_ioend(). As a result, the filesystem
leaks delalloc blocks and corrupts the filesystem block counters.

Since XFS is the only user of ->discard_page(), tweak the semantics
to invoke the callback unconditionally on mapping errors and provide
the file offset that failed to map. Update xfs_discard_page() to
discard the corresponding portion of the file and pass the range
along to iomap_invalidatepage(). The latter already properly handles
both full and sub-page scenarios by not changing any iomap or page
state on sub-page invalidations.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
fs/iomap/buffered-io.c
fs/xfs/xfs_aops.c
include/linux/iomap.h