]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 16 Oct 2019 13:29:03 +0000 (06:29 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 16 Oct 2019 13:29:03 +0000 (06:29 -0700)
added patches:
btrfs-fix-incorrect-updating-of-log-root-tree.patch
mips-disable-loongson-mmi-instructions-for-kernel-build.patch
nfs-fix-o_direct-accounting-of-number-of-bytes-read-written.patch

queue-4.14/btrfs-fix-incorrect-updating-of-log-root-tree.patch [new file with mode: 0644]
queue-4.14/mips-disable-loongson-mmi-instructions-for-kernel-build.patch [new file with mode: 0644]
queue-4.14/nfs-fix-o_direct-accounting-of-number-of-bytes-read-written.patch [new file with mode: 0644]
queue-4.14/series

diff --git a/queue-4.14/btrfs-fix-incorrect-updating-of-log-root-tree.patch b/queue-4.14/btrfs-fix-incorrect-updating-of-log-root-tree.patch
new file mode 100644 (file)
index 0000000..b89ebb8
--- /dev/null
@@ -0,0 +1,132 @@
+From 4203e968947071586a98b5314fd7ffdea3b4f971 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Mon, 30 Sep 2019 16:27:25 -0400
+Subject: btrfs: fix incorrect updating of log root tree
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+commit 4203e968947071586a98b5314fd7ffdea3b4f971 upstream.
+
+We've historically had reports of being unable to mount file systems
+because the tree log root couldn't be read.  Usually this is the "parent
+transid failure", but could be any of the related errors, including
+"fsid mismatch" or "bad tree block", depending on which block got
+allocated.
+
+The modification of the individual log root items are serialized on the
+per-log root root_mutex.  This means that any modification to the
+per-subvol log root_item is completely protected.
+
+However we update the root item in the log root tree outside of the log
+root tree log_mutex.  We do this in order to allow multiple subvolumes
+to be updated in each log transaction.
+
+This is problematic however because when we are writing the log root
+tree out we update the super block with the _current_ log root node
+information.  Since these two operations happen independently of each
+other, you can end up updating the log root tree in between writing out
+the dirty blocks and setting the super block to point at the current
+root.
+
+This means we'll point at the new root node that hasn't been written
+out, instead of the one we should be pointing at.  Thus whatever garbage
+or old block we end up pointing at complains when we mount the file
+system later and try to replay the log.
+
+Fix this by copying the log's root item into a local root item copy.
+Then once we're safely under the log_root_tree->log_mutex we update the
+root item in the log_root_tree.  This way we do not modify the
+log_root_tree while we're committing it, fixing the problem.
+
+CC: stable@vger.kernel.org # 4.4+
+Reviewed-by: Chris Mason <clm@fb.com>
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/tree-log.c |   36 +++++++++++++++++++++++++++---------
+ 1 file changed, 27 insertions(+), 9 deletions(-)
+
+--- a/fs/btrfs/tree-log.c
++++ b/fs/btrfs/tree-log.c
+@@ -2729,7 +2729,8 @@ out:
+  * in the tree of log roots
+  */
+ static int update_log_root(struct btrfs_trans_handle *trans,
+-                         struct btrfs_root *log)
++                         struct btrfs_root *log,
++                         struct btrfs_root_item *root_item)
+ {
+       struct btrfs_fs_info *fs_info = log->fs_info;
+       int ret;
+@@ -2737,10 +2738,10 @@ static int update_log_root(struct btrfs_
+       if (log->log_transid == 1) {
+               /* insert root item on the first sync */
+               ret = btrfs_insert_root(trans, fs_info->log_root_tree,
+-                              &log->root_key, &log->root_item);
++                              &log->root_key, root_item);
+       } else {
+               ret = btrfs_update_root(trans, fs_info->log_root_tree,
+-                              &log->root_key, &log->root_item);
++                              &log->root_key, root_item);
+       }
+       return ret;
+ }
+@@ -2836,6 +2837,7 @@ int btrfs_sync_log(struct btrfs_trans_ha
+       struct btrfs_fs_info *fs_info = root->fs_info;
+       struct btrfs_root *log = root->log_root;
+       struct btrfs_root *log_root_tree = fs_info->log_root_tree;
++      struct btrfs_root_item new_root_item;
+       int log_transid = 0;
+       struct btrfs_log_ctx root_log_ctx;
+       struct blk_plug plug;
+@@ -2901,18 +2903,26 @@ int btrfs_sync_log(struct btrfs_trans_ha
+               goto out;
+       }
++      /*
++       * We _must_ update under the root->log_mutex in order to make sure we
++       * have a consistent view of the log root we are trying to commit at
++       * this moment.
++       *
++       * We _must_ copy this into a local copy, because we are not holding the
++       * log_root_tree->log_mutex yet.  This is important because when we
++       * commit the log_root_tree we must have a consistent view of the
++       * log_root_tree when we update the super block to point at the
++       * log_root_tree bytenr.  If we update the log_root_tree here we'll race
++       * with the commit and possibly point at the new block which we may not
++       * have written out.
++       */
+       btrfs_set_root_node(&log->root_item, log->node);
++      memcpy(&new_root_item, &log->root_item, sizeof(new_root_item));
+       root->log_transid++;
+       log->log_transid = root->log_transid;
+       root->log_start_pid = 0;
+       /*
+-       * Update or create log root item under the root's log_mutex to prevent
+-       * races with concurrent log syncs that can lead to failure to update
+-       * log root item because it was not created yet.
+-       */
+-      ret = update_log_root(trans, log);
+-      /*
+        * IO has been started, blocks of the log tree have WRITTEN flag set
+        * in their headers. new modifications of the log will be written to
+        * new positions. so it's safe to allow log writers to go in.
+@@ -2932,6 +2942,14 @@ int btrfs_sync_log(struct btrfs_trans_ha
+       mutex_unlock(&log_root_tree->log_mutex);
+       mutex_lock(&log_root_tree->log_mutex);
++
++      /*
++       * Now we are safe to update the log_root_tree because we're under the
++       * log_mutex, and we're a current writer so we're holding the commit
++       * open until we drop the log_mutex.
++       */
++      ret = update_log_root(trans, log, &new_root_item);
++
+       if (atomic_dec_and_test(&log_root_tree->log_writers)) {
+               /*
+                * Implicit memory barrier after atomic_dec_and_test
diff --git a/queue-4.14/mips-disable-loongson-mmi-instructions-for-kernel-build.patch b/queue-4.14/mips-disable-loongson-mmi-instructions-for-kernel-build.patch
new file mode 100644 (file)
index 0000000..fc62c73
--- /dev/null
@@ -0,0 +1,60 @@
+From 2f2b4fd674cadd8c6b40eb629e140a14db4068fd Mon Sep 17 00:00:00 2001
+From: Paul Burton <paul.burton@mips.com>
+Date: Thu, 10 Oct 2019 18:54:03 +0000
+Subject: MIPS: Disable Loongson MMI instructions for kernel build
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Paul Burton <paul.burton@mips.com>
+
+commit 2f2b4fd674cadd8c6b40eb629e140a14db4068fd upstream.
+
+GCC 9.x automatically enables support for Loongson MMI instructions when
+using some -march= flags, and then errors out when -msoft-float is
+specified with:
+
+  cc1: error: ‘-mloongson-mmi’ must be used with ‘-mhard-float’
+
+The kernel shouldn't be using these MMI instructions anyway, just as it
+doesn't use floating point instructions. Explicitly disable them in
+order to fix the build with GCC 9.x.
+
+Signed-off-by: Paul Burton <paul.burton@mips.com>
+Fixes: 3702bba5eb4f ("MIPS: Loongson: Add GCC 4.4 support for Loongson2E")
+Fixes: 6f7a251a259e ("MIPS: Loongson: Add basic Loongson 2F support")
+Fixes: 5188129b8c9f ("MIPS: Loongson-3: Improve -march option and move it to Platform")
+Cc: Huacai Chen <chenhc@lemote.com>
+Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Cc: stable@vger.kernel.org # v2.6.32+
+Cc: linux-mips@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/mips/loongson64/Platform |    4 ++++
+ arch/mips/vdso/Makefile       |    1 +
+ 2 files changed, 5 insertions(+)
+
+--- a/arch/mips/loongson64/Platform
++++ b/arch/mips/loongson64/Platform
+@@ -43,6 +43,10 @@ else
+       $(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64)
+ endif
++# Some -march= flags enable MMI instructions, and GCC complains about that
++# support being enabled alongside -msoft-float. Thus explicitly disable MMI.
++cflags-y += $(call cc-option,-mno-loongson-mmi)
++
+ #
+ # Loongson Machines' Support
+ #
+--- a/arch/mips/vdso/Makefile
++++ b/arch/mips/vdso/Makefile
+@@ -9,6 +9,7 @@ ccflags-vdso := \
+       $(filter -mmicromips,$(KBUILD_CFLAGS)) \
+       $(filter -march=%,$(KBUILD_CFLAGS)) \
+       $(filter -m%-float,$(KBUILD_CFLAGS)) \
++      $(filter -mno-loongson-%,$(KBUILD_CFLAGS)) \
+       -D__VDSO__
+ cflags-vdso := $(ccflags-vdso) \
+       $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
diff --git a/queue-4.14/nfs-fix-o_direct-accounting-of-number-of-bytes-read-written.patch b/queue-4.14/nfs-fix-o_direct-accounting-of-number-of-bytes-read-written.patch
new file mode 100644 (file)
index 0000000..97db006
--- /dev/null
@@ -0,0 +1,155 @@
+From 031d73ed768a40684f3ca21992265ffdb6a270bf Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trondmy@gmail.com>
+Date: Mon, 30 Sep 2019 14:02:56 -0400
+Subject: NFS: Fix O_DIRECT accounting of number of bytes read/written
+
+From: Trond Myklebust <trondmy@gmail.com>
+
+commit 031d73ed768a40684f3ca21992265ffdb6a270bf upstream.
+
+When a series of O_DIRECT reads or writes are truncated, either due to
+eof or due to an error, then we should return the number of contiguous
+bytes that were received/sent starting at the offset specified by the
+application.
+
+Currently, we are failing to correctly check contiguity, and so we're
+failing the generic/465 in xfstests when the race between the read
+and write RPCs causes the file to get extended while the 2 reads are
+outstanding. If the first read RPC call wins the race and returns with
+eof set, we should treat the second read RPC as being truncated.
+
+Reported-by: Su Yanjun <suyj.fnst@cn.fujitsu.com>
+Fixes: 1ccbad9f9f9bd ("nfs: fix DIO good bytes calculation")
+Cc: stable@vger.kernel.org # 4.1+
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/direct.c |   78 ++++++++++++++++++++++++++++++--------------------------
+ 1 file changed, 43 insertions(+), 35 deletions(-)
+
+--- a/fs/nfs/direct.c
++++ b/fs/nfs/direct.c
+@@ -122,32 +122,49 @@ static inline int put_dreq(struct nfs_di
+ }
+ static void
+-nfs_direct_good_bytes(struct nfs_direct_req *dreq, struct nfs_pgio_header *hdr)
++nfs_direct_handle_truncated(struct nfs_direct_req *dreq,
++                          const struct nfs_pgio_header *hdr,
++                          ssize_t dreq_len)
++{
++      struct nfs_direct_mirror *mirror = &dreq->mirrors[hdr->pgio_mirror_idx];
++
++      if (!(test_bit(NFS_IOHDR_ERROR, &hdr->flags) ||
++            test_bit(NFS_IOHDR_EOF, &hdr->flags)))
++              return;
++      if (dreq->max_count >= dreq_len) {
++              dreq->max_count = dreq_len;
++              if (dreq->count > dreq_len)
++                      dreq->count = dreq_len;
++
++              if (test_bit(NFS_IOHDR_ERROR, &hdr->flags))
++                      dreq->error = hdr->error;
++              else /* Clear outstanding error if this is EOF */
++                      dreq->error = 0;
++      }
++      if (mirror->count > dreq_len)
++              mirror->count = dreq_len;
++}
++
++static void
++nfs_direct_count_bytes(struct nfs_direct_req *dreq,
++                     const struct nfs_pgio_header *hdr)
+ {
+-      int i;
+-      ssize_t count;
++      struct nfs_direct_mirror *mirror = &dreq->mirrors[hdr->pgio_mirror_idx];
++      loff_t hdr_end = hdr->io_start + hdr->good_bytes;
++      ssize_t dreq_len = 0;
+-      WARN_ON_ONCE(dreq->count >= dreq->max_count);
++      if (hdr_end > dreq->io_start)
++              dreq_len = hdr_end - dreq->io_start;
+-      if (dreq->mirror_count == 1) {
+-              dreq->mirrors[hdr->pgio_mirror_idx].count += hdr->good_bytes;
+-              dreq->count += hdr->good_bytes;
+-      } else {
+-              /* mirrored writes */
+-              count = dreq->mirrors[hdr->pgio_mirror_idx].count;
+-              if (count + dreq->io_start < hdr->io_start + hdr->good_bytes) {
+-                      count = hdr->io_start + hdr->good_bytes - dreq->io_start;
+-                      dreq->mirrors[hdr->pgio_mirror_idx].count = count;
+-              }
+-              /* update the dreq->count by finding the minimum agreed count from all
+-               * mirrors */
+-              count = dreq->mirrors[0].count;
++      nfs_direct_handle_truncated(dreq, hdr, dreq_len);
+-              for (i = 1; i < dreq->mirror_count; i++)
+-                      count = min(count, dreq->mirrors[i].count);
++      if (dreq_len > dreq->max_count)
++              dreq_len = dreq->max_count;
+-              dreq->count = count;
+-      }
++      if (mirror->count < dreq_len)
++              mirror->count = dreq_len;
++      if (dreq->count < dreq_len)
++              dreq->count = dreq_len;
+ }
+ /*
+@@ -401,20 +418,12 @@ static void nfs_direct_read_completion(s
+       struct nfs_direct_req *dreq = hdr->dreq;
+       spin_lock(&dreq->lock);
+-      if (test_bit(NFS_IOHDR_ERROR, &hdr->flags))
+-              dreq->error = hdr->error;
+-
+       if (test_bit(NFS_IOHDR_REDO, &hdr->flags)) {
+               spin_unlock(&dreq->lock);
+               goto out_put;
+       }
+-      if (hdr->good_bytes != 0)
+-              nfs_direct_good_bytes(dreq, hdr);
+-
+-      if (test_bit(NFS_IOHDR_EOF, &hdr->flags))
+-              dreq->error = 0;
+-
++      nfs_direct_count_bytes(dreq, hdr);
+       spin_unlock(&dreq->lock);
+       while (!list_empty(&hdr->pages)) {
+@@ -651,6 +660,9 @@ static void nfs_direct_write_reschedule(
+       nfs_direct_write_scan_commit_list(dreq->inode, &reqs, &cinfo);
+       dreq->count = 0;
++      dreq->max_count = 0;
++      list_for_each_entry(req, &reqs, wb_list)
++              dreq->max_count += req->wb_bytes;
+       dreq->verf.committed = NFS_INVALID_STABLE_HOW;
+       nfs_clear_pnfs_ds_commit_verifiers(&dreq->ds_cinfo);
+       for (i = 0; i < dreq->mirror_count; i++)
+@@ -783,17 +795,13 @@ static void nfs_direct_write_completion(
+       nfs_init_cinfo_from_dreq(&cinfo, dreq);
+       spin_lock(&dreq->lock);
+-
+-      if (test_bit(NFS_IOHDR_ERROR, &hdr->flags))
+-              dreq->error = hdr->error;
+-
+       if (test_bit(NFS_IOHDR_REDO, &hdr->flags)) {
+               spin_unlock(&dreq->lock);
+               goto out_put;
+       }
++      nfs_direct_count_bytes(dreq, hdr);
+       if (hdr->good_bytes != 0) {
+-              nfs_direct_good_bytes(dreq, hdr);
+               if (nfs_write_need_commit(hdr)) {
+                       if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES)
+                               request_commit = true;
index 896fa137716836b4135175e0473e784e98afa8c1..96844722b60396404657956c67ed07ec55a0bda6 100644 (file)
@@ -52,3 +52,6 @@ gpiolib-don-t-clear-flag_is_out-when-emulating-open-.patch
 staging-fbtft-fix-memory-leak-in-fbtft_framebuffer_a.patch
 iio-hx711-add-delay-until-dout-is-ready.patch
 iio-adc-hx711-fix-bug-in-sampling-of-data.patch
+btrfs-fix-incorrect-updating-of-log-root-tree.patch
+nfs-fix-o_direct-accounting-of-number-of-bytes-read-written.patch
+mips-disable-loongson-mmi-instructions-for-kernel-build.patch