Skip to content

Commit b9a7816

Browse files
jankaragregkh
authored andcommitted
xfs: Fix missed holes in SEEK_HOLE implementation
commit 5375023ae1266553a7baa0845e82917d8803f48c upstream. XFS SEEK_HOLE implementation could miss a hole in an unwritten extent as can be seen by the following command: xfs_io -c "falloc 0 256k" -c "pwrite 0 56k" -c "pwrite 128k 8k" -c "seek -h 0" file wrote 57344/57344 bytes at offset 0 56 KiB, 14 ops; 0.0000 sec (49.312 MiB/sec and 12623.9856 ops/sec) wrote 8192/8192 bytes at offset 131072 8 KiB, 2 ops; 0.0000 sec (70.383 MiB/sec and 18018.0180 ops/sec) Whence Result HOLE 139264 Where we can see that hole at offset 56k was just ignored by SEEK_HOLE implementation. The bug is in xfs_find_get_desired_pgoff() which does not properly detect the case when pages are not contiguous. Fix the problem by properly detecting when found page has larger offset than expected. Fixes: d126d43 Signed-off-by: Jan Kara <jack@suse.cz> Reviewed-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 03489bf commit b9a7816

1 file changed

Lines changed: 9 additions & 20 deletions

File tree

fs/xfs/xfs_file.c

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,17 +1235,6 @@ xfs_find_get_desired_pgoff(
12351235
break;
12361236
}
12371237

1238-
/*
1239-
* At lease we found one page. If this is the first time we
1240-
* step into the loop, and if the first page index offset is
1241-
* greater than the given search offset, a hole was found.
1242-
*/
1243-
if (type == HOLE_OFF && lastoff == startoff &&
1244-
lastoff < page_offset(pvec.pages[0])) {
1245-
found = true;
1246-
break;
1247-
}
1248-
12491238
for (i = 0; i < nr_pages; i++) {
12501239
struct page *page = pvec.pages[i];
12511240
loff_t b_offset;
@@ -1257,18 +1246,18 @@ xfs_find_get_desired_pgoff(
12571246
* file mapping. However, page->index will not change
12581247
* because we have a reference on the page.
12591248
*
1260-
* Searching done if the page index is out of range.
1261-
* If the current offset is not reaches the end of
1262-
* the specified search range, there should be a hole
1263-
* between them.
1249+
* If current page offset is beyond where we've ended,
1250+
* we've found a hole.
12641251
*/
1265-
if (page->index > end) {
1266-
if (type == HOLE_OFF && lastoff < endoff) {
1267-
*offset = lastoff;
1268-
found = true;
1269-
}
1252+
if (type == HOLE_OFF && lastoff < endoff &&
1253+
lastoff < page_offset(pvec.pages[i])) {
1254+
found = true;
1255+
*offset = lastoff;
12701256
goto out;
12711257
}
1258+
/* Searching done if the page index is out of range. */
1259+
if (page->index > end)
1260+
goto out;
12721261

12731262
lock_page(page);
12741263
/*

0 commit comments

Comments
 (0)