* [PATCH 1/3] xfs: Fix missed holes in SEEK_HOLE implementation
[not found] <20170517121046.2632-1-jack@suse.cz>
@ 2017-05-17 12:10 ` Jan Kara
0 siblings, 0 replies; 3+ messages in thread
From: Jan Kara @ 2017-05-17 12:10 UTC (permalink / raw)
To: Darrick J . Wong; +Cc: linux-xfs, Brian Foster, Jan Kara, stable
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.
CC: stable@vger.kernel.org
Fixes: d126d43f631f996daeee5006714fed914be32368
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/xfs/xfs_file.c | 29 +++++++++--------------------
1 file changed, 9 insertions(+), 20 deletions(-)
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 35703a801372..f371812e20c6 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1076,17 +1076,6 @@ xfs_find_get_desired_pgoff(
break;
}
- /*
- * At lease we found one page. If this is the first time we
- * step into the loop, and if the first page index offset is
- * greater than the given search offset, a hole was found.
- */
- if (type == HOLE_OFF && lastoff == startoff &&
- lastoff < page_offset(pvec.pages[0])) {
- found = true;
- break;
- }
-
for (i = 0; i < nr_pages; i++) {
struct page *page = pvec.pages[i];
loff_t b_offset;
@@ -1098,18 +1087,18 @@ xfs_find_get_desired_pgoff(
* file mapping. However, page->index will not change
* because we have a reference on the page.
*
- * Searching done if the page index is out of range.
- * If the current offset is not reaches the end of
- * the specified search range, there should be a hole
- * between them.
+ * If current page offset is beyond where we've ended,
+ * we've found a hole.
*/
- if (page->index > end) {
- if (type == HOLE_OFF && lastoff < endoff) {
- *offset = lastoff;
- found = true;
- }
+ if (type == HOLE_OFF && lastoff < endoff &&
+ lastoff < page_offset(pvec.pages[i])) {
+ found = true;
+ *offset = lastoff;
goto out;
}
+ /* Searching done if the page index is out of range. */
+ if (page->index > end)
+ goto out;
lock_page(page);
/*
--
2.12.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 1/3] xfs: Fix missed holes in SEEK_HOLE implementation
[not found] <20170518104850.14508-1-jack@suse.cz>
@ 2017-05-18 10:48 ` Jan Kara
2017-05-22 17:50 ` Brian Foster
0 siblings, 1 reply; 3+ messages in thread
From: Jan Kara @ 2017-05-18 10:48 UTC (permalink / raw)
To: Darrick J. Wong; +Cc: linux-xfs, Brian Foster, Eryu Guan, Jan Kara, stable
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.
CC: stable@vger.kernel.org
Fixes: d126d43f631f996daeee5006714fed914be32368
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/xfs/xfs_file.c | 29 +++++++++--------------------
1 file changed, 9 insertions(+), 20 deletions(-)
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 35703a801372..f371812e20c6 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1076,17 +1076,6 @@ xfs_find_get_desired_pgoff(
break;
}
- /*
- * At lease we found one page. If this is the first time we
- * step into the loop, and if the first page index offset is
- * greater than the given search offset, a hole was found.
- */
- if (type == HOLE_OFF && lastoff == startoff &&
- lastoff < page_offset(pvec.pages[0])) {
- found = true;
- break;
- }
-
for (i = 0; i < nr_pages; i++) {
struct page *page = pvec.pages[i];
loff_t b_offset;
@@ -1098,18 +1087,18 @@ xfs_find_get_desired_pgoff(
* file mapping. However, page->index will not change
* because we have a reference on the page.
*
- * Searching done if the page index is out of range.
- * If the current offset is not reaches the end of
- * the specified search range, there should be a hole
- * between them.
+ * If current page offset is beyond where we've ended,
+ * we've found a hole.
*/
- if (page->index > end) {
- if (type == HOLE_OFF && lastoff < endoff) {
- *offset = lastoff;
- found = true;
- }
+ if (type == HOLE_OFF && lastoff < endoff &&
+ lastoff < page_offset(pvec.pages[i])) {
+ found = true;
+ *offset = lastoff;
goto out;
}
+ /* Searching done if the page index is out of range. */
+ if (page->index > end)
+ goto out;
lock_page(page);
/*
--
2.12.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 1/3] xfs: Fix missed holes in SEEK_HOLE implementation
2017-05-18 10:48 ` [PATCH 1/3] xfs: Fix missed holes in SEEK_HOLE implementation Jan Kara
@ 2017-05-22 17:50 ` Brian Foster
0 siblings, 0 replies; 3+ messages in thread
From: Brian Foster @ 2017-05-22 17:50 UTC (permalink / raw)
To: Jan Kara; +Cc: Darrick J. Wong, linux-xfs, Eryu Guan, stable
On Thu, May 18, 2017 at 12:48:48PM +0200, Jan Kara wrote:
> 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.
>
> CC: stable@vger.kernel.org
> Fixes: d126d43f631f996daeee5006714fed914be32368
> Signed-off-by: Jan Kara <jack@suse.cz>
> ---
Reviewed-by: Brian Foster <bfoster@redhat.com>
> fs/xfs/xfs_file.c | 29 +++++++++--------------------
> 1 file changed, 9 insertions(+), 20 deletions(-)
>
> diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> index 35703a801372..f371812e20c6 100644
> --- a/fs/xfs/xfs_file.c
> +++ b/fs/xfs/xfs_file.c
> @@ -1076,17 +1076,6 @@ xfs_find_get_desired_pgoff(
> break;
> }
>
> - /*
> - * At lease we found one page. If this is the first time we
> - * step into the loop, and if the first page index offset is
> - * greater than the given search offset, a hole was found.
> - */
> - if (type == HOLE_OFF && lastoff == startoff &&
> - lastoff < page_offset(pvec.pages[0])) {
> - found = true;
> - break;
> - }
> -
> for (i = 0; i < nr_pages; i++) {
> struct page *page = pvec.pages[i];
> loff_t b_offset;
> @@ -1098,18 +1087,18 @@ xfs_find_get_desired_pgoff(
> * file mapping. However, page->index will not change
> * because we have a reference on the page.
> *
> - * Searching done if the page index is out of range.
> - * If the current offset is not reaches the end of
> - * the specified search range, there should be a hole
> - * between them.
> + * If current page offset is beyond where we've ended,
> + * we've found a hole.
> */
> - if (page->index > end) {
> - if (type == HOLE_OFF && lastoff < endoff) {
> - *offset = lastoff;
> - found = true;
> - }
> + if (type == HOLE_OFF && lastoff < endoff &&
> + lastoff < page_offset(pvec.pages[i])) {
> + found = true;
> + *offset = lastoff;
> goto out;
> }
> + /* Searching done if the page index is out of range. */
> + if (page->index > end)
> + goto out;
>
> lock_page(page);
> /*
> --
> 2.12.0
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-05-22 17:50 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20170518104850.14508-1-jack@suse.cz>
2017-05-18 10:48 ` [PATCH 1/3] xfs: Fix missed holes in SEEK_HOLE implementation Jan Kara
2017-05-22 17:50 ` Brian Foster
[not found] <20170517121046.2632-1-jack@suse.cz>
2017-05-17 12:10 ` Jan Kara
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).