]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 1 Jul 2018 14:48:20 +0000 (16:48 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 1 Jul 2018 14:48:20 +0000 (16:48 +0200)
added patches:
block-fix-transfer-when-chunk-sectors-exceeds-max.patch
btrfs-fix-unexpected-cow-in-run_delalloc_nocow.patch
dm-thin-handle-running-out-of-data-space-vs-concurrent-discard.patch
spi-fix-scatterlist-elements-size-in-spi_map_buf.patch

queue-4.4/block-fix-transfer-when-chunk-sectors-exceeds-max.patch [new file with mode: 0644]
queue-4.4/btrfs-fix-unexpected-cow-in-run_delalloc_nocow.patch [new file with mode: 0644]
queue-4.4/dm-thin-handle-running-out-of-data-space-vs-concurrent-discard.patch [new file with mode: 0644]
queue-4.4/series
queue-4.4/spi-fix-scatterlist-elements-size-in-spi_map_buf.patch [new file with mode: 0644]

diff --git a/queue-4.4/block-fix-transfer-when-chunk-sectors-exceeds-max.patch b/queue-4.4/block-fix-transfer-when-chunk-sectors-exceeds-max.patch
new file mode 100644 (file)
index 0000000..ffeb976
--- /dev/null
@@ -0,0 +1,38 @@
+From 15bfd21fbc5d35834b9ea383dc458a1f0c9e3434 Mon Sep 17 00:00:00 2001
+From: Keith Busch <keith.busch@intel.com>
+Date: Tue, 26 Jun 2018 09:14:58 -0600
+Subject: block: Fix transfer when chunk sectors exceeds max
+
+From: Keith Busch <keith.busch@intel.com>
+
+commit 15bfd21fbc5d35834b9ea383dc458a1f0c9e3434 upstream.
+
+A device may have boundary restrictions where the number of sectors
+between boundaries exceeds its max transfer size. In this case, we need
+to cap the max size to the smaller of the two limits.
+
+Reported-by: Jitendra Bhivare <jitendra.bhivare@broadcom.com>
+Tested-by: Jitendra Bhivare <jitendra.bhivare@broadcom.com>
+Cc: <stable@vger.kernel.org>
+Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Keith Busch <keith.busch@intel.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/blkdev.h |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -882,8 +882,8 @@ static inline unsigned int blk_max_size_
+       if (!q->limits.chunk_sectors)
+               return q->limits.max_sectors;
+-      return q->limits.chunk_sectors -
+-                      (offset & (q->limits.chunk_sectors - 1));
++      return min(q->limits.max_sectors, (unsigned int)(q->limits.chunk_sectors -
++                      (offset & (q->limits.chunk_sectors - 1))));
+ }
+ static inline unsigned int blk_rq_get_max_sectors(struct request *rq)
diff --git a/queue-4.4/btrfs-fix-unexpected-cow-in-run_delalloc_nocow.patch b/queue-4.4/btrfs-fix-unexpected-cow-in-run_delalloc_nocow.patch
new file mode 100644 (file)
index 0000000..9db5726
--- /dev/null
@@ -0,0 +1,92 @@
+From 5811375325420052fcadd944792a416a43072b7f Mon Sep 17 00:00:00 2001
+From: Liu Bo <bo.li.liu@oracle.com>
+Date: Wed, 31 Jan 2018 17:09:13 -0700
+Subject: Btrfs: fix unexpected cow in run_delalloc_nocow
+
+From: Liu Bo <bo.li.liu@oracle.com>
+
+commit 5811375325420052fcadd944792a416a43072b7f upstream.
+
+Fstests generic/475 provides a way to fail metadata reads while
+checking if checksum exists for the inode inside run_delalloc_nocow(),
+and csum_exist_in_range() interprets error (-EIO) as inode having
+checksum and makes its caller enter the cow path.
+
+In case of free space inode, this ends up with a warning in
+cow_file_range().
+
+The same problem applies to btrfs_cross_ref_exist() since it may also
+read metadata in between.
+
+With this, run_delalloc_nocow() bails out when errors occur at the two
+places.
+
+cc: <stable@vger.kernel.org> v2.6.28+
+Fixes: 17d217fe970d ("Btrfs: fix nodatasum handling in balancing code")
+Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/inode.c |   33 ++++++++++++++++++++++++++++++---
+ 1 file changed, 30 insertions(+), 3 deletions(-)
+
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -1202,6 +1202,8 @@ static noinline int csum_exist_in_range(
+               list_del(&sums->list);
+               kfree(sums);
+       }
++      if (ret < 0)
++              return ret;
+       return 1;
+ }
+@@ -1351,10 +1353,23 @@ next_slot:
+                               goto out_check;
+                       if (btrfs_extent_readonly(root, disk_bytenr))
+                               goto out_check;
+-                      if (btrfs_cross_ref_exist(trans, root, ino,
++                      ret = btrfs_cross_ref_exist(trans, root, ino,
+                                                 found_key.offset -
+-                                                extent_offset, disk_bytenr))
++                                                extent_offset, disk_bytenr);
++                      if (ret) {
++                              /*
++                               * ret could be -EIO if the above fails to read
++                               * metadata.
++                               */
++                              if (ret < 0) {
++                                      if (cow_start != (u64)-1)
++                                              cur_offset = cow_start;
++                                      goto error;
++                              }
++
++                              WARN_ON_ONCE(nolock);
+                               goto out_check;
++                      }
+                       disk_bytenr += extent_offset;
+                       disk_bytenr += cur_offset - found_key.offset;
+                       num_bytes = min(end + 1, extent_end) - cur_offset;
+@@ -1372,8 +1387,20 @@ next_slot:
+                        * this ensure that csum for a given extent are
+                        * either valid or do not exist.
+                        */
+-                      if (csum_exist_in_range(root, disk_bytenr, num_bytes))
++                      ret = csum_exist_in_range(root, disk_bytenr, num_bytes);
++                      if (ret) {
++                              /*
++                               * ret could be -EIO if the above fails to read
++                               * metadata.
++                               */
++                              if (ret < 0) {
++                                      if (cow_start != (u64)-1)
++                                              cur_offset = cow_start;
++                                      goto error;
++                              }
++                              WARN_ON_ONCE(nolock);
+                               goto out_check;
++                      }
+                       nocow = 1;
+               } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
+                       extent_end = found_key.offset +
diff --git a/queue-4.4/dm-thin-handle-running-out-of-data-space-vs-concurrent-discard.patch b/queue-4.4/dm-thin-handle-running-out-of-data-space-vs-concurrent-discard.patch
new file mode 100644 (file)
index 0000000..e810051
--- /dev/null
@@ -0,0 +1,92 @@
+From a685557fbbc3122ed11e8ad3fa63a11ebc5de8c3 Mon Sep 17 00:00:00 2001
+From: Mike Snitzer <snitzer@redhat.com>
+Date: Tue, 26 Jun 2018 12:04:23 -0400
+Subject: dm thin: handle running out of data space vs concurrent discard
+
+From: Mike Snitzer <snitzer@redhat.com>
+
+commit a685557fbbc3122ed11e8ad3fa63a11ebc5de8c3 upstream.
+
+Discards issued to a DM thin device can complete to userspace (via
+fstrim) _before_ the metadata changes associated with the discards is
+reflected in the thinp superblock (e.g. free blocks).  As such, if a
+user constructs a test that loops repeatedly over these steps, block
+allocation can fail due to discards not having completed yet:
+1) fill thin device via filesystem file
+2) remove file
+3) fstrim
+
+From initial report, here:
+https://www.redhat.com/archives/dm-devel/2018-April/msg00022.html
+
+"The root cause of this issue is that dm-thin will first remove
+mapping and increase corresponding blocks' reference count to prevent
+them from being reused before DISCARD bios get processed by the
+underlying layers. However. increasing blocks' reference count could
+also increase the nr_allocated_this_transaction in struct sm_disk
+which makes smd->old_ll.nr_allocated +
+smd->nr_allocated_this_transaction bigger than smd->old_ll.nr_blocks.
+In this case, alloc_data_block() will never commit metadata to reset
+the begin pointer of struct sm_disk, because sm_disk_get_nr_free()
+always return an underflow value."
+
+While there is room for improvement to the space-map accounting that
+thinp is making use of: the reality is this test is inherently racey and
+will result in the previous iteration's fstrim's discard(s) completing
+vs concurrent block allocation, via dd, in the next iteration of the
+loop.
+
+No amount of space map accounting improvements will be able to allow
+user's to use a block before a discard of that block has completed.
+
+So the best we can really do is allow DM thinp to gracefully handle such
+aggressive use of all the pool's data by degrading the pool into
+out-of-data-space (OODS) mode.  We _should_ get that behaviour already
+(if space map accounting didn't falsely cause alloc_data_block() to
+believe free space was available).. but short of that we handle the
+current reality that dm_pool_alloc_data_block() can return -ENOSPC.
+
+Reported-by: Dennis Yang <dennisyang@qnap.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/dm-thin.c |   11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+--- a/drivers/md/dm-thin.c
++++ b/drivers/md/dm-thin.c
+@@ -1299,6 +1299,8 @@ static void schedule_external_copy(struc
+ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode);
++static void requeue_bios(struct pool *pool);
++
+ static void check_for_space(struct pool *pool)
+ {
+       int r;
+@@ -1311,8 +1313,10 @@ static void check_for_space(struct pool
+       if (r)
+               return;
+-      if (nr_free)
++      if (nr_free) {
+               set_pool_mode(pool, PM_WRITE);
++              requeue_bios(pool);
++      }
+ }
+ /*
+@@ -1389,7 +1393,10 @@ static int alloc_data_block(struct thin_
+       r = dm_pool_alloc_data_block(pool->pmd, result);
+       if (r) {
+-              metadata_operation_failed(pool, "dm_pool_alloc_data_block", r);
++              if (r == -ENOSPC)
++                      set_pool_mode(pool, PM_OUT_OF_DATA_SPACE);
++              else
++                      metadata_operation_failed(pool, "dm_pool_alloc_data_block", r);
+               return r;
+       }
index db707269896d2a4834cd37c92f48f40a6a4a0dd4..85180df33ae0c9f9a69ef95da38d16bacaf9274f 100644 (file)
@@ -97,3 +97,7 @@ input-elan_i2c_smbus-fix-more-potential-stack-buffer-overflows.patch
 input-elantech-enable-middle-button-of-touchpads-on-thinkpad-p52.patch
 input-elantech-fix-v4-report-decoding-for-module-with-middle-key.patch
 alsa-hda-realtek-add-a-quirk-for-fsc-esprimo-u9210.patch
+btrfs-fix-unexpected-cow-in-run_delalloc_nocow.patch
+spi-fix-scatterlist-elements-size-in-spi_map_buf.patch
+block-fix-transfer-when-chunk-sectors-exceeds-max.patch
+dm-thin-handle-running-out-of-data-space-vs-concurrent-discard.patch
diff --git a/queue-4.4/spi-fix-scatterlist-elements-size-in-spi_map_buf.patch b/queue-4.4/spi-fix-scatterlist-elements-size-in-spi_map_buf.patch
new file mode 100644 (file)
index 0000000..61a6ec8
--- /dev/null
@@ -0,0 +1,50 @@
+From ce99319a182fe766be67f96338386f3ec73e321c Mon Sep 17 00:00:00 2001
+From: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Date: Fri, 2 Mar 2018 15:55:09 +0100
+Subject: spi: Fix scatterlist elements size in spi_map_buf
+
+From: Maxime Chevallier <maxime.chevallier@bootlin.com>
+
+commit ce99319a182fe766be67f96338386f3ec73e321c upstream.
+
+When SPI transfers can be offloaded using DMA, the SPI core need to
+build a scatterlist to make sure that the buffer to be transferred is
+dma-able.
+
+This patch fixes the scatterlist entry size computation in the case
+where the maximum acceptable scatterlist entry supported by the DMA
+controller is less than PAGE_SIZE, when the buffer is vmalloced.
+
+For each entry, the actual size is given by the minimum between the
+desc_len (which is the max buffer size supported by the DMA controller)
+and the remaining buffer length until we cross a page boundary.
+
+Fixes: 65598c13fd66 ("spi: Fix per-page mapping of unaligned vmalloc-ed buffer")
+Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi.c |   10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/spi/spi.c
++++ b/drivers/spi/spi.c
+@@ -707,8 +707,14 @@ static int spi_map_buf(struct spi_master
+       for (i = 0; i < sgs; i++) {
+               if (vmalloced_buf) {
+-                      min = min_t(size_t,
+-                                  len, desc_len - offset_in_page(buf));
++                      /*
++                       * Next scatterlist entry size is the minimum between
++                       * the desc_len and the remaining buffer length that
++                       * fits in a page.
++                       */
++                      min = min_t(size_t, desc_len,
++                                  min_t(size_t, len,
++                                        PAGE_SIZE - offset_in_page(buf)));
+                       vm_page = vmalloc_to_page(buf);
+                       if (!vm_page) {
+                               sg_free_table(sgt);