From: Sasha Levin Date: Sat, 23 Sep 2023 12:16:15 +0000 (-0400) Subject: Fixes for 5.10 X-Git-Tag: v6.5.6~112 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4a49dce723e7284e2a1cf2cd5df8fab191651112;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.10 Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/ata-ahci-drop-pointless-vprintk-calls-and-convert-th.patch b/queue-5.10/ata-ahci-drop-pointless-vprintk-calls-and-convert-th.patch new file mode 100644 index 00000000000..96821b9ed62 --- /dev/null +++ b/queue-5.10/ata-ahci-drop-pointless-vprintk-calls-and-convert-th.patch @@ -0,0 +1,155 @@ +From eadb1c5c1c49c4ac6f9333730a5c566529e57510 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Dec 2021 08:20:47 +0100 +Subject: ata: ahci: Drop pointless VPRINTK() calls and convert the remaining + ones + +From: Hannes Reinecke + +[ Upstream commit 93c7711494f47f9c829321e2a8711671b02f6e4c ] + +Drop pointless VPRINTK() calls for entering and existing interrupt +routines and convert the remaining calls to dev_dbg(). + +Signed-off-by: Hannes Reinecke +Signed-off-by: Damien Le Moal +Stable-dep-of: 737dd811a3db ("ata: libahci: clear pending interrupt status") +Signed-off-by: Sasha Levin +--- + drivers/ata/ahci.c | 4 +--- + drivers/ata/ahci_xgene.c | 4 ---- + drivers/ata/libahci.c | 18 ++++-------------- + 3 files changed, 5 insertions(+), 21 deletions(-) + +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index bf949f7da483f..d831a80c25f04 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -703,7 +703,7 @@ static void ahci_pci_init_controller(struct ata_host *host) + + /* clear port IRQ */ + tmp = readl(port_mmio + PORT_IRQ_STAT); +- VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); ++ dev_dbg(&pdev->dev, "PORT_IRQ_STAT 0x%x\n", tmp); + if (tmp) + writel(tmp, port_mmio + PORT_IRQ_STAT); + } +@@ -1495,7 +1495,6 @@ static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance) + u32 irq_stat, irq_masked; + unsigned int handled = 1; + +- VPRINTK("ENTER\n"); + hpriv = host->private_data; + mmio = hpriv->mmio; + irq_stat = readl(mmio + HOST_IRQ_STAT); +@@ -1512,7 +1511,6 @@ static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance) + irq_stat = readl(mmio + HOST_IRQ_STAT); + spin_unlock(&host->lock); + } while (irq_stat); +- VPRINTK("EXIT\n"); + + return IRQ_RETVAL(handled); + } +diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c +index 16246c843365e..e0f0577ac191c 100644 +--- a/drivers/ata/ahci_xgene.c ++++ b/drivers/ata/ahci_xgene.c +@@ -588,8 +588,6 @@ static irqreturn_t xgene_ahci_irq_intr(int irq, void *dev_instance) + void __iomem *mmio; + u32 irq_stat, irq_masked; + +- VPRINTK("ENTER\n"); +- + hpriv = host->private_data; + mmio = hpriv->mmio; + +@@ -612,8 +610,6 @@ static irqreturn_t xgene_ahci_irq_intr(int irq, void *dev_instance) + + spin_unlock(&host->lock); + +- VPRINTK("EXIT\n"); +- + return IRQ_RETVAL(rc); + } + +diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c +index fec2e9754aed2..08c4b641691b1 100644 +--- a/drivers/ata/libahci.c ++++ b/drivers/ata/libahci.c +@@ -1215,12 +1215,12 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap, + + /* clear SError */ + tmp = readl(port_mmio + PORT_SCR_ERR); +- VPRINTK("PORT_SCR_ERR 0x%x\n", tmp); ++ dev_dbg(dev, "PORT_SCR_ERR 0x%x\n", tmp); + writel(tmp, port_mmio + PORT_SCR_ERR); + + /* clear port IRQ */ + tmp = readl(port_mmio + PORT_IRQ_STAT); +- VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); ++ dev_dbg(dev, "PORT_IRQ_STAT 0x%x\n", tmp); + if (tmp) + writel(tmp, port_mmio + PORT_IRQ_STAT); + +@@ -1251,10 +1251,10 @@ void ahci_init_controller(struct ata_host *host) + } + + tmp = readl(mmio + HOST_CTL); +- VPRINTK("HOST_CTL 0x%x\n", tmp); ++ dev_dbg(host->dev, "HOST_CTL 0x%x\n", tmp); + writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL); + tmp = readl(mmio + HOST_CTL); +- VPRINTK("HOST_CTL 0x%x\n", tmp); ++ dev_dbg(host->dev, "HOST_CTL 0x%x\n", tmp); + } + EXPORT_SYMBOL_GPL(ahci_init_controller); + +@@ -1905,8 +1905,6 @@ static irqreturn_t ahci_multi_irqs_intr_hard(int irq, void *dev_instance) + void __iomem *port_mmio = ahci_port_base(ap); + u32 status; + +- VPRINTK("ENTER\n"); +- + status = readl(port_mmio + PORT_IRQ_STAT); + writel(status, port_mmio + PORT_IRQ_STAT); + +@@ -1914,8 +1912,6 @@ static irqreturn_t ahci_multi_irqs_intr_hard(int irq, void *dev_instance) + ahci_handle_port_interrupt(ap, port_mmio, status); + spin_unlock(ap->lock); + +- VPRINTK("EXIT\n"); +- + return IRQ_HANDLED; + } + +@@ -1932,9 +1928,7 @@ u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked) + ap = host->ports[i]; + if (ap) { + ahci_port_intr(ap); +- VPRINTK("port %u\n", i); + } else { +- VPRINTK("port %u (no irq)\n", i); + if (ata_ratelimit()) + dev_warn(host->dev, + "interrupt on disabled port %u\n", i); +@@ -1955,8 +1949,6 @@ static irqreturn_t ahci_single_level_irq_intr(int irq, void *dev_instance) + void __iomem *mmio; + u32 irq_stat, irq_masked; + +- VPRINTK("ENTER\n"); +- + hpriv = host->private_data; + mmio = hpriv->mmio; + +@@ -1984,8 +1976,6 @@ static irqreturn_t ahci_single_level_irq_intr(int irq, void *dev_instance) + + spin_unlock(&host->lock); + +- VPRINTK("EXIT\n"); +- + return IRQ_RETVAL(rc); + } + +-- +2.40.1 + diff --git a/queue-5.10/ata-libahci-clear-pending-interrupt-status.patch b/queue-5.10/ata-libahci-clear-pending-interrupt-status.patch new file mode 100644 index 00000000000..cf949d59a82 --- /dev/null +++ b/queue-5.10/ata-libahci-clear-pending-interrupt-status.patch @@ -0,0 +1,101 @@ +From 163f4a44885a3fdd1b55ae6e628d72d2930182eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Sep 2023 16:17:10 +0800 +Subject: ata: libahci: clear pending interrupt status + +From: Szuying Chen + +[ Upstream commit 737dd811a3dbfd7edd4ad2ba5152e93d99074f83 ] + +When a CRC error occurs, the HBA asserts an interrupt to indicate an +interface fatal error (PxIS.IFS). The ISR clears PxIE and PxIS, then +does error recovery. If the adapter receives another SDB FIS +with an error (PxIS.TFES) from the device before the start of the EH +recovery process, the interrupt signaling the new SDB cannot be +serviced as PxIE was cleared already. This in turn results in the HBA +inability to issue any command during the error recovery process after +setting PxCMD.ST to 1 because PxIS.TFES is still set. + +According to AHCI 1.3.1 specifications section 6.2.2, fatal errors +notified by setting PxIS.HBFS, PxIS.HBDS, PxIS.IFS or PxIS.TFES will +cause the HBA to enter the ERR:Fatal state. In this state, the HBA +shall not issue any new commands. + +To avoid this situation, introduce the function +ahci_port_clear_pending_irq() to clear pending interrupts before +executing a COMRESET. This follows the AHCI 1.3.1 - section 6.2.2.2 +specification. + +Signed-off-by: Szuying Chen +Fixes: e0bfd149973d ("[PATCH] ahci: stop engine during hard reset") +Cc: stable@vger.kernel.org +Reviewed-by: Niklas Cassel +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/libahci.c | 35 +++++++++++++++++++++++------------ + 1 file changed, 23 insertions(+), 12 deletions(-) + +diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c +index 08c4b641691b1..e188850f65ff2 100644 +--- a/drivers/ata/libahci.c ++++ b/drivers/ata/libahci.c +@@ -1199,6 +1199,26 @@ static ssize_t ahci_activity_show(struct ata_device *dev, char *buf) + return sprintf(buf, "%d\n", emp->blink_policy); + } + ++static void ahci_port_clear_pending_irq(struct ata_port *ap) ++{ ++ struct ahci_host_priv *hpriv = ap->host->private_data; ++ void __iomem *port_mmio = ahci_port_base(ap); ++ u32 tmp; ++ ++ /* clear SError */ ++ tmp = readl(port_mmio + PORT_SCR_ERR); ++ dev_dbg(ap->host->dev, "PORT_SCR_ERR 0x%x\n", tmp); ++ writel(tmp, port_mmio + PORT_SCR_ERR); ++ ++ /* clear port IRQ */ ++ tmp = readl(port_mmio + PORT_IRQ_STAT); ++ dev_dbg(ap->host->dev, "PORT_IRQ_STAT 0x%x\n", tmp); ++ if (tmp) ++ writel(tmp, port_mmio + PORT_IRQ_STAT); ++ ++ writel(1 << ap->port_no, hpriv->mmio + HOST_IRQ_STAT); ++} ++ + static void ahci_port_init(struct device *dev, struct ata_port *ap, + int port_no, void __iomem *mmio, + void __iomem *port_mmio) +@@ -1213,18 +1233,7 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap, + if (rc) + dev_warn(dev, "%s (%d)\n", emsg, rc); + +- /* clear SError */ +- tmp = readl(port_mmio + PORT_SCR_ERR); +- dev_dbg(dev, "PORT_SCR_ERR 0x%x\n", tmp); +- writel(tmp, port_mmio + PORT_SCR_ERR); +- +- /* clear port IRQ */ +- tmp = readl(port_mmio + PORT_IRQ_STAT); +- dev_dbg(dev, "PORT_IRQ_STAT 0x%x\n", tmp); +- if (tmp) +- writel(tmp, port_mmio + PORT_IRQ_STAT); +- +- writel(1 << port_no, mmio + HOST_IRQ_STAT); ++ ahci_port_clear_pending_irq(ap); + + /* mark esata ports */ + tmp = readl(port_mmio + PORT_CMD); +@@ -1554,6 +1563,8 @@ int ahci_do_hardreset(struct ata_link *link, unsigned int *class, + tf.command = ATA_BUSY; + ata_tf_to_fis(&tf, 0, 0, d2h_fis); + ++ ahci_port_clear_pending_irq(ap); ++ + rc = sata_link_hardreset(link, timing, deadline, online, + ahci_check_ready); + +-- +2.40.1 + diff --git a/queue-5.10/ext4-add-new-helper-interface-ext4_try_to_trim_range.patch b/queue-5.10/ext4-add-new-helper-interface-ext4_try_to_trim_range.patch new file mode 100644 index 00000000000..6ac564bb0c7 --- /dev/null +++ b/queue-5.10/ext4-add-new-helper-interface-ext4_try_to_trim_range.patch @@ -0,0 +1,165 @@ +From 94c43c58c9f68224449300d1526f1c07a416021c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 24 Jul 2021 15:41:21 +0800 +Subject: ext4: add new helper interface ext4_try_to_trim_range() + +From: Wang Jianchao + +[ Upstream commit 6920b3913235f517728bb69abe9b39047a987113 ] + +There is no functional change in this patch but just split the +codes, which serachs free block and does trim, into a new function +ext4_try_to_trim_range. This is preparing for the following async +backgroup discard. + +Reviewed-by: Andreas Dilger +Signed-off-by: Wang Jianchao +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20210724074124.25731-3-jianchao.wan9@gmail.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: 45e4ab320c9b ("ext4: move setting of trimmed bit into ext4_try_to_trim_range()") +Signed-off-by: Sasha Levin +--- + fs/ext4/mballoc.c | 102 ++++++++++++++++++++++++++-------------------- + 1 file changed, 57 insertions(+), 45 deletions(-) + +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index 342225c1cf332..54c718d471978 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -5894,6 +5894,54 @@ __acquires(bitlock) + return ret; + } + ++static int ext4_try_to_trim_range(struct super_block *sb, ++ struct ext4_buddy *e4b, ext4_grpblk_t start, ++ ext4_grpblk_t max, ext4_grpblk_t minblocks) ++{ ++ ext4_grpblk_t next, count, free_count; ++ void *bitmap; ++ int ret = 0; ++ ++ bitmap = e4b->bd_bitmap; ++ start = (e4b->bd_info->bb_first_free > start) ? ++ e4b->bd_info->bb_first_free : start; ++ count = 0; ++ free_count = 0; ++ ++ while (start <= max) { ++ start = mb_find_next_zero_bit(bitmap, max + 1, start); ++ if (start > max) ++ break; ++ next = mb_find_next_bit(bitmap, max + 1, start); ++ ++ if ((next - start) >= minblocks) { ++ ret = ext4_trim_extent(sb, start, next - start, e4b); ++ if (ret && ret != -EOPNOTSUPP) ++ break; ++ ret = 0; ++ count += next - start; ++ } ++ free_count += next - start; ++ start = next + 1; ++ ++ if (fatal_signal_pending(current)) { ++ count = -ERESTARTSYS; ++ break; ++ } ++ ++ if (need_resched()) { ++ ext4_unlock_group(sb, e4b->bd_group); ++ cond_resched(); ++ ext4_lock_group(sb, e4b->bd_group); ++ } ++ ++ if ((e4b->bd_info->bb_free - free_count) < minblocks) ++ break; ++ } ++ ++ return count; ++} ++ + /** + * ext4_trim_all_free -- function to trim all free space in alloc. group + * @sb: super block for file system +@@ -5917,10 +5965,8 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group, + ext4_grpblk_t start, ext4_grpblk_t max, + ext4_grpblk_t minblocks) + { +- void *bitmap; +- ext4_grpblk_t next, count = 0, free_count = 0; + struct ext4_buddy e4b; +- int ret = 0; ++ int ret; + + trace_ext4_trim_all_free(sb, group, start, max); + +@@ -5930,57 +5976,23 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group, + ret, group); + return ret; + } +- bitmap = e4b.bd_bitmap; + + ext4_lock_group(sb, group); +- if (EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) && +- minblocks >= atomic_read(&EXT4_SB(sb)->s_last_trim_minblks)) +- goto out; +- +- start = (e4b.bd_info->bb_first_free > start) ? +- e4b.bd_info->bb_first_free : start; + +- while (start <= max) { +- start = mb_find_next_zero_bit(bitmap, max + 1, start); +- if (start > max) +- break; +- next = mb_find_next_bit(bitmap, max + 1, start); +- +- if ((next - start) >= minblocks) { +- ret = ext4_trim_extent(sb, start, next - start, &e4b); +- if (ret && ret != -EOPNOTSUPP) +- break; +- ret = 0; +- count += next - start; +- } +- free_count += next - start; +- start = next + 1; +- +- if (fatal_signal_pending(current)) { +- count = -ERESTARTSYS; +- break; +- } +- +- if (need_resched()) { +- ext4_unlock_group(sb, group); +- cond_resched(); +- ext4_lock_group(sb, group); +- } +- +- if ((e4b.bd_info->bb_free - free_count) < minblocks) +- break; ++ if (!EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) || ++ minblocks < atomic_read(&EXT4_SB(sb)->s_last_trim_minblks)) { ++ ret = ext4_try_to_trim_range(sb, &e4b, start, max, minblocks); ++ if (ret >= 0) ++ EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info); ++ } else { ++ ret = 0; + } + +- if (!ret) { +- ret = count; +- EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info); +- } +-out: + ext4_unlock_group(sb, group); + ext4_mb_unload_buddy(&e4b); + + ext4_debug("trimmed %d blocks in the group %d\n", +- count, group); ++ ret, group); + + return ret; + } +-- +2.40.1 + diff --git a/queue-5.10/ext4-change-s_last_trim_minblks-type-to-unsigned-lon.patch b/queue-5.10/ext4-change-s_last_trim_minblks-type-to-unsigned-lon.patch new file mode 100644 index 00000000000..3f49a3db5f5 --- /dev/null +++ b/queue-5.10/ext4-change-s_last_trim_minblks-type-to-unsigned-lon.patch @@ -0,0 +1,64 @@ +From 145f12a5aaf9f0516b0aa6cfa3d4348078c4194a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Nov 2021 15:51:21 +0100 +Subject: ext4: change s_last_trim_minblks type to unsigned long + +From: Lukas Czerner + +[ Upstream commit 2327fb2e23416cfb2795ccca2f77d4d65925be99 ] + +There is no good reason for the s_last_trim_minblks to be atomic. There is +no data integrity needed and there is no real danger in setting and +reading it in a racy manner. Change it to be unsigned long, the same type +as s_clusters_per_group which is the maximum that's allowed. + +Signed-off-by: Lukas Czerner +Suggested-by: Andreas Dilger +Reviewed-by: Andreas Dilger +Link: https://lore.kernel.org/r/20211103145122.17338-1-lczerner@redhat.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: 45e4ab320c9b ("ext4: move setting of trimmed bit into ext4_try_to_trim_range()") +Signed-off-by: Sasha Levin +--- + fs/ext4/ext4.h | 2 +- + fs/ext4/mballoc.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index c3e9cb5037631..fec021e6bb600 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1580,7 +1580,7 @@ struct ext4_sb_info { + struct task_struct *s_mmp_tsk; + + /* record the last minlen when FITRIM is called. */ +- atomic_t s_last_trim_minblks; ++ unsigned long s_last_trim_minblks; + + /* Reference to checksum algorithm driver via cryptoapi */ + struct crypto_shash *s_chksum_driver; +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index e0428cec6ff60..7bc17eb5ea74a 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -5979,7 +5979,7 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group, + ext4_lock_group(sb, group); + + if (!EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) || +- minblocks < atomic_read(&EXT4_SB(sb)->s_last_trim_minblks)) { ++ minblocks < EXT4_SB(sb)->s_last_trim_minblks) { + ret = ext4_try_to_trim_range(sb, &e4b, start, max, minblocks); + if (ret >= 0) + EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info); +@@ -6090,7 +6090,7 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) + } + + if (!ret) +- atomic_set(&EXT4_SB(sb)->s_last_trim_minblks, minlen); ++ EXT4_SB(sb)->s_last_trim_minblks = minlen; + + out: + range->len = EXT4_C2B(EXT4_SB(sb), trimmed) << sb->s_blocksize_bits; +-- +2.40.1 + diff --git a/queue-5.10/ext4-do-not-let-fstrim-block-system-suspend.patch b/queue-5.10/ext4-do-not-let-fstrim-block-system-suspend.patch new file mode 100644 index 00000000000..68454b978e0 --- /dev/null +++ b/queue-5.10/ext4-do-not-let-fstrim-block-system-suspend.patch @@ -0,0 +1,76 @@ +From 78a05a2f1a017e2f0f239661f2b84aa9a1835901 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Sep 2023 17:04:55 +0200 +Subject: ext4: do not let fstrim block system suspend + +From: Jan Kara + +[ Upstream commit 5229a658f6453362fbb9da6bf96872ef25a7097e ] + +Len Brown has reported that system suspend sometimes fail due to +inability to freeze a task working in ext4_trim_fs() for one minute. +Trimming a large filesystem on a disk that slowly processes discard +requests can indeed take a long time. Since discard is just an advisory +call, it is perfectly fine to interrupt it at any time and the return +number of discarded blocks until that moment. Do that when we detect the +task is being frozen. + +Cc: stable@kernel.org +Reported-by: Len Brown +Suggested-by: Dave Chinner +References: https://bugzilla.kernel.org/show_bug.cgi?id=216322 +Signed-off-by: Jan Kara +Link: https://lore.kernel.org/r/20230913150504.9054-2-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/mballoc.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index 2907bf57744a8..b35d59d41c896 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include + + /* +@@ -5904,6 +5905,11 @@ static ext4_grpblk_t ext4_last_grp_cluster(struct super_block *sb, + EXT4_CLUSTER_BITS(sb); + } + ++static bool ext4_trim_interrupted(void) ++{ ++ return fatal_signal_pending(current) || freezing(current); ++} ++ + static int ext4_try_to_trim_range(struct super_block *sb, + struct ext4_buddy *e4b, ext4_grpblk_t start, + ext4_grpblk_t max, ext4_grpblk_t minblocks) +@@ -5935,8 +5941,8 @@ static int ext4_try_to_trim_range(struct super_block *sb, + free_count += next - start; + start = next + 1; + +- if (fatal_signal_pending(current)) +- return -ERESTARTSYS; ++ if (ext4_trim_interrupted()) ++ return count; + + if (need_resched()) { + ext4_unlock_group(sb, e4b->bd_group); +@@ -6063,6 +6069,8 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) + end = EXT4_CLUSTERS_PER_GROUP(sb) - 1; + + for (group = first_group; group <= last_group; group++) { ++ if (ext4_trim_interrupted()) ++ break; + grp = ext4_get_group_info(sb, group); + if (!grp) + continue; +-- +2.40.1 + diff --git a/queue-5.10/ext4-mark-group-as-trimmed-only-if-it-was-fully-scan.patch b/queue-5.10/ext4-mark-group-as-trimmed-only-if-it-was-fully-scan.patch new file mode 100644 index 00000000000..b83b249c4d6 --- /dev/null +++ b/queue-5.10/ext4-mark-group-as-trimmed-only-if-it-was-fully-scan.patch @@ -0,0 +1,107 @@ +From 61e3e2926388fd4caa217c6782d9a1f8f963d3c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 17 Apr 2022 20:03:15 +0300 +Subject: ext4: mark group as trimmed only if it was fully scanned + +From: Dmitry Monakhov + +[ Upstream commit d63c00ea435a5352f486c259665a4ced60399421 ] + +Otherwise nonaligned fstrim calls will works inconveniently for iterative +scanners, for example: + +// trim [0,16MB] for group-1, but mark full group as trimmed +fstrim -o $((1024*1024*128)) -l $((1024*1024*16)) ./m +// handle [16MB,16MB] for group-1, do nothing because group already has the flag. +fstrim -o $((1024*1024*144)) -l $((1024*1024*16)) ./m + +[ Update function documentation for ext4_trim_all_free -- TYT ] + +Signed-off-by: Dmitry Monakhov +Link: https://lore.kernel.org/r/1650214995-860245-1-git-send-email-dmtrmonakhov@yandex-team.ru +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Stable-dep-of: 45e4ab320c9b ("ext4: move setting of trimmed bit into ext4_try_to_trim_range()") +Signed-off-by: Sasha Levin +--- + fs/ext4/mballoc.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index 7bc17eb5ea74a..5c650e28dcb6b 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -5948,6 +5948,7 @@ static int ext4_try_to_trim_range(struct super_block *sb, + * @start: first group block to examine + * @max: last group block to examine + * @minblocks: minimum extent block count ++ * @set_trimmed: set the trimmed flag if at least one block is trimmed + * + * ext4_trim_all_free walks through group's buddy bitmap searching for free + * extents. When the free block is found, ext4_trim_extent is called to TRIM +@@ -5962,7 +5963,7 @@ static int ext4_try_to_trim_range(struct super_block *sb, + static ext4_grpblk_t + ext4_trim_all_free(struct super_block *sb, ext4_group_t group, + ext4_grpblk_t start, ext4_grpblk_t max, +- ext4_grpblk_t minblocks) ++ ext4_grpblk_t minblocks, bool set_trimmed) + { + struct ext4_buddy e4b; + int ret; +@@ -5981,7 +5982,7 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group, + if (!EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) || + minblocks < EXT4_SB(sb)->s_last_trim_minblks) { + ret = ext4_try_to_trim_range(sb, &e4b, start, max, minblocks); +- if (ret >= 0) ++ if (ret >= 0 && set_trimmed) + EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info); + } else { + ret = 0; +@@ -6018,6 +6019,7 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) + ext4_fsblk_t first_data_blk = + le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); + ext4_fsblk_t max_blks = ext4_blocks_count(EXT4_SB(sb)->s_es); ++ bool whole_group, eof = false; + int ret = 0; + + start = range->start >> sb->s_blocksize_bits; +@@ -6036,8 +6038,10 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) + if (minlen > EXT4_CLUSTERS_PER_GROUP(sb)) + goto out; + } +- if (end >= max_blks) ++ if (end >= max_blks - 1) { + end = max_blks - 1; ++ eof = true; ++ } + if (end <= first_data_blk) + goto out; + if (start < first_data_blk) +@@ -6051,6 +6055,7 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) + + /* end now represents the last cluster to discard in this group */ + end = EXT4_CLUSTERS_PER_GROUP(sb) - 1; ++ whole_group = true; + + for (group = first_group; group <= last_group; group++) { + grp = ext4_get_group_info(sb, group); +@@ -6069,12 +6074,13 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) + * change it for the last group, note that last_cluster is + * already computed earlier by ext4_get_group_no_and_offset() + */ +- if (group == last_group) ++ if (group == last_group) { + end = last_cluster; +- ++ whole_group = eof ? true : end == EXT4_CLUSTERS_PER_GROUP(sb) - 1; ++ } + if (grp->bb_free >= minlen) { + cnt = ext4_trim_all_free(sb, group, first_cluster, +- end, minlen); ++ end, minlen, whole_group); + if (cnt < 0) { + ret = cnt; + break; +-- +2.40.1 + diff --git a/queue-5.10/ext4-move-setting-of-trimmed-bit-into-ext4_try_to_tr.patch b/queue-5.10/ext4-move-setting-of-trimmed-bit-into-ext4_try_to_tr.patch new file mode 100644 index 00000000000..d4706758d2a --- /dev/null +++ b/queue-5.10/ext4-move-setting-of-trimmed-bit-into-ext4_try_to_tr.patch @@ -0,0 +1,168 @@ +From d3789f9dc4d047ed1ef52fb4590c1faad8530f0e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Sep 2023 17:04:54 +0200 +Subject: ext4: move setting of trimmed bit into ext4_try_to_trim_range() + +From: Jan Kara + +[ Upstream commit 45e4ab320c9b5fa67b1fc3b6a9b381cfcc0c8488 ] + +Currently we set the group's trimmed bit in ext4_trim_all_free() based +on return value of ext4_try_to_trim_range(). However when we will want +to abort trimming because of suspend attempt, we want to return success +from ext4_try_to_trim_range() but not set the trimmed bit. Instead +implementing awkward propagation of this information, just move setting +of trimmed bit into ext4_try_to_trim_range() when the whole group is +trimmed. + +Cc: stable@kernel.org +Signed-off-by: Jan Kara +Link: https://lore.kernel.org/r/20230913150504.9054-1-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/mballoc.c | 46 +++++++++++++++++++++++++--------------------- + 1 file changed, 25 insertions(+), 21 deletions(-) + +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index c06f304f38edf..2907bf57744a8 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -5894,14 +5894,27 @@ __acquires(bitlock) + return ret; + } + ++static ext4_grpblk_t ext4_last_grp_cluster(struct super_block *sb, ++ ext4_group_t grp) ++{ ++ if (grp < ext4_get_groups_count(sb)) ++ return EXT4_CLUSTERS_PER_GROUP(sb) - 1; ++ return (ext4_blocks_count(EXT4_SB(sb)->s_es) - ++ ext4_group_first_block_no(sb, grp) - 1) >> ++ EXT4_CLUSTER_BITS(sb); ++} ++ + static int ext4_try_to_trim_range(struct super_block *sb, + struct ext4_buddy *e4b, ext4_grpblk_t start, + ext4_grpblk_t max, ext4_grpblk_t minblocks) + { + ext4_grpblk_t next, count, free_count; ++ bool set_trimmed = false; + void *bitmap; + + bitmap = e4b->bd_bitmap; ++ if (start == 0 && max >= ext4_last_grp_cluster(sb, e4b->bd_group)) ++ set_trimmed = true; + start = max(e4b->bd_info->bb_first_free, start); + count = 0; + free_count = 0; +@@ -5916,16 +5929,14 @@ static int ext4_try_to_trim_range(struct super_block *sb, + int ret = ext4_trim_extent(sb, start, next - start, e4b); + + if (ret && ret != -EOPNOTSUPP) +- break; ++ return count; + count += next - start; + } + free_count += next - start; + start = next + 1; + +- if (fatal_signal_pending(current)) { +- count = -ERESTARTSYS; +- break; +- } ++ if (fatal_signal_pending(current)) ++ return -ERESTARTSYS; + + if (need_resched()) { + ext4_unlock_group(sb, e4b->bd_group); +@@ -5937,6 +5948,9 @@ static int ext4_try_to_trim_range(struct super_block *sb, + break; + } + ++ if (set_trimmed) ++ EXT4_MB_GRP_SET_TRIMMED(e4b->bd_info); ++ + return count; + } + +@@ -5947,7 +5961,6 @@ static int ext4_try_to_trim_range(struct super_block *sb, + * @start: first group block to examine + * @max: last group block to examine + * @minblocks: minimum extent block count +- * @set_trimmed: set the trimmed flag if at least one block is trimmed + * + * ext4_trim_all_free walks through group's buddy bitmap searching for free + * extents. When the free block is found, ext4_trim_extent is called to TRIM +@@ -5962,7 +5975,7 @@ static int ext4_try_to_trim_range(struct super_block *sb, + static ext4_grpblk_t + ext4_trim_all_free(struct super_block *sb, ext4_group_t group, + ext4_grpblk_t start, ext4_grpblk_t max, +- ext4_grpblk_t minblocks, bool set_trimmed) ++ ext4_grpblk_t minblocks) + { + struct ext4_buddy e4b; + int ret; +@@ -5979,13 +5992,10 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group, + ext4_lock_group(sb, group); + + if (!EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) || +- minblocks < EXT4_SB(sb)->s_last_trim_minblks) { ++ minblocks < EXT4_SB(sb)->s_last_trim_minblks) + ret = ext4_try_to_trim_range(sb, &e4b, start, max, minblocks); +- if (ret >= 0 && set_trimmed) +- EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info); +- } else { ++ else + ret = 0; +- } + + ext4_unlock_group(sb, group); + ext4_mb_unload_buddy(&e4b); +@@ -6018,7 +6028,6 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) + ext4_fsblk_t first_data_blk = + le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); + ext4_fsblk_t max_blks = ext4_blocks_count(EXT4_SB(sb)->s_es); +- bool whole_group, eof = false; + int ret = 0; + + start = range->start >> sb->s_blocksize_bits; +@@ -6037,10 +6046,8 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) + if (minlen > EXT4_CLUSTERS_PER_GROUP(sb)) + goto out; + } +- if (end >= max_blks - 1) { ++ if (end >= max_blks - 1) + end = max_blks - 1; +- eof = true; +- } + if (end <= first_data_blk) + goto out; + if (start < first_data_blk) +@@ -6054,7 +6061,6 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) + + /* end now represents the last cluster to discard in this group */ + end = EXT4_CLUSTERS_PER_GROUP(sb) - 1; +- whole_group = true; + + for (group = first_group; group <= last_group; group++) { + grp = ext4_get_group_info(sb, group); +@@ -6073,13 +6079,11 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) + * change it for the last group, note that last_cluster is + * already computed earlier by ext4_get_group_no_and_offset() + */ +- if (group == last_group) { ++ if (group == last_group) + end = last_cluster; +- whole_group = eof ? true : end == EXT4_CLUSTERS_PER_GROUP(sb) - 1; +- } + if (grp->bb_free >= minlen) { + cnt = ext4_trim_all_free(sb, group, first_cluster, +- end, minlen, whole_group); ++ end, minlen); + if (cnt < 0) { + ret = cnt; + break; +-- +2.40.1 + diff --git a/queue-5.10/ext4-remove-the-group-parameter-of-ext4_trim_extent.patch b/queue-5.10/ext4-remove-the-group-parameter-of-ext4_trim_extent.patch new file mode 100644 index 00000000000..ad49ac54152 --- /dev/null +++ b/queue-5.10/ext4-remove-the-group-parameter-of-ext4_trim_extent.patch @@ -0,0 +1,63 @@ +From 2925db3a0ce15fe1e06c486a9c60138438ac4815 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 24 Jul 2021 15:41:20 +0800 +Subject: ext4: remove the 'group' parameter of ext4_trim_extent + +From: Wang Jianchao + +[ Upstream commit bd2eea8d0a6b6a9aca22f20bf74f73b71d8808af ] + +Get rid of the 'group' parameter of ext4_trim_extent as we can get +it from the 'e4b'. + +Reviewed-by: Andreas Dilger +Signed-off-by: Wang Jianchao +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20210724074124.25731-2-jianchao.wan9@gmail.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: 45e4ab320c9b ("ext4: move setting of trimmed bit into ext4_try_to_trim_range()") +Signed-off-by: Sasha Levin +--- + fs/ext4/mballoc.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index 2f6ed59d81f02..342225c1cf332 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -5859,19 +5859,19 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb, + * @sb: super block for the file system + * @start: starting block of the free extent in the alloc. group + * @count: number of blocks to TRIM +- * @group: alloc. group we are working with + * @e4b: ext4 buddy for the group + * + * Trim "count" blocks starting at "start" in the "group". To assure that no + * one will allocate those blocks, mark it as used in buddy bitmap. This must + * be called with under the group lock. + */ +-static int ext4_trim_extent(struct super_block *sb, int start, int count, +- ext4_group_t group, struct ext4_buddy *e4b) ++static int ext4_trim_extent(struct super_block *sb, ++ int start, int count, struct ext4_buddy *e4b) + __releases(bitlock) + __acquires(bitlock) + { + struct ext4_free_extent ex; ++ ext4_group_t group = e4b->bd_group; + int ret = 0; + + trace_ext4_trim_extent(sb, group, start, count); +@@ -5947,8 +5947,7 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group, + next = mb_find_next_bit(bitmap, max + 1, start); + + if ((next - start) >= minblocks) { +- ret = ext4_trim_extent(sb, start, +- next - start, group, &e4b); ++ ret = ext4_trim_extent(sb, start, next - start, &e4b); + if (ret && ret != -EOPNOTSUPP) + break; + ret = 0; +-- +2.40.1 + diff --git a/queue-5.10/ext4-replace-the-traditional-ternary-conditional-ope.patch b/queue-5.10/ext4-replace-the-traditional-ternary-conditional-ope.patch new file mode 100644 index 00000000000..c37418397a2 --- /dev/null +++ b/queue-5.10/ext4-replace-the-traditional-ternary-conditional-ope.patch @@ -0,0 +1,49 @@ +From 1e9986d62b40addae9c5c6c38d20eefdd7ed207f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Aug 2023 22:32:00 +0800 +Subject: ext4: replace the traditional ternary conditional operator with with + max()/min() + +From: Kemeng Shi + +[ Upstream commit de8bf0e5ee7482585450357c6d4eddec8efc5cb7 ] + +Replace the traditional ternary conditional operator with with max()/min() + +Signed-off-by: Kemeng Shi +Reviewed-by: Ritesh Harjani (IBM) +Link: https://lore.kernel.org/r/20230801143204.2284343-7-shikemeng@huaweicloud.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: 45e4ab320c9b ("ext4: move setting of trimmed bit into ext4_try_to_trim_range()") +Signed-off-by: Sasha Levin +--- + fs/ext4/mballoc.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index 5c650e28dcb6b..c06f304f38edf 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -5902,8 +5902,7 @@ static int ext4_try_to_trim_range(struct super_block *sb, + void *bitmap; + + bitmap = e4b->bd_bitmap; +- start = (e4b->bd_info->bb_first_free > start) ? +- e4b->bd_info->bb_first_free : start; ++ start = max(e4b->bd_info->bb_first_free, start); + count = 0; + free_count = 0; + +@@ -6125,8 +6124,7 @@ ext4_mballoc_query_range( + + ext4_lock_group(sb, group); + +- start = (e4b.bd_info->bb_first_free > start) ? +- e4b.bd_info->bb_first_free : start; ++ start = max(e4b.bd_info->bb_first_free, start); + if (end >= EXT4_CLUSTERS_PER_GROUP(sb)) + end = EXT4_CLUSTERS_PER_GROUP(sb) - 1; + +-- +2.40.1 + diff --git a/queue-5.10/ext4-scope-ret-locally-in-ext4_try_to_trim_range.patch b/queue-5.10/ext4-scope-ret-locally-in-ext4_try_to_trim_range.patch new file mode 100644 index 00000000000..edb4e1f07ad --- /dev/null +++ b/queue-5.10/ext4-scope-ret-locally-in-ext4_try_to_trim_range.patch @@ -0,0 +1,55 @@ +From 08e162b3e7ff1feb4e137dc807ce60d36bb3a8e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Aug 2021 14:08:53 +0200 +Subject: ext4: scope ret locally in ext4_try_to_trim_range() + +From: Lukas Bulwahn + +[ Upstream commit afcc4e32f606dbfb47aa7309172c89174b86e74c ] + +As commit 6920b3913235 ("ext4: add new helper interface +ext4_try_to_trim_range()") moves some code into the separate function +ext4_try_to_trim_range(), the use of the variable ret within that +function is more limited and can be adjusted as well. + +Scope the use of the variable ret locally and drop dead assignments. + +No functional change. + +Signed-off-by: Lukas Bulwahn +Link: https://lore.kernel.org/r/20210820120853.23134-1-lukas.bulwahn@gmail.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: 45e4ab320c9b ("ext4: move setting of trimmed bit into ext4_try_to_trim_range()") +Signed-off-by: Sasha Levin +--- + fs/ext4/mballoc.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index 54c718d471978..e0428cec6ff60 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -5900,7 +5900,6 @@ static int ext4_try_to_trim_range(struct super_block *sb, + { + ext4_grpblk_t next, count, free_count; + void *bitmap; +- int ret = 0; + + bitmap = e4b->bd_bitmap; + start = (e4b->bd_info->bb_first_free > start) ? +@@ -5915,10 +5914,10 @@ static int ext4_try_to_trim_range(struct super_block *sb, + next = mb_find_next_bit(bitmap, max + 1, start); + + if ((next - start) >= minblocks) { +- ret = ext4_trim_extent(sb, start, next - start, e4b); ++ int ret = ext4_trim_extent(sb, start, next - start, e4b); ++ + if (ret && ret != -EOPNOTSUPP) + break; +- ret = 0; + count += next - start; + } + free_count += next - start; +-- +2.40.1 + diff --git a/queue-5.10/nfs-pnfs-report-einval-errors-from-connect-to-the-se.patch b/queue-5.10/nfs-pnfs-report-einval-errors-from-connect-to-the-se.patch new file mode 100644 index 00000000000..8694697f6a6 --- /dev/null +++ b/queue-5.10/nfs-pnfs-report-einval-errors-from-connect-to-the-se.patch @@ -0,0 +1,36 @@ +From 9986ccc886bd9b57c17c535b1f552faa529a94ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Sep 2023 12:43:58 -0400 +Subject: NFS/pNFS: Report EINVAL errors from connect() to the server + +From: Trond Myklebust + +[ Upstream commit dd7d7ee3ba2a70d12d02defb478790cf57d5b87b ] + +With IPv6, connect() can occasionally return EINVAL if a route is +unavailable. If this happens during I/O to a data server, we want to +report it using LAYOUTERROR as an inability to connect. + +Fixes: dd52128afdde ("NFSv4.1/pnfs Ensure flexfiles reports all connection related errors") +Signed-off-by: Trond Myklebust +Signed-off-by: Anna Schumaker +Signed-off-by: Sasha Levin +--- + fs/nfs/flexfilelayout/flexfilelayout.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c +index a8a02081942d2..e4f2820ba5a59 100644 +--- a/fs/nfs/flexfilelayout/flexfilelayout.c ++++ b/fs/nfs/flexfilelayout/flexfilelayout.c +@@ -1240,6 +1240,7 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg, + case -EPFNOSUPPORT: + case -EPROTONOSUPPORT: + case -EOPNOTSUPP: ++ case -EINVAL: + case -ECONNREFUSED: + case -ECONNRESET: + case -EHOSTDOWN: +-- +2.40.1 + diff --git a/queue-5.10/nfs-use-the-correct-commit-info-in-nfs_join_page_gro.patch b/queue-5.10/nfs-use-the-correct-commit-info-in-nfs_join_page_gro.patch new file mode 100644 index 00000000000..3e656f366f2 --- /dev/null +++ b/queue-5.10/nfs-use-the-correct-commit-info-in-nfs_join_page_gro.patch @@ -0,0 +1,150 @@ +From b7284cdf6553048006df6e81c8dd44b6efcf2b03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Sep 2023 12:34:40 -0400 +Subject: NFS: Use the correct commit info in nfs_join_page_group() + +From: Trond Myklebust + +[ Upstream commit b193a78ddb5ee7dba074d3f28dc050069ba083c0 ] + +Ensure that nfs_clear_request_commit() updates the correct counters when +it removes them from the commit list. + +Fixes: ed5d588fe47f ("NFS: Try to join page groups before an O_DIRECT retransmission") +Signed-off-by: Trond Myklebust +Signed-off-by: Anna Schumaker +Signed-off-by: Sasha Levin +--- + fs/nfs/direct.c | 8 +++++--- + fs/nfs/write.c | 23 ++++++++++++----------- + include/linux/nfs_page.h | 4 +++- + 3 files changed, 20 insertions(+), 15 deletions(-) + +diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c +index 018af6ec97b40..5d86ffa72ceab 100644 +--- a/fs/nfs/direct.c ++++ b/fs/nfs/direct.c +@@ -525,7 +525,9 @@ static void nfs_direct_add_page_head(struct list_head *list, + kref_get(&head->wb_kref); + } + +-static void nfs_direct_join_group(struct list_head *list, struct inode *inode) ++static void nfs_direct_join_group(struct list_head *list, ++ struct nfs_commit_info *cinfo, ++ struct inode *inode) + { + struct nfs_page *req, *subreq; + +@@ -547,7 +549,7 @@ static void nfs_direct_join_group(struct list_head *list, struct inode *inode) + nfs_release_request(subreq); + } + } while ((subreq = subreq->wb_this_page) != req); +- nfs_join_page_group(req, inode); ++ nfs_join_page_group(req, cinfo, inode); + } + } + +@@ -573,7 +575,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) + nfs_init_cinfo_from_dreq(&cinfo, dreq); + nfs_direct_write_scan_commit_list(dreq->inode, &reqs, &cinfo); + +- nfs_direct_join_group(&reqs, dreq->inode); ++ nfs_direct_join_group(&reqs, &cinfo, dreq->inode); + + dreq->count = 0; + dreq->max_count = 0; +diff --git a/fs/nfs/write.c b/fs/nfs/write.c +index dc08a0c02f095..d3cd099ffb6e1 100644 +--- a/fs/nfs/write.c ++++ b/fs/nfs/write.c +@@ -58,7 +58,8 @@ static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops; + static const struct nfs_commit_completion_ops nfs_commit_completion_ops; + static const struct nfs_rw_ops nfs_rw_write_ops; + static void nfs_inode_remove_request(struct nfs_page *req); +-static void nfs_clear_request_commit(struct nfs_page *req); ++static void nfs_clear_request_commit(struct nfs_commit_info *cinfo, ++ struct nfs_page *req); + static void nfs_init_cinfo_from_inode(struct nfs_commit_info *cinfo, + struct inode *inode); + static struct nfs_page * +@@ -500,8 +501,8 @@ nfs_destroy_unlinked_subrequests(struct nfs_page *destroy_list, + * the (former) group. All subrequests are removed from any write or commit + * lists, unlinked from the group and destroyed. + */ +-void +-nfs_join_page_group(struct nfs_page *head, struct inode *inode) ++void nfs_join_page_group(struct nfs_page *head, struct nfs_commit_info *cinfo, ++ struct inode *inode) + { + struct nfs_page *subreq; + struct nfs_page *destroy_list = NULL; +@@ -531,7 +532,7 @@ nfs_join_page_group(struct nfs_page *head, struct inode *inode) + * Commit list removal accounting is done after locks are dropped */ + subreq = head; + do { +- nfs_clear_request_commit(subreq); ++ nfs_clear_request_commit(cinfo, subreq); + subreq = subreq->wb_this_page; + } while (subreq != head); + +@@ -565,8 +566,10 @@ nfs_lock_and_join_requests(struct page *page) + { + struct inode *inode = page_file_mapping(page)->host; + struct nfs_page *head; ++ struct nfs_commit_info cinfo; + int ret; + ++ nfs_init_cinfo_from_inode(&cinfo, inode); + /* + * A reference is taken only on the head request which acts as a + * reference to the whole page group - the group will not be destroyed +@@ -583,7 +586,7 @@ nfs_lock_and_join_requests(struct page *page) + return ERR_PTR(ret); + } + +- nfs_join_page_group(head, inode); ++ nfs_join_page_group(head, &cinfo, inode); + + return head; + } +@@ -944,18 +947,16 @@ nfs_clear_page_commit(struct page *page) + } + + /* Called holding the request lock on @req */ +-static void +-nfs_clear_request_commit(struct nfs_page *req) ++static void nfs_clear_request_commit(struct nfs_commit_info *cinfo, ++ struct nfs_page *req) + { + if (test_bit(PG_CLEAN, &req->wb_flags)) { + struct nfs_open_context *ctx = nfs_req_openctx(req); + struct inode *inode = d_inode(ctx->dentry); +- struct nfs_commit_info cinfo; + +- nfs_init_cinfo_from_inode(&cinfo, inode); + mutex_lock(&NFS_I(inode)->commit_mutex); +- if (!pnfs_clear_request_commit(req, &cinfo)) { +- nfs_request_remove_commit_list(req, &cinfo); ++ if (!pnfs_clear_request_commit(req, cinfo)) { ++ nfs_request_remove_commit_list(req, cinfo); + } + mutex_unlock(&NFS_I(inode)->commit_mutex); + nfs_clear_page_commit(req->wb_page); +diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h +index f0373a6cb5fb6..40aa09a21f75d 100644 +--- a/include/linux/nfs_page.h ++++ b/include/linux/nfs_page.h +@@ -145,7 +145,9 @@ extern void nfs_unlock_request(struct nfs_page *req); + extern void nfs_unlock_and_release_request(struct nfs_page *); + extern struct nfs_page *nfs_page_group_lock_head(struct nfs_page *req); + extern int nfs_page_group_lock_subrequests(struct nfs_page *head); +-extern void nfs_join_page_group(struct nfs_page *head, struct inode *inode); ++extern void nfs_join_page_group(struct nfs_page *head, ++ struct nfs_commit_info *cinfo, ++ struct inode *inode); + extern int nfs_page_group_lock(struct nfs_page *); + extern void nfs_page_group_unlock(struct nfs_page *); + extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int); +-- +2.40.1 + diff --git a/queue-5.10/series b/queue-5.10/series new file mode 100644 index 00000000000..e5f1b481266 --- /dev/null +++ b/queue-5.10/series @@ -0,0 +1,15 @@ +nfs-use-the-correct-commit-info-in-nfs_join_page_gro.patch +nfs-pnfs-report-einval-errors-from-connect-to-the-se.patch +sunrpc-mark-the-cred-for-revalidation-if-the-server-.patch +tracing-increase-trace-array-ref-count-on-enable-and.patch +ata-ahci-drop-pointless-vprintk-calls-and-convert-th.patch +ata-libahci-clear-pending-interrupt-status.patch +ext4-remove-the-group-parameter-of-ext4_trim_extent.patch +ext4-add-new-helper-interface-ext4_try_to_trim_range.patch +ext4-scope-ret-locally-in-ext4_try_to_trim_range.patch +ext4-change-s_last_trim_minblks-type-to-unsigned-lon.patch +ext4-mark-group-as-trimmed-only-if-it-was-fully-scan.patch +ext4-replace-the-traditional-ternary-conditional-ope.patch +ext4-move-setting-of-trimmed-bit-into-ext4_try_to_tr.patch +ext4-do-not-let-fstrim-block-system-suspend.patch +tracing-have-event-inject-files-inc-the-trace-array-.patch diff --git a/queue-5.10/sunrpc-mark-the-cred-for-revalidation-if-the-server-.patch b/queue-5.10/sunrpc-mark-the-cred-for-revalidation-if-the-server-.patch new file mode 100644 index 00000000000..323deaa96ce --- /dev/null +++ b/queue-5.10/sunrpc-mark-the-cred-for-revalidation-if-the-server-.patch @@ -0,0 +1,35 @@ +From 62cd62584c9970f37e8ce1da8c1d6be44acbf3dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Sep 2023 12:50:09 -0400 +Subject: SUNRPC: Mark the cred for revalidation if the server rejects it + +From: Trond Myklebust + +[ Upstream commit 611fa42dfa9d2f3918ac5f4dd5705dfad81b323d ] + +If the server rejects the credential as being stale, or bad, then we +should mark it for revalidation before retransmitting. + +Fixes: 7f5667a5f8c4 ("SUNRPC: Clean up rpc_verify_header()") +Signed-off-by: Trond Myklebust +Signed-off-by: Anna Schumaker +Signed-off-by: Sasha Levin +--- + net/sunrpc/clnt.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c +index e1ce0f261f0be..e9a3fca4aedc0 100644 +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -2630,6 +2630,7 @@ rpc_decode_header(struct rpc_task *task, struct xdr_stream *xdr) + case rpc_autherr_rejectedverf: + case rpcsec_gsserr_credproblem: + case rpcsec_gsserr_ctxproblem: ++ rpcauth_invalcred(task); + if (!task->tk_cred_retry) + break; + task->tk_cred_retry--; +-- +2.40.1 + diff --git a/queue-5.10/tracing-have-event-inject-files-inc-the-trace-array-.patch b/queue-5.10/tracing-have-event-inject-files-inc-the-trace-array-.patch new file mode 100644 index 00000000000..29df5da1161 --- /dev/null +++ b/queue-5.10/tracing-have-event-inject-files-inc-the-trace-array-.patch @@ -0,0 +1,49 @@ +From 7465b1c3fcef0cadf01cc5fe19969a6e8a664013 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Sep 2023 22:47:16 -0400 +Subject: tracing: Have event inject files inc the trace array ref count + +From: Steven Rostedt (Google) + +[ Upstream commit e5c624f027ac74f97e97c8f36c69228ac9f1102d ] + +The event inject files add events for a specific trace array. For an +instance, if the file is opened and the instance is deleted, reading or +writing to the file will cause a use after free. + +Up the ref count of the trace_array when a event inject file is opened. + +Link: https://lkml.kernel.org/r/20230907024804.292337868@goodmis.org +Link: https://lore.kernel.org/all/1cb3aee2-19af-c472-e265-05176fe9bd84@huawei.com/ + +Cc: stable@vger.kernel.org +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Andrew Morton +Cc: Zheng Yejian +Fixes: 6c3edaf9fd6a ("tracing: Introduce trace event injection") +Tested-by: Linux Kernel Functional Testing +Tested-by: Naresh Kamboju +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + kernel/trace/trace_events_inject.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/kernel/trace/trace_events_inject.c b/kernel/trace/trace_events_inject.c +index 22bcf7c51d1ee..149c7dc6a4473 100644 +--- a/kernel/trace/trace_events_inject.c ++++ b/kernel/trace/trace_events_inject.c +@@ -323,7 +323,8 @@ event_inject_read(struct file *file, char __user *buf, size_t size, + } + + const struct file_operations event_inject_fops = { +- .open = tracing_open_generic, ++ .open = tracing_open_file_tr, + .read = event_inject_read, + .write = event_inject_write, ++ .release = tracing_release_file_tr, + }; +-- +2.40.1 + diff --git a/queue-5.10/tracing-increase-trace-array-ref-count-on-enable-and.patch b/queue-5.10/tracing-increase-trace-array-ref-count-on-enable-and.patch new file mode 100644 index 00000000000..25fedf03478 --- /dev/null +++ b/queue-5.10/tracing-increase-trace-array-ref-count-on-enable-and.patch @@ -0,0 +1,115 @@ +From ec4a6f70ce42d49a866c37aa9e4fbb49d6d9f1df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Sep 2023 22:47:12 -0400 +Subject: tracing: Increase trace array ref count on enable and filter files + +From: Steven Rostedt (Google) + +[ Upstream commit f5ca233e2e66dc1c249bf07eefa37e34a6c9346a ] + +When the trace event enable and filter files are opened, increment the +trace array ref counter, otherwise they can be accessed when the trace +array is being deleted. The ref counter keeps the trace array from being +deleted while those files are opened. + +Link: https://lkml.kernel.org/r/20230907024803.456187066@goodmis.org +Link: https://lore.kernel.org/all/1cb3aee2-19af-c472-e265-05176fe9bd84@huawei.com/ + +Cc: stable@vger.kernel.org +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Andrew Morton +Fixes: 8530dec63e7b4 ("tracing: Add tracing_check_open_get_tr()") +Tested-by: Linux Kernel Functional Testing +Tested-by: Naresh Kamboju +Reported-by: Zheng Yejian +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + kernel/trace/trace.c | 27 +++++++++++++++++++++++++++ + kernel/trace/trace.h | 2 ++ + kernel/trace/trace_events.c | 6 ++++-- + 3 files changed, 33 insertions(+), 2 deletions(-) + +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index 7a64c0cd8819d..196eec0423ff2 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -4559,6 +4559,33 @@ int tracing_open_generic_tr(struct inode *inode, struct file *filp) + return 0; + } + ++/* ++ * The private pointer of the inode is the trace_event_file. ++ * Update the tr ref count associated to it. ++ */ ++int tracing_open_file_tr(struct inode *inode, struct file *filp) ++{ ++ struct trace_event_file *file = inode->i_private; ++ int ret; ++ ++ ret = tracing_check_open_get_tr(file->tr); ++ if (ret) ++ return ret; ++ ++ filp->private_data = inode->i_private; ++ ++ return 0; ++} ++ ++int tracing_release_file_tr(struct inode *inode, struct file *filp) ++{ ++ struct trace_event_file *file = inode->i_private; ++ ++ trace_array_put(file->tr); ++ ++ return 0; ++} ++ + static int tracing_release(struct inode *inode, struct file *file) + { + struct trace_array *tr = inode->i_private; +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index dfde855dafda7..7fa00b83dfa4b 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -730,6 +730,8 @@ void tracing_reset_all_online_cpus(void); + void tracing_reset_all_online_cpus_unlocked(void); + int tracing_open_generic(struct inode *inode, struct file *filp); + int tracing_open_generic_tr(struct inode *inode, struct file *filp); ++int tracing_open_file_tr(struct inode *inode, struct file *filp); ++int tracing_release_file_tr(struct inode *inode, struct file *filp); + bool tracing_is_disabled(void); + bool tracer_tracing_is_on(struct trace_array *tr); + void tracer_tracing_on(struct trace_array *tr); +diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c +index a46d34d840f69..321cfda1b3338 100644 +--- a/kernel/trace/trace_events.c ++++ b/kernel/trace/trace_events.c +@@ -1855,9 +1855,10 @@ static const struct file_operations ftrace_set_event_notrace_pid_fops = { + }; + + static const struct file_operations ftrace_enable_fops = { +- .open = tracing_open_generic, ++ .open = tracing_open_file_tr, + .read = event_enable_read, + .write = event_enable_write, ++ .release = tracing_release_file_tr, + .llseek = default_llseek, + }; + +@@ -1874,9 +1875,10 @@ static const struct file_operations ftrace_event_id_fops = { + }; + + static const struct file_operations ftrace_event_filter_fops = { +- .open = tracing_open_generic, ++ .open = tracing_open_file_tr, + .read = event_filter_read, + .write = event_filter_write, ++ .release = tracing_release_file_tr, + .llseek = default_llseek, + }; + +-- +2.40.1 +