]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 5 Jun 2017 14:08:28 +0000 (16:08 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 5 Jun 2017 14:08:28 +0000 (16:08 +0200)
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

queue-4.4/series
queue-4.4/xfs-fix-missed-holes-in-seek_hole-implementation.patch [new file with mode: 0644]
queue-4.4/xfs-fix-off-by-one-on-max-nr_pages-in-xfs_find_get_desired_pgoff.patch [new file with mode: 0644]

index 6f76faaba12e932e9016082eac51a7e44c762056..3dc8b748e389ec272d1f86ed8d3f60d7cd2068d2 100644 (file)
@@ -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 (file)
index 0000000..829f134
--- /dev/null
@@ -0,0 +1,87 @@
+From 5375023ae1266553a7baa0845e82917d8803f48c Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 18 May 2017 16:36:22 -0700
+Subject: xfs: Fix missed holes in SEEK_HOLE implementation
+
+From: Jan Kara <jack@suse.cz>
+
+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 <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>
+
+---
+ 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 (file)
index 0000000..5ae1a2b
--- /dev/null
@@ -0,0 +1,54 @@
+From 8affebe16d79ebefb1d9d6d56a46dc89716f9453 Mon Sep 17 00:00:00 2001
+From: Eryu Guan <eguan@redhat.com>
+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 <eguan@redhat.com>
+
+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 <eguan@redhat.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+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>
+
+---
+ 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);
+               /*