From: Sasha Levin Date: Wed, 4 Sep 2019 01:24:31 +0000 (-0400) Subject: fixes for 4.19 X-Git-Tag: v4.4.191~16 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=61ca79b25238f66ed5d87b3be963654eb832d5a6;p=thirdparty%2Fkernel%2Fstable-queue.git fixes for 4.19 Signed-off-by: Sasha Levin --- diff --git a/queue-4.19/i2c-piix4-fix-port-selection-for-amd-family-16h-mode.patch b/queue-4.19/i2c-piix4-fix-port-selection-for-amd-family-16h-mode.patch new file mode 100644 index 00000000000..3ae3c5b7401 --- /dev/null +++ b/queue-4.19/i2c-piix4-fix-port-selection-for-amd-family-16h-mode.patch @@ -0,0 +1,95 @@ +From eff46a2bfc4c007a702057f70825739651eb24c6 Mon Sep 17 00:00:00 2001 +From: Andrew Cooks +Date: Fri, 2 Aug 2019 14:52:46 +0200 +Subject: i2c: piix4: Fix port selection for AMD Family 16h Model 30h + +[ Upstream commit c7c06a1532f3fe106687ac82a13492c6a619ff1c ] + +Family 16h Model 30h SMBus controller needs the same port selection fix +as described and fixed in commit 0fe16195f891 ("i2c: piix4: Fix SMBus port +selection for AMD Family 17h chips") + +commit 6befa3fde65f ("i2c: piix4: Support alternative port selection +register") also fixed the port selection for Hudson2, but unfortunately +this is not the exact same device and the AMD naming and PCI Device IDs +aren't particularly helpful here. + +The SMBus port selection register is common to the following Families +and models, as documented in AMD's publicly available BIOS and Kernel +Developer Guides: + + 50742 - Family 15h Model 60h-6Fh (PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) + 55072 - Family 15h Model 70h-7Fh (PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) + 52740 - Family 16h Model 30h-3Fh (PCI_DEVICE_ID_AMD_HUDSON2_SMBUS) + +The Hudson2 PCI Device ID (PCI_DEVICE_ID_AMD_HUDSON2_SMBUS) is shared +between Bolton FCH and Family 16h Model 30h, but the location of the +SmBus0Sel port selection bits are different: + + 51192 - Bolton Register Reference Guide + +We distinguish between Bolton and Family 16h Model 30h using the PCI +Revision ID: + + Bolton is device 0x780b, revision 0x15 + Family 16h Model 30h is device 0x780b, revision 0x1F + Family 15h Model 60h and 70h are both device 0x790b, revision 0x4A. + +The following additional public AMD BKDG documents were checked and do +not share the same port selection register: + + 42301 - Family 15h Model 00h-0Fh doesn't mention any + 42300 - Family 15h Model 10h-1Fh doesn't mention any + 49125 - Family 15h Model 30h-3Fh doesn't mention any + + 48751 - Family 16h Model 00h-0Fh uses the previously supported + index register SB800_PIIX4_PORT_IDX_ALT at 0x2e + +Signed-off-by: Andrew Cooks +Signed-off-by: Jean Delvare +Cc: stable@vger.kernel.org [v4.6+] +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-piix4.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c +index 90946a8b9a75a..9ff3371ec385d 100644 +--- a/drivers/i2c/busses/i2c-piix4.c ++++ b/drivers/i2c/busses/i2c-piix4.c +@@ -98,7 +98,7 @@ + #define SB800_PIIX4_PORT_IDX_MASK 0x06 + #define SB800_PIIX4_PORT_IDX_SHIFT 1 + +-/* On kerncz, SmBus0Sel is at bit 20:19 of PMx00 DecodeEn */ ++/* On kerncz and Hudson2, SmBus0Sel is at bit 20:19 of PMx00 DecodeEn */ + #define SB800_PIIX4_PORT_IDX_KERNCZ 0x02 + #define SB800_PIIX4_PORT_IDX_MASK_KERNCZ 0x18 + #define SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ 3 +@@ -362,18 +362,16 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, + + /* Find which register is used for port selection */ + if (PIIX4_dev->vendor == PCI_VENDOR_ID_AMD) { +- switch (PIIX4_dev->device) { +- case PCI_DEVICE_ID_AMD_KERNCZ_SMBUS: ++ if (PIIX4_dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS || ++ (PIIX4_dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS && ++ PIIX4_dev->revision >= 0x1F)) { + piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_KERNCZ; + piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK_KERNCZ; + piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ; +- break; +- case PCI_DEVICE_ID_AMD_HUDSON2_SMBUS: +- default: ++ } else { + piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_ALT; + piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK; + piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT; +- break; + } + } else { + if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2, +-- +2.20.1 + diff --git a/queue-4.19/kvm-arm-arm64-vgic-fix-potential-deadlock-when-ap_li.patch b/queue-4.19/kvm-arm-arm64-vgic-fix-potential-deadlock-when-ap_li.patch new file mode 100644 index 00000000000..889bf5c06b9 --- /dev/null +++ b/queue-4.19/kvm-arm-arm64-vgic-fix-potential-deadlock-when-ap_li.patch @@ -0,0 +1,46 @@ +From 34df884147c0cb5a9d261b6bc83a334d914a654b Mon Sep 17 00:00:00 2001 +From: Heyi Guo +Date: Tue, 27 Aug 2019 12:26:50 +0100 +Subject: KVM: arm/arm64: vgic: Fix potential deadlock when ap_list is long + +[ Upstream commit d4a8061a7c5f7c27a2dc002ee4cb89b3e6637e44 ] + +If the ap_list is longer than 256 entries, merge_final() in list_sort() +will call the comparison callback with the same element twice, causing +a deadlock in vgic_irq_cmp(). + +Fix it by returning early when irqa == irqb. + +Cc: stable@vger.kernel.org # 4.7+ +Fixes: 8e4447457965 ("KVM: arm/arm64: vgic-new: Add IRQ sorting") +Signed-off-by: Zenghui Yu +Signed-off-by: Heyi Guo +[maz: massaged commit log and patch, added Fixes and Cc-stable] +Signed-off-by: Marc Zyngier +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + virt/kvm/arm/vgic/vgic.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c +index 250cd72c95a52..4040a33cdc902 100644 +--- a/virt/kvm/arm/vgic/vgic.c ++++ b/virt/kvm/arm/vgic/vgic.c +@@ -244,6 +244,13 @@ static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b) + bool penda, pendb; + int ret; + ++ /* ++ * list_sort may call this function with the same element when ++ * the list is fairly long. ++ */ ++ if (unlikely(irqa == irqb)) ++ return 0; ++ + spin_lock(&irqa->irq_lock); + spin_lock_nested(&irqb->irq_lock, SINGLE_DEPTH_NESTING); + +-- +2.20.1 + diff --git a/queue-4.19/kvm-arm-arm64-vgic-v2-handle-sgi-bits-in-gicd_i-s-c-.patch b/queue-4.19/kvm-arm-arm64-vgic-v2-handle-sgi-bits-in-gicd_i-s-c-.patch new file mode 100644 index 00000000000..2998e83b9a8 --- /dev/null +++ b/queue-4.19/kvm-arm-arm64-vgic-v2-handle-sgi-bits-in-gicd_i-s-c-.patch @@ -0,0 +1,103 @@ +From 584c5ae3bbeca8873dff21c8fc9746ebaf4c348c Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Wed, 28 Aug 2019 11:10:16 +0100 +Subject: KVM: arm/arm64: vgic-v2: Handle SGI bits in GICD_I{S,C}PENDR0 as WI + +[ Upstream commit 82e40f558de566fdee214bec68096bbd5e64a6a4 ] + +A guest is not allowed to inject a SGI (or clear its pending state) +by writing to GICD_ISPENDR0 (resp. GICD_ICPENDR0), as these bits are +defined as WI (as per ARM IHI 0048B 4.3.7 and 4.3.8). + +Make sure we correctly emulate the architecture. + +Fixes: 96b298000db4 ("KVM: arm/arm64: vgic-new: Add PENDING registers handlers") +Cc: stable@vger.kernel.org # 4.7+ +Reported-by: Andre Przywara +Signed-off-by: Marc Zyngier +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + virt/kvm/arm/vgic/vgic-mmio.c | 18 ++++++++++++++++++ + virt/kvm/arm/vgic/vgic-v2.c | 5 ++++- + virt/kvm/arm/vgic/vgic-v3.c | 5 ++++- + 3 files changed, 26 insertions(+), 2 deletions(-) + +diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c +index ceeda7e04a4d9..762f81900529e 100644 +--- a/virt/kvm/arm/vgic/vgic-mmio.c ++++ b/virt/kvm/arm/vgic/vgic-mmio.c +@@ -203,6 +203,12 @@ static void vgic_hw_irq_spending(struct kvm_vcpu *vcpu, struct vgic_irq *irq, + vgic_irq_set_phys_active(irq, true); + } + ++static bool is_vgic_v2_sgi(struct kvm_vcpu *vcpu, struct vgic_irq *irq) ++{ ++ return (vgic_irq_is_sgi(irq->intid) && ++ vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2); ++} ++ + void vgic_mmio_write_spending(struct kvm_vcpu *vcpu, + gpa_t addr, unsigned int len, + unsigned long val) +@@ -215,6 +221,12 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu, + for_each_set_bit(i, &val, len * 8) { + struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); + ++ /* GICD_ISPENDR0 SGI bits are WI */ ++ if (is_vgic_v2_sgi(vcpu, irq)) { ++ vgic_put_irq(vcpu->kvm, irq); ++ continue; ++ } ++ + spin_lock_irqsave(&irq->irq_lock, flags); + if (irq->hw) + vgic_hw_irq_spending(vcpu, irq, is_uaccess); +@@ -262,6 +274,12 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu, + for_each_set_bit(i, &val, len * 8) { + struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); + ++ /* GICD_ICPENDR0 SGI bits are WI */ ++ if (is_vgic_v2_sgi(vcpu, irq)) { ++ vgic_put_irq(vcpu->kvm, irq); ++ continue; ++ } ++ + spin_lock_irqsave(&irq->irq_lock, flags); + + if (irq->hw) +diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c +index 57281c1594d0f..91b14dfacd1dd 100644 +--- a/virt/kvm/arm/vgic/vgic-v2.c ++++ b/virt/kvm/arm/vgic/vgic-v2.c +@@ -195,7 +195,10 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr) + if (vgic_irq_is_sgi(irq->intid)) { + u32 src = ffs(irq->source); + +- BUG_ON(!src); ++ if (WARN_RATELIMIT(!src, "No SGI source for INTID %d\n", ++ irq->intid)) ++ return; ++ + val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT; + irq->source &= ~(1 << (src - 1)); + if (irq->source) { +diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c +index 5c55995a1a164..8b958ed05306e 100644 +--- a/virt/kvm/arm/vgic/vgic-v3.c ++++ b/virt/kvm/arm/vgic/vgic-v3.c +@@ -179,7 +179,10 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr) + model == KVM_DEV_TYPE_ARM_VGIC_V2) { + u32 src = ffs(irq->source); + +- BUG_ON(!src); ++ if (WARN_RATELIMIT(!src, "No SGI source for INTID %d\n", ++ irq->intid)) ++ return; ++ + val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT; + irq->source &= ~(1 << (src - 1)); + if (irq->source) { +-- +2.20.1 + diff --git a/queue-4.19/kvm-ppc-book3s-fix-incorrect-guest-to-user-translati.patch b/queue-4.19/kvm-ppc-book3s-fix-incorrect-guest-to-user-translati.patch new file mode 100644 index 00000000000..86337068a86 --- /dev/null +++ b/queue-4.19/kvm-ppc-book3s-fix-incorrect-guest-to-user-translati.patch @@ -0,0 +1,66 @@ +From a5d004887495eb0aaa1fcf1697cdf1afa4b66719 Mon Sep 17 00:00:00 2001 +From: Alexey Kardashevskiy +Date: Tue, 3 Sep 2019 16:16:27 -0400 +Subject: KVM: PPC: Book3S: Fix incorrect guest-to-user-translation error + handling + +[ Upstream commit ddfd151f3def9258397fcde7a372205a2d661903 ] + +H_PUT_TCE_INDIRECT handlers receive a page with up to 512 TCEs from +a guest. Although we verify correctness of TCEs before we do anything +with the existing tables, there is a small window when a check in +kvmppc_tce_validate might pass and right after that the guest alters +the page of TCEs, causing an early exit from the handler and leaving +srcu_read_lock(&vcpu->kvm->srcu) (virtual mode) or lock_rmap(rmap) +(real mode) locked. + +This fixes the bug by jumping to the common exit code with an appropriate +unlock. + +Cc: stable@vger.kernel.org # v4.11+ +Fixes: 121f80ba68f1 ("KVM: PPC: VFIO: Add in-kernel acceleration for VFIO") +Signed-off-by: Alexey Kardashevskiy +Signed-off-by: Paul Mackerras +Signed-off-by: Sasha Levin +--- + arch/powerpc/kvm/book3s_64_vio.c | 6 ++++-- + arch/powerpc/kvm/book3s_64_vio_hv.c | 6 ++++-- + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c +index 9a3f2646ecc7e..07a8004c3c237 100644 +--- a/arch/powerpc/kvm/book3s_64_vio.c ++++ b/arch/powerpc/kvm/book3s_64_vio.c +@@ -602,8 +602,10 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu, + + if (kvmppc_gpa_to_ua(vcpu->kvm, + tce & ~(TCE_PCI_READ | TCE_PCI_WRITE), +- &ua, NULL)) +- return H_PARAMETER; ++ &ua, NULL)) { ++ ret = H_PARAMETER; ++ goto unlock_exit; ++ } + + list_for_each_entry_lockless(stit, &stt->iommu_tables, next) { + ret = kvmppc_tce_iommu_map(vcpu->kvm, stt, +diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c +index 6821ead4b4ebc..eb8b11515a7ff 100644 +--- a/arch/powerpc/kvm/book3s_64_vio_hv.c ++++ b/arch/powerpc/kvm/book3s_64_vio_hv.c +@@ -528,8 +528,10 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu, + ua = 0; + if (kvmppc_gpa_to_ua(vcpu->kvm, + tce & ~(TCE_PCI_READ | TCE_PCI_WRITE), +- &ua, NULL)) +- return H_PARAMETER; ++ &ua, NULL)) { ++ ret = H_PARAMETER; ++ goto unlock_exit; ++ } + + list_for_each_entry_lockless(stit, &stt->iommu_tables, next) { + ret = kvmppc_rm_tce_iommu_map(vcpu->kvm, stt, +-- +2.20.1 + diff --git a/queue-4.19/nfs-clean-up-list-moves-of-struct-nfs_page.patch b/queue-4.19/nfs-clean-up-list-moves-of-struct-nfs_page.patch new file mode 100644 index 00000000000..77493a37516 --- /dev/null +++ b/queue-4.19/nfs-clean-up-list-moves-of-struct-nfs_page.patch @@ -0,0 +1,102 @@ +From c5b9c5821bc9e091db06728992659ebcf03ed476 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Mon, 18 Feb 2019 11:35:54 -0500 +Subject: NFS: Clean up list moves of struct nfs_page + +[ Upstream commit 078b5fd92c4913dd367361db6c28568386077c89 ] + +In several places we're just moving the struct nfs_page from one list to +another by first removing from the existing list, then adding to the new +one. + +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/direct.c | 3 +-- + fs/nfs/pagelist.c | 12 ++++-------- + include/linux/nfs_page.h | 10 ++++++++++ + 3 files changed, 15 insertions(+), 10 deletions(-) + +diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c +index 33824a0a57bfe..1377ee20ecf91 100644 +--- a/fs/nfs/direct.c ++++ b/fs/nfs/direct.c +@@ -664,8 +664,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) + + list_for_each_entry_safe(req, tmp, &reqs, wb_list) { + if (!nfs_pageio_add_request(&desc, req)) { +- nfs_list_remove_request(req); +- nfs_list_add_request(req, &failed); ++ nfs_list_move_request(req, &failed); + spin_lock(&cinfo.inode->i_lock); + dreq->flags = 0; + if (desc.pg_error < 0) +diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c +index 0ec6bce3dd692..d40bf560f3ca7 100644 +--- a/fs/nfs/pagelist.c ++++ b/fs/nfs/pagelist.c +@@ -769,8 +769,7 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc, + pageused = 0; + while (!list_empty(head)) { + req = nfs_list_entry(head->next); +- nfs_list_remove_request(req); +- nfs_list_add_request(req, &hdr->pages); ++ nfs_list_move_request(req, &hdr->pages); + + if (!last_page || last_page != req->wb_page) { + pageused++; +@@ -962,8 +961,7 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc, + } + if (!nfs_can_coalesce_requests(prev, req, desc)) + return 0; +- nfs_list_remove_request(req); +- nfs_list_add_request(req, &mirror->pg_list); ++ nfs_list_move_request(req, &mirror->pg_list); + mirror->pg_count += req->wb_bytes; + return 1; + } +@@ -995,8 +993,7 @@ nfs_pageio_cleanup_request(struct nfs_pageio_descriptor *desc, + { + LIST_HEAD(head); + +- nfs_list_remove_request(req); +- nfs_list_add_request(req, &head); ++ nfs_list_move_request(req, &head); + desc->pg_completion_ops->error_cleanup(&head); + } + +@@ -1242,9 +1239,8 @@ int nfs_pageio_resend(struct nfs_pageio_descriptor *desc, + while (!list_empty(&hdr->pages)) { + struct nfs_page *req = nfs_list_entry(hdr->pages.next); + +- nfs_list_remove_request(req); + if (!nfs_pageio_add_request(desc, req)) +- nfs_list_add_request(req, &failed); ++ nfs_list_move_request(req, &failed); + } + nfs_pageio_complete(desc); + if (!list_empty(&failed)) { +diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h +index e27572d30d977..ad69430fd0eb5 100644 +--- a/include/linux/nfs_page.h ++++ b/include/linux/nfs_page.h +@@ -164,6 +164,16 @@ nfs_list_add_request(struct nfs_page *req, struct list_head *head) + list_add_tail(&req->wb_list, head); + } + ++/** ++ * nfs_list_move_request - Move a request to a new list ++ * @req: request ++ * @head: head of list into which to insert the request. ++ */ ++static inline void ++nfs_list_move_request(struct nfs_page *req, struct list_head *head) ++{ ++ list_move_tail(&req->wb_list, head); ++} + + /** + * nfs_list_remove_request - Remove a request from its wb_list +-- +2.20.1 + diff --git a/queue-4.19/nfs-ensure-o_direct-reports-an-error-if-the-bytes-re.patch b/queue-4.19/nfs-ensure-o_direct-reports-an-error-if-the-bytes-re.patch new file mode 100644 index 00000000000..e99d75f2f4c --- /dev/null +++ b/queue-4.19/nfs-ensure-o_direct-reports-an-error-if-the-bytes-re.patch @@ -0,0 +1,89 @@ +From 5d45209bee4f09991ca2efa2cae99699d7e46257 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Mon, 12 Aug 2019 18:04:36 -0400 +Subject: NFS: Ensure O_DIRECT reports an error if the bytes read/written is 0 + +[ Upstream commit eb2c50da9e256dbbb3ff27694440e4c1900cfef8 ] + +If the attempt to resend the I/O results in no bytes being read/written, +we must ensure that we report the error. + +Signed-off-by: Trond Myklebust +Fixes: 0a00b77b331a ("nfs: mirroring support for direct io") +Cc: stable@vger.kernel.org # v3.20+ +Signed-off-by: Sasha Levin +--- + fs/nfs/direct.c | 27 ++++++++++++++++++--------- + fs/nfs/pagelist.c | 1 + + 2 files changed, 19 insertions(+), 9 deletions(-) + +diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c +index 0fd811ac08b52..f516ace8f45d3 100644 +--- a/fs/nfs/direct.c ++++ b/fs/nfs/direct.c +@@ -400,15 +400,21 @@ static void nfs_direct_read_completion(struct nfs_pgio_header *hdr) + unsigned long bytes = 0; + struct nfs_direct_req *dreq = hdr->dreq; + +- if (test_bit(NFS_IOHDR_REDO, &hdr->flags)) +- goto out_put; +- + spin_lock(&dreq->lock); +- if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) && (hdr->good_bytes == 0)) ++ if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) + dreq->error = hdr->error; +- else ++ ++ 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; ++ + spin_unlock(&dreq->lock); + + while (!list_empty(&hdr->pages)) { +@@ -774,16 +780,19 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr) + bool request_commit = false; + struct nfs_page *req = nfs_list_entry(hdr->pages.next); + +- if (test_bit(NFS_IOHDR_REDO, &hdr->flags)) +- goto out_put; +- + nfs_init_cinfo_from_dreq(&cinfo, dreq); + + spin_lock(&dreq->lock); + + if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) + dreq->error = hdr->error; +- if (dreq->error == 0) { ++ ++ 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 (nfs_write_need_commit(hdr)) { + if (dreq->flags == NFS_ODIRECT_RESCHED_WRITES) +diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c +index 7f0b9409202cc..d23ea74b5d203 100644 +--- a/fs/nfs/pagelist.c ++++ b/fs/nfs/pagelist.c +@@ -1248,6 +1248,7 @@ int nfs_pageio_resend(struct nfs_pageio_descriptor *desc, + if (!list_empty(&pages)) { + int err = desc->pg_error < 0 ? desc->pg_error : -EIO; + hdr->completion_ops->error_cleanup(&pages, err); ++ nfs_set_pgio_error(hdr, err, hdr->io_start); + return err; + } + return 0; +-- +2.20.1 + diff --git a/queue-4.19/nfs-pass-error-information-to-the-pgio-error-cleanup.patch b/queue-4.19/nfs-pass-error-information-to-the-pgio-error-cleanup.patch new file mode 100644 index 00000000000..b1d75288368 --- /dev/null +++ b/queue-4.19/nfs-pass-error-information-to-the-pgio-error-cleanup.patch @@ -0,0 +1,129 @@ +From b4943ce2cdb2c34ce990c39d320f885731209376 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Wed, 13 Feb 2019 10:39:39 -0500 +Subject: NFS: Pass error information to the pgio error cleanup routine + +[ Upstream commit df3accb849607a86278a37c35e6b313635ccc48b ] + +Allow the caller to pass error information when cleaning up a failed +I/O request so that we can conditionally take action to cancel the +request altogether if the error turned out to be fatal. + +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/direct.c | 4 ++-- + fs/nfs/pagelist.c | 5 +++-- + fs/nfs/read.c | 2 +- + fs/nfs/write.c | 11 +++++++++-- + include/linux/nfs_xdr.h | 2 +- + 5 files changed, 16 insertions(+), 8 deletions(-) + +diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c +index 1377ee20ecf91..0fd811ac08b52 100644 +--- a/fs/nfs/direct.c ++++ b/fs/nfs/direct.c +@@ -428,7 +428,7 @@ out_put: + hdr->release(hdr); + } + +-static void nfs_read_sync_pgio_error(struct list_head *head) ++static void nfs_read_sync_pgio_error(struct list_head *head, int error) + { + struct nfs_page *req; + +@@ -820,7 +820,7 @@ out_put: + hdr->release(hdr); + } + +-static void nfs_write_sync_pgio_error(struct list_head *head) ++static void nfs_write_sync_pgio_error(struct list_head *head, int error) + { + struct nfs_page *req; + +diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c +index 9cbd829b4ed5f..7f0b9409202cc 100644 +--- a/fs/nfs/pagelist.c ++++ b/fs/nfs/pagelist.c +@@ -994,7 +994,7 @@ nfs_pageio_cleanup_request(struct nfs_pageio_descriptor *desc, + LIST_HEAD(head); + + nfs_list_move_request(req, &head); +- desc->pg_completion_ops->error_cleanup(&head); ++ desc->pg_completion_ops->error_cleanup(&head, desc->pg_error); + } + + /** +@@ -1130,7 +1130,8 @@ static void nfs_pageio_error_cleanup(struct nfs_pageio_descriptor *desc) + + for (midx = 0; midx < desc->pg_mirror_count; midx++) { + mirror = &desc->pg_mirrors[midx]; +- desc->pg_completion_ops->error_cleanup(&mirror->pg_list); ++ desc->pg_completion_ops->error_cleanup(&mirror->pg_list, ++ desc->pg_error); + } + } + +diff --git a/fs/nfs/read.c b/fs/nfs/read.c +index 48d7277c60a97..09d5c282f50e9 100644 +--- a/fs/nfs/read.c ++++ b/fs/nfs/read.c +@@ -205,7 +205,7 @@ static void nfs_initiate_read(struct nfs_pgio_header *hdr, + } + + static void +-nfs_async_read_error(struct list_head *head) ++nfs_async_read_error(struct list_head *head, int error) + { + struct nfs_page *req; + +diff --git a/fs/nfs/write.c b/fs/nfs/write.c +index 51d0b7913c04c..5ab997912d8d5 100644 +--- a/fs/nfs/write.c ++++ b/fs/nfs/write.c +@@ -1394,20 +1394,27 @@ static void nfs_redirty_request(struct nfs_page *req) + nfs_release_request(req); + } + +-static void nfs_async_write_error(struct list_head *head) ++static void nfs_async_write_error(struct list_head *head, int error) + { + struct nfs_page *req; + + while (!list_empty(head)) { + req = nfs_list_entry(head->next); + nfs_list_remove_request(req); ++ if (nfs_error_is_fatal(error)) { ++ nfs_context_set_write_error(req->wb_context, error); ++ if (nfs_error_is_fatal_on_server(error)) { ++ nfs_write_error_remove_page(req); ++ continue; ++ } ++ } + nfs_redirty_request(req); + } + } + + static void nfs_async_write_reschedule_io(struct nfs_pgio_header *hdr) + { +- nfs_async_write_error(&hdr->pages); ++ nfs_async_write_error(&hdr->pages, 0); + filemap_fdatawrite_range(hdr->inode->i_mapping, hdr->args.offset, + hdr->args.offset + hdr->args.count - 1); + } +diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h +index bd1c889a9ed95..cab24a127feb3 100644 +--- a/include/linux/nfs_xdr.h ++++ b/include/linux/nfs_xdr.h +@@ -1539,7 +1539,7 @@ struct nfs_commit_data { + }; + + struct nfs_pgio_completion_ops { +- void (*error_cleanup)(struct list_head *head); ++ void (*error_cleanup)(struct list_head *head, int); + void (*init_hdr)(struct nfs_pgio_header *hdr); + void (*completion)(struct nfs_pgio_header *hdr); + void (*reschedule_io)(struct nfs_pgio_header *hdr); +-- +2.20.1 + diff --git a/queue-4.19/nfsv4-pnfs-fix-a-page-lock-leak-in-nfs_pageio_resend.patch b/queue-4.19/nfsv4-pnfs-fix-a-page-lock-leak-in-nfs_pageio_resend.patch new file mode 100644 index 00000000000..ac8885e0e90 --- /dev/null +++ b/queue-4.19/nfsv4-pnfs-fix-a-page-lock-leak-in-nfs_pageio_resend.patch @@ -0,0 +1,55 @@ +From 94ffb514aa25d20c7340f2d53d36b101a6763203 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Mon, 12 Aug 2019 15:19:54 -0400 +Subject: NFSv4/pnfs: Fix a page lock leak in nfs_pageio_resend() + +[ Upstream commit f4340e9314dbfadc48758945f85fc3b16612d06f ] + +If the attempt to resend the pages fails, we need to ensure that we +clean up those pages that were not transmitted. + +Fixes: d600ad1f2bdb ("NFS41: pop some layoutget errors to application") +Signed-off-by: Trond Myklebust +Cc: stable@vger.kernel.org # v4.5+ +Signed-off-by: Sasha Levin +--- + fs/nfs/pagelist.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c +index d40bf560f3ca7..9cbd829b4ed5f 100644 +--- a/fs/nfs/pagelist.c ++++ b/fs/nfs/pagelist.c +@@ -1232,20 +1232,22 @@ static void nfs_pageio_complete_mirror(struct nfs_pageio_descriptor *desc, + int nfs_pageio_resend(struct nfs_pageio_descriptor *desc, + struct nfs_pgio_header *hdr) + { +- LIST_HEAD(failed); ++ LIST_HEAD(pages); + + desc->pg_io_completion = hdr->io_completion; + desc->pg_dreq = hdr->dreq; +- while (!list_empty(&hdr->pages)) { +- struct nfs_page *req = nfs_list_entry(hdr->pages.next); ++ list_splice_init(&hdr->pages, &pages); ++ while (!list_empty(&pages)) { ++ struct nfs_page *req = nfs_list_entry(pages.next); + + if (!nfs_pageio_add_request(desc, req)) +- nfs_list_move_request(req, &failed); ++ break; + } + nfs_pageio_complete(desc); +- if (!list_empty(&failed)) { +- list_move(&failed, &hdr->pages); +- return desc->pg_error < 0 ? desc->pg_error : -EIO; ++ if (!list_empty(&pages)) { ++ int err = desc->pg_error < 0 ? desc->pg_error : -EIO; ++ hdr->completion_ops->error_cleanup(&pages, err); ++ return err; + } + return 0; + } +-- +2.20.1 + diff --git a/queue-4.19/series b/queue-4.19/series index 9ce362c4421..8193a9008d3 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -81,3 +81,11 @@ revert-cfg80211-fix-processing-world-regdomain-when-non-modular.patch mac80211-fix-possible-sta-leak.patch mac80211-don-t-memset-rxcb-prior-to-pae-intercept.patch mac80211-correctly-set-noencrypt-for-pae-frames.patch +kvm-ppc-book3s-fix-incorrect-guest-to-user-translati.patch +kvm-arm-arm64-vgic-fix-potential-deadlock-when-ap_li.patch +kvm-arm-arm64-vgic-v2-handle-sgi-bits-in-gicd_i-s-c-.patch +nfs-clean-up-list-moves-of-struct-nfs_page.patch +nfsv4-pnfs-fix-a-page-lock-leak-in-nfs_pageio_resend.patch +nfs-pass-error-information-to-the-pgio-error-cleanup.patch +nfs-ensure-o_direct-reports-an-error-if-the-bytes-re.patch +i2c-piix4-fix-port-selection-for-amd-family-16h-mode.patch