mm/filemap: fix mapping_seek_hole_data on THP & 32-bit

No problem on 64-bit, or without huge pages, but xfstests generic/285
and other SEEK_HOLE/SEEK_DATA tests have regressed on huge tmpfs, and on
32-bit architectures, with the new mapping_seek_hole_data().  Several
different bugs turned out to need fixing.

u64 cast to stop losing bits when converting unsigned long to loff_t
(and let's use shifts throughout, rather than mixed with * and /).

Use round_up() when advancing pos, to stop assuming that pos was already
THP-aligned when advancing it by THP-size.  (This use of round_up()
assumes that any THP has THP-aligned index: true at present and true
going forward, but could be recoded to avoid the assumption.)

Use xas_set() when iterating away from a THP, so that xa_index stays in
synch with start, instead of drifting away to return bogus offset.

Check start against end to avoid wrapping 32-bit xa_index to 0 (and to
handle these additional cases, seek_data or not, it's easier to break
the loop than goto: so rearrange exit from the function).

[ remove unneeded u64 casts, per Matthew]

Fixes: 41139aa4c3a3 ("mm/filemap: add mapping_seek_hole_data")
Signed-off-by: Hugh Dickins <>
Cc: Christoph Hellwig <>
Cc: Dave Chinner <>
Cc: Jan Kara <>
Cc: Johannes Weiner <>
Cc: "Kirill A. Shutemov" <>
Cc: Matthew Wilcox <>
Cc: William Kucharski <>
Cc: Yang Shi <>
Signed-off-by: Andrew Morton <>
Signed-off-by: Linus Torvalds <>
1 file changed