From dee5b7e5a103e4f1128c1530f2005dec0092b202 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 24 Feb 2026 13:55:13 -0800 Subject: [PATCH] 6.19-stable patches added patches: alsa-hda-conexant-fix-headphone-jack-handling-on-acer-swift-sf314.patch alsa-hda-realtek-add-quirk-for-gigabyte-g5-kf5-2023.patch alsa-hda-realtek-add-quirk-for-samsung-galaxy-book3-pro-360-np965qfg.patch asoc-dt-bindings-asahi-kasei-ak4458-fix-the-supply-names.patch asoc-dt-bindings-asahi-kasei-ak4458-set-unevaluatedproperties-false.patch asoc-dt-bindings-asahi-kasei-ak5558-fix-the-supply-names.patch ata-libata-scsi-avoid-non-ncq-command-starvation.patch ata-libata-scsi-refactor-ata_scsi_translate.patch ata-pata_ftide010-fix-some-dma-timings.patch dt-bindings-media-qcom-qcs8300-camss-add-missing-power-supplies.patch dt-bindings-phy-qcom-edp-add-missing-clock-for-x-elite.patch ext4-always-allocate-blocks-only-from-groups-inode-can-use.patch ext4-don-t-cache-extent-during-splitting-extent.patch ext4-don-t-set-ext4_get_blocks_convert-when-splitting-before-submitting-i-o.patch ext4-don-t-zero-the-entire-extent-if-ext4_ext_data_partial_valid1.patch ext4-drop-extent-cache-after-doing-partial_valid1-zeroout.patch ext4-drop-extent-cache-when-splitting-extent-fails.patch ext4-fix-dirtyclusters-double-decrement-on-fs-shutdown.patch ext4-fix-e4b-bitmap-inconsistency-reports.patch ext4-fix-memory-leak-in-ext4_ext_shift_extents.patch ext4-subdivide-ext4_ext_data_valid1.patch ext4-use-optimized-mballoc-scanning-regardless-of-inode-format.patch ksmbd-call-ksmbd_vfs_kern_path_end_removing-on-some-error-paths.patch mips-work-around-llvm-bug-when-gp-is-used-as-global-register-variable.patch sunrpc-auth_gss-fix-memory-leaks-in-xdr-decoding-error-paths.patch sunrpc-fix-gss_auth-kref-leak-in-gss_alloc_msg-error-path.patch usb-cdns3-fix-role-switching-during-resume.patch --- ...ne-jack-handling-on-acer-swift-sf314.patch | 56 ++++ ...k-add-quirk-for-gigabyte-g5-kf5-2023.patch | 31 +++ ...amsung-galaxy-book3-pro-360-np965qfg.patch | 33 +++ ...hi-kasei-ak4458-fix-the-supply-names.patch | 42 +++ ...4458-set-unevaluatedproperties-false.patch | 35 +++ ...hi-kasei-ak5558-fix-the-supply-names.patch | 42 +++ ...csi-avoid-non-ncq-command-starvation.patch | 261 ++++++++++++++++++ ...ata-scsi-refactor-ata_scsi_translate.patch | 155 +++++++++++ ...a-pata_ftide010-fix-some-dma-timings.patch | 39 +++ ...300-camss-add-missing-power-supplies.patch | 62 +++++ ...om-edp-add-missing-clock-for-x-elite.patch | 80 ++++++ ...locks-only-from-groups-inode-can-use.patch | 103 +++++++ ...cache-extent-during-splitting-extent.patch | 74 +++++ ...when-splitting-before-submitting-i-o.patch | 96 +++++++ ...tent-if-ext4_ext_data_partial_valid1.patch | 85 ++++++ ...e-after-doing-partial_valid1-zeroout.patch | 84 ++++++ ...nt-cache-when-splitting-extent-fails.patch | 56 ++++ ...ters-double-decrement-on-fs-shutdown.patch | 116 ++++++++ ...fix-e4b-bitmap-inconsistency-reports.patch | 122 ++++++++ ...emory-leak-in-ext4_ext_shift_extents.patch | 40 +++ .../ext4-subdivide-ext4_ext_data_valid1.patch | 85 ++++++ ...-scanning-regardless-of-inode-format.patch | 43 +++ ...ath_end_removing-on-some-error-paths.patch | 63 +++++ ...-is-used-as-global-register-variable.patch | 98 +++++++ queue-6.19/series | 27 ++ ...ry-leaks-in-xdr-decoding-error-paths.patch | 222 +++++++++++++++ ...ref-leak-in-gss_alloc_msg-error-path.patch | 51 ++++ ...ns3-fix-role-switching-during-resume.patch | 87 ++++++ 28 files changed, 2288 insertions(+) create mode 100644 queue-6.19/alsa-hda-conexant-fix-headphone-jack-handling-on-acer-swift-sf314.patch create mode 100644 queue-6.19/alsa-hda-realtek-add-quirk-for-gigabyte-g5-kf5-2023.patch create mode 100644 queue-6.19/alsa-hda-realtek-add-quirk-for-samsung-galaxy-book3-pro-360-np965qfg.patch create mode 100644 queue-6.19/asoc-dt-bindings-asahi-kasei-ak4458-fix-the-supply-names.patch create mode 100644 queue-6.19/asoc-dt-bindings-asahi-kasei-ak4458-set-unevaluatedproperties-false.patch create mode 100644 queue-6.19/asoc-dt-bindings-asahi-kasei-ak5558-fix-the-supply-names.patch create mode 100644 queue-6.19/ata-libata-scsi-avoid-non-ncq-command-starvation.patch create mode 100644 queue-6.19/ata-libata-scsi-refactor-ata_scsi_translate.patch create mode 100644 queue-6.19/ata-pata_ftide010-fix-some-dma-timings.patch create mode 100644 queue-6.19/dt-bindings-media-qcom-qcs8300-camss-add-missing-power-supplies.patch create mode 100644 queue-6.19/dt-bindings-phy-qcom-edp-add-missing-clock-for-x-elite.patch create mode 100644 queue-6.19/ext4-always-allocate-blocks-only-from-groups-inode-can-use.patch create mode 100644 queue-6.19/ext4-don-t-cache-extent-during-splitting-extent.patch create mode 100644 queue-6.19/ext4-don-t-set-ext4_get_blocks_convert-when-splitting-before-submitting-i-o.patch create mode 100644 queue-6.19/ext4-don-t-zero-the-entire-extent-if-ext4_ext_data_partial_valid1.patch create mode 100644 queue-6.19/ext4-drop-extent-cache-after-doing-partial_valid1-zeroout.patch create mode 100644 queue-6.19/ext4-drop-extent-cache-when-splitting-extent-fails.patch create mode 100644 queue-6.19/ext4-fix-dirtyclusters-double-decrement-on-fs-shutdown.patch create mode 100644 queue-6.19/ext4-fix-e4b-bitmap-inconsistency-reports.patch create mode 100644 queue-6.19/ext4-fix-memory-leak-in-ext4_ext_shift_extents.patch create mode 100644 queue-6.19/ext4-subdivide-ext4_ext_data_valid1.patch create mode 100644 queue-6.19/ext4-use-optimized-mballoc-scanning-regardless-of-inode-format.patch create mode 100644 queue-6.19/ksmbd-call-ksmbd_vfs_kern_path_end_removing-on-some-error-paths.patch create mode 100644 queue-6.19/mips-work-around-llvm-bug-when-gp-is-used-as-global-register-variable.patch create mode 100644 queue-6.19/sunrpc-auth_gss-fix-memory-leaks-in-xdr-decoding-error-paths.patch create mode 100644 queue-6.19/sunrpc-fix-gss_auth-kref-leak-in-gss_alloc_msg-error-path.patch create mode 100644 queue-6.19/usb-cdns3-fix-role-switching-during-resume.patch diff --git a/queue-6.19/alsa-hda-conexant-fix-headphone-jack-handling-on-acer-swift-sf314.patch b/queue-6.19/alsa-hda-conexant-fix-headphone-jack-handling-on-acer-swift-sf314.patch new file mode 100644 index 0000000000..da98760af6 --- /dev/null +++ b/queue-6.19/alsa-hda-conexant-fix-headphone-jack-handling-on-acer-swift-sf314.patch @@ -0,0 +1,56 @@ +From 7bc0df86c2384bc1e2012a2c946f82305054da64 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 17 Feb 2026 11:44:11 +0100 +Subject: ALSA: hda/conexant: Fix headphone jack handling on Acer Swift SF314 + +From: Takashi Iwai + +commit 7bc0df86c2384bc1e2012a2c946f82305054da64 upstream. + +Acer Swift SF314 (SSID 1025:136d) needs a bit of tweaks of the pin +configurations for NID 0x16 and 0x19 to make the headphone / headset +jack working. NID 0x17 can remain as is for the working speaker, and +the built-in mic is supported via SOF. + +Cc: +Link: https://bugzilla.kernel.org/show_bug.cgi?id=221086 +Link: https://patch.msgid.link/20260217104414.62911-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/hda/codecs/conexant.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/sound/hda/codecs/conexant.c ++++ b/sound/hda/codecs/conexant.c +@@ -299,6 +299,7 @@ enum { + CXT_PINCFG_SWS_JS201D, + CXT_PINCFG_TOP_SPEAKER, + CXT_FIXUP_HP_A_U, ++ CXT_FIXUP_ACER_SWIFT_HP, + }; + + /* for hda_fixup_thinkpad_acpi() */ +@@ -1024,6 +1025,14 @@ static const struct hda_fixup cxt_fixups + .type = HDA_FIXUP_FUNC, + .v.func = cxt_fixup_hp_a_u, + }, ++ [CXT_FIXUP_ACER_SWIFT_HP] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x16, 0x0321403f }, /* Headphone */ ++ { 0x19, 0x40f001f0 }, /* Mic */ ++ { } ++ }, ++ }, + }; + + static const struct hda_quirk cxt5045_fixups[] = { +@@ -1073,6 +1082,7 @@ static const struct hda_quirk cxt5066_fi + SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC), + SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC), + SND_PCI_QUIRK(0x1025, 0x054f, "Acer Aspire 4830T", CXT_FIXUP_ASPIRE_DMIC), ++ SND_PCI_QUIRK(0x1025, 0x136d, "Acer Swift SF314", CXT_FIXUP_ACER_SWIFT_HP), + SND_PCI_QUIRK(0x103c, 0x8079, "HP EliteBook 840 G3", CXT_FIXUP_HP_DOCK), + SND_PCI_QUIRK(0x103c, 0x807C, "HP EliteBook 820 G3", CXT_FIXUP_HP_DOCK), + SND_PCI_QUIRK(0x103c, 0x80FD, "HP ProBook 640 G2", CXT_FIXUP_HP_DOCK), diff --git a/queue-6.19/alsa-hda-realtek-add-quirk-for-gigabyte-g5-kf5-2023.patch b/queue-6.19/alsa-hda-realtek-add-quirk-for-gigabyte-g5-kf5-2023.patch new file mode 100644 index 0000000000..8fc29f9020 --- /dev/null +++ b/queue-6.19/alsa-hda-realtek-add-quirk-for-gigabyte-g5-kf5-2023.patch @@ -0,0 +1,31 @@ +From 405d59fdd2038a65790eaad8c1013d37a2af6561 Mon Sep 17 00:00:00 2001 +From: Eric Naim +Date: Tue, 10 Feb 2026 17:34:02 +0800 +Subject: ALSA: hda/realtek: Add quirk for Gigabyte G5 KF5 (2023) + +From: Eric Naim + +commit 405d59fdd2038a65790eaad8c1013d37a2af6561 upstream. + +Fixes microphone detection when a headset is connected to the audio jack +using the ALC256. + +Cc: stable@vger.kernel.org +Signed-off-by: Eric Naim +Link: https://patch.msgid.link/20260210093403.21514-1-dnaim@cachyos.org +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/hda/codecs/realtek/alc269.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/hda/codecs/realtek/alc269.c ++++ b/sound/hda/codecs/realtek/alc269.c +@@ -7057,6 +7057,7 @@ static const struct hda_quirk alc269_fix + SND_PCI_QUIRK(0x144d, 0xc886, "Samsung Galaxy Book3 Pro (NP964XFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS), + SND_PCI_QUIRK(0x144d, 0xc1ca, "Samsung Galaxy Book3 Pro 360 (NP960QFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS), + SND_PCI_QUIRK(0x144d, 0xc1cc, "Samsung Galaxy Book3 Ultra (NT960XFH)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS), ++ SND_PCI_QUIRK(0x1458, 0x900e, "Gigabyte G5 KF5 (2023)", ALC2XX_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC), diff --git a/queue-6.19/alsa-hda-realtek-add-quirk-for-samsung-galaxy-book3-pro-360-np965qfg.patch b/queue-6.19/alsa-hda-realtek-add-quirk-for-samsung-galaxy-book3-pro-360-np965qfg.patch new file mode 100644 index 0000000000..5b0084f5f1 --- /dev/null +++ b/queue-6.19/alsa-hda-realtek-add-quirk-for-samsung-galaxy-book3-pro-360-np965qfg.patch @@ -0,0 +1,33 @@ +From 3a6b7dc431aab90744e973254604855e654294ae Mon Sep 17 00:00:00 2001 +From: Lewis Mason +Date: Tue, 10 Feb 2026 23:13:37 +0000 +Subject: ALSA: hda/realtek: Add quirk for Samsung Galaxy Book3 Pro 360 (NP965QFG) + +From: Lewis Mason + +commit 3a6b7dc431aab90744e973254604855e654294ae upstream. + +The Samsung Galaxy Book3 Pro 360 NP965QFG (subsystem ID 0x144d:0xc1cb) +uses the same Realtek ALC298 codec and amplifier configuration as the +NP960QFG (0x144d:0xc1ca). Apply the same ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS +fixup to enable the internal speakers. + +Cc: stable@vger.kernel.org +Signed-off-by: Lewis Mason +Link: https://patch.msgid.link/20260210231337.7265-1-lewis@ocuru.co.uk +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/hda/codecs/realtek/alc269.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/hda/codecs/realtek/alc269.c ++++ b/sound/hda/codecs/realtek/alc269.c +@@ -7056,6 +7056,7 @@ static const struct hda_quirk alc269_fix + SND_PCI_QUIRK(0x144d, 0xc872, "Samsung Galaxy Book2 Pro (NP950XEE)", ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS), + SND_PCI_QUIRK(0x144d, 0xc886, "Samsung Galaxy Book3 Pro (NP964XFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS), + SND_PCI_QUIRK(0x144d, 0xc1ca, "Samsung Galaxy Book3 Pro 360 (NP960QFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS), ++ SND_PCI_QUIRK(0x144d, 0xc1cb, "Samsung Galaxy Book3 Pro 360 (NP965QFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS), + SND_PCI_QUIRK(0x144d, 0xc1cc, "Samsung Galaxy Book3 Ultra (NT960XFH)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS), + SND_PCI_QUIRK(0x1458, 0x900e, "Gigabyte G5 KF5 (2023)", ALC2XX_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC), diff --git a/queue-6.19/asoc-dt-bindings-asahi-kasei-ak4458-fix-the-supply-names.patch b/queue-6.19/asoc-dt-bindings-asahi-kasei-ak4458-fix-the-supply-names.patch new file mode 100644 index 0000000000..bc902e6c89 --- /dev/null +++ b/queue-6.19/asoc-dt-bindings-asahi-kasei-ak4458-fix-the-supply-names.patch @@ -0,0 +1,42 @@ +From e570a5ca307f6d7a6acd080fc219db2ce3c0737b Mon Sep 17 00:00:00 2001 +From: Shengjiu Wang +Date: Thu, 12 Feb 2026 10:18:28 +0800 +Subject: ASoC: dt-bindings: asahi-kasei,ak4458: Fix the supply names + +From: Shengjiu Wang + +commit e570a5ca307f6d7a6acd080fc219db2ce3c0737b upstream. + +In the original txt format binding document ak4458.txt, the supply names +are 'AVDD-supply', 'DVDD-supply', and they are also used in driver. But in +the commit converting to yaml format, they are changed to 'avdd-supply', +'dvdd-supply'. After search all the dts file, these names 'AVDD-supply', +'DVDD-supply', 'avdd-supply', 'dvdd-supply' are not used in any dts +file. So it is safe to fix this yaml binding document. + +Fixes: 009e83b591dd ("ASoC: dt-bindings: ak4458: Convert to dtschema") +Cc: stable@vger.kernel.org +Signed-off-by: Shengjiu Wang +Reviewed-by: Krzysztof Kozlowski +Link: https://patch.msgid.link/20260212021829.3244736-3-shengjiu.wang@nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml ++++ b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml +@@ -21,10 +21,10 @@ properties: + reg: + maxItems: 1 + +- avdd-supply: ++ AVDD-supply: + description: Analog power supply + +- dvdd-supply: ++ DVDD-supply: + description: Digital power supply + + reset-gpios: diff --git a/queue-6.19/asoc-dt-bindings-asahi-kasei-ak4458-set-unevaluatedproperties-false.patch b/queue-6.19/asoc-dt-bindings-asahi-kasei-ak4458-set-unevaluatedproperties-false.patch new file mode 100644 index 0000000000..60ee9f16e5 --- /dev/null +++ b/queue-6.19/asoc-dt-bindings-asahi-kasei-ak4458-set-unevaluatedproperties-false.patch @@ -0,0 +1,35 @@ +From 50a634f1d795721ce68583c78ba493f1d7aa8bc2 Mon Sep 17 00:00:00 2001 +From: Shengjiu Wang +Date: Thu, 12 Feb 2026 10:18:27 +0800 +Subject: ASoC: dt-bindings: asahi-kasei,ak4458: set unevaluatedProperties:false + +From: Shengjiu Wang + +commit 50a634f1d795721ce68583c78ba493f1d7aa8bc2 upstream. + +When including the dai-common.yaml, and allow '#sound-dai-cells' and +"sound-name-prefix' to be used, should use unevaluatedProperties:false +according to writing-bindings.rst. + +Fixes: 8d7de4a014f5 ("ASoC: dt-bindings: asahi-kasei,ak4458: Reference common DAI properties") +Cc: stable@vger.kernel.org +Signed-off-by: Shengjiu Wang +Reviewed-by: Krzysztof Kozlowski +Link: https://patch.msgid.link/20260212021829.3244736-2-shengjiu.wang@nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml ++++ b/Documentation/devicetree/bindings/sound/asahi-kasei,ak4458.yaml +@@ -60,7 +60,7 @@ allOf: + properties: + dsd-path: false + +-additionalProperties: false ++unevaluatedProperties: false + + examples: + - | diff --git a/queue-6.19/asoc-dt-bindings-asahi-kasei-ak5558-fix-the-supply-names.patch b/queue-6.19/asoc-dt-bindings-asahi-kasei-ak5558-fix-the-supply-names.patch new file mode 100644 index 0000000000..dee7aac2ca --- /dev/null +++ b/queue-6.19/asoc-dt-bindings-asahi-kasei-ak5558-fix-the-supply-names.patch @@ -0,0 +1,42 @@ +From 80ca113671a005430207d351cb403c1637106212 Mon Sep 17 00:00:00 2001 +From: Shengjiu Wang +Date: Thu, 12 Feb 2026 10:18:29 +0800 +Subject: ASoC: dt-bindings: asahi-kasei,ak5558: Fix the supply names + +From: Shengjiu Wang + +commit 80ca113671a005430207d351cb403c1637106212 upstream. + +In the original txt format binding document ak4458.txt, the supply names +are 'AVDD-supply', 'DVDD-supply', and they are also used in driver. But in +the commit converting to yaml format, they are changed to 'avdd-supply', +'dvdd-supply'. After search all the dts file, these names 'AVDD-supply', +'DVDD-supply', 'avdd-supply', 'dvdd-supply' are not used in any dts +file. So it is safe to fix the yaml binding document. + +Fixes: 829d78e3ea32 ("ASoC: dt-bindings: ak5558: Convert to dtschema") +Cc: stable@vger.kernel.org +Signed-off-by: Shengjiu Wang +Reviewed-by: Krzysztof Kozlowski +Link: https://patch.msgid.link/20260212021829.3244736-4-shengjiu.wang@nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman +--- + Documentation/devicetree/bindings/sound/asahi-kasei,ak5558.yaml | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/Documentation/devicetree/bindings/sound/asahi-kasei,ak5558.yaml ++++ b/Documentation/devicetree/bindings/sound/asahi-kasei,ak5558.yaml +@@ -19,10 +19,10 @@ properties: + reg: + maxItems: 1 + +- avdd-supply: ++ AVDD-supply: + description: A 1.8V supply that powers up the AVDD pin. + +- dvdd-supply: ++ DVDD-supply: + description: A 1.2V supply that powers up the DVDD pin. + + reset-gpios: diff --git a/queue-6.19/ata-libata-scsi-avoid-non-ncq-command-starvation.patch b/queue-6.19/ata-libata-scsi-avoid-non-ncq-command-starvation.patch new file mode 100644 index 0000000000..ed0b7fc7c1 --- /dev/null +++ b/queue-6.19/ata-libata-scsi-avoid-non-ncq-command-starvation.patch @@ -0,0 +1,261 @@ +From 0ea84089dbf62a92dc7889c79e6b18fc89260808 Mon Sep 17 00:00:00 2001 +From: Damien Le Moal +Date: Wed, 17 Dec 2025 16:40:48 +0900 +Subject: ata: libata-scsi: avoid Non-NCQ command starvation + +From: Damien Le Moal + +commit 0ea84089dbf62a92dc7889c79e6b18fc89260808 upstream. + +When a non-NCQ command is issued while NCQ commands are being executed, +ata_scsi_qc_issue() indicates to the SCSI layer that the command issuing +should be deferred by returning SCSI_MLQUEUE_XXX_BUSY. This command +deferring is correct and as mandated by the ACS specifications since +NCQ and non-NCQ commands cannot be mixed. + +However, in the case of a host adapter using multiple submission queues, +when the target device is under a constant load of NCQ commands, there +are no guarantees that requeueing the non-NCQ command will be executed +later and it may be deferred again repeatedly as other submission queues +can constantly issue NCQ commands from different CPUs ahead of the +non-NCQ command. This can lead to very long delays for the execution of +non-NCQ commands, and even complete starvation for these commands in the +worst case scenario. + +Since the block layer and the SCSI layer do not distinguish between +queueable (NCQ) and non queueable (non-NCQ) commands, libata-scsi SAT +implementation must ensure forward progress for non-NCQ commands in the +presence of NCQ command traffic. This is similar to what SAS HBAs with a +hardware/firmware based SAT implementation do. + +Implement such forward progress guarantee by limiting requeueing of +non-NCQ commands from ata_scsi_qc_issue(): when a non-NCQ command is +received and NCQ commands are in-flight, do not force a requeue of the +non-NCQ command by returning SCSI_MLQUEUE_XXX_BUSY and instead return 0 +to indicate that the command was accepted but hold on to the qc using +the new deferred_qc field of struct ata_port. + +This deferred qc will be issued using the work item deferred_qc_work +running the function ata_scsi_deferred_qc_work() once all in-flight +commands complete, which is checked with the port qc_defer() callback +return value indicating that no further delay is necessary. This check +is done using the helper function ata_scsi_schedule_deferred_qc() which +is called from ata_scsi_qc_complete(). This thus excludes this mechanism +from all internal non-NCQ commands issued by ATA EH. + +When a port deferred_qc is non NULL, that is, the port has a command +waiting for the device queue to drain, the issuing of all incoming +commands (both NCQ and non-NCQ) is deferred using the regular busy +mechanism. This simplifies the code and also avoids potential denial of +service problems if a user issues too many non-NCQ commands. + +Finally, whenever ata EH is scheduled, regardless of the reason, a +deferred qc is always requeued so that it can be retried once EH +completes. This is done by calling the function +ata_scsi_requeue_deferred_qc() from ata_eh_set_pending(). This avoids +the need for any special processing for the deferred qc in case of NCQ +error, link or device reset, or device timeout. + +Reported-by: Xingui Yang +Reported-by: Igor Pylypiv +Fixes: bdb01301f3ea ("scsi: Add host and host template flag 'host_tagset'") +Cc: stable@vger.kernel.org +Signed-off-by: Damien Le Moal +Reviewed-by: Niklas Cassel +Reviewed-by: Martin K. Petersen +Reviewed-by: John Garry +Tested-by: Igor Pylypiv +Tested-by: Xingui Yang +Signed-off-by: Greg Kroah-Hartman +--- + drivers/ata/libata-core.c | 5 ++ + drivers/ata/libata-eh.c | 6 ++ + drivers/ata/libata-scsi.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++ + drivers/ata/libata.h | 2 + include/linux/libata.h | 3 + + 5 files changed, 109 insertions(+) + +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -5620,6 +5620,7 @@ struct ata_port *ata_port_alloc(struct a + mutex_init(&ap->scsi_scan_mutex); + INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug); + INIT_DELAYED_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan); ++ INIT_WORK(&ap->deferred_qc_work, ata_scsi_deferred_qc_work); + INIT_LIST_HEAD(&ap->eh_done_q); + init_waitqueue_head(&ap->eh_wait_q); + init_completion(&ap->park_req_pending); +@@ -6232,6 +6233,10 @@ static void ata_port_detach(struct ata_p + } + } + ++ /* Make sure the deferred qc work finished. */ ++ cancel_work_sync(&ap->deferred_qc_work); ++ WARN_ON(ap->deferred_qc); ++ + /* Tell EH to disable all devices */ + ap->pflags |= ATA_PFLAG_UNLOADING; + ata_port_schedule_eh(ap); +--- a/drivers/ata/libata-eh.c ++++ b/drivers/ata/libata-eh.c +@@ -917,6 +917,12 @@ static void ata_eh_set_pending(struct at + + ap->pflags |= ATA_PFLAG_EH_PENDING; + ++ /* ++ * If we have a deferred qc, requeue it so that it is retried once EH ++ * completes. ++ */ ++ ata_scsi_requeue_deferred_qc(ap); ++ + if (!fastdrain) + return; + +--- a/drivers/ata/libata-scsi.c ++++ b/drivers/ata/libata-scsi.c +@@ -1658,8 +1658,77 @@ static void ata_qc_done(struct ata_queue + done(cmd); + } + ++void ata_scsi_deferred_qc_work(struct work_struct *work) ++{ ++ struct ata_port *ap = ++ container_of(work, struct ata_port, deferred_qc_work); ++ struct ata_queued_cmd *qc; ++ unsigned long flags; ++ ++ spin_lock_irqsave(ap->lock, flags); ++ ++ /* ++ * If we still have a deferred qc and we are not in EH, issue it. In ++ * such case, we should not need any more deferring the qc, so warn if ++ * qc_defer() says otherwise. ++ */ ++ qc = ap->deferred_qc; ++ if (qc && !ata_port_eh_scheduled(ap)) { ++ WARN_ON_ONCE(ap->ops->qc_defer(qc)); ++ ap->deferred_qc = NULL; ++ ata_qc_issue(qc); ++ } ++ ++ spin_unlock_irqrestore(ap->lock, flags); ++} ++ ++void ata_scsi_requeue_deferred_qc(struct ata_port *ap) ++{ ++ struct ata_queued_cmd *qc = ap->deferred_qc; ++ struct scsi_cmnd *scmd; ++ ++ lockdep_assert_held(ap->lock); ++ ++ /* ++ * If we have a deferred qc when a reset occurs or NCQ commands fail, ++ * do not try to be smart about what to do with this deferred command ++ * and simply retry it by completing it with DID_SOFT_ERROR. ++ */ ++ if (!qc) ++ return; ++ ++ scmd = qc->scsicmd; ++ ap->deferred_qc = NULL; ++ ata_qc_free(qc); ++ scmd->result = (DID_SOFT_ERROR << 16); ++ scsi_done(scmd); ++} ++ ++static void ata_scsi_schedule_deferred_qc(struct ata_port *ap) ++{ ++ struct ata_queued_cmd *qc = ap->deferred_qc; ++ ++ lockdep_assert_held(ap->lock); ++ ++ /* ++ * If we have a deferred qc, then qc_defer() is defined and we can use ++ * this callback to determine if this qc is good to go, unless EH has ++ * been scheduled. ++ */ ++ if (!qc) ++ return; ++ ++ if (ata_port_eh_scheduled(ap)) { ++ ata_scsi_requeue_deferred_qc(ap); ++ return; ++ } ++ if (!ap->ops->qc_defer(qc)) ++ queue_work(system_highpri_wq, &ap->deferred_qc_work); ++} ++ + static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) + { ++ struct ata_port *ap = qc->ap; + struct scsi_cmnd *cmd = qc->scsicmd; + u8 *cdb = cmd->cmnd; + bool have_sense = qc->flags & ATA_QCFLAG_SENSE_VALID; +@@ -1689,6 +1758,8 @@ static void ata_scsi_qc_complete(struct + } + + ata_qc_done(qc); ++ ++ ata_scsi_schedule_deferred_qc(ap); + } + + static int ata_scsi_qc_issue(struct ata_port *ap, struct ata_queued_cmd *qc) +@@ -1698,6 +1769,16 @@ static int ata_scsi_qc_issue(struct ata_ + if (!ap->ops->qc_defer) + goto issue; + ++ /* ++ * If we already have a deferred qc, then rely on the SCSI layer to ++ * requeue and defer all incoming commands until the deferred qc is ++ * processed, once all on-going commands complete. ++ */ ++ if (ap->deferred_qc) { ++ ata_qc_free(qc); ++ return SCSI_MLQUEUE_DEVICE_BUSY; ++ } ++ + /* Check if the command needs to be deferred. */ + ret = ap->ops->qc_defer(qc); + switch (ret) { +@@ -1716,6 +1797,18 @@ static int ata_scsi_qc_issue(struct ata_ + } + + if (ret) { ++ /* ++ * We must defer this qc: if this is not an NCQ command, keep ++ * this qc as a deferred one and report to the SCSI layer that ++ * we issued it so that it is not requeued. The deferred qc will ++ * be issued with the port deferred_qc_work once all on-going ++ * commands complete. ++ */ ++ if (!ata_is_ncq(qc->tf.protocol)) { ++ ap->deferred_qc = qc; ++ return 0; ++ } ++ + /* Force a requeue of the command to defer its execution. */ + ata_qc_free(qc); + return ret; +--- a/drivers/ata/libata.h ++++ b/drivers/ata/libata.h +@@ -165,6 +165,8 @@ void ata_scsi_sdev_config(struct scsi_de + int ata_scsi_dev_config(struct scsi_device *sdev, struct queue_limits *lim, + struct ata_device *dev); + int __ata_scsi_queuecmd(struct scsi_cmnd *scmd, struct ata_device *dev); ++void ata_scsi_deferred_qc_work(struct work_struct *work); ++void ata_scsi_requeue_deferred_qc(struct ata_port *ap); + + /* libata-eh.c */ + extern unsigned int ata_internal_cmd_timeout(struct ata_device *dev, u8 cmd); +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -903,6 +903,9 @@ struct ata_port { + u64 qc_active; + int nr_active_links; /* #links with active qcs */ + ++ struct work_struct deferred_qc_work; ++ struct ata_queued_cmd *deferred_qc; ++ + struct ata_link link; /* host default link */ + struct ata_link *slave_link; /* see ata_slave_link_init() */ + diff --git a/queue-6.19/ata-libata-scsi-refactor-ata_scsi_translate.patch b/queue-6.19/ata-libata-scsi-refactor-ata_scsi_translate.patch new file mode 100644 index 0000000000..540ea1654d --- /dev/null +++ b/queue-6.19/ata-libata-scsi-refactor-ata_scsi_translate.patch @@ -0,0 +1,155 @@ +From bb3a8154b1a1dc2c86d037482c0a2cf9186829ed Mon Sep 17 00:00:00 2001 +From: Damien Le Moal +Date: Wed, 17 Dec 2025 14:05:25 +0900 +Subject: ata: libata-scsi: refactor ata_scsi_translate() + +From: Damien Le Moal + +commit bb3a8154b1a1dc2c86d037482c0a2cf9186829ed upstream. + +Factor out of ata_scsi_translate() the code handling queued command +deferral using the port qc_defer callback and issuing the queued +command with ata_qc_issue() into the new function ata_scsi_qc_issue(), +and simplify the goto used in ata_scsi_translate(). +While at it, also add a lockdep annotation to check that the port lock +is held when ata_scsi_translate() is called. + +No functional changes. + +Cc: stable@vger.kernel.org +Signed-off-by: Damien Le Moal +Reviewed-by: Niklas Cassel +Reviewed-by: Martin K. Petersen +Reviewed-by: John Garry +Reviewed-by: Igor Pylypiv +Signed-off-by: Greg Kroah-Hartman +--- + drivers/ata/libata-scsi.c | 81 ++++++++++++++++++++++++++++------------------ + 1 file changed, 50 insertions(+), 31 deletions(-) + +--- a/drivers/ata/libata-scsi.c ++++ b/drivers/ata/libata-scsi.c +@@ -1691,6 +1691,42 @@ static void ata_scsi_qc_complete(struct + ata_qc_done(qc); + } + ++static int ata_scsi_qc_issue(struct ata_port *ap, struct ata_queued_cmd *qc) ++{ ++ int ret; ++ ++ if (!ap->ops->qc_defer) ++ goto issue; ++ ++ /* Check if the command needs to be deferred. */ ++ ret = ap->ops->qc_defer(qc); ++ switch (ret) { ++ case 0: ++ break; ++ case ATA_DEFER_LINK: ++ ret = SCSI_MLQUEUE_DEVICE_BUSY; ++ break; ++ case ATA_DEFER_PORT: ++ ret = SCSI_MLQUEUE_HOST_BUSY; ++ break; ++ default: ++ WARN_ON_ONCE(1); ++ ret = SCSI_MLQUEUE_HOST_BUSY; ++ break; ++ } ++ ++ if (ret) { ++ /* Force a requeue of the command to defer its execution. */ ++ ata_qc_free(qc); ++ return ret; ++ } ++ ++issue: ++ ata_qc_issue(qc); ++ ++ return 0; ++} ++ + /** + * ata_scsi_translate - Translate then issue SCSI command to ATA device + * @dev: ATA device to which the command is addressed +@@ -1714,66 +1750,49 @@ static void ata_scsi_qc_complete(struct + * spin_lock_irqsave(host lock) + * + * RETURNS: +- * 0 on success, SCSI_ML_QUEUE_DEVICE_BUSY if the command +- * needs to be deferred. ++ * 0 on success, SCSI_ML_QUEUE_DEVICE_BUSY or SCSI_MLQUEUE_HOST_BUSY if the ++ * command needs to be deferred. + */ + static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd, + ata_xlat_func_t xlat_func) + { + struct ata_port *ap = dev->link->ap; + struct ata_queued_cmd *qc; +- int rc; + ++ lockdep_assert_held(ap->lock); ++ ++ /* ++ * ata_scsi_qc_new() calls scsi_done(cmd) in case of failure. So we ++ * have nothing further to do when allocating a qc fails. ++ */ + qc = ata_scsi_qc_new(dev, cmd); + if (!qc) +- goto err_mem; ++ return 0; + + /* data is present; dma-map it */ + if (cmd->sc_data_direction == DMA_FROM_DEVICE || + cmd->sc_data_direction == DMA_TO_DEVICE) { + if (unlikely(scsi_bufflen(cmd) < 1)) { + ata_dev_warn(dev, "WARNING: zero len r/w req\n"); +- goto err_did; ++ cmd->result = (DID_ERROR << 16); ++ goto done; + } + + ata_sg_init(qc, scsi_sglist(cmd), scsi_sg_count(cmd)); +- + qc->dma_dir = cmd->sc_data_direction; + } + + qc->complete_fn = ata_scsi_qc_complete; + + if (xlat_func(qc)) +- goto early_finish; +- +- if (ap->ops->qc_defer) { +- if ((rc = ap->ops->qc_defer(qc))) +- goto defer; +- } +- +- /* select device, send command to hardware */ +- ata_qc_issue(qc); +- +- return 0; ++ goto done; + +-early_finish: +- ata_qc_free(qc); +- scsi_done(cmd); +- return 0; ++ return ata_scsi_qc_issue(ap, qc); + +-err_did: ++done: + ata_qc_free(qc); +- cmd->result = (DID_ERROR << 16); + scsi_done(cmd); +-err_mem: + return 0; +- +-defer: +- ata_qc_free(qc); +- if (rc == ATA_DEFER_LINK) +- return SCSI_MLQUEUE_DEVICE_BUSY; +- else +- return SCSI_MLQUEUE_HOST_BUSY; + } + + /** diff --git a/queue-6.19/ata-pata_ftide010-fix-some-dma-timings.patch b/queue-6.19/ata-pata_ftide010-fix-some-dma-timings.patch new file mode 100644 index 0000000000..14b418c42f --- /dev/null +++ b/queue-6.19/ata-pata_ftide010-fix-some-dma-timings.patch @@ -0,0 +1,39 @@ +From ff4a46c278ac6a4b3f39be1492a4568b6dcc6105 Mon Sep 17 00:00:00 2001 +From: Linus Walleij +Date: Tue, 3 Feb 2026 11:23:01 +0100 +Subject: ata: pata_ftide010: Fix some DMA timings + +From: Linus Walleij + +commit ff4a46c278ac6a4b3f39be1492a4568b6dcc6105 upstream. + +The FTIDE010 has been missing some timing settings since its +inception, since the upstream OpenWrt patch was missing these. + +The community has since come up with the appropriate timings. + +Fixes: be4e456ed3a5 ("ata: Add driver for Faraday Technology FTIDE010") +Cc: stable@vger.kernel.org +Signed-off-by: Linus Walleij +Signed-off-by: Niklas Cassel +Signed-off-by: Greg Kroah-Hartman +--- + drivers/ata/pata_ftide010.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/ata/pata_ftide010.c ++++ b/drivers/ata/pata_ftide010.c +@@ -122,10 +122,10 @@ static const u8 mwdma_50_active_time[3] + static const u8 mwdma_50_recovery_time[3] = {6, 2, 1}; + static const u8 mwdma_66_active_time[3] = {8, 3, 3}; + static const u8 mwdma_66_recovery_time[3] = {8, 2, 1}; +-static const u8 udma_50_setup_time[6] = {3, 3, 2, 2, 1, 1}; ++static const u8 udma_50_setup_time[6] = {3, 3, 2, 2, 1, 9}; + static const u8 udma_50_hold_time[6] = {3, 1, 1, 1, 1, 1}; +-static const u8 udma_66_setup_time[7] = {4, 4, 3, 2, }; +-static const u8 udma_66_hold_time[7] = {}; ++static const u8 udma_66_setup_time[7] = {4, 4, 3, 2, 1, 9, 9}; ++static const u8 udma_66_hold_time[7] = {4, 2, 1, 1, 1, 1, 1}; + + /* + * We set 66 MHz for all MWDMA modes diff --git a/queue-6.19/dt-bindings-media-qcom-qcs8300-camss-add-missing-power-supplies.patch b/queue-6.19/dt-bindings-media-qcom-qcs8300-camss-add-missing-power-supplies.patch new file mode 100644 index 0000000000..1edc484718 --- /dev/null +++ b/queue-6.19/dt-bindings-media-qcom-qcs8300-camss-add-missing-power-supplies.patch @@ -0,0 +1,62 @@ +From 555e882051a3a7ecc2bcee2b2047822249dcd074 Mon Sep 17 00:00:00 2001 +From: Vikram Sharma +Date: Fri, 7 Nov 2025 21:55:20 +0530 +Subject: dt-bindings: media: qcom,qcs8300-camss: Add missing power supplies + +From: Vikram Sharma + +commit 555e882051a3a7ecc2bcee2b2047822249dcd074 upstream. + +Add missing vdda-phy-supply and vdda-pll-supply in the (monaco)qcs8300 +camss binding. While enabling imx412 sensor for qcs8300 we see a need +to add these supplies which were missing in initial submission. + +Fixes: 634a2958fae30 ("media: dt-bindings: Add qcom,qcs8300-camss compatible") +Cc: stable@vger.kernel.org +Co-developed-by: Nihal Kumar Gupta +Signed-off-by: Nihal Kumar Gupta +Signed-off-by: Vikram Sharma +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Bryan O'Donoghue +Signed-off-by: Hans Verkuil +Signed-off-by: Greg Kroah-Hartman +--- + Documentation/devicetree/bindings/media/qcom,qcs8300-camss.yaml | 13 ++++++++++ + 1 file changed, 13 insertions(+) + +--- a/Documentation/devicetree/bindings/media/qcom,qcs8300-camss.yaml ++++ b/Documentation/devicetree/bindings/media/qcom,qcs8300-camss.yaml +@@ -120,6 +120,14 @@ properties: + items: + - const: top + ++ vdda-phy-supply: ++ description: ++ Phandle to a 0.88V regulator supply to CSI PHYs. ++ ++ vdda-pll-supply: ++ description: ++ Phandle to 1.2V regulator supply to CSI PHYs pll block. ++ + ports: + $ref: /schemas/graph.yaml#/properties/ports + +@@ -160,6 +168,8 @@ required: + - power-domains + - power-domain-names + - ports ++ - vdda-phy-supply ++ - vdda-pll-supply + + additionalProperties: false + +@@ -328,6 +338,9 @@ examples: + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "top"; + ++ vdda-phy-supply = <&vreg_l4a_0p88>; ++ vdda-pll-supply = <&vreg_l1c_1p2>; ++ + ports { + #address-cells = <1>; + #size-cells = <0>; diff --git a/queue-6.19/dt-bindings-phy-qcom-edp-add-missing-clock-for-x-elite.patch b/queue-6.19/dt-bindings-phy-qcom-edp-add-missing-clock-for-x-elite.patch new file mode 100644 index 0000000000..9a0b2e3e53 --- /dev/null +++ b/queue-6.19/dt-bindings-phy-qcom-edp-add-missing-clock-for-x-elite.patch @@ -0,0 +1,80 @@ +From 6b99eeacf6abb1ff2d6463c84e490343f39cf11a Mon Sep 17 00:00:00 2001 +From: Abel Vesa +Date: Wed, 24 Dec 2025 12:53:27 +0200 +Subject: dt-bindings: phy: qcom-edp: Add missing clock for X Elite + +From: Abel Vesa + +commit 6b99eeacf6abb1ff2d6463c84e490343f39cf11a upstream. + +On X Elite platform, the eDP PHY uses one more clock called ref. + +The current X Elite devices supported upstream work fine without this +clock, because the boot firmware leaves this clock enabled. But we should +not rely on that. Also, even though this change breaks the ABI, it is +needed in order to make the driver disables this clock along with the +other ones, for a proper bring-down of the entire PHY. + +So attach the this ref clock to the PHY. + +Cc: stable@vger.kernel.org # v6.10 +Fixes: 5d5607861350 ("dt-bindings: phy: qcom-edp: Add X1E80100 PHY compatibles") +Reviewed-by: Krzysztof Kozlowski +Reviewed-by: Bjorn Andersson +Signed-off-by: Abel Vesa +Link: https://patch.msgid.link/20251224-phy-qcom-edp-add-missing-refclk-v5-1-3f45d349b5ac@oss.qualcomm.com +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman +--- + Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml | 28 +++++++++++++++- + 1 file changed, 27 insertions(+), 1 deletion(-) + +--- a/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml ++++ b/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml +@@ -37,12 +37,15 @@ properties: + - description: PLL register block + + clocks: +- maxItems: 2 ++ minItems: 2 ++ maxItems: 3 + + clock-names: ++ minItems: 2 + items: + - const: aux + - const: cfg_ahb ++ - const: ref + + "#clock-cells": + const: 1 +@@ -64,6 +67,29 @@ required: + - "#clock-cells" + - "#phy-cells" + ++allOf: ++ - if: ++ properties: ++ compatible: ++ enum: ++ - qcom,x1e80100-dp-phy ++ then: ++ properties: ++ clocks: ++ minItems: 3 ++ maxItems: 3 ++ clock-names: ++ minItems: 3 ++ maxItems: 3 ++ else: ++ properties: ++ clocks: ++ minItems: 2 ++ maxItems: 2 ++ clock-names: ++ minItems: 2 ++ maxItems: 2 ++ + additionalProperties: false + + examples: diff --git a/queue-6.19/ext4-always-allocate-blocks-only-from-groups-inode-can-use.patch b/queue-6.19/ext4-always-allocate-blocks-only-from-groups-inode-can-use.patch new file mode 100644 index 0000000000..dc32a6e1e0 --- /dev/null +++ b/queue-6.19/ext4-always-allocate-blocks-only-from-groups-inode-can-use.patch @@ -0,0 +1,103 @@ +From 4865c768b563deff1b6a6384e74a62f143427b42 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 14 Jan 2026 19:28:18 +0100 +Subject: ext4: always allocate blocks only from groups inode can use + +From: Jan Kara + +commit 4865c768b563deff1b6a6384e74a62f143427b42 upstream. + +For filesystems with more than 2^32 blocks inodes using indirect block +based format cannot use blocks beyond the 32-bit limit. +ext4_mb_scan_groups_linear() takes care to not select these unsupported +groups for such inodes however other functions selecting groups for +allocation don't. So far this is harmless because the other selection +functions are used only with mb_optimize_scan and this is currently +disabled for inodes with indirect blocks however in the following patch +we want to enable mb_optimize_scan regardless of inode format. + +Reviewed-by: Baokun Li +Reviewed-by: Zhang Yi +Signed-off-by: Jan Kara +Acked-by: Pedro Falcato +Cc: stable@kernel.org +Link: https://patch.msgid.link/20260114182836.14120-3-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/mballoc.c | 29 ++++++++++++++++++++--------- + 1 file changed, 20 insertions(+), 9 deletions(-) + +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -892,6 +892,21 @@ mb_update_avg_fragment_size(struct super + } + } + ++static ext4_group_t ext4_get_allocation_groups_count( ++ struct ext4_allocation_context *ac) ++{ ++ ext4_group_t ngroups = ext4_get_groups_count(ac->ac_sb); ++ ++ /* non-extent files are limited to low blocks/groups */ ++ if (!(ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS))) ++ ngroups = EXT4_SB(ac->ac_sb)->s_blockfile_groups; ++ ++ /* Pairs with smp_wmb() in ext4_update_super() */ ++ smp_rmb(); ++ ++ return ngroups; ++} ++ + static int ext4_mb_scan_groups_xa_range(struct ext4_allocation_context *ac, + struct xarray *xa, + ext4_group_t start, ext4_group_t end) +@@ -899,7 +914,7 @@ static int ext4_mb_scan_groups_xa_range( + struct super_block *sb = ac->ac_sb; + struct ext4_sb_info *sbi = EXT4_SB(sb); + enum criteria cr = ac->ac_criteria; +- ext4_group_t ngroups = ext4_get_groups_count(sb); ++ ext4_group_t ngroups = ext4_get_allocation_groups_count(ac); + unsigned long group = start; + struct ext4_group_info *grp; + +@@ -951,7 +966,7 @@ static int ext4_mb_scan_groups_p2_aligne + ext4_group_t start, end; + + start = group; +- end = ext4_get_groups_count(ac->ac_sb); ++ end = ext4_get_allocation_groups_count(ac); + wrap_around: + for (i = ac->ac_2order; i < MB_NUM_ORDERS(ac->ac_sb); i++) { + ret = ext4_mb_scan_groups_largest_free_order_range(ac, i, +@@ -1001,7 +1016,7 @@ static int ext4_mb_scan_groups_goal_fast + ext4_group_t start, end; + + start = group; +- end = ext4_get_groups_count(ac->ac_sb); ++ end = ext4_get_allocation_groups_count(ac); + wrap_around: + i = mb_avg_fragment_size_order(ac->ac_sb, ac->ac_g_ex.fe_len); + for (; i < MB_NUM_ORDERS(ac->ac_sb); i++) { +@@ -1083,7 +1098,7 @@ static int ext4_mb_scan_groups_best_avai + min_order = fls(ac->ac_o_ex.fe_len); + + start = group; +- end = ext4_get_groups_count(ac->ac_sb); ++ end = ext4_get_allocation_groups_count(ac); + wrap_around: + for (i = order; i >= min_order; i--) { + int frag_order; +@@ -1182,11 +1197,7 @@ static int ext4_mb_scan_groups(struct ex + int ret = 0; + ext4_group_t start; + struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb); +- ext4_group_t ngroups = ext4_get_groups_count(ac->ac_sb); +- +- /* non-extent files are limited to low blocks/groups */ +- if (!(ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS))) +- ngroups = sbi->s_blockfile_groups; ++ ext4_group_t ngroups = ext4_get_allocation_groups_count(ac); + + /* searching for the right group start from the goal value specified */ + start = ac->ac_g_ex.fe_group; diff --git a/queue-6.19/ext4-don-t-cache-extent-during-splitting-extent.patch b/queue-6.19/ext4-don-t-cache-extent-during-splitting-extent.patch new file mode 100644 index 0000000000..c86be5cbf6 --- /dev/null +++ b/queue-6.19/ext4-don-t-cache-extent-during-splitting-extent.patch @@ -0,0 +1,74 @@ +From 8b4b19a2f96348d70bfa306ef7d4a13b0bcbea79 Mon Sep 17 00:00:00 2001 +From: Zhang Yi +Date: Sat, 29 Nov 2025 18:32:37 +0800 +Subject: ext4: don't cache extent during splitting extent + +From: Zhang Yi + +commit 8b4b19a2f96348d70bfa306ef7d4a13b0bcbea79 upstream. + +Caching extents during the splitting process is risky, as it may result +in stale extents remaining in the status tree. Moreover, in most cases, +the corresponding extent block entries are likely already cached before +the split happens, making caching here not particularly useful. + +Assume we have an unwritten extent, and then DIO writes the first half. + + [UUUUUUUUUUUUUUUU] on-disk extent U: unwritten extent + [UUUUUUUUUUUUUUUU] extent status tree + |<- ->| ----> dio write this range + +First, when ext4_split_extent_at() splits this extent, it truncates the +existing extent and then inserts a new one. During this process, this +extent status entry may be shrunk, and calls to ext4_find_extent() and +ext4_cache_extents() may occur, which could potentially insert the +truncated range as a hole into the extent status tree. After the split +is completed, this hole is not replaced with the correct status. + + [UUUUUUU|UUUUUUUU] on-disk extent U: unwritten extent + [UUUUUUU|HHHHHHHH] extent status tree H: hole + +Then, the outer calling functions will not correct this remaining hole +extent either. Finally, if we perform a delayed buffer write on this +latter part, it will re-insert the delayed extent and cause an error in +space accounting. + +In adition, if the unwritten extent cache is not shrunk during the +splitting, ext4_cache_extents() also conflicts with existing extents +when caching extents. In the future, we will add checks when caching +extents, which will trigger a warning. Therefore, Do not cache extents +that are being split. + +Signed-off-by: Zhang Yi +Reviewed-by: Ojaswin Mujoo +Reviewed-by: Baokun Li +Cc: stable@kernel.org +Message-ID: <20251129103247.686136-6-yi.zhang@huaweicloud.com> +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/extents.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -3199,6 +3199,9 @@ static struct ext4_ext_path *ext4_split_ + BUG_ON((split_flag & EXT4_EXT_DATA_VALID1) && + (split_flag & EXT4_EXT_DATA_VALID2)); + ++ /* Do not cache extents that are in the process of being modified. */ ++ flags |= EXT4_EX_NOCACHE; ++ + ext_debug(inode, "logical block %llu\n", (unsigned long long)split); + + ext4_ext_show_leaf(inode, path); +@@ -3381,6 +3384,9 @@ static struct ext4_ext_path *ext4_split_ + ee_len = ext4_ext_get_actual_len(ex); + unwritten = ext4_ext_is_unwritten(ex); + ++ /* Do not cache extents that are in the process of being modified. */ ++ flags |= EXT4_EX_NOCACHE; ++ + if (map->m_lblk + map->m_len < ee_block + ee_len) { + split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT; + flags1 = flags | EXT4_GET_BLOCKS_SPLIT_NOMERGE; diff --git a/queue-6.19/ext4-don-t-set-ext4_get_blocks_convert-when-splitting-before-submitting-i-o.patch b/queue-6.19/ext4-don-t-set-ext4_get_blocks_convert-when-splitting-before-submitting-i-o.patch new file mode 100644 index 0000000000..02f417e3fe --- /dev/null +++ b/queue-6.19/ext4-don-t-set-ext4_get_blocks_convert-when-splitting-before-submitting-i-o.patch @@ -0,0 +1,96 @@ +From feaf2a80e78f89ee8a3464126077ba8683b62791 Mon Sep 17 00:00:00 2001 +From: Zhang Yi +Date: Sat, 29 Nov 2025 18:32:35 +0800 +Subject: ext4: don't set EXT4_GET_BLOCKS_CONVERT when splitting before submitting I/O + +From: Zhang Yi + +commit feaf2a80e78f89ee8a3464126077ba8683b62791 upstream. + +When allocating blocks during within-EOF DIO and writeback with +dioread_nolock enabled, EXT4_GET_BLOCKS_PRE_IO was set to split an +existing large unwritten extent. However, EXT4_GET_BLOCKS_CONVERT was +set when calling ext4_split_convert_extents(), which may potentially +result in stale data issues. + +Assume we have an unwritten extent, and then DIO writes the second half. + + [UUUUUUUUUUUUUUUU] on-disk extent U: unwritten extent + [UUUUUUUUUUUUUUUU] extent status tree + |<- ->| ----> dio write this range + +First, ext4_iomap_alloc() call ext4_map_blocks() with +EXT4_GET_BLOCKS_PRE_IO, EXT4_GET_BLOCKS_UNWRIT_EXT and +EXT4_GET_BLOCKS_CREATE flags set. ext4_map_blocks() find this extent and +call ext4_split_convert_extents() with EXT4_GET_BLOCKS_CONVERT and the +above flags set. + +Then, ext4_split_convert_extents() calls ext4_split_extent() with +EXT4_EXT_MAY_ZEROOUT, EXT4_EXT_MARK_UNWRIT2 and EXT4_EXT_DATA_VALID2 +flags set, and it calls ext4_split_extent_at() to split the second half +with EXT4_EXT_DATA_VALID2, EXT4_EXT_MARK_UNWRIT1, EXT4_EXT_MAY_ZEROOUT +and EXT4_EXT_MARK_UNWRIT2 flags set. However, ext4_split_extent_at() +failed to insert extent since a temporary lack -ENOSPC. It zeroes out +the first half but convert the entire on-disk extent to written since +the EXT4_EXT_DATA_VALID2 flag set, but left the second half as unwritten +in the extent status tree. + + [0000000000SSSSSS] data S: stale data, 0: zeroed + [WWWWWWWWWWWWWWWW] on-disk extent W: written extent + [WWWWWWWWWWUUUUUU] extent status tree + +Finally, if the DIO failed to write data to the disk, the stale data in +the second half will be exposed once the cached extent entry is gone. + +Fix this issue by not passing EXT4_GET_BLOCKS_CONVERT when splitting +an unwritten extent before submitting I/O, and make +ext4_split_convert_extents() to zero out the entire extent range +to zero for this case, and also mark the extent in the extent status +tree for consistency. + +Fixes: b8a8684502a0 ("ext4: Introduce FALLOC_FL_ZERO_RANGE flag for fallocate") +Signed-off-by: Zhang Yi +Reviewed-by: Ojaswin Mujoo +Reviewed-by: Baokun Li +Cc: stable@kernel.org +Message-ID: <20251129103247.686136-4-yi.zhang@huaweicloud.com> +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/extents.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -3735,15 +3735,19 @@ static struct ext4_ext_path *ext4_split_ + /* Convert to unwritten */ + if (flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN) { + split_flag |= EXT4_EXT_DATA_ENTIRE_VALID1; +- /* Convert to initialized */ +- } else if (flags & EXT4_GET_BLOCKS_CONVERT) { ++ /* Split the existing unwritten extent */ ++ } else if (flags & (EXT4_GET_BLOCKS_UNWRIT_EXT | ++ EXT4_GET_BLOCKS_CONVERT)) { + /* + * It is safe to convert extent to initialized via explicit + * zeroout only if extent is fully inside i_size or new_size. + */ + split_flag |= ee_block + ee_len <= eof_block ? + EXT4_EXT_MAY_ZEROOUT : 0; +- split_flag |= (EXT4_EXT_MARK_UNWRIT2 | EXT4_EXT_DATA_VALID2); ++ split_flag |= EXT4_EXT_MARK_UNWRIT2; ++ /* Convert to initialized */ ++ if (flags & EXT4_GET_BLOCKS_CONVERT) ++ split_flag |= EXT4_EXT_DATA_VALID2; + } + flags |= EXT4_GET_BLOCKS_SPLIT_NOMERGE; + return ext4_split_extent(handle, inode, path, map, split_flag, flags, +@@ -3919,7 +3923,7 @@ ext4_ext_handle_unwritten_extents(handle + /* get_block() before submitting IO, split the extent */ + if (flags & EXT4_GET_BLOCKS_SPLIT_NOMERGE) { + path = ext4_split_convert_extents(handle, inode, map, path, +- flags | EXT4_GET_BLOCKS_CONVERT, allocated); ++ flags, allocated); + if (IS_ERR(path)) + return path; + /* diff --git a/queue-6.19/ext4-don-t-zero-the-entire-extent-if-ext4_ext_data_partial_valid1.patch b/queue-6.19/ext4-don-t-zero-the-entire-extent-if-ext4_ext_data_partial_valid1.patch new file mode 100644 index 0000000000..49ad09562f --- /dev/null +++ b/queue-6.19/ext4-don-t-zero-the-entire-extent-if-ext4_ext_data_partial_valid1.patch @@ -0,0 +1,85 @@ +From 1bf6974822d1dba86cf11b5f05498581cf3488a2 Mon Sep 17 00:00:00 2001 +From: Zhang Yi +Date: Sat, 29 Nov 2025 18:32:34 +0800 +Subject: ext4: don't zero the entire extent if EXT4_EXT_DATA_PARTIAL_VALID1 + +From: Zhang Yi + +commit 1bf6974822d1dba86cf11b5f05498581cf3488a2 upstream. + +When allocating initialized blocks from a large unwritten extent, or +when splitting an unwritten extent during end I/O and converting it to +initialized, there is currently a potential issue of stale data if the +extent needs to be split in the middle. + + 0 A B N + [UUUUUUUUUUUU] U: unwritten extent + [--DDDDDDDD--] D: valid data + |<- ->| ----> this range needs to be initialized + +ext4_split_extent() first try to split this extent at B with +EXT4_EXT_DATA_ENTIRE_VALID1 and EXT4_EXT_MAY_ZEROOUT flag set, but +ext4_split_extent_at() failed to split this extent due to temporary lack +of space. It zeroout B to N and mark the entire extent from 0 to N +as written. + + 0 A B N + [WWWWWWWWWWWW] W: written extent + [SSDDDDDDDDZZ] Z: zeroed, S: stale data + +ext4_split_extent() then try to split this extent at A with +EXT4_EXT_DATA_VALID2 flag set. This time, it split successfully and left +a stale written extent from 0 to A. + + 0 A B N + [WW|WWWWWWWWWW] + [SS|DDDDDDDDZZ] + +Fix this by pass EXT4_EXT_DATA_PARTIAL_VALID1 to ext4_split_extent_at() +when splitting at B, don't convert the entire extent to written and left +it as unwritten after zeroing out B to N. The remaining work is just +like the standard two-part split. ext4_split_extent() will pass the +EXT4_EXT_DATA_VALID2 flag when it calls ext4_split_extent_at() for the +second time, allowing it to properly handle the split. If the split is +successful, it will keep extent from 0 to A as unwritten. + +Signed-off-by: Zhang Yi +Reviewed-by: Ojaswin Mujoo +Reviewed-by: Baokun Li +Cc: stable@kernel.org +Message-ID: <20251129103247.686136-3-yi.zhang@huaweicloud.com> +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/extents.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -3310,6 +3310,15 @@ static struct ext4_ext_path *ext4_split_ + } + + if (!err) { ++ /* ++ * The first half contains partially valid data, the ++ * splitting of this extent has not been completed, fix ++ * extent length and ext4_split_extent() split will the ++ * first half again. ++ */ ++ if (split_flag & EXT4_EXT_DATA_PARTIAL_VALID1) ++ goto fix_extent_len; ++ + /* update the extent length and mark as initialized */ + ex->ee_len = cpu_to_le16(ee_len); + ext4_ext_try_to_merge(handle, inode, path, ex); +@@ -3379,7 +3388,9 @@ static struct ext4_ext_path *ext4_split_ + split_flag1 |= EXT4_EXT_MARK_UNWRIT1 | + EXT4_EXT_MARK_UNWRIT2; + if (split_flag & EXT4_EXT_DATA_VALID2) +- split_flag1 |= EXT4_EXT_DATA_ENTIRE_VALID1; ++ split_flag1 |= map->m_lblk > ee_block ? ++ EXT4_EXT_DATA_PARTIAL_VALID1 : ++ EXT4_EXT_DATA_ENTIRE_VALID1; + path = ext4_split_extent_at(handle, inode, path, + map->m_lblk + map->m_len, split_flag1, flags1); + if (IS_ERR(path)) diff --git a/queue-6.19/ext4-drop-extent-cache-after-doing-partial_valid1-zeroout.patch b/queue-6.19/ext4-drop-extent-cache-after-doing-partial_valid1-zeroout.patch new file mode 100644 index 0000000000..bc62afe532 --- /dev/null +++ b/queue-6.19/ext4-drop-extent-cache-after-doing-partial_valid1-zeroout.patch @@ -0,0 +1,84 @@ +From 6d882ea3b0931b43530d44149b79fcd4ffc13030 Mon Sep 17 00:00:00 2001 +From: Zhang Yi +Date: Sat, 29 Nov 2025 18:32:38 +0800 +Subject: ext4: drop extent cache after doing PARTIAL_VALID1 zeroout + +From: Zhang Yi + +commit 6d882ea3b0931b43530d44149b79fcd4ffc13030 upstream. + +When splitting an unwritten extent in the middle and converting it to +initialized in ext4_split_extent() with the EXT4_EXT_MAY_ZEROOUT and +EXT4_EXT_DATA_VALID2 flags set, it could leave a stale unwritten extent. + +Assume we have an unwritten file and buffered write in the middle of it +without dioread_nolock enabled, it will allocate blocks as written +extent. + + 0 A B N + [UUUUUUUUUUUU] on-disk extent U: unwritten extent + [UUUUUUUUUUUU] extent status tree + [--DDDDDDDD--] D: valid data + |<- ->| ----> this range needs to be initialized + +ext4_split_extent() first try to split this extent at B with +EXT4_EXT_DATA_PARTIAL_VALID1 and EXT4_EXT_MAY_ZEROOUT flag set, but +ext4_split_extent_at() failed to split this extent due to temporary lack +of space. It zeroout B to N and leave the entire extent as unwritten. + + 0 A B N + [UUUUUUUUUUUU] on-disk extent + [UUUUUUUUUUUU] extent status tree + [--DDDDDDDDZZ] Z: zeroed data + +ext4_split_extent() then try to split this extent at A with +EXT4_EXT_DATA_VALID2 flag set. This time, it split successfully and +leave an written extent from A to N. + + 0 A B N + [UUWWWWWWWWWW] on-disk extent W: written extent + [UUUUUUUUUUUU] extent status tree + [--DDDDDDDDZZ] + +Finally ext4_map_create_blocks() only insert extent A to B to the extent +status tree, and leave an stale unwritten extent in the status tree. + + 0 A B N + [UUWWWWWWWWWW] on-disk extent W: written extent + [UUWWWWWWWWUU] extent status tree + [--DDDDDDDDZZ] + +Fix this issue by always cached extent status entry after zeroing out +the second part. + +Signed-off-by: Zhang Yi +Reviewed-by: Baokun Li +Cc: stable@kernel.org +Reviewed-by: Ojaswin Mujoo +Message-ID: <20251129103247.686136-7-yi.zhang@huaweicloud.com> +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/extents.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -3319,8 +3319,16 @@ static struct ext4_ext_path *ext4_split_ + * extent length and ext4_split_extent() split will the + * first half again. + */ +- if (split_flag & EXT4_EXT_DATA_PARTIAL_VALID1) ++ if (split_flag & EXT4_EXT_DATA_PARTIAL_VALID1) { ++ /* ++ * Drop extent cache to prevent stale unwritten ++ * extents remaining after zeroing out. ++ */ ++ ext4_es_remove_extent(inode, ++ le32_to_cpu(zero_ex.ee_block), ++ ext4_ext_get_actual_len(&zero_ex)); + goto fix_extent_len; ++ } + + /* update the extent length and mark as initialized */ + ex->ee_len = cpu_to_le16(ee_len); diff --git a/queue-6.19/ext4-drop-extent-cache-when-splitting-extent-fails.patch b/queue-6.19/ext4-drop-extent-cache-when-splitting-extent-fails.patch new file mode 100644 index 0000000000..9c856a7c4f --- /dev/null +++ b/queue-6.19/ext4-drop-extent-cache-when-splitting-extent-fails.patch @@ -0,0 +1,56 @@ +From 79b592e8f1b435796cbc2722190368e3e8ffd7a1 Mon Sep 17 00:00:00 2001 +From: Zhang Yi +Date: Sat, 29 Nov 2025 18:32:39 +0800 +Subject: ext4: drop extent cache when splitting extent fails + +From: Zhang Yi + +commit 79b592e8f1b435796cbc2722190368e3e8ffd7a1 upstream. + +When the split extent fails, we might leave some extents still being +processed and return an error directly, which will result in stale +extent entries remaining in the extent status tree. So drop all of the +remaining potentially stale extents if the splitting fails. + +Signed-off-by: Zhang Yi +Reviewed-by: Baokun Li +Cc: stable@kernel.org +Reviewed-by: Ojaswin Mujoo +Message-ID: <20251129103247.686136-8-yi.zhang@huaweicloud.com> +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/extents.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -3267,7 +3267,7 @@ static struct ext4_ext_path *ext4_split_ + + err = PTR_ERR(path); + if (err != -ENOSPC && err != -EDQUOT && err != -ENOMEM) +- return path; ++ goto out_path; + + /* + * Get a new path to try to zeroout or fix the extent length. +@@ -3281,7 +3281,7 @@ static struct ext4_ext_path *ext4_split_ + if (IS_ERR(path)) { + EXT4_ERROR_INODE(inode, "Failed split extent on %u, err %ld", + split, PTR_ERR(path)); +- return path; ++ goto out_path; + } + depth = ext_depth(inode); + ex = path[depth].p_ext; +@@ -3358,6 +3358,10 @@ out: + ext4_free_ext_path(path); + path = ERR_PTR(err); + } ++out_path: ++ if (IS_ERR(path)) ++ /* Remove all remaining potentially stale extents. */ ++ ext4_es_remove_extent(inode, ee_block, ee_len); + ext4_ext_show_leaf(inode, path); + return path; + } diff --git a/queue-6.19/ext4-fix-dirtyclusters-double-decrement-on-fs-shutdown.patch b/queue-6.19/ext4-fix-dirtyclusters-double-decrement-on-fs-shutdown.patch new file mode 100644 index 0000000000..48a172ca68 --- /dev/null +++ b/queue-6.19/ext4-fix-dirtyclusters-double-decrement-on-fs-shutdown.patch @@ -0,0 +1,116 @@ +From 94a8cea54cd935c54fa2fba70354757c0fc245e3 Mon Sep 17 00:00:00 2001 +From: Brian Foster +Date: Tue, 13 Jan 2026 12:19:05 -0500 +Subject: ext4: fix dirtyclusters double decrement on fs shutdown + +From: Brian Foster + +commit 94a8cea54cd935c54fa2fba70354757c0fc245e3 upstream. + +fstests test generic/388 occasionally reproduces a warning in +ext4_put_super() associated with the dirty clusters count: + + WARNING: CPU: 7 PID: 76064 at fs/ext4/super.c:1324 ext4_put_super+0x48c/0x590 [ext4] + +Tracing the failure shows that the warning fires due to an +s_dirtyclusters_counter value of -1. IOW, this appears to be a +spurious decrement as opposed to some sort of leak. Further tracing +of the dirty cluster count deltas and an LLM scan of the resulting +output identified the cause as a double decrement in the error path +between ext4_mb_mark_diskspace_used() and the caller +ext4_mb_new_blocks(). + +First, note that generic/388 is a shutdown vs. fsstress test and so +produces a random set of operations and shutdown injections. In the +problematic case, the shutdown triggers an error return from the +ext4_handle_dirty_metadata() call(s) made from +ext4_mb_mark_context(). The changed value is non-zero at this point, +so ext4_mb_mark_diskspace_used() does not exit after the error +bubbles up from ext4_mb_mark_context(). Instead, the former +decrements both cluster counters and returns the error up to +ext4_mb_new_blocks(). The latter falls into the !ar->len out path +which decrements the dirty clusters counter a second time, creating +the inconsistency. + +To avoid this problem and simplify ownership of the cluster +reservation in this codepath, lift the counter reduction to a single +place in the caller. This makes it more clear that +ext4_mb_new_blocks() is responsible for acquiring cluster +reservation (via ext4_claim_free_clusters()) in the !delalloc case +as well as releasing it, regardless of whether it ends up consumed +or returned due to failure. + +Fixes: 0087d9fb3f29 ("ext4: Fix s_dirty_blocks_counter if block allocation failed with nodelalloc") +Signed-off-by: Brian Foster +Reviewed-by: Baokun Li +Link: https://patch.msgid.link/20260113171905.118284-1-bfoster@redhat.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/mballoc-test.c | 2 +- + fs/ext4/mballoc.c | 21 +++++---------------- + 2 files changed, 6 insertions(+), 17 deletions(-) + +--- a/fs/ext4/mballoc-test.c ++++ b/fs/ext4/mballoc-test.c +@@ -567,7 +567,7 @@ test_mark_diskspace_used_range(struct ku + + bitmap = mbt_ctx_bitmap(sb, TEST_GOAL_GROUP); + memset(bitmap, 0, sb->s_blocksize); +- ret = ext4_mb_mark_diskspace_used(ac, NULL, 0); ++ ret = ext4_mb_mark_diskspace_used(ac, NULL); + KUNIT_ASSERT_EQ(test, ret, 0); + + max = EXT4_CLUSTERS_PER_GROUP(sb); +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -4186,8 +4186,7 @@ out_err: + * Returns 0 if success or error code + */ + static noinline_for_stack int +-ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, +- handle_t *handle, unsigned int reserv_clstrs) ++ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, handle_t *handle) + { + struct ext4_group_desc *gdp; + struct ext4_sb_info *sbi; +@@ -4242,13 +4241,6 @@ ext4_mb_mark_diskspace_used(struct ext4_ + BUG_ON(changed != ac->ac_b_ex.fe_len); + #endif + percpu_counter_sub(&sbi->s_freeclusters_counter, ac->ac_b_ex.fe_len); +- /* +- * Now reduce the dirty block count also. Should not go negative +- */ +- if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED)) +- /* release all the reserved blocks if non delalloc */ +- percpu_counter_sub(&sbi->s_dirtyclusters_counter, +- reserv_clstrs); + + return err; + } +@@ -6333,7 +6325,7 @@ repeat: + ext4_mb_pa_put_free(ac); + } + if (likely(ac->ac_status == AC_STATUS_FOUND)) { +- *errp = ext4_mb_mark_diskspace_used(ac, handle, reserv_clstrs); ++ *errp = ext4_mb_mark_diskspace_used(ac, handle); + if (*errp) { + ext4_discard_allocated_blocks(ac); + goto errout; +@@ -6364,12 +6356,9 @@ errout: + out: + if (inquota && ar->len < inquota) + dquot_free_block(ar->inode, EXT4_C2B(sbi, inquota - ar->len)); +- if (!ar->len) { +- if ((ar->flags & EXT4_MB_DELALLOC_RESERVED) == 0) +- /* release all the reserved blocks if non delalloc */ +- percpu_counter_sub(&sbi->s_dirtyclusters_counter, +- reserv_clstrs); +- } ++ /* release any reserved blocks */ ++ if (reserv_clstrs) ++ percpu_counter_sub(&sbi->s_dirtyclusters_counter, reserv_clstrs); + + trace_ext4_allocate_blocks(ar, (unsigned long long)block); + diff --git a/queue-6.19/ext4-fix-e4b-bitmap-inconsistency-reports.patch b/queue-6.19/ext4-fix-e4b-bitmap-inconsistency-reports.patch new file mode 100644 index 0000000000..708d2b56d8 --- /dev/null +++ b/queue-6.19/ext4-fix-e4b-bitmap-inconsistency-reports.patch @@ -0,0 +1,122 @@ +From bdc56a9c46b2a99c12313122b9352b619a2e719e Mon Sep 17 00:00:00 2001 +From: Yongjian Sun +Date: Tue, 6 Jan 2026 17:08:20 +0800 +Subject: ext4: fix e4b bitmap inconsistency reports + +From: Yongjian Sun + +commit bdc56a9c46b2a99c12313122b9352b619a2e719e upstream. + +A bitmap inconsistency issue was observed during stress tests under +mixed huge-page workloads. Ext4 reported multiple e4b bitmap check +failures like: + +ext4_mb_complex_scan_group:2508: group 350, 8179 free clusters as +per group info. But got 8192 blocks + +Analysis and experimentation confirmed that the issue is caused by a +race condition between page migration and bitmap modification. Although +this timing window is extremely narrow, it is still hit in practice: + +folio_lock ext4_mb_load_buddy +__migrate_folio + check ref count + folio_mc_copy __filemap_get_folio + folio_try_get(folio) + ...... + mb_mark_used + ext4_mb_unload_buddy + __folio_migrate_mapping + folio_ref_freeze +folio_unlock + +The root cause of this issue is that the fast path of load_buddy only +increments the folio's reference count, which is insufficient to prevent +concurrent folio migration. We observed that the folio migration process +acquires the folio lock. Therefore, we can determine whether to take the +fast path in load_buddy by checking the lock status. If the folio is +locked, we opt for the slow path (which acquires the lock) to close this +concurrency window. + +Additionally, this change addresses the following issues: + +When the DOUBLE_CHECK macro is enabled to inspect bitmap-related +issues, the following error may be triggered: + +corruption in group 324 at byte 784(6272): f in copy != ff on +disk/prealloc + +Analysis reveals that this is a false positive. There is a specific race +window where the bitmap and the group descriptor become momentarily +inconsistent, leading to this error report: + +ext4_mb_load_buddy ext4_mb_load_buddy + __filemap_get_folio(create|lock) + folio_lock + ext4_mb_init_cache + folio_mark_uptodate + __filemap_get_folio(no lock) + ...... + mb_mark_used + mb_mark_used_double + mb_cmp_bitmaps + mb_set_bits(e4b->bd_bitmap) + folio_unlock + +The original logic assumed that since mb_cmp_bitmaps is called when the +bitmap is newly loaded from disk, the folio lock would be sufficient to +prevent concurrent access. However, this overlooks a specific race +condition: if another process attempts to load buddy and finds the folio +is already in an uptodate state, it will immediately begin using it without +holding folio lock. + +Signed-off-by: Yongjian Sun +Reviewed-by: Zhang Yi +Reviewed-by: Baokun Li +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20260106090820.836242-1-sunyongjian@huaweicloud.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/mballoc.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -1706,16 +1706,17 @@ ext4_mb_load_buddy_gfp(struct super_bloc + + /* Avoid locking the folio in the fast path ... */ + folio = __filemap_get_folio(inode->i_mapping, pnum, FGP_ACCESSED, 0); +- if (IS_ERR(folio) || !folio_test_uptodate(folio)) { ++ if (IS_ERR(folio) || !folio_test_uptodate(folio) || folio_test_locked(folio)) { ++ /* ++ * folio_test_locked is employed to detect ongoing folio ++ * migrations, since concurrent migrations can lead to ++ * bitmap inconsistency. And if we are not uptodate that ++ * implies somebody just created the folio but is yet to ++ * initialize it. We can drop the folio reference and ++ * try to get the folio with lock in both cases to avoid ++ * concurrency. ++ */ + if (!IS_ERR(folio)) +- /* +- * drop the folio reference and try +- * to get the folio with lock. If we +- * are not uptodate that implies +- * somebody just created the folio but +- * is yet to initialize it. So +- * wait for it to initialize. +- */ + folio_put(folio); + folio = __filemap_get_folio(inode->i_mapping, pnum, + FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp); +@@ -1764,7 +1765,7 @@ ext4_mb_load_buddy_gfp(struct super_bloc + + /* we need another folio for the buddy */ + folio = __filemap_get_folio(inode->i_mapping, pnum, FGP_ACCESSED, 0); +- if (IS_ERR(folio) || !folio_test_uptodate(folio)) { ++ if (IS_ERR(folio) || !folio_test_uptodate(folio) || folio_test_locked(folio)) { + if (!IS_ERR(folio)) + folio_put(folio); + folio = __filemap_get_folio(inode->i_mapping, pnum, diff --git a/queue-6.19/ext4-fix-memory-leak-in-ext4_ext_shift_extents.patch b/queue-6.19/ext4-fix-memory-leak-in-ext4_ext_shift_extents.patch new file mode 100644 index 0000000000..67c00afb49 --- /dev/null +++ b/queue-6.19/ext4-fix-memory-leak-in-ext4_ext_shift_extents.patch @@ -0,0 +1,40 @@ +From ca81109d4a8f192dc1cbad4a1ee25246363c2833 Mon Sep 17 00:00:00 2001 +From: Zilin Guan +Date: Thu, 25 Dec 2025 08:48:00 +0000 +Subject: ext4: fix memory leak in ext4_ext_shift_extents() + +From: Zilin Guan + +commit ca81109d4a8f192dc1cbad4a1ee25246363c2833 upstream. + +In ext4_ext_shift_extents(), if the extent is NULL in the while loop, the +function returns immediately without releasing the path obtained via +ext4_find_extent(), leading to a memory leak. + +Fix this by jumping to the out label to ensure the path is properly +released. + +Fixes: a18ed359bdddc ("ext4: always check ext4_ext_find_extent result") +Signed-off-by: Zilin Guan +Reviewed-by: Zhang Yi +Reviewed-by: Baokun Li +Link: https://patch.msgid.link/20251225084800.905701-1-zilin@seu.edu.cn +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/extents.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -5414,7 +5414,8 @@ again: + if (!extent) { + EXT4_ERROR_INODE(inode, "unexpected hole at %lu", + (unsigned long) *iterator); +- return -EFSCORRUPTED; ++ ret = -EFSCORRUPTED; ++ goto out; + } + if (SHIFT == SHIFT_LEFT && *iterator > + le32_to_cpu(extent->ee_block)) { diff --git a/queue-6.19/ext4-subdivide-ext4_ext_data_valid1.patch b/queue-6.19/ext4-subdivide-ext4_ext_data_valid1.patch new file mode 100644 index 0000000000..21e26049c8 --- /dev/null +++ b/queue-6.19/ext4-subdivide-ext4_ext_data_valid1.patch @@ -0,0 +1,85 @@ +From 22784ca541c0f01c5ebad14e8228298dc0a390ed Mon Sep 17 00:00:00 2001 +From: Zhang Yi +Date: Sat, 29 Nov 2025 18:32:33 +0800 +Subject: ext4: subdivide EXT4_EXT_DATA_VALID1 + +From: Zhang Yi + +commit 22784ca541c0f01c5ebad14e8228298dc0a390ed upstream. + +When splitting an extent, if the EXT4_GET_BLOCKS_CONVERT flag is set and +it is necessary to split the target extent in the middle, +ext4_split_extent() first handles splitting the latter half of the +extent and passes the EXT4_EXT_DATA_VALID1 flag. This flag implies that +all blocks before the split point contain valid data; however, this +assumption is incorrect. + +Therefore, subdivid EXT4_EXT_DATA_VALID1 into +EXT4_EXT_DATA_ENTIRE_VALID1 and EXT4_EXT_DATA_PARTIAL_VALID1, which +indicate that the first half of the extent is either entirely valid or +only partially valid, respectively. These two flags cannot be set +simultaneously. + +This patch does not use EXT4_EXT_DATA_PARTIAL_VALID1, it only replaces +EXT4_EXT_DATA_VALID1 with EXT4_EXT_DATA_ENTIRE_VALID1 at the location +where it is set, no logical changes. + +Signed-off-by: Zhang Yi +Reviewed-by: Ojaswin Mujoo +Reviewed-by: Baokun Li +Cc: stable@kernel.org +Message-ID: <20251129103247.686136-2-yi.zhang@huaweicloud.com> +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/extents.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -43,8 +43,13 @@ + #define EXT4_EXT_MARK_UNWRIT1 0x2 /* mark first half unwritten */ + #define EXT4_EXT_MARK_UNWRIT2 0x4 /* mark second half unwritten */ + +-#define EXT4_EXT_DATA_VALID1 0x8 /* first half contains valid data */ +-#define EXT4_EXT_DATA_VALID2 0x10 /* second half contains valid data */ ++/* first half contains valid data */ ++#define EXT4_EXT_DATA_ENTIRE_VALID1 0x8 /* has entirely valid data */ ++#define EXT4_EXT_DATA_PARTIAL_VALID1 0x10 /* has partially valid data */ ++#define EXT4_EXT_DATA_VALID1 (EXT4_EXT_DATA_ENTIRE_VALID1 | \ ++ EXT4_EXT_DATA_PARTIAL_VALID1) ++ ++#define EXT4_EXT_DATA_VALID2 0x20 /* second half contains valid data */ + + static __le32 ext4_extent_block_csum(struct inode *inode, + struct ext4_extent_header *eh) +@@ -3190,8 +3195,9 @@ static struct ext4_ext_path *ext4_split_ + unsigned int ee_len, depth; + int err = 0; + +- BUG_ON((split_flag & (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)) == +- (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)); ++ BUG_ON((split_flag & EXT4_EXT_DATA_VALID1) == EXT4_EXT_DATA_VALID1); ++ BUG_ON((split_flag & EXT4_EXT_DATA_VALID1) && ++ (split_flag & EXT4_EXT_DATA_VALID2)); + + ext_debug(inode, "logical block %llu\n", (unsigned long long)split); + +@@ -3373,7 +3379,7 @@ static struct ext4_ext_path *ext4_split_ + split_flag1 |= EXT4_EXT_MARK_UNWRIT1 | + EXT4_EXT_MARK_UNWRIT2; + if (split_flag & EXT4_EXT_DATA_VALID2) +- split_flag1 |= EXT4_EXT_DATA_VALID1; ++ split_flag1 |= EXT4_EXT_DATA_ENTIRE_VALID1; + path = ext4_split_extent_at(handle, inode, path, + map->m_lblk + map->m_len, split_flag1, flags1); + if (IS_ERR(path)) +@@ -3728,7 +3734,7 @@ static struct ext4_ext_path *ext4_split_ + + /* Convert to unwritten */ + if (flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN) { +- split_flag |= EXT4_EXT_DATA_VALID1; ++ split_flag |= EXT4_EXT_DATA_ENTIRE_VALID1; + /* Convert to initialized */ + } else if (flags & EXT4_GET_BLOCKS_CONVERT) { + /* diff --git a/queue-6.19/ext4-use-optimized-mballoc-scanning-regardless-of-inode-format.patch b/queue-6.19/ext4-use-optimized-mballoc-scanning-regardless-of-inode-format.patch new file mode 100644 index 0000000000..45822cd85d --- /dev/null +++ b/queue-6.19/ext4-use-optimized-mballoc-scanning-regardless-of-inode-format.patch @@ -0,0 +1,43 @@ +From 3574c322b1d0eb32dbd76b469cb08f9a67641599 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 14 Jan 2026 19:28:19 +0100 +Subject: ext4: use optimized mballoc scanning regardless of inode format + +From: Jan Kara + +commit 3574c322b1d0eb32dbd76b469cb08f9a67641599 upstream. + +Currently we don't used mballoc optimized scanning (using max free +extent order and avg free extent order group lists) for inodes with +indirect block based format. This is confusing for users and I don't see +a good reason for that. Even with indirect block based inode format we +can spend big amount of time searching for free blocks for large +filesystems with fragmented free space. To add to the confusion before +commit 077d0c2c78df ("ext4: make mb_optimize_scan performance mount +option work with extents") optimized scanning was applied *only* to +indirect block based inodes so that commit appears as a performance +regression to some users. Just use optimized scanning whenever it is +enabled by mount options. + +Reviewed-by: Baokun Li +Reviewed-by: Zhang Yi +Signed-off-by: Jan Kara +Cc: stable@kernel.org +Link: https://patch.msgid.link/20260114182836.14120-4-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/mballoc.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -1148,8 +1148,6 @@ static inline int should_optimize_scan(s + return 0; + if (ac->ac_criteria >= CR_GOAL_LEN_SLOW) + return 0; +- if (!ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS)) +- return 0; + return 1; + } + diff --git a/queue-6.19/ksmbd-call-ksmbd_vfs_kern_path_end_removing-on-some-error-paths.patch b/queue-6.19/ksmbd-call-ksmbd_vfs_kern_path_end_removing-on-some-error-paths.patch new file mode 100644 index 0000000000..6c52bd543a --- /dev/null +++ b/queue-6.19/ksmbd-call-ksmbd_vfs_kern_path_end_removing-on-some-error-paths.patch @@ -0,0 +1,63 @@ +From a09dc10d1353f0e92c21eae2a79af1c2b1ddcde8 Mon Sep 17 00:00:00 2001 +From: Fedor Pchelkin +Date: Sat, 14 Feb 2026 18:45:14 +0300 +Subject: ksmbd: call ksmbd_vfs_kern_path_end_removing() on some error paths + +From: Fedor Pchelkin + +commit a09dc10d1353f0e92c21eae2a79af1c2b1ddcde8 upstream. + +There are two places where ksmbd_vfs_kern_path_end_removing() needs to be +called in order to balance what the corresponding successful call to +ksmbd_vfs_kern_path_start_removing() has done, i.e. drop inode locks and +put the taken references. Otherwise there might be potential deadlocks +and unbalanced locks which are caught like: + +BUG: workqueue leaked lock or atomic: kworker/5:21/0x00000000/7596 + last function: handle_ksmbd_work +2 locks held by kworker/5:21/7596: + #0: ffff8881051ae448 (sb_writers#3){.+.+}-{0:0}, at: ksmbd_vfs_kern_path_locked+0x142/0x660 + #1: ffff888130e966c0 (&type->i_mutex_dir_key#3/1){+.+.}-{4:4}, at: ksmbd_vfs_kern_path_locked+0x17d/0x660 +CPU: 5 PID: 7596 Comm: kworker/5:21 Not tainted 6.1.162-00456-gc29b353f383b #138 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014 +Workqueue: ksmbd-io handle_ksmbd_work +Call Trace: + + dump_stack_lvl+0x44/0x5b + process_one_work.cold+0x57/0x5c + worker_thread+0x82/0x600 + kthread+0x153/0x190 + ret_from_fork+0x22/0x30 + + +Found by Linux Verification Center (linuxtesting.org). + +Fixes: d5fc1400a34b ("smb/server: avoid deadlock when linking with ReplaceIfExists") +Cc: stable@vger.kernel.org +Signed-off-by: Fedor Pchelkin +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman +--- + fs/smb/server/smb2pdu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -6114,14 +6114,14 @@ static int smb2_create_link(struct ksmbd + rc = -EINVAL; + ksmbd_debug(SMB, "cannot delete %s\n", + link_name); +- goto out; + } + } else { + rc = -EEXIST; + ksmbd_debug(SMB, "link already exists\n"); +- goto out; + } + ksmbd_vfs_kern_path_end_removing(&path); ++ if (rc) ++ goto out; + } + rc = ksmbd_vfs_link(work, target_name, link_name); + if (rc) diff --git a/queue-6.19/mips-work-around-llvm-bug-when-gp-is-used-as-global-register-variable.patch b/queue-6.19/mips-work-around-llvm-bug-when-gp-is-used-as-global-register-variable.patch new file mode 100644 index 0000000000..0479a0efde --- /dev/null +++ b/queue-6.19/mips-work-around-llvm-bug-when-gp-is-used-as-global-register-variable.patch @@ -0,0 +1,98 @@ +From 30bfc2d6a1132a89a5f1c3b96c59cf3e4d076ea3 Mon Sep 17 00:00:00 2001 +From: Yao Zi +Date: Thu, 5 Feb 2026 15:56:44 +0000 +Subject: MIPS: Work around LLVM bug when gp is used as global register variable + +From: Yao Zi + +commit 30bfc2d6a1132a89a5f1c3b96c59cf3e4d076ea3 upstream. + +On MIPS, __current_thread_info is defined as global register variable +locating in $gp, and is simply assigned with new address during kernel +relocation. + +This however is broken with LLVM, which always restores $gp if it finds +$gp is clobbered in any form, including when intentionally through a +global register variable. This is against GCC's documentation[1], which +requires a callee-saved register used as global register variable not to +be restored if it's clobbered. + +As a result, $gp will continue to point to the unrelocated kernel after +the epilog of relocate_kernel(), leading to an early crash in init_idle, + +[ 0.000000] CPU 0 Unable to handle kernel paging request at virtual address 0000000000000000, epc == ffffffff81afada8, ra == ffffffff81afad90 +[ 0.000000] Oops[#1]: +[ 0.000000] CPU: 0 UID: 0 PID: 0 Comm: swapper Tainted: G W 6.19.0-rc5-00262-gd3eeb99bbc99-dirty #188 VOLUNTARY +[ 0.000000] Tainted: [W]=WARN +[ 0.000000] Hardware name: loongson,loongson64v-4core-virtio +[ 0.000000] $ 0 : 0000000000000000 0000000000000000 0000000000000001 0000000000000000 +[ 0.000000] $ 4 : ffffffff80b80ec0 ffffffff80b53d48 0000000000000000 00000000000f4240 +[ 0.000000] $ 8 : 0000000000000100 ffffffff81d82f80 ffffffff81d82f80 0000000000000001 +[ 0.000000] $12 : 0000000000000000 ffffffff81776f58 00000000000005da 0000000000000002 +[ 0.000000] $16 : ffffffff80b80e40 0000000000000000 ffffffff80b81614 9800000005dfbe80 +[ 0.000000] $20 : 00000000540000e0 ffffffff81980000 0000000000000000 ffffffff80f81c80 +[ 0.000000] $24 : 0000000000000a26 ffffffff8114fb90 +[ 0.000000] $28 : ffffffff80b50000 ffffffff80b53d40 0000000000000000 ffffffff81afad90 +[ 0.000000] Hi : 0000000000000000 +[ 0.000000] Lo : 0000000000000000 +[ 0.000000] epc : ffffffff81afada8 init_idle+0x130/0x270 +[ 0.000000] ra : ffffffff81afad90 init_idle+0x118/0x270 +[ 0.000000] Status: 540000e2 KX SX UX KERNEL EXL +[ 0.000000] Cause : 00000008 (ExcCode 02) +[ 0.000000] BadVA : 0000000000000000 +[ 0.000000] PrId : 00006305 (ICT Loongson-3) +[ 0.000000] Process swapper (pid: 0, threadinfo=(____ptrval____), task=(____ptrval____), tls=0000000000000000) +[ 0.000000] Stack : 9800000005dfbf00 ffffffff8178e950 0000000000000000 0000000000000000 +[ 0.000000] 0000000000000000 ffffffff81970000 000000000000003f ffffffff810a6528 +[ 0.000000] 0000000000000001 9800000005dfbe80 9800000005dfbf00 ffffffff81980000 +[ 0.000000] ffffffff810a6450 ffffffff81afb6c0 0000000000000000 ffffffff810a2258 +[ 0.000000] ffffffff81d82ec8 ffffffff8198d010 ffffffff81b67e80 ffffffff8197dd98 +[ 0.000000] ffffffff81d81c80 ffffffff81930000 0000000000000040 0000000000000000 +[ 0.000000] 0000000000000000 0000000000000000 0000000000000000 0000000000000000 +[ 0.000000] 0000000000000000 000000000000009e ffffffff9fc01000 0000000000000000 +[ 0.000000] 0000000000000000 0000000000000000 0000000000000000 0000000000000000 +[ 0.000000] 0000000000000000 ffffffff81ae86dc ffffffff81b3c741 0000000000000002 +[ 0.000000] ... +[ 0.000000] Call Trace: +[ 0.000000] [] init_idle+0x130/0x270 +[ 0.000000] [] sched_init+0x5c8/0x6c0 +[ 0.000000] [] start_kernel+0x27c/0x7a8 + +This bug has been reported to LLVM[2] and affects version from (at +least) 18 to 21. Let's work around this by using inline assembly to +assign $gp before a fix is widely available. + +Cc: stable@vger.kernel.org +Link: https://gcc.gnu.org/onlinedocs/gcc-15.2.0/gcc/Global-Register-Variables.html # [1] +Link: https://github.com/llvm/llvm-project/issues/176546 # [2] +Signed-off-by: Yao Zi +Acked-by: Nathan Chancellor +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Greg Kroah-Hartman +--- + arch/mips/kernel/relocate.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/arch/mips/kernel/relocate.c ++++ b/arch/mips/kernel/relocate.c +@@ -420,7 +420,20 @@ void *__init relocate_kernel(void) + goto out; + + /* The current thread is now within the relocated image */ ++#ifndef CONFIG_CC_IS_CLANG + __current_thread_info = RELOCATED(&init_thread_union); ++#else ++ /* ++ * LLVM may wrongly restore $gp ($28) in epilog even if it's ++ * intentionally modified. Work around this by using inline ++ * assembly to assign $gp. $gp couldn't be listed as output or ++ * clobber, or LLVM will still restore its original value. ++ * See also LLVM upstream issue ++ * https://github.com/llvm/llvm-project/issues/176546 ++ */ ++ asm volatile("move $28, %0" : : ++ "r" (RELOCATED(&init_thread_union))); ++#endif + + /* Return the new kernel's entry point */ + kernel_entry = RELOCATED(start_kernel); diff --git a/queue-6.19/series b/queue-6.19/series index 668618b03e..d13194f732 100644 --- a/queue-6.19/series +++ b/queue-6.19/series @@ -750,3 +750,30 @@ drm-amd-display-initialize-dac-in-dce-link-encoder-u.patch drm-amd-display-set-crtc-source-for-dac-using-regist.patch drm-amd-display-enable-dac-in-dce-link-encoder.patch pci-dwc-ep-always-clear-ib-maps-on-bar-update.patch +usb-cdns3-fix-role-switching-during-resume.patch +mips-work-around-llvm-bug-when-gp-is-used-as-global-register-variable.patch +ksmbd-call-ksmbd_vfs_kern_path_end_removing-on-some-error-paths.patch +ext4-subdivide-ext4_ext_data_valid1.patch +ext4-don-t-set-ext4_get_blocks_convert-when-splitting-before-submitting-i-o.patch +ext4-don-t-zero-the-entire-extent-if-ext4_ext_data_partial_valid1.patch +ext4-don-t-cache-extent-during-splitting-extent.patch +ext4-drop-extent-cache-after-doing-partial_valid1-zeroout.patch +ext4-drop-extent-cache-when-splitting-extent-fails.patch +ext4-fix-memory-leak-in-ext4_ext_shift_extents.patch +ext4-fix-e4b-bitmap-inconsistency-reports.patch +ext4-fix-dirtyclusters-double-decrement-on-fs-shutdown.patch +ext4-always-allocate-blocks-only-from-groups-inode-can-use.patch +ext4-use-optimized-mballoc-scanning-regardless-of-inode-format.patch +ata-pata_ftide010-fix-some-dma-timings.patch +ata-libata-scsi-refactor-ata_scsi_translate.patch +ata-libata-scsi-avoid-non-ncq-command-starvation.patch +sunrpc-auth_gss-fix-memory-leaks-in-xdr-decoding-error-paths.patch +sunrpc-fix-gss_auth-kref-leak-in-gss_alloc_msg-error-path.patch +dt-bindings-phy-qcom-edp-add-missing-clock-for-x-elite.patch +dt-bindings-media-qcom-qcs8300-camss-add-missing-power-supplies.patch +asoc-dt-bindings-asahi-kasei-ak4458-set-unevaluatedproperties-false.patch +asoc-dt-bindings-asahi-kasei-ak4458-fix-the-supply-names.patch +asoc-dt-bindings-asahi-kasei-ak5558-fix-the-supply-names.patch +alsa-hda-realtek-add-quirk-for-gigabyte-g5-kf5-2023.patch +alsa-hda-conexant-fix-headphone-jack-handling-on-acer-swift-sf314.patch +alsa-hda-realtek-add-quirk-for-samsung-galaxy-book3-pro-360-np965qfg.patch diff --git a/queue-6.19/sunrpc-auth_gss-fix-memory-leaks-in-xdr-decoding-error-paths.patch b/queue-6.19/sunrpc-auth_gss-fix-memory-leaks-in-xdr-decoding-error-paths.patch new file mode 100644 index 0000000000..1758317294 --- /dev/null +++ b/queue-6.19/sunrpc-auth_gss-fix-memory-leaks-in-xdr-decoding-error-paths.patch @@ -0,0 +1,222 @@ +From 3e6397b056335cc56ef0e9da36c95946a19f5118 Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Fri, 26 Dec 2025 10:15:32 -0500 +Subject: SUNRPC: auth_gss: fix memory leaks in XDR decoding error paths + +From: Chuck Lever + +commit 3e6397b056335cc56ef0e9da36c95946a19f5118 upstream. + +The gssx_dec_ctx(), gssx_dec_status(), and gssx_dec_name() +functions allocate memory via gssx_dec_buffer(), which calls +kmemdup(). When a subsequent decode operation fails, these +functions return immediately without freeing previously +allocated buffers, causing memory leaks. + +The leak in gssx_dec_ctx() is particularly relevant because +the caller (gssp_accept_sec_context_upcall) initializes several +buffer length fields to non-zero values, resulting in memory +allocation: + + struct gssx_ctx rctxh = { + .exported_context_token.len = GSSX_max_output_handle_sz, + .mech.len = GSS_OID_MAX_LEN, + .src_name.display_name.len = GSSX_max_princ_sz, + .targ_name.display_name.len = GSSX_max_princ_sz + }; + +If, for example, gssx_dec_name() succeeds for src_name but +fails for targ_name, the memory allocated for +exported_context_token, mech, and src_name.display_name +remains unreferenced and cannot be reclaimed. + +Add error handling with goto-based cleanup to free any +previously allocated buffers before returning an error. + +Reported-by: Xingjing Deng +Closes: https://lore.kernel.org/linux-nfs/CAK+ZN9qttsFDu6h1FoqGadXjMx1QXqPMoYQ=6O9RY4SxVTvKng@mail.gmail.com/ +Fixes: 1d658336b05f ("SUNRPC: Add RPC based upcall mechanism for RPCGSS auth") +Cc: stable@vger.kernel.org +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + net/sunrpc/auth_gss/gss_rpc_xdr.c | 82 +++++++++++++++++++++++++++++--------- + 1 file changed, 64 insertions(+), 18 deletions(-) + +--- a/net/sunrpc/auth_gss/gss_rpc_xdr.c ++++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c +@@ -320,29 +320,47 @@ static int gssx_dec_status(struct xdr_st + + /* status->minor_status */ + p = xdr_inline_decode(xdr, 8); +- if (unlikely(p == NULL)) +- return -ENOSPC; ++ if (unlikely(p == NULL)) { ++ err = -ENOSPC; ++ goto out_free_mech; ++ } + p = xdr_decode_hyper(p, &status->minor_status); + + /* status->major_status_string */ + err = gssx_dec_buffer(xdr, &status->major_status_string); + if (err) +- return err; ++ goto out_free_mech; + + /* status->minor_status_string */ + err = gssx_dec_buffer(xdr, &status->minor_status_string); + if (err) +- return err; ++ goto out_free_major_status_string; + + /* status->server_ctx */ + err = gssx_dec_buffer(xdr, &status->server_ctx); + if (err) +- return err; ++ goto out_free_minor_status_string; + + /* we assume we have no options for now, so simply consume them */ + /* status->options */ + err = dummy_dec_opt_array(xdr, &status->options); ++ if (err) ++ goto out_free_server_ctx; + ++ return 0; ++ ++out_free_server_ctx: ++ kfree(status->server_ctx.data); ++ status->server_ctx.data = NULL; ++out_free_minor_status_string: ++ kfree(status->minor_status_string.data); ++ status->minor_status_string.data = NULL; ++out_free_major_status_string: ++ kfree(status->major_status_string.data); ++ status->major_status_string.data = NULL; ++out_free_mech: ++ kfree(status->mech.data); ++ status->mech.data = NULL; + return err; + } + +@@ -505,28 +523,35 @@ static int gssx_dec_name(struct xdr_stre + /* name->name_type */ + err = gssx_dec_buffer(xdr, &dummy_netobj); + if (err) +- return err; ++ goto out_free_display_name; + + /* name->exported_name */ + err = gssx_dec_buffer(xdr, &dummy_netobj); + if (err) +- return err; ++ goto out_free_display_name; + + /* name->exported_composite_name */ + err = gssx_dec_buffer(xdr, &dummy_netobj); + if (err) +- return err; ++ goto out_free_display_name; + + /* we assume we have no attributes for now, so simply consume them */ + /* name->name_attributes */ + err = dummy_dec_nameattr_array(xdr, &dummy_name_attr_array); + if (err) +- return err; ++ goto out_free_display_name; + + /* we assume we have no options for now, so simply consume them */ + /* name->extensions */ + err = dummy_dec_opt_array(xdr, &dummy_option_array); ++ if (err) ++ goto out_free_display_name; + ++ return 0; ++ ++out_free_display_name: ++ kfree(name->display_name.data); ++ name->display_name.data = NULL; + return err; + } + +@@ -649,32 +674,34 @@ static int gssx_dec_ctx(struct xdr_strea + /* ctx->state */ + err = gssx_dec_buffer(xdr, &ctx->state); + if (err) +- return err; ++ goto out_free_exported_context_token; + + /* ctx->need_release */ + err = gssx_dec_bool(xdr, &ctx->need_release); + if (err) +- return err; ++ goto out_free_state; + + /* ctx->mech */ + err = gssx_dec_buffer(xdr, &ctx->mech); + if (err) +- return err; ++ goto out_free_state; + + /* ctx->src_name */ + err = gssx_dec_name(xdr, &ctx->src_name); + if (err) +- return err; ++ goto out_free_mech; + + /* ctx->targ_name */ + err = gssx_dec_name(xdr, &ctx->targ_name); + if (err) +- return err; ++ goto out_free_src_name; + + /* ctx->lifetime */ + p = xdr_inline_decode(xdr, 8+8); +- if (unlikely(p == NULL)) +- return -ENOSPC; ++ if (unlikely(p == NULL)) { ++ err = -ENOSPC; ++ goto out_free_targ_name; ++ } + p = xdr_decode_hyper(p, &ctx->lifetime); + + /* ctx->ctx_flags */ +@@ -683,17 +710,36 @@ static int gssx_dec_ctx(struct xdr_strea + /* ctx->locally_initiated */ + err = gssx_dec_bool(xdr, &ctx->locally_initiated); + if (err) +- return err; ++ goto out_free_targ_name; + + /* ctx->open */ + err = gssx_dec_bool(xdr, &ctx->open); + if (err) +- return err; ++ goto out_free_targ_name; + + /* we assume we have no options for now, so simply consume them */ + /* ctx->options */ + err = dummy_dec_opt_array(xdr, &ctx->options); ++ if (err) ++ goto out_free_targ_name; ++ ++ return 0; + ++out_free_targ_name: ++ kfree(ctx->targ_name.display_name.data); ++ ctx->targ_name.display_name.data = NULL; ++out_free_src_name: ++ kfree(ctx->src_name.display_name.data); ++ ctx->src_name.display_name.data = NULL; ++out_free_mech: ++ kfree(ctx->mech.data); ++ ctx->mech.data = NULL; ++out_free_state: ++ kfree(ctx->state.data); ++ ctx->state.data = NULL; ++out_free_exported_context_token: ++ kfree(ctx->exported_context_token.data); ++ ctx->exported_context_token.data = NULL; + return err; + } + diff --git a/queue-6.19/sunrpc-fix-gss_auth-kref-leak-in-gss_alloc_msg-error-path.patch b/queue-6.19/sunrpc-fix-gss_auth-kref-leak-in-gss_alloc_msg-error-path.patch new file mode 100644 index 0000000000..090eab2103 --- /dev/null +++ b/queue-6.19/sunrpc-fix-gss_auth-kref-leak-in-gss_alloc_msg-error-path.patch @@ -0,0 +1,51 @@ +From dd2fdc3504592d85e549c523b054898a036a6afe Mon Sep 17 00:00:00 2001 +From: Daniel Hodges +Date: Fri, 6 Feb 2026 15:41:46 -0500 +Subject: SUNRPC: fix gss_auth kref leak in gss_alloc_msg error path + +From: Daniel Hodges + +commit dd2fdc3504592d85e549c523b054898a036a6afe upstream. + +Commit 5940d1cf9f42 ("SUNRPC: Rebalance a kref in auth_gss.c") added +a kref_get(&gss_auth->kref) call to balance the gss_put_auth() done +in gss_release_msg(), but forgot to add a corresponding kref_put() +on the error path when kstrdup_const() fails. + +If service_name is non-NULL and kstrdup_const() fails, the function +jumps to err_put_pipe_version which calls put_pipe_version() and +kfree(gss_msg), but never releases the gss_auth reference. This leads +to a kref leak where the gss_auth structure is never freed. + +Add a forward declaration for gss_free_callback() and call kref_put() +in the err_put_pipe_version error path to properly release the +reference taken earlier. + +Fixes: 5940d1cf9f42 ("SUNRPC: Rebalance a kref in auth_gss.c") +Cc: stable@vger.kernel.org +Signed-off-by: Daniel Hodges +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman +--- + net/sunrpc/auth_gss/auth_gss.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/sunrpc/auth_gss/auth_gss.c ++++ b/net/sunrpc/auth_gss/auth_gss.c +@@ -39,6 +39,8 @@ static const struct rpc_authops authgss_ + static const struct rpc_credops gss_credops; + static const struct rpc_credops gss_nullops; + ++static void gss_free_callback(struct kref *kref); ++ + #define GSS_RETRY_EXPIRED 5 + static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED; + +@@ -551,6 +553,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, + } + return gss_msg; + err_put_pipe_version: ++ kref_put(&gss_auth->kref, gss_free_callback); + put_pipe_version(gss_auth->net); + err_free_msg: + kfree(gss_msg); diff --git a/queue-6.19/usb-cdns3-fix-role-switching-during-resume.patch b/queue-6.19/usb-cdns3-fix-role-switching-during-resume.patch new file mode 100644 index 0000000000..a7a53e1ffc --- /dev/null +++ b/queue-6.19/usb-cdns3-fix-role-switching-during-resume.patch @@ -0,0 +1,87 @@ +From 87e4b043b98a1d269be0b812f383881abee0ca45 Mon Sep 17 00:00:00 2001 +From: "Thomas Richard (TI)" +Date: Fri, 30 Jan 2026 11:05:45 +0100 +Subject: usb: cdns3: fix role switching during resume + +From: Thomas Richard (TI) + +commit 87e4b043b98a1d269be0b812f383881abee0ca45 upstream. + +If the role change while we are suspended, the cdns3 driver switches to the +new mode during resume. However, switching to host mode in this context +causes a NULL pointer dereference. + +The host role's start() operation registers a xhci-hcd device, but its +probe is deferred while we are in the resume path. The host role's resume() +operation assumes the xhci-hcd device is already probed, which is not the +case, leading to the dereference. Since the start() operation of the new +role is already called, the resume operation can be skipped. + +So skip the resume operation for the new role if a role switch occurs +during resume. Once the resume sequence is complete, the xhci-hcd device +can be probed in case of host mode. + +Unable to handle kernel NULL pointer dereference at virtual address 0000000000000208 +Mem abort info: +... +Data abort info: +... +[0000000000000208] pgd=0000000000000000, p4d=0000000000000000 +Internal error: Oops: 0000000096000004 [#1] SMP +Modules linked in: +CPU: 0 UID: 0 PID: 146 Comm: sh Not tainted +6.19.0-rc7-00013-g6e64f4aabfae-dirty #135 PREEMPT +Hardware name: Texas Instruments J7200 EVM (DT) +pstate: 20000005 (nzCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) +pc : usb_hcd_is_primary_hcd+0x0/0x1c +lr : cdns_host_resume+0x24/0x5c +... +Call trace: + usb_hcd_is_primary_hcd+0x0/0x1c (P) + cdns_resume+0x6c/0xbc + cdns3_controller_resume.isra.0+0xe8/0x17c + cdns3_plat_resume+0x18/0x24 + platform_pm_resume+0x2c/0x68 + dpm_run_callback+0x90/0x248 + device_resume+0x100/0x24c + dpm_resume+0x190/0x2ec + dpm_resume_end+0x18/0x34 + suspend_devices_and_enter+0x2b0/0xa44 + pm_suspend+0x16c/0x5fc + state_store+0x80/0xec + kobj_attr_store+0x18/0x2c + sysfs_kf_write+0x7c/0x94 + kernfs_fop_write_iter+0x130/0x1dc + vfs_write+0x240/0x370 + ksys_write+0x70/0x108 + __arm64_sys_write+0x1c/0x28 + invoke_syscall+0x48/0x10c + el0_svc_common.constprop.0+0x40/0xe0 + do_el0_svc+0x1c/0x28 + el0_svc+0x34/0x108 + el0t_64_sync_handler+0xa0/0xe4 + el0t_64_sync+0x198/0x19c +Code: 52800003 f9407ca5 d63f00a0 17ffffe4 (f9410401) +---[ end trace 0000000000000000 ]--- + +Cc: stable +Fixes: 2cf2581cd229 ("usb: cdns3: add power lost support for system resume") +Signed-off-by: Thomas Richard (TI) +Acked-by: Peter Chen +Link: https://patch.msgid.link/20260130-usb-cdns3-fix-role-switching-during-resume-v1-1-44c456852b52@bootlin.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/cdns3/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/cdns3/core.c ++++ b/drivers/usb/cdns3/core.c +@@ -551,7 +551,7 @@ int cdns_resume(struct cdns *cdns) + } + } + +- if (cdns->roles[cdns->role]->resume) ++ if (!role_changed && cdns->roles[cdns->role]->resume) + cdns->roles[cdns->role]->resume(cdns, power_lost); + + return 0; -- 2.47.3