From 4cc2ad094557e15955b0e000cc827bc1e11d86cd Mon Sep 17 00:00:00 2001 From: bouhaa Date: Wed, 13 Sep 2023 19:40:57 +0200 Subject: [PATCH] linux 6.5.3-chos1 --- ...nd-CONFIG-to-disallow-unprivileged-C.patch | 8 +- ...-skip-simpledrm-if-nvidia-drm.modese.patch | 4 +- ...y-Convert-outdir-to-str-before-using.patch | 33 +++ ...SoC-Intel-soc-acpi-fix-Dell-SKU-0B34.patch | 51 ++++ ...cached-block-groups-on-every-allocat.patch | 255 ++++++++++++++++++ ...ir-index-to-the-current-last-index-w.patch | 86 ++++++ ...r-last-index-during-a-rewinddir-3-ca.patch | 102 +++++++ ...etween-reading-a-directory-and-addin.patch | 143 ++++++++++ linux/PKGBUILD | 28 +- linux/config | 9 +- 10 files changed, 696 insertions(+), 23 deletions(-) create mode 100644 linux/0003-sphinx-kfigure.py-Convert-outdir-to-str-before-using.patch create mode 100644 linux/0004-ASoC-Intel-soc-acpi-fix-Dell-SKU-0B34.patch create mode 100644 linux/0005-btrfs-wait-on-uncached-block-groups-on-every-allocat.patch create mode 100644 linux/0006-btrfs-set-last-dir-index-to-the-current-last-index-w.patch create mode 100644 linux/0007-btrfs-refresh-dir-last-index-during-a-rewinddir-3-ca.patch create mode 100644 linux/0008-btrfs-fix-race-between-reading-a-directory-and-addin.patch diff --git a/linux/0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch b/linux/0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch index 7df735f..aa5ec1a 100644 --- a/linux/0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch +++ b/linux/0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch @@ -1,7 +1,7 @@ -From 8659d263820b50c42036dd38fff16e0f6852575d Mon Sep 17 00:00:00 2001 +From 92b8cd4f582347e53163d544db15d20f563d1c17 Mon Sep 17 00:00:00 2001 From: "Jan Alexander Steffens (heftig)" Date: Mon, 16 Sep 2019 04:53:20 +0200 -Subject: [PATCH 1/6] ZEN: Add sysctl and CONFIG to disallow unprivileged +Subject: [PATCH 1/8] ZEN: Add sysctl and CONFIG to disallow unprivileged CLONE_NEWUSER Our default behavior continues to match the vanilla kernel. @@ -36,10 +36,10 @@ index 45f09bec02c48..87b20e2ee2744 100644 { return &init_user_ns; diff --git a/init/Kconfig b/init/Kconfig -index f7f65af4ee129..c2ecb3bb33928 100644 +index 5e7d4885d1bf8..13ad937752373 100644 --- a/init/Kconfig +++ b/init/Kconfig -@@ -1225,6 +1225,22 @@ config USER_NS +@@ -1226,6 +1226,22 @@ config USER_NS If unsure, say N. diff --git a/linux/0002-drivers-firmware-skip-simpledrm-if-nvidia-drm.modese.patch b/linux/0002-drivers-firmware-skip-simpledrm-if-nvidia-drm.modese.patch index a73ca59..1f518e6 100644 --- a/linux/0002-drivers-firmware-skip-simpledrm-if-nvidia-drm.modese.patch +++ b/linux/0002-drivers-firmware-skip-simpledrm-if-nvidia-drm.modese.patch @@ -1,7 +1,7 @@ -From f0d16bed34435cef3908134d6af13aee7793cfdc Mon Sep 17 00:00:00 2001 +From 5e9d8dd3971972048485610161c2556a7608849e Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 19 May 2022 14:40:07 +0200 -Subject: [PATCH 2/6] drivers/firmware: skip simpledrm if nvidia-drm.modeset=1 +Subject: [PATCH 2/8] drivers/firmware: skip simpledrm if nvidia-drm.modeset=1 is set The Nvidia proprietary driver has some bugs that leads to issues if used diff --git a/linux/0003-sphinx-kfigure.py-Convert-outdir-to-str-before-using.patch b/linux/0003-sphinx-kfigure.py-Convert-outdir-to-str-before-using.patch new file mode 100644 index 0000000..3ec7388 --- /dev/null +++ b/linux/0003-sphinx-kfigure.py-Convert-outdir-to-str-before-using.patch @@ -0,0 +1,33 @@ +From 37d1bd4999f06c7c4b3094cb74b7614c552ecc1d Mon Sep 17 00:00:00 2001 +From: "Jan Alexander Steffens (heftig)" +Date: Thu, 24 Aug 2023 01:28:17 +0200 +Subject: [PATCH 3/8] sphinx: kfigure.py: Convert outdir to str before using + len + +Sphinx 7.2 replaced several uses of str with pathlib Paths, causing the +build to fail with a TypeError when attempting to use len on one. + +Patch by @loqs; thanks. + +Fixes: https://bugs.archlinux.org/task/79446 +Signed-off-by: Jan Alexander Steffens (heftig) +--- + Documentation/sphinx/kfigure.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Documentation/sphinx/kfigure.py b/Documentation/sphinx/kfigure.py +index cefdbb7e75230..13e885bbd499c 100644 +--- a/Documentation/sphinx/kfigure.py ++++ b/Documentation/sphinx/kfigure.py +@@ -309,7 +309,7 @@ def convert_image(img_node, translator, src_fname=None): + if dst_fname: + # the builder needs not to copy one more time, so pop it if exists. + translator.builder.images.pop(img_node['uri'], None) +- _name = dst_fname[len(translator.builder.outdir) + 1:] ++ _name = dst_fname[len(str(translator.builder.outdir)) + 1:] + + if isNewer(dst_fname, src_fname): + kernellog.verbose(app, +-- +2.41.0 + diff --git a/linux/0004-ASoC-Intel-soc-acpi-fix-Dell-SKU-0B34.patch b/linux/0004-ASoC-Intel-soc-acpi-fix-Dell-SKU-0B34.patch new file mode 100644 index 0000000..1a6234f --- /dev/null +++ b/linux/0004-ASoC-Intel-soc-acpi-fix-Dell-SKU-0B34.patch @@ -0,0 +1,51 @@ +From eb39b2a95930f53bd2cb4fbda0e1372609dff976 Mon Sep 17 00:00:00 2001 +From: Pierre-Louis Bossart +Date: Tue, 5 Sep 2023 11:16:16 -0400 +Subject: [PATCH 4/8] ASoC: Intel: soc-acpi: fix Dell SKU 0B34 + +The rule for the SoundWire tables is that the platforms with more +devices need to be added first. We broke that rule with the Dell SKU +0B34, and caused the second amplifier for SKU 0AF3 to be ignored. + +The fix is simple, we need to move the single-amplifier entry after +the two-amplifier one. + +Fixes: b62a1a839b48 ("ASoC: Intel: soc-acpi: add tables for Dell SKU 0B34") +Closes: https://github.com/thesofproject/linux/issues/4559 +Signed-off-by: Pierre-Louis Bossart +--- + sound/soc/intel/common/soc-acpi-intel-adl-match.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c +index bcd66e0094b4b..c4b57cca6b228 100644 +--- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c ++++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c +@@ -648,18 +648,18 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[] = { + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-adl-rt1316-l2-mono-rt714-l3.tplg", + }, +- { +- .link_mask = 0x3, /* rt1316 on link1 & rt714 on link0 */ +- .links = adl_sdw_rt1316_link1_rt714_link0, +- .drv_name = "sof_sdw", +- .sof_tplg_filename = "sof-adl-rt1316-l1-mono-rt714-l0.tplg", +- }, + { + .link_mask = 0x7, /* rt714 on link0 & two rt1316s on link1 and link2 */ + .links = adl_sdw_rt1316_link12_rt714_link0, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-adl-rt1316-l12-rt714-l0.tplg", + }, ++ { ++ .link_mask = 0x3, /* rt1316 on link1 & rt714 on link0 */ ++ .links = adl_sdw_rt1316_link1_rt714_link0, ++ .drv_name = "sof_sdw", ++ .sof_tplg_filename = "sof-adl-rt1316-l1-mono-rt714-l0.tplg", ++ }, + { + .link_mask = 0x5, /* 2 active links required */ + .links = adl_sdw_rt1316_link2_rt714_link0, +-- +2.41.0 + diff --git a/linux/0005-btrfs-wait-on-uncached-block-groups-on-every-allocat.patch b/linux/0005-btrfs-wait-on-uncached-block-groups-on-every-allocat.patch new file mode 100644 index 0000000..493337c --- /dev/null +++ b/linux/0005-btrfs-wait-on-uncached-block-groups-on-every-allocat.patch @@ -0,0 +1,255 @@ +From 8da079307d115705e243d226591dcb4388cef7e2 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Mon, 31 Jul 2023 16:28:43 -0400 +Subject: [PATCH 5/8] btrfs: wait on uncached block groups on every allocation + loop + +My initial fix for the generic/475 hangs was related to metadata, but +our CI testing uncovered another case where we hang for similar reasons. +We again have a task with a plug that is holding an outstanding request +that is keeping the dm device from finishing it's suspend, and that task +is stuck in the allocator. + +This time it is stuck trying to allocate data, but we do not have a +block group that matches the size class. The larger loop in the +allocator looks like this (simplified of course) + + find_free_extent + for_each_block_group { + ffe_ctl->cached == btrfs_block_group_cache_done(bg) + if (!ffe_ctl->cached) + ffe_ctl->have_caching_bg = true; + do_allocation() + btrfs_wait_block_group_cache_progress(); + } + + if (loop == LOOP_CACHING_WAIT && ffe_ctl->have_caching_bg) + go search again; + +In my earlier fix we were trying to allocate from the block group, but +we weren't waiting for the progress because we were only waiting for the +free space to be >= the amount of free space we wanted. My fix made it +so we waited for forward progress to be made as well, so we would be +sure to wait. + +This time however we did not have a block group that matched our size +class, so what was happening was this + + find_free_extent + for_each_block_group { + ffe_ctl->cached == btrfs_block_group_cache_done(bg) + if (!ffe_ctl->cached) + ffe_ctl->have_caching_bg = true; + if (size_class_doesn't_match()) + goto loop; + do_allocation() + btrfs_wait_block_group_cache_progress(); + loop: + release_block_group(block_group); + } + + if (loop == LOOP_CACHING_WAIT && ffe_ctl->have_caching_bg) + go search again; + +The size_class_doesn't_match() part was true, so we'd just skip this +block group and never wait for caching, and then because we found a +caching block group we'd just go back and do the loop again. We never +sleep and thus never flush the plug and we have the same deadlock. + +Fix the logic for waiting on the block group caching to instead do it +unconditionally when we goto loop. This takes the logic out of the +allocation step, so now the loop looks more like this + + find_free_extent + for_each_block_group { + ffe_ctl->cached == btrfs_block_group_cache_done(bg) + if (!ffe_ctl->cached) + ffe_ctl->have_caching_bg = true; + if (size_class_doesn't_match()) + goto loop; + do_allocation() + btrfs_wait_block_group_cache_progress(); + loop: + if (loop > LOOP_CACHING_NOWAIT && !ffe_ctl->retry_uncached && + !ffe_ctl->cached) { + ffe_ctl->retry_uncached = true; + btrfs_wait_block_group_cache_progress(); + } + + release_block_group(block_group); + } + + if (loop == LOOP_CACHING_WAIT && ffe_ctl->have_caching_bg) + go search again; + +This simplifies the logic a lot, and makes sure that if we're hitting +uncached block groups we're always waiting on them at some point. + +I ran this through 100 iterations of generic/475, as this particular +case was harder to hit than the previous one. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +--- + fs/btrfs/extent-tree.c | 61 +++++++++++++----------------------------- + fs/btrfs/extent-tree.h | 13 +++------ + 2 files changed, 22 insertions(+), 52 deletions(-) + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index f396a9afa4032..6096bd98e6c70 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -3427,7 +3427,6 @@ btrfs_release_block_group(struct btrfs_block_group *cache, + * Helper function for find_free_extent(). + * + * Return -ENOENT to inform caller that we need fallback to unclustered mode. +- * Return -EAGAIN to inform caller that we need to re-search this block group + * Return >0 to inform caller that we find nothing + * Return 0 means we have found a location and set ffe_ctl->found_offset. + */ +@@ -3508,14 +3507,6 @@ static int find_free_extent_clustered(struct btrfs_block_group *bg, + trace_btrfs_reserve_extent_cluster(bg, ffe_ctl); + return 0; + } +- } else if (!ffe_ctl->cached && ffe_ctl->loop > LOOP_CACHING_NOWAIT && +- !ffe_ctl->retry_clustered) { +- spin_unlock(&last_ptr->refill_lock); +- +- ffe_ctl->retry_clustered = true; +- btrfs_wait_block_group_cache_progress(bg, ffe_ctl->num_bytes + +- ffe_ctl->empty_cluster + ffe_ctl->empty_size); +- return -EAGAIN; + } + /* + * At this point we either didn't find a cluster or we weren't able to +@@ -3530,7 +3521,6 @@ static int find_free_extent_clustered(struct btrfs_block_group *bg, + /* + * Return >0 to inform caller that we find nothing + * Return 0 when we found an free extent and set ffe_ctrl->found_offset +- * Return -EAGAIN to inform caller that we need to re-search this block group + */ + static int find_free_extent_unclustered(struct btrfs_block_group *bg, + struct find_free_extent_ctl *ffe_ctl) +@@ -3568,25 +3558,8 @@ static int find_free_extent_unclustered(struct btrfs_block_group *bg, + offset = btrfs_find_space_for_alloc(bg, ffe_ctl->search_start, + ffe_ctl->num_bytes, ffe_ctl->empty_size, + &ffe_ctl->max_extent_size); +- +- /* +- * If we didn't find a chunk, and we haven't failed on this block group +- * before, and this block group is in the middle of caching and we are +- * ok with waiting, then go ahead and wait for progress to be made, and +- * set @retry_unclustered to true. +- * +- * If @retry_unclustered is true then we've already waited on this +- * block group once and should move on to the next block group. +- */ +- if (!offset && !ffe_ctl->retry_unclustered && !ffe_ctl->cached && +- ffe_ctl->loop > LOOP_CACHING_NOWAIT) { +- btrfs_wait_block_group_cache_progress(bg, ffe_ctl->num_bytes + +- ffe_ctl->empty_size); +- ffe_ctl->retry_unclustered = true; +- return -EAGAIN; +- } else if (!offset) { ++ if (!offset) + return 1; +- } + ffe_ctl->found_offset = offset; + return 0; + } +@@ -3600,7 +3573,7 @@ static int do_allocation_clustered(struct btrfs_block_group *block_group, + /* We want to try and use the cluster allocator, so lets look there */ + if (ffe_ctl->last_ptr && ffe_ctl->use_cluster) { + ret = find_free_extent_clustered(block_group, ffe_ctl, bg_ret); +- if (ret >= 0 || ret == -EAGAIN) ++ if (ret >= 0) + return ret; + /* ret == -ENOENT case falls through */ + } +@@ -3816,8 +3789,7 @@ static void release_block_group(struct btrfs_block_group *block_group, + { + switch (ffe_ctl->policy) { + case BTRFS_EXTENT_ALLOC_CLUSTERED: +- ffe_ctl->retry_clustered = false; +- ffe_ctl->retry_unclustered = false; ++ ffe_ctl->retry_uncached = false; + break; + case BTRFS_EXTENT_ALLOC_ZONED: + /* Nothing to do */ +@@ -4168,9 +4140,7 @@ static noinline int find_free_extent(struct btrfs_root *root, + ffe_ctl->orig_have_caching_bg = false; + ffe_ctl->index = btrfs_bg_flags_to_raid_index(ffe_ctl->flags); + ffe_ctl->loop = 0; +- /* For clustered allocation */ +- ffe_ctl->retry_clustered = false; +- ffe_ctl->retry_unclustered = false; ++ ffe_ctl->retry_uncached = false; + ffe_ctl->cached = 0; + ffe_ctl->max_extent_size = 0; + ffe_ctl->total_free_space = 0; +@@ -4321,16 +4291,12 @@ static noinline int find_free_extent(struct btrfs_root *root, + + bg_ret = NULL; + ret = do_allocation(block_group, ffe_ctl, &bg_ret); +- if (ret == 0) { +- if (bg_ret && bg_ret != block_group) { +- btrfs_release_block_group(block_group, +- ffe_ctl->delalloc); +- block_group = bg_ret; +- } +- } else if (ret == -EAGAIN) { +- goto have_block_group; +- } else if (ret > 0) { ++ if (ret > 0) + goto loop; ++ ++ if (bg_ret && bg_ret != block_group) { ++ btrfs_release_block_group(block_group, ffe_ctl->delalloc); ++ block_group = bg_ret; + } + + /* Checks */ +@@ -4371,6 +4337,15 @@ static noinline int find_free_extent(struct btrfs_root *root, + btrfs_release_block_group(block_group, ffe_ctl->delalloc); + break; + loop: ++ if (!ffe_ctl->cached && ffe_ctl->loop > LOOP_CACHING_NOWAIT && ++ !ffe_ctl->retry_uncached) { ++ ffe_ctl->retry_uncached = true; ++ btrfs_wait_block_group_cache_progress(block_group, ++ ffe_ctl->num_bytes + ++ ffe_ctl->empty_cluster + ++ ffe_ctl->empty_size); ++ goto have_block_group; ++ } + release_block_group(block_group, ffe_ctl, ffe_ctl->delalloc); + cond_resched(); + } +diff --git a/fs/btrfs/extent-tree.h b/fs/btrfs/extent-tree.h +index 429d5c5700618..6bfba2f22fdd4 100644 +--- a/fs/btrfs/extent-tree.h ++++ b/fs/btrfs/extent-tree.h +@@ -48,16 +48,11 @@ struct find_free_extent_ctl { + int loop; + + /* +- * Whether we're refilling a cluster, if true we need to re-search +- * current block group but don't try to refill the cluster again. ++ * Set to true if we're retrying the allocation on this block group ++ * after waiting for caching progress, this is so that we retry only ++ * once before moving on to another block group. + */ +- bool retry_clustered; +- +- /* +- * Whether we're updating free space cache, if true we need to re-search +- * current block group but don't try updating free space cache again. +- */ +- bool retry_unclustered; ++ bool retry_uncached; + + /* If current block group is cached */ + int cached; +-- +2.41.0 + diff --git a/linux/0006-btrfs-set-last-dir-index-to-the-current-last-index-w.patch b/linux/0006-btrfs-set-last-dir-index-to-the-current-last-index-w.patch new file mode 100644 index 0000000..c0cbc0f --- /dev/null +++ b/linux/0006-btrfs-set-last-dir-index-to-the-current-last-index-w.patch @@ -0,0 +1,86 @@ +From c8026dde1f99ec4f682765aaac7993a964184a15 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Sat, 9 Sep 2023 11:34:40 +0100 +Subject: [PATCH 6/8] btrfs: set last dir index to the current last index when + opening dir + +When opening a directory for reading it, we set the last index where we +stop iteration to the value in struct btrfs_inode::index_cnt. That value +does not match the index of the most recently added directory entry but +it's instead the index number that will be assigned the next directory +entry. + +This means that if after the call to opendir(3) new directory entries are +added, a readdir(3) call will return the first new directory entry. This +is fine because POSIX says the following [1]: + + "If a file is removed from or added to the directory after the most + recent call to opendir() or rewinddir(), whether a subsequent call to + readdir() returns an entry for that file is unspecified." + +For example for the test script from commit 9b378f6ad48c ("btrfs: fix +infinite directory reads"), where we have 2000 files in a directory, ext4 +doesn't return any new directory entry after opendir(3), while xfs returns +the first 13 new directory entries added after the opendir(3) call. + +If we move to a shorter example with an empty directory when opendir(3) is +called, and 2 files added to the directory after the opendir(3) call, then +readdir(3) on btrfs will return the first file, ext4 and xfs return the 2 +files (but in a different order). A test program for this, reported by +Ian Johnson, is the following: + + #include + #include + + int main(void) { + DIR *dir = opendir("test"); + + FILE *file; + file = fopen("test/1", "w"); + fwrite("1", 1, 1, file); + fclose(file); + + file = fopen("test/2", "w"); + fwrite("2", 1, 1, file); + fclose(file); + + struct dirent *entry; + while ((entry = readdir(dir))) { + printf("%s\n", entry->d_name); + } + closedir(dir); + return 0; + } + +To make this less odd, change the behaviour to never return new entries +that were added after the opendir(3) call. This is done by setting the +last_index field of the struct btrfs_file_private attached to the +directory's file handle with a value matching btrfs_inode::index_cnt +minus 1, since that value always matches the index of the next new +directory entry and not the index of the most recently added entry. + +[1] https://pubs.opengroup.org/onlinepubs/007904875/functions/readdir_r.html + +Link: https://lore.kernel.org/linux-btrfs/YR1P0S.NGASEG570GJ8@ianjohnson.dev/ +Signed-off-by: Filipe Manana +--- + fs/btrfs/inode.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index aa090b0b5d298..e3a52438f4f1f 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -5935,7 +5935,8 @@ static int btrfs_get_dir_last_index(struct btrfs_inode *dir, u64 *index) + } + } + +- *index = dir->index_cnt; ++ /* index_cnt is the index number of next new entry, so decrement it. */ ++ *index = dir->index_cnt - 1; + + return 0; + } +-- +2.41.0 + diff --git a/linux/0007-btrfs-refresh-dir-last-index-during-a-rewinddir-3-ca.patch b/linux/0007-btrfs-refresh-dir-last-index-during-a-rewinddir-3-ca.patch new file mode 100644 index 0000000..6218aa7 --- /dev/null +++ b/linux/0007-btrfs-refresh-dir-last-index-during-a-rewinddir-3-ca.patch @@ -0,0 +1,102 @@ +From f2e0f18c8bd9c6d61575a2311d488e21831e1163 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Sat, 9 Sep 2023 12:12:14 +0100 +Subject: [PATCH 7/8] btrfs: refresh dir last index during a rewinddir(3) call + +When opening a directory we find what's the index of its last entry and +then store it in the directory's file handle private data (struct +btrfs_file_private::last_index), so that in the case new directory entries +are added to a directory after an opendir(3) call we don't end up in an +infinite loop (see commit 9b378f6ad48c ("btrfs: fix infinite directory +reads")) when calling readdir(3). + +However once rewinddir(3) is called, POSIX states [1] that any new +directory entries added after the previous opendir(3) call, must be +returned by subsequent calls to readdir(3): + + "The rewinddir() function shall reset the position of the directory + stream to which dirp refers to the beginning of the directory. + It shall also cause the directory stream to refer to the current + state of the corresponding directory, as a call to opendir() would + have done." + +We currently don't refresh the last_index field of the struct +btrfs_file_private associated to the directory, so after a rewinddir(3) +we are not returning any new entries added after the opendir(3) call. + +Fix this by finding the current last index of the directory when llseek +is called agains the directory. + +This can be reproduced by the following C program provided by Ian Johnson: + + #include + #include + + int main(void) { + DIR *dir = opendir("test"); + + FILE *file; + file = fopen("test/1", "w"); + fwrite("1", 1, 1, file); + fclose(file); + + file = fopen("test/2", "w"); + fwrite("2", 1, 1, file); + fclose(file); + + rewinddir(dir); + + struct dirent *entry; + while ((entry = readdir(dir))) { + printf("%s\n", entry->d_name); + } + closedir(dir); + return 0; + } + +[1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/rewinddir.html + +Reported-by: Ian Johnson +Link: https://lore.kernel.org/linux-btrfs/YR1P0S.NGASEG570GJ8@ianjohnson.dev/ +Fixes: 9b378f6ad48c ("btrfs: fix infinite directory reads") +Signed-off-by: Filipe Manana +--- + fs/btrfs/inode.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index e3a52438f4f1f..a50cbcafca03c 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -5973,6 +5973,19 @@ static int btrfs_opendir(struct inode *inode, struct file *file) + return 0; + } + ++static loff_t btrfs_dir_llseek(struct file *file, loff_t offset, int whence) ++{ ++ struct btrfs_file_private *private = file->private_data; ++ int ret; ++ ++ ret = btrfs_get_dir_last_index(BTRFS_I(file_inode(file)), ++ &private->last_index); ++ if (ret) ++ return ret; ++ ++ return generic_file_llseek(file, offset, whence); ++} ++ + struct dir_entry { + u64 ino; + u64 offset; +@@ -11053,7 +11066,7 @@ static const struct inode_operations btrfs_dir_inode_operations = { + }; + + static const struct file_operations btrfs_dir_file_operations = { +- .llseek = generic_file_llseek, ++ .llseek = btrfs_dir_llseek, + .read = generic_read_dir, + .iterate_shared = btrfs_real_readdir, + .open = btrfs_opendir, +-- +2.41.0 + diff --git a/linux/0008-btrfs-fix-race-between-reading-a-directory-and-addin.patch b/linux/0008-btrfs-fix-race-between-reading-a-directory-and-addin.patch new file mode 100644 index 0000000..7da77c9 --- /dev/null +++ b/linux/0008-btrfs-fix-race-between-reading-a-directory-and-addin.patch @@ -0,0 +1,143 @@ +From 5c640491ba9cea8c0a01144db26b2c8892506717 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Tue, 12 Sep 2023 11:45:39 +0100 +Subject: [PATCH 8/8] btrfs: fix race between reading a directory and adding + entries to it + +When opening a directory (opendir(3)) or rewinding it (rewinddir(3)), we +are not holding the directory's inode locked, and this can result in later +attempting to add two entries to the directory with the same index number, +resulting in a transaction abort, with -EEXIST (-17), when inserting the +second delayed dir index. This results in a trace like the following: + + Sep 11 22:34:59 myhostname kernel: BTRFS error (device dm-3): err add delayed dir index item(name: cockroach-stderr.log) into the insertion tree of the delayed node(root id: 5, inode id: 4539217, errno: -17) + Sep 11 22:34:59 myhostname kernel: ------------[ cut here ]------------ + Sep 11 22:34:59 myhostname kernel: kernel BUG at fs/btrfs/delayed-inode.c:1504! + Sep 11 22:34:59 myhostname kernel: invalid opcode: 0000 [#1] PREEMPT SMP NOPTI + Sep 11 22:34:59 myhostname kernel: CPU: 0 PID: 7159 Comm: cockroach Not tainted 6.4.15-200.fc38.x86_64 #1 + Sep 11 22:34:59 myhostname kernel: Hardware name: ASUS ESC500 G3/P9D WS, BIOS 2402 06/27/2018 + Sep 11 22:34:59 myhostname kernel: RIP: 0010:btrfs_insert_delayed_dir_index+0x1da/0x260 + Sep 11 22:34:59 myhostname kernel: Code: eb dd 48 (...) + Sep 11 22:34:59 myhostname kernel: RSP: 0000:ffffa9980e0fbb28 EFLAGS: 00010282 + Sep 11 22:34:59 myhostname kernel: RAX: 0000000000000000 RBX: ffff8b10b8f4a3c0 RCX: 0000000000000000 + Sep 11 22:34:59 myhostname kernel: RDX: 0000000000000000 RSI: ffff8b177ec21540 RDI: ffff8b177ec21540 + Sep 11 22:34:59 myhostname kernel: RBP: ffff8b110cf80888 R08: 0000000000000000 R09: ffffa9980e0fb938 + Sep 11 22:34:59 myhostname kernel: R10: 0000000000000003 R11: ffffffff86146508 R12: 0000000000000014 + Sep 11 22:34:59 myhostname kernel: R13: ffff8b1131ae5b40 R14: ffff8b10b8f4a418 R15: 00000000ffffffef + Sep 11 22:34:59 myhostname kernel: FS: 00007fb14a7fe6c0(0000) GS:ffff8b177ec00000(0000) knlGS:0000000000000000 + Sep 11 22:34:59 myhostname kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + Sep 11 22:34:59 myhostname kernel: CR2: 000000c00143d000 CR3: 00000001b3b4e002 CR4: 00000000001706f0 + Sep 11 22:34:59 myhostname kernel: Call Trace: + Sep 11 22:34:59 myhostname kernel: + Sep 11 22:34:59 myhostname kernel: ? die+0x36/0x90 + Sep 11 22:34:59 myhostname kernel: ? do_trap+0xda/0x100 + Sep 11 22:34:59 myhostname kernel: ? btrfs_insert_delayed_dir_index+0x1da/0x260 + Sep 11 22:34:59 myhostname kernel: ? do_error_trap+0x6a/0x90 + Sep 11 22:34:59 myhostname kernel: ? btrfs_insert_delayed_dir_index+0x1da/0x260 + Sep 11 22:34:59 myhostname kernel: ? exc_invalid_op+0x50/0x70 + Sep 11 22:34:59 myhostname kernel: ? btrfs_insert_delayed_dir_index+0x1da/0x260 + Sep 11 22:34:59 myhostname kernel: ? asm_exc_invalid_op+0x1a/0x20 + Sep 11 22:34:59 myhostname kernel: ? btrfs_insert_delayed_dir_index+0x1da/0x260 + Sep 11 22:34:59 myhostname kernel: ? btrfs_insert_delayed_dir_index+0x1da/0x260 + Sep 11 22:34:59 myhostname kernel: btrfs_insert_dir_item+0x200/0x280 + Sep 11 22:34:59 myhostname kernel: btrfs_add_link+0xab/0x4f0 + Sep 11 22:34:59 myhostname kernel: ? ktime_get_real_ts64+0x47/0xe0 + Sep 11 22:34:59 myhostname kernel: btrfs_create_new_inode+0x7cd/0xa80 + Sep 11 22:34:59 myhostname kernel: btrfs_symlink+0x190/0x4d0 + Sep 11 22:34:59 myhostname kernel: ? schedule+0x5e/0xd0 + Sep 11 22:34:59 myhostname kernel: ? __d_lookup+0x7e/0xc0 + Sep 11 22:34:59 myhostname kernel: vfs_symlink+0x148/0x1e0 + Sep 11 22:34:59 myhostname kernel: do_symlinkat+0x130/0x140 + Sep 11 22:34:59 myhostname kernel: __x64_sys_symlinkat+0x3d/0x50 + Sep 11 22:34:59 myhostname kernel: do_syscall_64+0x5d/0x90 + Sep 11 22:34:59 myhostname kernel: ? syscall_exit_to_user_mode+0x2b/0x40 + Sep 11 22:34:59 myhostname kernel: ? do_syscall_64+0x6c/0x90 + Sep 11 22:34:59 myhostname kernel: entry_SYSCALL_64_after_hwframe+0x72/0xdc + +The race leading to the problem happens like this: + +1) Directory inode X is loaded into memory, its ->index_cnt field is + initialized to (u64)-1 (at btrfs_alloc_inode()); + +2) Task A is adding a new file to directory X, holding its vfs inode lock, + and calls btrfs_set_inode_index() to get an index number for the entry. + + Because the inode's index_cnt field is set to (u64)-1 it calls + btrfs_inode_delayed_dir_index_count() which fails because no dir index + entries were added yet to the delayed inode and then it calls + btrfs_set_inode_index_count(). This functions finds the last dir index + key and then sets index_cnt to that index value + 1. It found that the + last index key has an offset of 100. However before it assigns a value + of 101 to index_cnt... + +3) Task B calls opendir(3), ending up at btrfs_opendir(), where the vfs + lock for inode X is not taken, so it calls btrfs_get_dir_last_index() + and sees index_cnt still with a value of (u64)-1. Because of that it + calls btrfs_inode_delayed_dir_index_count() which fails since no dir + index entries were added to the delayed inode yet, and then it also + calls btrfs_set_inode_index_count(). This also finds that the last + index key has an offset of 100, and before it assigns the value 101 + to the index_cnt field of inode X... + +4) Task A assigns a value of 101 to index_cnt. And then the code flow + goes to btrfs_set_inode_index() where it increments index_cnt from + 101 to 102. Task A then creates a delayed dir index entry with a + sequence number of 101 and adds it to the delayed inode; + +5) Task B assigns 101 to the index_cnt field of inode X; + +6) At some later point when someone tries to add a new entry to the + directory, btrfs_set_inode_index() will return 101 again and shortly + after an attempt to add another delayed dir index key with index + number 101 will fail with -EEXIST resulting in a transaction abort. + +Fix this by locking the inode at btrfs_get_dir_last_index(), which is only +only used when opening a directory or attempting to lseek on it. + +Reported-by: ken +Link: https://lore.kernel.org/linux-btrfs/CAE6xmH+Lp=Q=E61bU+v9eWX8gYfLvu6jLYxjxjFpo3zHVPR0EQ@mail.gmail.com/ +Reported-by: syzbot+d13490c82ad5353c779d@syzkaller.appspotmail.com +Link: https://lore.kernel.org/linux-btrfs/00000000000036e1290603e097e0@google.com/ +Fixes: 9b378f6ad48c ("btrfs: fix infinite directory reads") +Signed-off-by: Filipe Manana +Cherry-picked-for: https://bugs.archlinux.org/task/79673 +--- + fs/btrfs/inode.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index a50cbcafca03c..0d4196cede7d2 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -5924,21 +5924,24 @@ static int btrfs_set_inode_index_count(struct btrfs_inode *inode) + + static int btrfs_get_dir_last_index(struct btrfs_inode *dir, u64 *index) + { +- if (dir->index_cnt == (u64)-1) { +- int ret; ++ int ret = 0; + ++ btrfs_inode_lock(dir, 0); ++ if (dir->index_cnt == (u64)-1) { + ret = btrfs_inode_delayed_dir_index_count(dir); + if (ret) { + ret = btrfs_set_inode_index_count(dir); + if (ret) +- return ret; ++ goto out; + } + } + + /* index_cnt is the index number of next new entry, so decrement it. */ + *index = dir->index_cnt - 1; ++out: ++ btrfs_inode_unlock(dir, 0); + +- return 0; ++ return ret; + } + + /* +-- +2.41.0 + diff --git a/linux/PKGBUILD b/linux/PKGBUILD index 229ecc9..e7959d3 100644 --- a/linux/PKGBUILD +++ b/linux/PKGBUILD @@ -2,7 +2,7 @@ # Maintainer: Joaquín I. Aramendía (samsagax) pkgbase=linux-chimeraos -pkgver=6.5.2.chos1 +pkgver=6.5.3.chos1 pkgrel=1 pkgdesc='Linux ChimeraOS' _srctag=${pkgver%.*} @@ -37,9 +37,12 @@ source=( # Arch Linux patches 0001-ZEN-Add-sysctl-and-CONFIG-to-disallow-unprivileged-C.patch 0002-drivers-firmware-skip-simpledrm-if-nvidia-drm.modese.patch - 0003-tpm-Enable-hwrng-only-for-Pluton-on-AMD-CPUs.patch - 0004-sphinx-kfigure.py-Convert-outdir-to-str-before-using.patch - 0005-Revert-ASoC-Intel-soc-acpi-add-tables-for-Dell-SKU-0.patch + 0003-sphinx-kfigure.py-Convert-outdir-to-str-before-using.patch + 0004-ASoC-Intel-soc-acpi-fix-Dell-SKU-0B34.patch + 0005-btrfs-wait-on-uncached-block-groups-on-every-allocat.patch + 0006-btrfs-set-last-dir-index-to-the-current-last-index-w.patch + 0007-btrfs-refresh-dir-last-index-during-a-rewinddir-3-ca.patch + 0008-btrfs-fix-race-between-reading-a-directory-and-addin.patch # ChimeraOS specific patches # Some patches from TKG Team @@ -85,14 +88,17 @@ validpgpkeys=( A2FF3A36AAA56654109064AB19802F8B0D70FC30 # Jan Alexander Steffens (heftig) C7E7849466FE2358343588377258734B41C31549 # David Runge ) -b2sums=('74a4f998987780001e924e28f8a3f585cd50da9d87d120bcb33fe1fd4fccccc2301fbc3c84c62e914e4694b5eb138e33cacda515db51d5a3997d114154449be3' - 'd062b02a97b7d8ea58c6020ee5f45136941cc4c19b4f08befb1f63da5b8f8e99b90b75386ef56633b8571919697b985df4099c951785e1029acf63abbf15b43c' +b2sums=('7673a5375b0a715eca2dcff5b4f6fca13c8564a930b3b7ee112b67ed51541277378408abed1e1b128610f0db3425abbb30cd3751ce30ff73795cf594fb508142' + '07152aa6ad7b89d583cfd9cf97f4d56cb8d5b46385fd818861b10ad11a964370cc4bc334bd275ff0f4610c006d8b7dc51bf4ca63dfe64301e7196f2a745b4416' 'b1653bee12c29f1d6b183d4365542ed05b4a1309f76e6722dd1cbce784e771979e655e0ceeb0ca89cd230fb62d005de198861f565654588435bc0137d5f10cba' - '1ef41b2b0d6f77bc3cab6b0cdb030bc7aa14bbbec359f5263b9f89193f2d17373e8b29531ff7211cb4d3e01659f09813e24ef3e0b0a479091161c5740f9a06c1' - '43e9629ca17c8c46b08427c8c28225d8ba28865a6241d795d61b63ba4e416b8a0f9a7ba6288c3bf4e0f71f1da38718f1341e3e2f0bdb3a30692ff994b9cb9c52' - '074fb4357c67bfb5edb4db2c0e78db56d3642caae90da80f962fdecf52a6161c7c43c5c5de15914520441fdc912be9ec15c22e4829abb27363d68b4a8eef41cb' - '8bde0d883cb8127f292d591cc0f0cf6378132765b0fc8ff1760cf14c1673436fbd73768b81b22355ee5d58042149ef6cefec6788f0142cfee8bf217df70d16b8' - 'd62af7121dc9ea797adf73d87f1ee7a1d5c666794b77b085d24ab5b03f475ae8f7bb5b3a0b62df5fe778bfc3693a0ee32376a5b3052f7ae706ba1accc0776ea5' + 'bbb99e347a55d14265d4d7c2914f708bb3d25c6d8c18e382e90c9e207903584d124c71f4adcb19ba456887eb55e6fafc5ea9c452c5e956294501ebd816e5870e' + '133d299e407795acaffcca145382a6941c2be86714d1a949d5b4e368884f3b5195ecd164c1d12834e478cdec0585cc3c25a223b1f1f9dbb5481d132254336509' + '9178ca3920404af359eaf1882af1ad4669ca4b84784d0899679ceb192da140cea3fd493f605b770657c24039be76012985213b2892fa94a244c7d5bbed356e24' + 'e330f1e7e9ceae0e1c026fbab7c8a2d4408d57997a3550e6ee5384c734dcfcc42eaf9b45dabb4a837b79963a3fb36cd9d626e801bd4b84030f1acf9b0b2ed582' + '09daf201cab41fe1bbd56108cd6469860666e59aed0a6b8c91fbf01524ebf9649ee40da0fbcfb0b086cec577dfb2823ef27152a6e94f2e04e78045e769e0ac89' + '6f9f647ccca27820247fc210f4b031a74bc7bb105deec722df2eae90d61af25cef94412ae36fdb3559c24c05d52186c0e2cda92bdd825a8aae80a3c74bfb6a4d' + '20c2bb8b0c7d79b705853d1864bfaae8d5b036bd46a0c0af3816d95c6e8ced82d0e5d7b7f22e6e5a487ea9f5c5988f4a21584f6bd76f82a238179025db68417c' + '556eb3d85c0bebd362ab32c57be27ebb3576f5dbecf6cf37d15652beba7f80668787a40e63cd6c2f36cca5d3dc3bb301bd2ca26185c9ba179b0f60ce4d269f87' 'e2e364387efe34a1a392cdf9801b6f164d84de428edd8e43ccb1f12690019078db297b9dcf61a5dd4a83ca40dca8f25d9117e240c1ffd8b969d81e4dc6e972fd' '0aabd614b3318880fe940d4f3eb93f8b7f0e91892864f95d5b12eabfce1650ef036bf4e2ccee8b391c8a3cef4ff1ff7661b118a4f72d82214dbf713743809f78' '5a578620cc03574218a22c1eebbba91047815f0c7b0b3f2f3d1eb5534aa17254f0ea5f061cadfe7bbe3b32f0a20b2008e28a494cfd7be84600c4b6a89afd6940' diff --git a/linux/config b/linux/config index ac9ea29..1e33c05 100644 --- a/linux/config +++ b/linux/config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86 6.5.1-chos1 Kernel Configuration +# Linux/x86 6.5.3-chos1 Kernel Configuration # CONFIG_CC_VERSION_TEXT="gcc (GCC) 13.2.1 20230801" CONFIG_CC_IS_GCC=y @@ -6128,6 +6128,7 @@ CONFIG_DVB_BUDGET_CORE=m CONFIG_DVB_BUDGET=m CONFIG_DVB_BUDGET_CI=m CONFIG_DVB_BUDGET_AV=m +CONFIG_IPU_BRIDGE=m CONFIG_VIDEO_IPU3_CIO2=m CONFIG_CIO2_BRIDGE=y CONFIG_RADIO_ADAPTERS=m @@ -6312,10 +6313,7 @@ CONFIG_MEDIA_ATTACH=y # IR I2C driver auto-selected by 'Autoselect ancillary drivers' # CONFIG_VIDEO_IR_I2C=m - -# -# Camera sensor devices -# +CONFIG_VIDEO_CAMERA_SENSOR=y CONFIG_VIDEO_APTINA_PLL=m CONFIG_VIDEO_CCS_PLL=m CONFIG_VIDEO_AR0521=m @@ -6378,7 +6376,6 @@ CONFIG_VIDEO_S5K5BAF=m CONFIG_VIDEO_S5K6A3=m CONFIG_VIDEO_CCS=m CONFIG_VIDEO_ET8EK8=m -# end of Camera sensor devices # # Lens drivers