From: Greg Kroah-Hartman Date: Sun, 10 Feb 2019 12:40:19 +0000 (+0100) Subject: 4.20-stable patches X-Git-Tag: v4.9.156~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=54da6a9e90ba2267f6437a38ed6eef1be04095b2;p=thirdparty%2Fkernel%2Fstable-queue.git 4.20-stable patches added patches: alsa-compress-fix-stop-handling-on-compressed-capture-streams.patch alsa-hda-realtek-fix-lose-hp_pins-for-disable-auto-mute.patch alsa-hda-realtek-headset-microphone-support-for-system76-darp5.patch alsa-hda-realtek-use-a-common-helper-for-hp-pin-reference.patch alsa-hda-serialize-codec-registrations.patch alsa-usb-audio-add-support-for-new-t-a-usb-dac.patch cuse-fix-ioctl.patch fuse-call-pipe_buf_release-under-pipe-lock.patch fuse-decrement-nr_writeback_temp-on-the-right-page.patch fuse-handle-zero-sized-retrieve-correctly.patch hid-debug-fix-the-ring-buffer-implementation.patch xfs-eof-trim-writeback-mapping-as-soon-as-it-is-cached.patch --- diff --git a/queue-4.20/alsa-compress-fix-stop-handling-on-compressed-capture-streams.patch b/queue-4.20/alsa-compress-fix-stop-handling-on-compressed-capture-streams.patch new file mode 100644 index 00000000000..68d66f19a91 --- /dev/null +++ b/queue-4.20/alsa-compress-fix-stop-handling-on-compressed-capture-streams.patch @@ -0,0 +1,51 @@ +From 4f2ab5e1d13d6aa77c55f4914659784efd776eb4 Mon Sep 17 00:00:00 2001 +From: Charles Keepax +Date: Tue, 5 Feb 2019 16:29:40 +0000 +Subject: ALSA: compress: Fix stop handling on compressed capture streams + +From: Charles Keepax + +commit 4f2ab5e1d13d6aa77c55f4914659784efd776eb4 upstream. + +It is normal user behaviour to start, stop, then start a stream +again without closing it. Currently this works for compressed +playback streams but not capture ones. + +The states on a compressed capture stream go directly from OPEN to +PREPARED, unlike a playback stream which moves to SETUP and waits +for a write of data before moving to PREPARED. Currently however, +when a stop is sent the state is set to SETUP for both types of +streams. This leaves a capture stream in the situation where a new +start can't be sent as that requires the state to be PREPARED and +a new set_params can't be sent as that requires the state to be +OPEN. The only option being to close the stream, and then reopen. + +Correct this issues by allowing snd_compr_drain_notify to set the +state depending on the stream direction, as we already do in +set_params. + +Fixes: 49bb6402f1aa ("ALSA: compress_core: Add support for capture streams") +Signed-off-by: Charles Keepax +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + include/sound/compress_driver.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/include/sound/compress_driver.h ++++ b/include/sound/compress_driver.h +@@ -171,7 +171,11 @@ static inline void snd_compr_drain_notif + if (snd_BUG_ON(!stream)) + return; + +- stream->runtime->state = SNDRV_PCM_STATE_SETUP; ++ if (stream->direction == SND_COMPRESS_PLAYBACK) ++ stream->runtime->state = SNDRV_PCM_STATE_SETUP; ++ else ++ stream->runtime->state = SNDRV_PCM_STATE_PREPARED; ++ + wake_up(&stream->runtime->sleep); + } + diff --git a/queue-4.20/alsa-hda-realtek-fix-lose-hp_pins-for-disable-auto-mute.patch b/queue-4.20/alsa-hda-realtek-fix-lose-hp_pins-for-disable-auto-mute.patch new file mode 100644 index 00000000000..903a5790714 --- /dev/null +++ b/queue-4.20/alsa-hda-realtek-fix-lose-hp_pins-for-disable-auto-mute.patch @@ -0,0 +1,135 @@ +From d561aa0a70bb2e1dd85fde98b6a5561e4175ac3e Mon Sep 17 00:00:00 2001 +From: Kailang Yang +Date: Fri, 1 Feb 2019 16:51:10 +0800 +Subject: ALSA: hda/realtek - Fix lose hp_pins for disable auto mute + +From: Kailang Yang + +commit d561aa0a70bb2e1dd85fde98b6a5561e4175ac3e upstream. + +When auto_mute = no or spec->suppress_auto_mute = 1, cfg->hp_pins will +lose value. + +Add this patch to find hp_pins value. +I add fixed for ALC282 ALC225 ALC256 ALC294 and alc_default_init() +alc_default_shutup(). + +Signed-off-by: Kailang Yang +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_realtek.c | 45 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -2963,6 +2963,11 @@ static void alc282_init(struct hda_codec + bool hp_pin_sense; + int coef78; + ++ if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { ++ if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) ++ hp_pin = spec->gen.autocfg.line_out_pins[0]; ++ } ++ + alc282_restore_default_value(codec); + + if (!hp_pin) +@@ -3000,6 +3005,11 @@ static void alc282_shutup(struct hda_cod + bool hp_pin_sense; + int coef78; + ++ if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { ++ if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) ++ hp_pin = spec->gen.autocfg.line_out_pins[0]; ++ } ++ + if (!hp_pin) { + alc269_shutup(codec); + return; +@@ -3159,6 +3169,11 @@ static void alc256_init(struct hda_codec + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp_pin_sense; + ++ if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { ++ if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) ++ hp_pin = spec->gen.autocfg.line_out_pins[0]; ++ } ++ + if (!hp_pin) + return; + +@@ -3195,6 +3210,11 @@ static void alc256_shutup(struct hda_cod + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp_pin_sense; + ++ if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { ++ if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) ++ hp_pin = spec->gen.autocfg.line_out_pins[0]; ++ } ++ + if (!hp_pin) { + alc269_shutup(codec); + return; +@@ -3231,6 +3251,11 @@ static void alc225_init(struct hda_codec + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp1_pin_sense, hp2_pin_sense; + ++ if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { ++ if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) ++ hp_pin = spec->gen.autocfg.line_out_pins[0]; ++ } ++ + if (!hp_pin) + return; + +@@ -3274,6 +3299,11 @@ static void alc225_shutup(struct hda_cod + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp1_pin_sense, hp2_pin_sense; + ++ if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { ++ if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) ++ hp_pin = spec->gen.autocfg.line_out_pins[0]; ++ } ++ + if (!hp_pin) { + alc269_shutup(codec); + return; +@@ -3318,6 +3348,11 @@ static void alc_default_init(struct hda_ + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp_pin_sense; + ++ if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { ++ if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) ++ hp_pin = spec->gen.autocfg.line_out_pins[0]; ++ } ++ + if (!hp_pin) + return; + +@@ -3347,6 +3382,11 @@ static void alc_default_shutup(struct hd + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp_pin_sense; + ++ if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { ++ if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) ++ hp_pin = spec->gen.autocfg.line_out_pins[0]; ++ } ++ + if (!hp_pin) { + alc269_shutup(codec); + return; +@@ -3379,6 +3419,11 @@ static void alc294_hp_init(struct hda_co + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + int i, val; + ++ if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { ++ if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) ++ hp_pin = spec->gen.autocfg.line_out_pins[0]; ++ } ++ + if (!hp_pin) + return; + diff --git a/queue-4.20/alsa-hda-realtek-headset-microphone-support-for-system76-darp5.patch b/queue-4.20/alsa-hda-realtek-headset-microphone-support-for-system76-darp5.patch new file mode 100644 index 00000000000..320e0d3feab --- /dev/null +++ b/queue-4.20/alsa-hda-realtek-headset-microphone-support-for-system76-darp5.patch @@ -0,0 +1,60 @@ +From 89e3a5682edaa4e5bb334719afb180256ac7bf78 Mon Sep 17 00:00:00 2001 +From: Jeremy Soller +Date: Wed, 30 Jan 2019 16:12:31 -0700 +Subject: ALSA: hda/realtek - Headset microphone support for System76 darp5 + +From: Jeremy Soller + +commit 89e3a5682edaa4e5bb334719afb180256ac7bf78 upstream. + +On the System76 Darter Pro (darp5), there is a headset microphone +input attached to 0x1a that does not have a jack detect. In order to +get it working, the pin configuration needs to be set correctly, and +the ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC fixup needs to be applied. +This is similar to the MIC_NO_PRESENCE fixups for some Dell laptops, +except we have a separate microphone jack that is already configured +correctly. + +Signed-off-by: Jeremy Soller +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_realtek.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -5572,6 +5572,7 @@ enum { + ALC294_FIXUP_ASUS_MIC, + ALC294_FIXUP_ASUS_HEADSET_MIC, + ALC294_FIXUP_ASUS_SPK, ++ ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE, + }; + + static const struct hda_fixup alc269_fixups[] = { +@@ -6496,6 +6497,15 @@ static const struct hda_fixup alc269_fix + .chained = true, + .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC + }, ++ [ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */ ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC ++ }, + }; + + static const struct snd_pci_quirk alc269_fixup_tbl[] = { +@@ -6674,6 +6684,7 @@ static const struct snd_pci_quirk alc269 + 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), ++ SND_PCI_QUIRK(0x1558, 0x1325, "System76 Darter Pro (darp5)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS), + SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), diff --git a/queue-4.20/alsa-hda-realtek-use-a-common-helper-for-hp-pin-reference.patch b/queue-4.20/alsa-hda-realtek-use-a-common-helper-for-hp-pin-reference.patch new file mode 100644 index 00000000000..6f5f4c53f57 --- /dev/null +++ b/queue-4.20/alsa-hda-realtek-use-a-common-helper-for-hp-pin-reference.patch @@ -0,0 +1,257 @@ +From 35a39f98567d8d3f1cea48f0f30de1a7e736b644 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 1 Feb 2019 11:19:50 +0100 +Subject: ALSA: hda/realtek - Use a common helper for hp pin reference + +From: Takashi Iwai + +commit 35a39f98567d8d3f1cea48f0f30de1a7e736b644 upstream. + +Replace the open-codes in many places with a new common helper for +performing the same thing: referring to the primary headphone pin. + +This eventually fixes the potentially missing headphone pin on some +weird devices, too. + +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_realtek.c | 96 ++++++++++-------------------------------- + 1 file changed, 24 insertions(+), 72 deletions(-) + +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -515,6 +515,15 @@ static void alc_auto_init_amp(struct hda + } + } + ++/* get a primary headphone pin if available */ ++static hda_nid_t alc_get_hp_pin(struct alc_spec *spec) ++{ ++ if (spec->gen.autocfg.hp_pins[0]) ++ return spec->gen.autocfg.hp_pins[0]; ++ if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) ++ return spec->gen.autocfg.line_out_pins[0]; ++ return 0; ++} + + /* + * Realtek SSID verification +@@ -725,9 +734,7 @@ do_sku: + * 15 : 1 --> enable the function "Mute internal speaker + * when the external headphone out jack is plugged" + */ +- if (!spec->gen.autocfg.hp_pins[0] && +- !(spec->gen.autocfg.line_out_pins[0] && +- spec->gen.autocfg.line_out_type == AUTO_PIN_HP_OUT)) { ++ if (!alc_get_hp_pin(spec)) { + hda_nid_t nid; + tmp = (ass >> 11) & 0x3; /* HP to chassis */ + nid = ports[tmp]; +@@ -2959,15 +2966,10 @@ static void alc282_restore_default_value + static void alc282_init(struct hda_codec *codec) + { + struct alc_spec *spec = codec->spec; +- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; ++ hda_nid_t hp_pin = alc_get_hp_pin(spec); + bool hp_pin_sense; + int coef78; + +- if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { +- if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) +- hp_pin = spec->gen.autocfg.line_out_pins[0]; +- } +- + alc282_restore_default_value(codec); + + if (!hp_pin) +@@ -3001,15 +3003,10 @@ static void alc282_init(struct hda_codec + static void alc282_shutup(struct hda_codec *codec) + { + struct alc_spec *spec = codec->spec; +- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; ++ hda_nid_t hp_pin = alc_get_hp_pin(spec); + bool hp_pin_sense; + int coef78; + +- if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { +- if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) +- hp_pin = spec->gen.autocfg.line_out_pins[0]; +- } +- + if (!hp_pin) { + alc269_shutup(codec); + return; +@@ -3084,14 +3081,9 @@ static void alc283_restore_default_value + static void alc283_init(struct hda_codec *codec) + { + struct alc_spec *spec = codec->spec; +- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; ++ hda_nid_t hp_pin = alc_get_hp_pin(spec); + bool hp_pin_sense; + +- if (!spec->gen.autocfg.hp_outs) { +- if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) +- hp_pin = spec->gen.autocfg.line_out_pins[0]; +- } +- + alc283_restore_default_value(codec); + + if (!hp_pin) +@@ -3125,14 +3117,9 @@ static void alc283_init(struct hda_codec + static void alc283_shutup(struct hda_codec *codec) + { + struct alc_spec *spec = codec->spec; +- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; ++ hda_nid_t hp_pin = alc_get_hp_pin(spec); + bool hp_pin_sense; + +- if (!spec->gen.autocfg.hp_outs) { +- if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) +- hp_pin = spec->gen.autocfg.line_out_pins[0]; +- } +- + if (!hp_pin) { + alc269_shutup(codec); + return; +@@ -3166,14 +3153,9 @@ static void alc283_shutup(struct hda_cod + static void alc256_init(struct hda_codec *codec) + { + struct alc_spec *spec = codec->spec; +- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; ++ hda_nid_t hp_pin = alc_get_hp_pin(spec); + bool hp_pin_sense; + +- if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { +- if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) +- hp_pin = spec->gen.autocfg.line_out_pins[0]; +- } +- + if (!hp_pin) + return; + +@@ -3207,14 +3189,9 @@ static void alc256_init(struct hda_codec + static void alc256_shutup(struct hda_codec *codec) + { + struct alc_spec *spec = codec->spec; +- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; ++ hda_nid_t hp_pin = alc_get_hp_pin(spec); + bool hp_pin_sense; + +- if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { +- if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) +- hp_pin = spec->gen.autocfg.line_out_pins[0]; +- } +- + if (!hp_pin) { + alc269_shutup(codec); + return; +@@ -3248,14 +3225,9 @@ static void alc256_shutup(struct hda_cod + static void alc225_init(struct hda_codec *codec) + { + struct alc_spec *spec = codec->spec; +- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; ++ hda_nid_t hp_pin = alc_get_hp_pin(spec); + bool hp1_pin_sense, hp2_pin_sense; + +- if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { +- if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) +- hp_pin = spec->gen.autocfg.line_out_pins[0]; +- } +- + if (!hp_pin) + return; + +@@ -3296,14 +3268,9 @@ static void alc225_init(struct hda_codec + static void alc225_shutup(struct hda_codec *codec) + { + struct alc_spec *spec = codec->spec; +- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; ++ hda_nid_t hp_pin = alc_get_hp_pin(spec); + bool hp1_pin_sense, hp2_pin_sense; + +- if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { +- if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) +- hp_pin = spec->gen.autocfg.line_out_pins[0]; +- } +- + if (!hp_pin) { + alc269_shutup(codec); + return; +@@ -3345,14 +3312,9 @@ static void alc225_shutup(struct hda_cod + static void alc_default_init(struct hda_codec *codec) + { + struct alc_spec *spec = codec->spec; +- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; ++ hda_nid_t hp_pin = alc_get_hp_pin(spec); + bool hp_pin_sense; + +- if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { +- if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) +- hp_pin = spec->gen.autocfg.line_out_pins[0]; +- } +- + if (!hp_pin) + return; + +@@ -3379,14 +3341,9 @@ static void alc_default_init(struct hda_ + static void alc_default_shutup(struct hda_codec *codec) + { + struct alc_spec *spec = codec->spec; +- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; ++ hda_nid_t hp_pin = alc_get_hp_pin(spec); + bool hp_pin_sense; + +- if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { +- if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) +- hp_pin = spec->gen.autocfg.line_out_pins[0]; +- } +- + if (!hp_pin) { + alc269_shutup(codec); + return; +@@ -3416,14 +3373,9 @@ static void alc_default_shutup(struct hd + static void alc294_hp_init(struct hda_codec *codec) + { + struct alc_spec *spec = codec->spec; +- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; ++ hda_nid_t hp_pin = alc_get_hp_pin(spec); + int i, val; + +- if (!spec->gen.autocfg.hp_outs && spec->gen.suppress_auto_mute) { +- if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT) +- hp_pin = spec->gen.autocfg.line_out_pins[0]; +- } +- + if (!hp_pin) + return; + +@@ -4825,7 +4777,7 @@ static void alc_update_headset_mode(stru + struct alc_spec *spec = codec->spec; + + hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]]; +- hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; ++ hda_nid_t hp_pin = alc_get_hp_pin(spec); + + int new_headset_mode; + +@@ -5104,7 +5056,7 @@ static void alc_fixup_tpt470_dock(struct + static void alc_shutup_dell_xps13(struct hda_codec *codec) + { + struct alc_spec *spec = codec->spec; +- int hp_pin = spec->gen.autocfg.hp_pins[0]; ++ int hp_pin = alc_get_hp_pin(spec); + + /* Prevent pop noises when headphones are plugged in */ + snd_hda_codec_write(codec, hp_pin, 0, +@@ -5197,7 +5149,7 @@ static void alc271_hp_gate_mic_jack(stru + + if (action == HDA_FIXUP_ACT_PROBE) { + int mic_pin = find_ext_mic_pin(codec); +- int hp_pin = spec->gen.autocfg.hp_pins[0]; ++ int hp_pin = alc_get_hp_pin(spec); + + if (snd_BUG_ON(!mic_pin || !hp_pin)) + return; diff --git a/queue-4.20/alsa-hda-serialize-codec-registrations.patch b/queue-4.20/alsa-hda-serialize-codec-registrations.patch new file mode 100644 index 00000000000..e158c33f5cd --- /dev/null +++ b/queue-4.20/alsa-hda-serialize-codec-registrations.patch @@ -0,0 +1,70 @@ +From 305a0ade180981686eec1f92aa6252a7c6ebb1cf Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 30 Jan 2019 17:46:03 +0100 +Subject: ALSA: hda - Serialize codec registrations + +From: Takashi Iwai + +commit 305a0ade180981686eec1f92aa6252a7c6ebb1cf upstream. + +In the current code, the codec registration may happen both at the +codec bind time and the end of the controller probe time. In a rare +occasion, they race with each other, leading to Oops due to the still +uninitialized card device. + +This patch introduces a simple flag to prevent the codec registration +at the codec bind time as long as the controller probe is going on. +The controller probe invokes snd_card_register() that does the whole +registration task, and we don't need to register each piece +beforehand. + +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + include/sound/hda_codec.h | 1 + + sound/pci/hda/hda_bind.c | 3 ++- + sound/pci/hda/hda_intel.c | 2 ++ + 3 files changed, 5 insertions(+), 1 deletion(-) + +--- a/include/sound/hda_codec.h ++++ b/include/sound/hda_codec.h +@@ -68,6 +68,7 @@ struct hda_bus { + unsigned int response_reset:1; /* controller was reset */ + unsigned int in_reset:1; /* during reset operation */ + unsigned int no_response_fallback:1; /* don't fallback at RIRB error */ ++ unsigned int bus_probing :1; /* during probing process */ + + int primary_dig_out_type; /* primary digital out PCM type */ + unsigned int mixer_assigned; /* codec addr for mixer name */ +--- a/sound/pci/hda/hda_bind.c ++++ b/sound/pci/hda/hda_bind.c +@@ -115,7 +115,8 @@ static int hda_codec_driver_probe(struct + err = snd_hda_codec_build_controls(codec); + if (err < 0) + goto error_module; +- if (codec->card->registered) { ++ /* only register after the bus probe finished; otherwise it's racy */ ++ if (!codec->bus->bus_probing && codec->card->registered) { + err = snd_card_register(codec->card); + if (err < 0) + goto error_module; +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -2228,6 +2228,7 @@ static int azx_probe_continue(struct azx + int dev = chip->dev_index; + int err; + ++ to_hda_bus(bus)->bus_probing = 1; + hda->probe_continued = 1; + + /* bind with i915 if needed */ +@@ -2323,6 +2324,7 @@ i915_power_fail: + if (err < 0) + hda->init_failed = 1; + complete_all(&hda->probe_wait); ++ to_hda_bus(bus)->bus_probing = 0; + return err; + } + diff --git a/queue-4.20/alsa-usb-audio-add-support-for-new-t-a-usb-dac.patch b/queue-4.20/alsa-usb-audio-add-support-for-new-t-a-usb-dac.patch new file mode 100644 index 00000000000..00805e37dfa --- /dev/null +++ b/queue-4.20/alsa-usb-audio-add-support-for-new-t-a-usb-dac.patch @@ -0,0 +1,33 @@ +From 3bff2407fbd28fd55ad5b5cccd98fc0c9598f23b Mon Sep 17 00:00:00 2001 +From: Udo Eberhardt +Date: Tue, 5 Feb 2019 17:20:47 +0100 +Subject: ALSA: usb-audio: Add support for new T+A USB DAC + +From: Udo Eberhardt + +commit 3bff2407fbd28fd55ad5b5cccd98fc0c9598f23b upstream. + +This patch adds the T+A VID to the generic check in order to enable +native DSD support for T+A devices. This works with the new T+A USB +DAC model SD3100HV and will also work with future devices which +support the XMOS/Thesycon style DSD format. + +Signed-off-by: Udo Eberhardt +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/usb/quirks.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -1448,6 +1448,7 @@ u64 snd_usb_interface_dsd_format_quirks( + case 0x20b1: /* XMOS based devices */ + case 0x152a: /* Thesycon devices */ + case 0x25ce: /* Mytek devices */ ++ case 0x2ab6: /* T+A devices */ + if (fp->dsd_raw) + return SNDRV_PCM_FMTBIT_DSD_U32_BE; + break; diff --git a/queue-4.20/cuse-fix-ioctl.patch b/queue-4.20/cuse-fix-ioctl.patch new file mode 100644 index 00000000000..e1f8f315c62 --- /dev/null +++ b/queue-4.20/cuse-fix-ioctl.patch @@ -0,0 +1,40 @@ +From 8a3177db59cd644fde05ba9efee29392dfdec8aa Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Wed, 16 Jan 2019 10:27:59 +0100 +Subject: cuse: fix ioctl + +From: Miklos Szeredi + +commit 8a3177db59cd644fde05ba9efee29392dfdec8aa upstream. + +cuse_process_init_reply() doesn't initialize fc->max_pages and thus all +cuse bases ioctls fail with ENOMEM. + +Reported-by: Andreas Steinmetz +Fixes: 5da784cce430 ("fuse: add max_pages to init_out") +Cc: # v4.20 +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman + +--- + fs/fuse/inode.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/fuse/inode.c ++++ b/fs/fuse/inode.c +@@ -628,6 +628,7 @@ void fuse_conn_init(struct fuse_conn *fc + get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); + fc->pid_ns = get_pid_ns(task_active_pid_ns(current)); + fc->user_ns = get_user_ns(user_ns); ++ fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ; + } + EXPORT_SYMBOL_GPL(fuse_conn_init); + +@@ -1162,7 +1163,6 @@ static int fuse_fill_super(struct super_ + fc->user_id = d.user_id; + fc->group_id = d.group_id; + fc->max_read = max_t(unsigned, 4096, d.max_read); +- fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ; + + /* Used by get_root_inode() */ + sb->s_fs_info = fc; diff --git a/queue-4.20/fuse-call-pipe_buf_release-under-pipe-lock.patch b/queue-4.20/fuse-call-pipe_buf_release-under-pipe-lock.patch new file mode 100644 index 00000000000..1ee632b1404 --- /dev/null +++ b/queue-4.20/fuse-call-pipe_buf_release-under-pipe-lock.patch @@ -0,0 +1,40 @@ +From 9509941e9c534920ccc4771ae70bd6cbbe79df1c Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Sat, 12 Jan 2019 02:39:05 +0100 +Subject: fuse: call pipe_buf_release() under pipe lock + +From: Jann Horn + +commit 9509941e9c534920ccc4771ae70bd6cbbe79df1c upstream. + +Some of the pipe_buf_release() handlers seem to assume that the pipe is +locked - in particular, anon_pipe_buf_release() accesses pipe->tmp_page +without taking any extra locks. From a glance through the callers of +pipe_buf_release(), it looks like FUSE is the only one that calls +pipe_buf_release() without having the pipe locked. + +This bug should only lead to a memory leak, nothing terrible. + +Fixes: dd3bb14f44a6 ("fuse: support splice() writing to fuse device") +Cc: stable@vger.kernel.org +Signed-off-by: Jann Horn +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman + +--- + fs/fuse/dev.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -2077,8 +2077,10 @@ static ssize_t fuse_dev_splice_write(str + + ret = fuse_dev_do_write(fud, &cs, len); + ++ pipe_lock(pipe); + for (idx = 0; idx < nbuf; idx++) + pipe_buf_release(pipe, &bufs[idx]); ++ pipe_unlock(pipe); + + out: + kvfree(bufs); diff --git a/queue-4.20/fuse-decrement-nr_writeback_temp-on-the-right-page.patch b/queue-4.20/fuse-decrement-nr_writeback_temp-on-the-right-page.patch new file mode 100644 index 00000000000..b25a7a64189 --- /dev/null +++ b/queue-4.20/fuse-decrement-nr_writeback_temp-on-the-right-page.patch @@ -0,0 +1,32 @@ +From a2ebba824106dabe79937a9f29a875f837e1b6d4 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Wed, 16 Jan 2019 10:27:59 +0100 +Subject: fuse: decrement NR_WRITEBACK_TEMP on the right page + +From: Miklos Szeredi + +commit a2ebba824106dabe79937a9f29a875f837e1b6d4 upstream. + +NR_WRITEBACK_TEMP is accounted on the temporary page in the request, not +the page cache page. + +Fixes: 8b284dc47291 ("fuse: writepages: handle same page rewrites") +Cc: # v3.13 +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman + +--- + fs/fuse/file.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -1782,7 +1782,7 @@ static bool fuse_writepage_in_flight(str + spin_unlock(&fc->lock); + + dec_wb_stat(&bdi->wb, WB_WRITEBACK); +- dec_node_page_state(page, NR_WRITEBACK_TEMP); ++ dec_node_page_state(new_req->pages[0], NR_WRITEBACK_TEMP); + wb_writeout_inc(&bdi->wb); + fuse_writepage_free(fc, new_req); + fuse_request_free(new_req); diff --git a/queue-4.20/fuse-handle-zero-sized-retrieve-correctly.patch b/queue-4.20/fuse-handle-zero-sized-retrieve-correctly.patch new file mode 100644 index 00000000000..02691f4df93 --- /dev/null +++ b/queue-4.20/fuse-handle-zero-sized-retrieve-correctly.patch @@ -0,0 +1,40 @@ +From 97e1532ef81acb31c30f9e75bf00306c33a77812 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Wed, 16 Jan 2019 10:27:59 +0100 +Subject: fuse: handle zero sized retrieve correctly + +From: Miklos Szeredi + +commit 97e1532ef81acb31c30f9e75bf00306c33a77812 upstream. + +Dereferencing req->page_descs[0] will Oops if req->max_pages is zero. + +Reported-by: syzbot+c1e36d30ee3416289cc0@syzkaller.appspotmail.com +Tested-by: syzbot+c1e36d30ee3416289cc0@syzkaller.appspotmail.com +Fixes: b2430d7567a3 ("fuse: add per-page descriptor to fuse_req") +Cc: # v3.9 +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman + +--- + fs/fuse/dev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -1742,7 +1742,6 @@ static int fuse_retrieve(struct fuse_con + req->in.h.nodeid = outarg->nodeid; + req->in.numargs = 2; + req->in.argpages = 1; +- req->page_descs[0].offset = offset; + req->end = fuse_retrieve_end; + + index = outarg->offset >> PAGE_SHIFT; +@@ -1757,6 +1756,7 @@ static int fuse_retrieve(struct fuse_con + + this_num = min_t(unsigned, num, PAGE_SIZE - offset); + req->pages[req->num_pages] = page; ++ req->page_descs[req->num_pages].offset = offset; + req->page_descs[req->num_pages].length = this_num; + req->num_pages++; + diff --git a/queue-4.20/hid-debug-fix-the-ring-buffer-implementation.patch b/queue-4.20/hid-debug-fix-the-ring-buffer-implementation.patch new file mode 100644 index 00000000000..da24da5cfc1 --- /dev/null +++ b/queue-4.20/hid-debug-fix-the-ring-buffer-implementation.patch @@ -0,0 +1,257 @@ +From 13054abbaa4f1fd4e6f3b4b63439ec033b4c8035 Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Tue, 29 Jan 2019 11:58:35 +0100 +Subject: HID: debug: fix the ring buffer implementation + +From: Vladis Dronov + +commit 13054abbaa4f1fd4e6f3b4b63439ec033b4c8035 upstream. + +Ring buffer implementation in hid_debug_event() and hid_debug_events_read() +is strange allowing lost or corrupted data. After commit 717adfdaf147 +("HID: debug: check length before copy_to_user()") it is possible to enter +an infinite loop in hid_debug_events_read() by providing 0 as count, this +locks up a system. Fix this by rewriting the ring buffer implementation +with kfifo and simplify the code. + +This fixes CVE-2019-3819. + +v2: fix an execution logic and add a comment +v3: use __set_current_state() instead of set_current_state() + +Link: https://bugzilla.redhat.com/show_bug.cgi?id=1669187 +Cc: stable@vger.kernel.org # v4.18+ +Fixes: cd667ce24796 ("HID: use debugfs for events/reports dumping") +Fixes: 717adfdaf147 ("HID: debug: check length before copy_to_user()") +Signed-off-by: Vladis Dronov +Reviewed-by: Oleg Nesterov +Signed-off-by: Benjamin Tissoires +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-debug.c | 120 ++++++++++++++++++---------------------------- + include/linux/hid-debug.h | 9 +-- + 2 files changed, 51 insertions(+), 78 deletions(-) + +--- a/drivers/hid/hid-debug.c ++++ b/drivers/hid/hid-debug.c +@@ -30,6 +30,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -661,17 +662,12 @@ EXPORT_SYMBOL_GPL(hid_dump_device); + /* enqueue string to 'events' ring buffer */ + void hid_debug_event(struct hid_device *hdev, char *buf) + { +- unsigned i; + struct hid_debug_list *list; + unsigned long flags; + + spin_lock_irqsave(&hdev->debug_list_lock, flags); +- list_for_each_entry(list, &hdev->debug_list, node) { +- for (i = 0; buf[i]; i++) +- list->hid_debug_buf[(list->tail + i) % HID_DEBUG_BUFSIZE] = +- buf[i]; +- list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE; +- } ++ list_for_each_entry(list, &hdev->debug_list, node) ++ kfifo_in(&list->hid_debug_fifo, buf, strlen(buf)); + spin_unlock_irqrestore(&hdev->debug_list_lock, flags); + + wake_up_interruptible(&hdev->debug_wait); +@@ -722,8 +718,7 @@ void hid_dump_input(struct hid_device *h + hid_debug_event(hdev, buf); + + kfree(buf); +- wake_up_interruptible(&hdev->debug_wait); +- ++ wake_up_interruptible(&hdev->debug_wait); + } + EXPORT_SYMBOL_GPL(hid_dump_input); + +@@ -1088,8 +1083,8 @@ static int hid_debug_events_open(struct + goto out; + } + +- if (!(list->hid_debug_buf = kzalloc(HID_DEBUG_BUFSIZE, GFP_KERNEL))) { +- err = -ENOMEM; ++ err = kfifo_alloc(&list->hid_debug_fifo, HID_DEBUG_FIFOSIZE, GFP_KERNEL); ++ if (err) { + kfree(list); + goto out; + } +@@ -1109,77 +1104,57 @@ static ssize_t hid_debug_events_read(str + size_t count, loff_t *ppos) + { + struct hid_debug_list *list = file->private_data; +- int ret = 0, len; ++ int ret = 0, copied; + DECLARE_WAITQUEUE(wait, current); + + mutex_lock(&list->read_mutex); +- while (ret == 0) { +- if (list->head == list->tail) { +- add_wait_queue(&list->hdev->debug_wait, &wait); +- set_current_state(TASK_INTERRUPTIBLE); +- +- while (list->head == list->tail) { +- if (file->f_flags & O_NONBLOCK) { +- ret = -EAGAIN; +- break; +- } +- if (signal_pending(current)) { +- ret = -ERESTARTSYS; +- break; +- } +- +- if (!list->hdev || !list->hdev->debug) { +- ret = -EIO; +- set_current_state(TASK_RUNNING); +- goto out; +- } +- +- /* allow O_NONBLOCK from other threads */ +- mutex_unlock(&list->read_mutex); +- schedule(); +- mutex_lock(&list->read_mutex); +- set_current_state(TASK_INTERRUPTIBLE); ++ if (kfifo_is_empty(&list->hid_debug_fifo)) { ++ add_wait_queue(&list->hdev->debug_wait, &wait); ++ set_current_state(TASK_INTERRUPTIBLE); ++ ++ while (kfifo_is_empty(&list->hid_debug_fifo)) { ++ if (file->f_flags & O_NONBLOCK) { ++ ret = -EAGAIN; ++ break; + } + +- set_current_state(TASK_RUNNING); +- remove_wait_queue(&list->hdev->debug_wait, &wait); +- } +- +- if (ret) +- goto out; +- +- /* pass the ringbuffer contents to userspace */ +-copy_rest: +- if (list->tail == list->head) +- goto out; +- if (list->tail > list->head) { +- len = list->tail - list->head; +- if (len > count) +- len = count; +- +- if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) { +- ret = -EFAULT; +- goto out; ++ if (signal_pending(current)) { ++ ret = -ERESTARTSYS; ++ break; + } +- ret += len; +- list->head += len; +- } else { +- len = HID_DEBUG_BUFSIZE - list->head; +- if (len > count) +- len = count; + +- if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) { +- ret = -EFAULT; ++ /* if list->hdev is NULL we cannot remove_wait_queue(). ++ * if list->hdev->debug is 0 then hid_debug_unregister() ++ * was already called and list->hdev is being destroyed. ++ * if we add remove_wait_queue() here we can hit a race. ++ */ ++ if (!list->hdev || !list->hdev->debug) { ++ ret = -EIO; ++ set_current_state(TASK_RUNNING); + goto out; + } +- list->head = 0; +- ret += len; +- count -= len; +- if (count > 0) +- goto copy_rest; ++ ++ /* allow O_NONBLOCK from other threads */ ++ mutex_unlock(&list->read_mutex); ++ schedule(); ++ mutex_lock(&list->read_mutex); ++ set_current_state(TASK_INTERRUPTIBLE); + } + ++ __set_current_state(TASK_RUNNING); ++ remove_wait_queue(&list->hdev->debug_wait, &wait); ++ ++ if (ret) ++ goto out; + } ++ ++ /* pass the fifo content to userspace, locking is not needed with only ++ * one concurrent reader and one concurrent writer ++ */ ++ ret = kfifo_to_user(&list->hid_debug_fifo, buffer, count, &copied); ++ if (ret) ++ goto out; ++ ret = copied; + out: + mutex_unlock(&list->read_mutex); + return ret; +@@ -1190,7 +1165,7 @@ static __poll_t hid_debug_events_poll(st + struct hid_debug_list *list = file->private_data; + + poll_wait(file, &list->hdev->debug_wait, wait); +- if (list->head != list->tail) ++ if (!kfifo_is_empty(&list->hid_debug_fifo)) + return EPOLLIN | EPOLLRDNORM; + if (!list->hdev->debug) + return EPOLLERR | EPOLLHUP; +@@ -1205,7 +1180,7 @@ static int hid_debug_events_release(stru + spin_lock_irqsave(&list->hdev->debug_list_lock, flags); + list_del(&list->node); + spin_unlock_irqrestore(&list->hdev->debug_list_lock, flags); +- kfree(list->hid_debug_buf); ++ kfifo_free(&list->hid_debug_fifo); + kfree(list); + + return 0; +@@ -1256,4 +1231,3 @@ void hid_debug_exit(void) + { + debugfs_remove_recursive(hid_debug_root); + } +- +--- a/include/linux/hid-debug.h ++++ b/include/linux/hid-debug.h +@@ -24,7 +24,10 @@ + + #ifdef CONFIG_DEBUG_FS + ++#include ++ + #define HID_DEBUG_BUFSIZE 512 ++#define HID_DEBUG_FIFOSIZE 512 + + void hid_dump_input(struct hid_device *, struct hid_usage *, __s32); + void hid_dump_report(struct hid_device *, int , u8 *, int); +@@ -37,11 +40,8 @@ void hid_debug_init(void); + void hid_debug_exit(void); + void hid_debug_event(struct hid_device *, char *); + +- + struct hid_debug_list { +- char *hid_debug_buf; +- int head; +- int tail; ++ DECLARE_KFIFO_PTR(hid_debug_fifo, char); + struct fasync_struct *fasync; + struct hid_device *hdev; + struct list_head node; +@@ -64,4 +64,3 @@ struct hid_debug_list { + #endif + + #endif +- diff --git a/queue-4.20/series b/queue-4.20/series index 4d3c21d6446..71c1ddf5a50 100644 --- a/queue-4.20/series +++ b/queue-4.20/series @@ -310,3 +310,15 @@ net-cls_flower-remove-filter-from-mask-before-freeing-it.patch net-dsa-b53-fix-for-failure-when-irq-is-not-defined-in-dt.patch net-mlx5e-use-the-inner-headers-to-determine-tc-pedit-offload-limitation-on-decap-flows.patch net-mlx5e-force-checksum_unnecessary-for-short-ethernet-frames.patch +xfs-eof-trim-writeback-mapping-as-soon-as-it-is-cached.patch +alsa-compress-fix-stop-handling-on-compressed-capture-streams.patch +alsa-usb-audio-add-support-for-new-t-a-usb-dac.patch +alsa-hda-serialize-codec-registrations.patch +alsa-hda-realtek-fix-lose-hp_pins-for-disable-auto-mute.patch +alsa-hda-realtek-use-a-common-helper-for-hp-pin-reference.patch +alsa-hda-realtek-headset-microphone-support-for-system76-darp5.patch +fuse-call-pipe_buf_release-under-pipe-lock.patch +fuse-decrement-nr_writeback_temp-on-the-right-page.patch +fuse-handle-zero-sized-retrieve-correctly.patch +cuse-fix-ioctl.patch +hid-debug-fix-the-ring-buffer-implementation.patch diff --git a/queue-4.20/xfs-eof-trim-writeback-mapping-as-soon-as-it-is-cached.patch b/queue-4.20/xfs-eof-trim-writeback-mapping-as-soon-as-it-is-cached.patch new file mode 100644 index 00000000000..bcb8fa4c997 --- /dev/null +++ b/queue-4.20/xfs-eof-trim-writeback-mapping-as-soon-as-it-is-cached.patch @@ -0,0 +1,64 @@ +From aa6ee4ab69293969867ab09b57546d226ace3d7a Mon Sep 17 00:00:00 2001 +From: Brian Foster +Date: Fri, 1 Feb 2019 09:36:36 -0800 +Subject: xfs: eof trim writeback mapping as soon as it is cached + +From: Brian Foster + +commit aa6ee4ab69293969867ab09b57546d226ace3d7a upstream. + +The cached writeback mapping is EOF trimmed to try and avoid races +between post-eof block management and writeback that result in +sending cached data to a stale location. The cached mapping is +currently trimmed on the validation check, which leaves a race +window between the time the mapping is cached and when it is trimmed +against the current inode size. + +For example, if a new mapping is cached by delalloc conversion on a +blocksize == page size fs, we could cycle various locks, perform +memory allocations, etc. in the writeback codepath before the +associated mapping is eventually trimmed to i_size. This leaves +enough time for a post-eof truncate and file append before the +cached mapping is trimmed. The former event essentially invalidates +a range of the cached mapping and the latter bumps the inode size +such the trim on the next writepage event won't trim all of the +invalid blocks. fstest generic/464 reproduces this scenario +occasionally and causes a lost writeback and stale delalloc blocks +warning on inode inactivation. + +To work around this problem, trim the cached writeback mapping as +soon as it is cached in addition to on subsequent validation checks. +This is a minor tweak to tighten the race window as much as possible +until a proper invalidation mechanism is available. + +Fixes: 40214d128e07 ("xfs: trim writepage mapping to within eof") +Cc: # v4.14+ +Signed-off-by: Brian Foster +Reviewed-by: Allison Henderson +Reviewed-by: Christoph Hellwig +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman + +--- + fs/xfs/xfs_aops.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/xfs/xfs_aops.c ++++ b/fs/xfs/xfs_aops.c +@@ -449,6 +449,7 @@ xfs_map_blocks( + } + + wpc->imap = imap; ++ xfs_trim_extent_eof(&wpc->imap, ip); + trace_xfs_map_blocks_found(ip, offset, count, wpc->io_type, &imap); + return 0; + allocate_blocks: +@@ -459,6 +460,7 @@ allocate_blocks: + ASSERT(whichfork == XFS_COW_FORK || cow_fsb == NULLFILEOFF || + imap.br_startoff + imap.br_blockcount <= cow_fsb); + wpc->imap = imap; ++ xfs_trim_extent_eof(&wpc->imap, ip); + trace_xfs_map_blocks_alloc(ip, offset, count, wpc->io_type, &imap); + return 0; + }