From: Greg Kroah-Hartman Date: Mon, 5 Jun 2017 14:08:28 +0000 (+0200) Subject: 4.4-stable patches X-Git-Tag: v3.18.56~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=937a74c176e4cc98e89ba8d4efeaf3df770c5f27;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: xfs-fix-missed-holes-in-seek_hole-implementation.patch xfs-fix-off-by-one-on-max-nr_pages-in-xfs_find_get_desired_pgoff.patch --- diff --git a/queue-4.4/series b/queue-4.4/series index 6f76faaba12..3dc8b748e38 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -37,3 +37,5 @@ drm-gma500-psb-actually-use-vbt-mode-when-it-is-found.patch mm-migrate-fix-refcount-handling-when-hugepage_migration_supported.patch mlock-fix-mlock-count-can-not-decrease-in-race-condition.patch pci-pm-add-needs_resume-flag-to-avoid-suspend-complete-optimization.patch +xfs-fix-missed-holes-in-seek_hole-implementation.patch +xfs-fix-off-by-one-on-max-nr_pages-in-xfs_find_get_desired_pgoff.patch diff --git a/queue-4.4/xfs-fix-missed-holes-in-seek_hole-implementation.patch b/queue-4.4/xfs-fix-missed-holes-in-seek_hole-implementation.patch new file mode 100644 index 00000000000..829f134b85a --- /dev/null +++ b/queue-4.4/xfs-fix-missed-holes-in-seek_hole-implementation.patch @@ -0,0 +1,87 @@ +From 5375023ae1266553a7baa0845e82917d8803f48c Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Thu, 18 May 2017 16:36:22 -0700 +Subject: xfs: Fix missed holes in SEEK_HOLE implementation + +From: Jan Kara + +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: d126d43f631f996daeee5006714fed914be32368 +Signed-off-by: Jan Kara +Reviewed-by: Brian Foster +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman + +--- + fs/xfs/xfs_file.c | 29 +++++++++-------------------- + 1 file changed, 9 insertions(+), 20 deletions(-) + +--- a/fs/xfs/xfs_file.c ++++ b/fs/xfs/xfs_file.c +@@ -1235,17 +1235,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; +@@ -1257,18 +1246,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); + /* diff --git a/queue-4.4/xfs-fix-off-by-one-on-max-nr_pages-in-xfs_find_get_desired_pgoff.patch b/queue-4.4/xfs-fix-off-by-one-on-max-nr_pages-in-xfs_find_get_desired_pgoff.patch new file mode 100644 index 00000000000..5ae1a2bf880 --- /dev/null +++ b/queue-4.4/xfs-fix-off-by-one-on-max-nr_pages-in-xfs_find_get_desired_pgoff.patch @@ -0,0 +1,54 @@ +From 8affebe16d79ebefb1d9d6d56a46dc89716f9453 Mon Sep 17 00:00:00 2001 +From: Eryu Guan +Date: Tue, 23 May 2017 08:30:46 -0700 +Subject: xfs: fix off-by-one on max nr_pages in xfs_find_get_desired_pgoff() + +From: Eryu Guan + +commit 8affebe16d79ebefb1d9d6d56a46dc89716f9453 upstream. + +xfs_find_get_desired_pgoff() is used to search for offset of hole or +data in page range [index, end] (both inclusive), and the max number +of pages to search should be at least one, if end == index. +Otherwise the only page is missed and no hole or data is found, +which is not correct. + +When block size is smaller than page size, this can be demonstrated +by preallocating a file with size smaller than page size and writing +data to the last block. E.g. run this xfs_io command on a 1k block +size XFS on x86_64 host. + + # xfs_io -fc "falloc 0 3k" -c "pwrite 2k 1k" \ + -c "seek -d 0" /mnt/xfs/testfile + wrote 1024/1024 bytes at offset 2048 + 1 KiB, 1 ops; 0.0000 sec (33.675 MiB/sec and 34482.7586 ops/sec) + Whence Result + DATA EOF + +Data at offset 2k was missed, and lseek(2) returned ENXIO. + +This is uncovered by generic/285 subtest 07 and 08 on ppc64 host, +where pagesize is 64k. Because a recent change to generic/285 +reduced the preallocated file size to smaller than 64k. + +Signed-off-by: Eryu Guan +Reviewed-by: Jan Kara +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman + +--- + fs/xfs/xfs_file.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/xfs/xfs_file.c ++++ b/fs/xfs/xfs_file.c +@@ -1208,7 +1208,7 @@ xfs_find_get_desired_pgoff( + unsigned nr_pages; + unsigned int i; + +- want = min_t(pgoff_t, end - index, PAGEVEC_SIZE); ++ want = min_t(pgoff_t, end - index, PAGEVEC_SIZE - 1) + 1; + nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index, + want); + /*