From: Greg Kroah-Hartman Date: Wed, 16 Oct 2019 13:29:03 +0000 (-0700) Subject: 4.14-stable patches X-Git-Tag: v4.4.197~20 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7a4d477fc4ccbc906b3088b0b3be07b07722aedf;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches 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 --- 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 index 00000000000..b89ebb84b0f --- /dev/null +++ b/queue-4.14/btrfs-fix-incorrect-updating-of-log-root-tree.patch @@ -0,0 +1,132 @@ +From 4203e968947071586a98b5314fd7ffdea3b4f971 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Mon, 30 Sep 2019 16:27:25 -0400 +Subject: btrfs: fix incorrect updating of log root tree + +From: Josef Bacik + +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 +Reviewed-by: Filipe Manana +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..fc62c73310b --- /dev/null +++ b/queue-4.14/mips-disable-loongson-mmi-instructions-for-kernel-build.patch @@ -0,0 +1,60 @@ +From 2f2b4fd674cadd8c6b40eb629e140a14db4068fd Mon Sep 17 00:00:00 2001 +From: Paul Burton +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 + +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 +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 +Cc: Jiaxun Yang +Cc: stable@vger.kernel.org # v2.6.32+ +Cc: linux-mips@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..97db0061b5c --- /dev/null +++ b/queue-4.14/nfs-fix-o_direct-accounting-of-number-of-bytes-read-written.patch @@ -0,0 +1,155 @@ +From 031d73ed768a40684f3ca21992265ffdb6a270bf Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Mon, 30 Sep 2019 14:02:56 -0400 +Subject: NFS: Fix O_DIRECT accounting of number of bytes read/written + +From: Trond Myklebust + +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 +Fixes: 1ccbad9f9f9bd ("nfs: fix DIO good bytes calculation") +Cc: stable@vger.kernel.org # 4.1+ +Signed-off-by: Trond Myklebust +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-4.14/series b/queue-4.14/series index 896fa137716..96844722b60 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -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