From: Greg Kroah-Hartman Date: Tue, 17 Mar 2026 15:31:59 +0000 (+0100) Subject: 6.19-stable patches X-Git-Tag: v6.18.19~27 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8a41251395b824d1c2ae038b68a0d111c10bc4a2;p=thirdparty%2Fkernel%2Fstable-queue.git 6.19-stable patches added patches: io_uring-ensure-ctx-rings-is-stable-for-task-work-flags-manipulation.patch io_uring-eventfd-use-ctx-rings_rcu-for-flags-checking.patch kvm-arm64-eagerly-init-vgic-dist-redist-on-vgic-creation.patch kvm-arm64-gic-set-vgic_model-before-initing-private-irqs.patch mm-damon-core-disallow-non-power-of-two-min_region_sz.patch mm-damon-rename-damon_min_region-to-damon_min_region_sz.patch mm-damon-rename-min_sz_region-of-damon_ctx-to-min_region_sz.patch --- diff --git a/queue-6.19/io_uring-ensure-ctx-rings-is-stable-for-task-work-flags-manipulation.patch b/queue-6.19/io_uring-ensure-ctx-rings-is-stable-for-task-work-flags-manipulation.patch new file mode 100644 index 0000000000..0c6e8cca90 --- /dev/null +++ b/queue-6.19/io_uring-ensure-ctx-rings-is-stable-for-task-work-flags-manipulation.patch @@ -0,0 +1,137 @@ +From 8e746bd1dadaf93542ca59dc971b233332c46ca6 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Mon, 9 Mar 2026 14:21:37 -0600 +Subject: io_uring: ensure ctx->rings is stable for task work flags manipulation + +From: Jens Axboe + +Commit 96189080265e6bb5dde3a4afbaf947af493e3f82 upstream. + +If DEFER_TASKRUN | SETUP_TASKRUN is used and task work is added while +the ring is being resized, it's possible for the OR'ing of +IORING_SQ_TASKRUN to happen in the small window of swapping into the +new rings and the old rings being freed. + +Prevent this by adding a 2nd ->rings pointer, ->rings_rcu, which is +protected by RCU. The task work flags manipulation is inside RCU +already, and if the resize ring freeing is done post an RCU synchronize, +then there's no need to add locking to the fast path of task work +additions. + +Note: this is only done for DEFER_TASKRUN, as that's the only setup mode +that supports ring resizing. If this ever changes, then they too need to +use the io_ctx_mark_taskrun() helper. + +Link: https://lore.kernel.org/io-uring/20260309062759.482210-1-naup96721@gmail.com/ +Cc: stable@vger.kernel.org +Fixes: 79cfe9e59c2a ("io_uring/register: add IORING_REGISTER_RESIZE_RINGS") +Reported-by: Hao-Yu Yang +Suggested-by: Pavel Begunkov +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/io_uring_types.h | 1 + + io_uring/io_uring.c | 24 ++++++++++++++++++++++-- + io_uring/register.c | 12 ++++++++++++ + 3 files changed, 35 insertions(+), 2 deletions(-) + +--- a/include/linux/io_uring_types.h ++++ b/include/linux/io_uring_types.h +@@ -371,6 +371,7 @@ struct io_ring_ctx { + * regularly bounce b/w CPUs. + */ + struct { ++ struct io_rings __rcu *rings_rcu; + struct llist_head work_llist; + struct llist_head retry_llist; + unsigned long check_cq; +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -1202,6 +1202,21 @@ void tctx_task_work(struct callback_head + WARN_ON_ONCE(ret); + } + ++/* ++ * Sets IORING_SQ_TASKRUN in the sq_flags shared with userspace, using the ++ * RCU protected rings pointer to be safe against concurrent ring resizing. ++ */ ++static void io_ctx_mark_taskrun(struct io_ring_ctx *ctx) ++{ ++ lockdep_assert_in_rcu_read_lock(); ++ ++ if (ctx->flags & IORING_SETUP_TASKRUN_FLAG) { ++ struct io_rings *rings = rcu_dereference(ctx->rings_rcu); ++ ++ atomic_or(IORING_SQ_TASKRUN, &rings->sq_flags); ++ } ++} ++ + static void io_req_local_work_add(struct io_kiocb *req, unsigned flags) + { + struct io_ring_ctx *ctx = req->ctx; +@@ -1256,8 +1271,7 @@ static void io_req_local_work_add(struct + */ + + if (!head) { +- if (ctx->flags & IORING_SETUP_TASKRUN_FLAG) +- atomic_or(IORING_SQ_TASKRUN, &ctx->rings->sq_flags); ++ io_ctx_mark_taskrun(ctx); + if (ctx->has_evfd) + io_eventfd_signal(ctx, false); + } +@@ -1281,6 +1295,10 @@ static void io_req_normal_work_add(struc + if (!llist_add(&req->io_task_work.node, &tctx->task_list)) + return; + ++ /* ++ * Doesn't need to use ->rings_rcu, as resizing isn't supported for ++ * !DEFER_TASKRUN. ++ */ + if (ctx->flags & IORING_SETUP_TASKRUN_FLAG) + atomic_or(IORING_SQ_TASKRUN, &ctx->rings->sq_flags); + +@@ -2760,6 +2778,7 @@ static void io_rings_free(struct io_ring + io_free_region(ctx->user, &ctx->sq_region); + io_free_region(ctx->user, &ctx->ring_region); + ctx->rings = NULL; ++ RCU_INIT_POINTER(ctx->rings_rcu, NULL); + ctx->sq_sqes = NULL; + } + +@@ -3389,6 +3408,7 @@ static __cold int io_allocate_scq_urings + if (ret) + return ret; + ctx->rings = rings = io_region_get_ptr(&ctx->ring_region); ++ rcu_assign_pointer(ctx->rings_rcu, rings); + if (!(ctx->flags & IORING_SETUP_NO_SQARRAY)) + ctx->sq_array = (u32 *)((char *)rings + rl->sq_array_offset); + +--- a/io_uring/register.c ++++ b/io_uring/register.c +@@ -545,7 +545,15 @@ overflow: + ctx->sq_entries = p->sq_entries; + ctx->cq_entries = p->cq_entries; + ++ /* ++ * Just mark any flag we may have missed and that the application ++ * should act on unconditionally. Worst case it'll be an extra ++ * syscall. ++ */ ++ atomic_or(IORING_SQ_TASKRUN | IORING_SQ_NEED_WAKEUP, &n.rings->sq_flags); + ctx->rings = n.rings; ++ rcu_assign_pointer(ctx->rings_rcu, n.rings); ++ + ctx->sq_sqes = n.sq_sqes; + swap_old(ctx, o, n, ring_region); + swap_old(ctx, o, n, sq_region); +@@ -554,6 +562,10 @@ overflow: + out: + spin_unlock(&ctx->completion_lock); + mutex_unlock(&ctx->mmap_lock); ++ ++ /* Wait for concurrent io_ctx_mark_taskrun() */ ++ if (to_free == &o) ++ synchronize_rcu_expedited(); + io_register_free_rings(ctx, to_free); + + if (ctx->sq_data) diff --git a/queue-6.19/io_uring-eventfd-use-ctx-rings_rcu-for-flags-checking.patch b/queue-6.19/io_uring-eventfd-use-ctx-rings_rcu-for-flags-checking.patch new file mode 100644 index 0000000000..d31b1cef80 --- /dev/null +++ b/queue-6.19/io_uring-eventfd-use-ctx-rings_rcu-for-flags-checking.patch @@ -0,0 +1,42 @@ +From 70710c220b58e84e08b924833d4caeb1d1500859 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Mon, 9 Mar 2026 14:35:49 -0600 +Subject: io_uring/eventfd: use ctx->rings_rcu for flags checking + +From: Jens Axboe + +Commit 177c69432161f6e4bab07ccacf8a1748a6898a6b upstream. + +Similarly to what commit e78f7b70e837 did for local task work additions, +use ->rings_rcu under RCU rather than dereference ->rings directly. See +that commit for more details. + +Cc: stable@vger.kernel.org +Fixes: 79cfe9e59c2a ("io_uring/register: add IORING_REGISTER_RESIZE_RINGS") +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + io_uring/eventfd.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/io_uring/eventfd.c ++++ b/io_uring/eventfd.c +@@ -76,11 +76,15 @@ void io_eventfd_signal(struct io_ring_ct + { + bool skip = false; + struct io_ev_fd *ev_fd; +- +- if (READ_ONCE(ctx->rings->cq_flags) & IORING_CQ_EVENTFD_DISABLED) +- return; ++ struct io_rings *rings; + + guard(rcu)(); ++ ++ rings = rcu_dereference(ctx->rings_rcu); ++ if (!rings) ++ return; ++ if (READ_ONCE(rings->cq_flags) & IORING_CQ_EVENTFD_DISABLED) ++ return; + ev_fd = rcu_dereference(ctx->io_ev_fd); + /* + * Check again if ev_fd exists in case an io_eventfd_unregister call diff --git a/queue-6.19/kvm-arm64-eagerly-init-vgic-dist-redist-on-vgic-creation.patch b/queue-6.19/kvm-arm64-eagerly-init-vgic-dist-redist-on-vgic-creation.patch new file mode 100644 index 0000000000..79afb6f30e --- /dev/null +++ b/queue-6.19/kvm-arm64-eagerly-init-vgic-dist-redist-on-vgic-creation.patch @@ -0,0 +1,87 @@ +From stable+bounces-225686-greg=kroah.com@vger.kernel.org Mon Mar 16 20:36:48 2026 +From: Sasha Levin +Date: Mon, 16 Mar 2026 15:36:40 -0400 +Subject: KVM: arm64: Eagerly init vgic dist/redist on vgic creation +To: stable@vger.kernel.org +Cc: Marc Zyngier , syzbot+f6a46b038fc243ac0175@syzkaller.appspotmail.com, Sasha Levin +Message-ID: <20260316193640.1358554-2-sashal@kernel.org> + +From: Marc Zyngier + +[ Upstream commit ac6769c8f948dff33265c50e524aebf9aa6f1be0 ] + +If vgic_allocate_private_irqs_locked() fails for any odd reason, +we exit kvm_vgic_create() early, leaving dist->rd_regions uninitialised. + +kvm_vgic_dist_destroy() then comes along and walks into the weeds +trying to free the RDs. Got to love this stuff. + +Solve it by moving all the static initialisation early, and make +sure that if we fail halfway, we're in a reasonable shape to +perform the rest of the teardown. While at it, reset the vgic model +on failure, just in case... + +Reported-by: syzbot+f6a46b038fc243ac0175@syzkaller.appspotmail.com +Tested-by: syzbot+f6a46b038fc243ac0175@syzkaller.appspotmail.com +Fixes: b3aa9283c0c50 ("KVM: arm64: vgic: Hoist SGI/PPI alloc from vgic_init() to kvm_create_vgic()") +Link: https://lore.kernel.org/r/69a2d58c.050a0220.3a55be.003b.GAE@google.com +Link: https://patch.msgid.link/20260228164559.936268-1-maz@kernel.org +Signed-off-by: Marc Zyngier +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kvm/vgic/vgic-init.c | 32 ++++++++++++++++---------------- + 1 file changed, 16 insertions(+), 16 deletions(-) + +--- a/arch/arm64/kvm/vgic/vgic-init.c ++++ b/arch/arm64/kvm/vgic/vgic-init.c +@@ -143,6 +143,21 @@ int kvm_vgic_create(struct kvm *kvm, u32 + kvm->arch.vgic.in_kernel = true; + kvm->arch.vgic.vgic_model = type; + kvm->arch.vgic.implementation_rev = KVM_VGIC_IMP_REV_LATEST; ++ kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF; ++ ++ aa64pfr0 = kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1) & ~ID_AA64PFR0_EL1_GIC; ++ pfr1 = kvm_read_vm_id_reg(kvm, SYS_ID_PFR1_EL1) & ~ID_PFR1_EL1_GIC; ++ ++ if (type == KVM_DEV_TYPE_ARM_VGIC_V2) { ++ kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF; ++ } else { ++ INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions); ++ aa64pfr0 |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, GIC, IMP); ++ pfr1 |= SYS_FIELD_PREP_ENUM(ID_PFR1_EL1, GIC, GICv3); ++ } ++ ++ kvm_set_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1, aa64pfr0); ++ kvm_set_vm_id_reg(kvm, SYS_ID_PFR1_EL1, pfr1); + + kvm_for_each_vcpu(i, vcpu, kvm) { + ret = vgic_allocate_private_irqs_locked(vcpu, type); +@@ -157,25 +172,10 @@ int kvm_vgic_create(struct kvm *kvm, u32 + vgic_cpu->private_irqs = NULL; + } + ++ kvm->arch.vgic.vgic_model = 0; + goto out_unlock; + } + +- kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF; +- +- aa64pfr0 = kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1) & ~ID_AA64PFR0_EL1_GIC; +- pfr1 = kvm_read_vm_id_reg(kvm, SYS_ID_PFR1_EL1) & ~ID_PFR1_EL1_GIC; +- +- if (type == KVM_DEV_TYPE_ARM_VGIC_V2) { +- kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF; +- } else { +- INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions); +- aa64pfr0 |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, GIC, IMP); +- pfr1 |= SYS_FIELD_PREP_ENUM(ID_PFR1_EL1, GIC, GICv3); +- } +- +- kvm_set_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1, aa64pfr0); +- kvm_set_vm_id_reg(kvm, SYS_ID_PFR1_EL1, pfr1); +- + if (type == KVM_DEV_TYPE_ARM_VGIC_V3) + kvm->arch.vgic.nassgicap = system_supports_direct_sgis(); + diff --git a/queue-6.19/kvm-arm64-gic-set-vgic_model-before-initing-private-irqs.patch b/queue-6.19/kvm-arm64-gic-set-vgic_model-before-initing-private-irqs.patch new file mode 100644 index 0000000000..8be68c7a75 --- /dev/null +++ b/queue-6.19/kvm-arm64-gic-set-vgic_model-before-initing-private-irqs.patch @@ -0,0 +1,59 @@ +From stable+bounces-225685-greg=kroah.com@vger.kernel.org Mon Mar 16 20:36:46 2026 +From: Sasha Levin +Date: Mon, 16 Mar 2026 15:36:39 -0400 +Subject: KVM: arm64: gic: Set vgic_model before initing private IRQs +To: stable@vger.kernel.org +Cc: Sascha Bischoff , Sascha Bischoff , Jonathan Cameron , Marc Zyngier , Sasha Levin +Message-ID: <20260316193640.1358554-1-sashal@kernel.org> + +From: Sascha Bischoff + +[ Upstream commit 9435c1e1431003e23aa34ef8e46c30d09c3dbcb5 ] + +Different GIC types require the private IRQs to be initialised +differently. GICv5 is the culprit as it supports both a different +number of private IRQs, and all of these are PPIs (there are no +SGIs). Moreover, as GICv5 uses the top bits of the interrupt ID to +encode the type, the intid also needs to computed differently. + +Up until now, the GIC model has been set after initialising the +private IRQs for a VCPU. Move this earlier to ensure that the GIC +model is available when configuring the private IRQs. While we're at +it, also move the setting of the in_kernel flag and implementation +revision to keep them grouped together as before. + +Signed-off-by: Sascha Bischoff +Reviewed-by: Jonathan Cameron +Link: https://patch.msgid.link/20260128175919.3828384-7-sascha.bischoff@arm.com +Signed-off-by: Marc Zyngier +Stable-dep-of: ac6769c8f948 ("KVM: arm64: Eagerly init vgic dist/redist on vgic creation") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kvm/vgic/vgic-init.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/arch/arm64/kvm/vgic/vgic-init.c ++++ b/arch/arm64/kvm/vgic/vgic-init.c +@@ -140,6 +140,10 @@ int kvm_vgic_create(struct kvm *kvm, u32 + goto out_unlock; + } + ++ kvm->arch.vgic.in_kernel = true; ++ kvm->arch.vgic.vgic_model = type; ++ kvm->arch.vgic.implementation_rev = KVM_VGIC_IMP_REV_LATEST; ++ + kvm_for_each_vcpu(i, vcpu, kvm) { + ret = vgic_allocate_private_irqs_locked(vcpu, type); + if (ret) +@@ -156,10 +160,6 @@ int kvm_vgic_create(struct kvm *kvm, u32 + goto out_unlock; + } + +- kvm->arch.vgic.in_kernel = true; +- kvm->arch.vgic.vgic_model = type; +- kvm->arch.vgic.implementation_rev = KVM_VGIC_IMP_REV_LATEST; +- + kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF; + + aa64pfr0 = kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1) & ~ID_AA64PFR0_EL1_GIC; diff --git a/queue-6.19/mm-damon-core-disallow-non-power-of-two-min_region_sz.patch b/queue-6.19/mm-damon-core-disallow-non-power-of-two-min_region_sz.patch new file mode 100644 index 0000000000..6fadae589d --- /dev/null +++ b/queue-6.19/mm-damon-core-disallow-non-power-of-two-min_region_sz.patch @@ -0,0 +1,61 @@ +From stable+bounces-226038-greg=kroah.com@vger.kernel.org Tue Mar 17 15:52:37 2026 +From: Sasha Levin +Date: Tue, 17 Mar 2026 10:43:02 -0400 +Subject: mm/damon/core: disallow non-power of two min_region_sz +To: stable@vger.kernel.org +Cc: SeongJae Park , Quanmin Yan , Andrew Morton , Sasha Levin +Message-ID: <20260317144302.174364-3-sashal@kernel.org> + +From: SeongJae Park + +[ Upstream commit c80f46ac228b48403866d65391ad09bdf0e8562a ] + +DAMON core uses min_region_sz parameter value as the DAMON region +alignment. The alignment is made using ALIGN() and ALIGN_DOWN(), which +support only the power of two alignments. But DAMON core API callers can +set min_region_sz to an arbitrary number. Users can also set it +indirectly, using addr_unit. + +When the alignment is not properly set, DAMON behavior becomes difficult +to expect and understand, makes it effectively broken. It doesn't cause a +kernel crash-like significant issue, though. + +Fix the issue by disallowing min_region_sz input that is not a power of +two. Add the check to damon_commit_ctx(), as all DAMON API callers who +set min_region_sz uses the function. + +This can be a sort of behavioral change, but it does not break users, for +the following reasons. As the symptom is making DAMON effectively broken, +it is not reasonable to believe there are real use cases of non-power of +two min_region_sz. There is no known use case or issue reports from the +setup, either. + +In future, if we find real use cases of non-power of two alignments and we +can support it with low enough overhead, we can consider moving the +restriction. But, for now, simply disallowing the corner case should be +good enough as a hot fix. + +Link: https://lkml.kernel.org/r/20260214214124.87689-1-sj@kernel.org +Fixes: d8f867fa0825 ("mm/damon: add damon_ctx->min_sz_region") +Signed-off-by: SeongJae Park +Cc: Quanmin Yan +Cc: [6.18+] +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + mm/damon/core.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/mm/damon/core.c ++++ b/mm/damon/core.c +@@ -1241,6 +1241,9 @@ int damon_commit_ctx(struct damon_ctx *d + { + int err; + ++ if (!is_power_of_2(src->min_region_sz)) ++ return -EINVAL; ++ + err = damon_commit_schemes(dst, src); + if (err) + return err; diff --git a/queue-6.19/mm-damon-rename-damon_min_region-to-damon_min_region_sz.patch b/queue-6.19/mm-damon-rename-damon_min_region-to-damon_min_region_sz.patch new file mode 100644 index 0000000000..7265d5005b --- /dev/null +++ b/queue-6.19/mm-damon-rename-damon_min_region-to-damon_min_region_sz.patch @@ -0,0 +1,160 @@ +From stable+bounces-226036-greg=kroah.com@vger.kernel.org Tue Mar 17 15:51:25 2026 +From: Sasha Levin +Date: Tue, 17 Mar 2026 10:43:00 -0400 +Subject: mm/damon: rename DAMON_MIN_REGION to DAMON_MIN_REGION_SZ +To: stable@vger.kernel.org +Cc: SeongJae Park , Andrew Morton , Sasha Levin +Message-ID: <20260317144302.174364-1-sashal@kernel.org> + +From: SeongJae Park + +[ Upstream commit dfb1b0c9dc0d61e422905640e1e7334b3cf6f384 ] + +The macro is for the default minimum size of each DAMON region. There was +a case that a reader was confused if it is the minimum number of total +DAMON regions, which is set on damon_attrs->min_nr_regions. Make the name +more explicit. + +Link: https://lkml.kernel.org/r/20260117175256.82826-8-sj@kernel.org +Signed-off-by: SeongJae Park +Signed-off-by: Andrew Morton +Stable-dep-of: c80f46ac228b ("mm/damon/core: disallow non-power of two min_region_sz") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/damon.h | 2 +- + mm/damon/core.c | 2 +- + mm/damon/lru_sort.c | 2 +- + mm/damon/reclaim.c | 2 +- + mm/damon/sysfs.c | 2 +- + mm/damon/tests/vaddr-kunit.h | 2 +- + mm/damon/vaddr.c | 24 ++++++++++++------------ + 7 files changed, 18 insertions(+), 18 deletions(-) + +--- a/include/linux/damon.h ++++ b/include/linux/damon.h +@@ -15,7 +15,7 @@ + #include + + /* Minimal region size. Every damon_region is aligned by this. */ +-#define DAMON_MIN_REGION PAGE_SIZE ++#define DAMON_MIN_REGION_SZ PAGE_SIZE + /* Max priority score for DAMON-based operation schemes */ + #define DAMOS_MAX_SCORE (99) + +--- a/mm/damon/core.c ++++ b/mm/damon/core.c +@@ -546,7 +546,7 @@ struct damon_ctx *damon_new_ctx(void) + ctx->attrs.max_nr_regions = 1000; + + ctx->addr_unit = 1; +- ctx->min_sz_region = DAMON_MIN_REGION; ++ ctx->min_sz_region = DAMON_MIN_REGION_SZ; + + INIT_LIST_HEAD(&ctx->adaptive_targets); + INIT_LIST_HEAD(&ctx->schemes); +--- a/mm/damon/lru_sort.c ++++ b/mm/damon/lru_sort.c +@@ -212,7 +212,7 @@ static int damon_lru_sort_apply_paramete + if (!monitor_region_start && !monitor_region_end) + addr_unit = 1; + param_ctx->addr_unit = addr_unit; +- param_ctx->min_sz_region = max(DAMON_MIN_REGION / addr_unit, 1); ++ param_ctx->min_sz_region = max(DAMON_MIN_REGION_SZ / addr_unit, 1); + + if (!damon_lru_sort_mon_attrs.sample_interval) { + err = -EINVAL; +--- a/mm/damon/reclaim.c ++++ b/mm/damon/reclaim.c +@@ -208,7 +208,7 @@ static int damon_reclaim_apply_parameter + if (!monitor_region_start && !monitor_region_end) + addr_unit = 1; + param_ctx->addr_unit = addr_unit; +- param_ctx->min_sz_region = max(DAMON_MIN_REGION / addr_unit, 1); ++ param_ctx->min_sz_region = max(DAMON_MIN_REGION_SZ / addr_unit, 1); + + if (!damon_reclaim_mon_attrs.aggr_interval) { + err = -EINVAL; +--- a/mm/damon/sysfs.c ++++ b/mm/damon/sysfs.c +@@ -1470,7 +1470,7 @@ static int damon_sysfs_apply_inputs(stru + /* addr_unit is respected by only DAMON_OPS_PADDR */ + if (sys_ctx->ops_id == DAMON_OPS_PADDR) + ctx->min_sz_region = max( +- DAMON_MIN_REGION / sys_ctx->addr_unit, 1); ++ DAMON_MIN_REGION_SZ / sys_ctx->addr_unit, 1); + err = damon_sysfs_set_attrs(ctx, sys_ctx->attrs); + if (err) + return err; +--- a/mm/damon/tests/vaddr-kunit.h ++++ b/mm/damon/tests/vaddr-kunit.h +@@ -147,7 +147,7 @@ static void damon_do_test_apply_three_re + damon_add_region(r, t); + } + +- damon_set_regions(t, three_regions, 3, DAMON_MIN_REGION); ++ damon_set_regions(t, three_regions, 3, DAMON_MIN_REGION_SZ); + + for (i = 0; i < nr_expected / 2; i++) { + r = __nth_region_of(t, i); +--- a/mm/damon/vaddr.c ++++ b/mm/damon/vaddr.c +@@ -19,8 +19,8 @@ + #include "ops-common.h" + + #ifdef CONFIG_DAMON_VADDR_KUNIT_TEST +-#undef DAMON_MIN_REGION +-#define DAMON_MIN_REGION 1 ++#undef DAMON_MIN_REGION_SZ ++#define DAMON_MIN_REGION_SZ 1 + #endif + + /* +@@ -78,7 +78,7 @@ static int damon_va_evenly_split_region( + + orig_end = r->ar.end; + sz_orig = damon_sz_region(r); +- sz_piece = ALIGN_DOWN(sz_orig / nr_pieces, DAMON_MIN_REGION); ++ sz_piece = ALIGN_DOWN(sz_orig / nr_pieces, DAMON_MIN_REGION_SZ); + + if (!sz_piece) + return -EINVAL; +@@ -161,12 +161,12 @@ next: + swap(first_gap, second_gap); + + /* Store the result */ +- regions[0].start = ALIGN(start, DAMON_MIN_REGION); +- regions[0].end = ALIGN(first_gap.start, DAMON_MIN_REGION); +- regions[1].start = ALIGN(first_gap.end, DAMON_MIN_REGION); +- regions[1].end = ALIGN(second_gap.start, DAMON_MIN_REGION); +- regions[2].start = ALIGN(second_gap.end, DAMON_MIN_REGION); +- regions[2].end = ALIGN(prev->vm_end, DAMON_MIN_REGION); ++ regions[0].start = ALIGN(start, DAMON_MIN_REGION_SZ); ++ regions[0].end = ALIGN(first_gap.start, DAMON_MIN_REGION_SZ); ++ regions[1].start = ALIGN(first_gap.end, DAMON_MIN_REGION_SZ); ++ regions[1].end = ALIGN(second_gap.start, DAMON_MIN_REGION_SZ); ++ regions[2].start = ALIGN(second_gap.end, DAMON_MIN_REGION_SZ); ++ regions[2].end = ALIGN(prev->vm_end, DAMON_MIN_REGION_SZ); + + return 0; + } +@@ -259,8 +259,8 @@ static void __damon_va_init_regions(stru + sz += regions[i].end - regions[i].start; + if (ctx->attrs.min_nr_regions) + sz /= ctx->attrs.min_nr_regions; +- if (sz < DAMON_MIN_REGION) +- sz = DAMON_MIN_REGION; ++ if (sz < DAMON_MIN_REGION_SZ) ++ sz = DAMON_MIN_REGION_SZ; + + /* Set the initial three regions of the target */ + for (i = 0; i < 3; i++) { +@@ -299,7 +299,7 @@ static void damon_va_update(struct damon + damon_for_each_target(t, ctx) { + if (damon_va_three_regions(t, three_regions)) + continue; +- damon_set_regions(t, three_regions, 3, DAMON_MIN_REGION); ++ damon_set_regions(t, three_regions, 3, DAMON_MIN_REGION_SZ); + } + } + diff --git a/queue-6.19/mm-damon-rename-min_sz_region-of-damon_ctx-to-min_region_sz.patch b/queue-6.19/mm-damon-rename-min_sz_region-of-damon_ctx-to-min_region_sz.patch new file mode 100644 index 0000000000..26bc9b65ef --- /dev/null +++ b/queue-6.19/mm-damon-rename-min_sz_region-of-damon_ctx-to-min_region_sz.patch @@ -0,0 +1,422 @@ +From stable+bounces-226037-greg=kroah.com@vger.kernel.org Tue Mar 17 15:51:24 2026 +From: Sasha Levin +Date: Tue, 17 Mar 2026 10:43:01 -0400 +Subject: mm/damon: rename min_sz_region of damon_ctx to min_region_sz +To: stable@vger.kernel.org +Cc: SeongJae Park , Andrew Morton , Sasha Levin +Message-ID: <20260317144302.174364-2-sashal@kernel.org> + +From: SeongJae Park + +[ Upstream commit cc1db8dff8e751ec3ab352483de366b7f23aefe2 ] + +'min_sz_region' field of 'struct damon_ctx' represents the minimum size of +each DAMON region for the context. 'struct damos_access_pattern' has a +field of the same name. It confuses readers and makes 'grep' less optimal +for them. Rename it to 'min_region_sz'. + +Link: https://lkml.kernel.org/r/20260117175256.82826-9-sj@kernel.org +Signed-off-by: SeongJae Park +Signed-off-by: Andrew Morton +Stable-dep-of: c80f46ac228b ("mm/damon/core: disallow non-power of two min_region_sz") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/damon.h | 8 ++--- + mm/damon/core.c | 69 +++++++++++++++++++++++++------------------------- + mm/damon/lru_sort.c | 4 +- + mm/damon/reclaim.c | 4 +- + mm/damon/stat.c | 2 - + mm/damon/sysfs.c | 9 +++--- + 6 files changed, 49 insertions(+), 47 deletions(-) + +--- a/include/linux/damon.h ++++ b/include/linux/damon.h +@@ -769,7 +769,7 @@ struct damon_attrs { + * + * @ops: Set of monitoring operations for given use cases. + * @addr_unit: Scale factor for core to ops address conversion. +- * @min_sz_region: Minimum region size. ++ * @min_region_sz: Minimum region size. + * @adaptive_targets: Head of monitoring targets (&damon_target) list. + * @schemes: Head of schemes (&damos) list. + */ +@@ -812,7 +812,7 @@ struct damon_ctx { + + struct damon_operations ops; + unsigned long addr_unit; +- unsigned long min_sz_region; ++ unsigned long min_region_sz; + + struct list_head adaptive_targets; + struct list_head schemes; +@@ -901,7 +901,7 @@ static inline void damon_insert_region(s + void damon_add_region(struct damon_region *r, struct damon_target *t); + void damon_destroy_region(struct damon_region *r, struct damon_target *t); + int damon_set_regions(struct damon_target *t, struct damon_addr_range *ranges, +- unsigned int nr_ranges, unsigned long min_sz_region); ++ unsigned int nr_ranges, unsigned long min_region_sz); + void damon_update_region_access_rate(struct damon_region *r, bool accessed, + struct damon_attrs *attrs); + +@@ -968,7 +968,7 @@ int damos_walk(struct damon_ctx *ctx, st + + int damon_set_region_biggest_system_ram_default(struct damon_target *t, + unsigned long *start, unsigned long *end, +- unsigned long min_sz_region); ++ unsigned long min_region_sz); + + #endif /* CONFIG_DAMON */ + +--- a/mm/damon/core.c ++++ b/mm/damon/core.c +@@ -197,7 +197,7 @@ static int damon_fill_regions_holes(stru + * @t: the given target. + * @ranges: array of new monitoring target ranges. + * @nr_ranges: length of @ranges. +- * @min_sz_region: minimum region size. ++ * @min_region_sz: minimum region size. + * + * This function adds new regions to, or modify existing regions of a + * monitoring target to fit in specific ranges. +@@ -205,7 +205,7 @@ static int damon_fill_regions_holes(stru + * Return: 0 if success, or negative error code otherwise. + */ + int damon_set_regions(struct damon_target *t, struct damon_addr_range *ranges, +- unsigned int nr_ranges, unsigned long min_sz_region) ++ unsigned int nr_ranges, unsigned long min_region_sz) + { + struct damon_region *r, *next; + unsigned int i; +@@ -242,16 +242,16 @@ int damon_set_regions(struct damon_targe + /* no region intersects with this range */ + newr = damon_new_region( + ALIGN_DOWN(range->start, +- min_sz_region), +- ALIGN(range->end, min_sz_region)); ++ min_region_sz), ++ ALIGN(range->end, min_region_sz)); + if (!newr) + return -ENOMEM; + damon_insert_region(newr, damon_prev_region(r), r, t); + } else { + /* resize intersecting regions to fit in this range */ + first->ar.start = ALIGN_DOWN(range->start, +- min_sz_region); +- last->ar.end = ALIGN(range->end, min_sz_region); ++ min_region_sz); ++ last->ar.end = ALIGN(range->end, min_region_sz); + + /* fill possible holes in the range */ + err = damon_fill_regions_holes(first, last, t); +@@ -546,7 +546,7 @@ struct damon_ctx *damon_new_ctx(void) + ctx->attrs.max_nr_regions = 1000; + + ctx->addr_unit = 1; +- ctx->min_sz_region = DAMON_MIN_REGION_SZ; ++ ctx->min_region_sz = DAMON_MIN_REGION_SZ; + + INIT_LIST_HEAD(&ctx->adaptive_targets); + INIT_LIST_HEAD(&ctx->schemes); +@@ -1131,7 +1131,7 @@ static struct damon_target *damon_nth_ta + * If @src has no region, @dst keeps current regions. + */ + static int damon_commit_target_regions(struct damon_target *dst, +- struct damon_target *src, unsigned long src_min_sz_region) ++ struct damon_target *src, unsigned long src_min_region_sz) + { + struct damon_region *src_region; + struct damon_addr_range *ranges; +@@ -1148,7 +1148,7 @@ static int damon_commit_target_regions(s + i = 0; + damon_for_each_region(src_region, src) + ranges[i++] = src_region->ar; +- err = damon_set_regions(dst, ranges, i, src_min_sz_region); ++ err = damon_set_regions(dst, ranges, i, src_min_region_sz); + kfree(ranges); + return err; + } +@@ -1156,11 +1156,11 @@ static int damon_commit_target_regions(s + static int damon_commit_target( + struct damon_target *dst, bool dst_has_pid, + struct damon_target *src, bool src_has_pid, +- unsigned long src_min_sz_region) ++ unsigned long src_min_region_sz) + { + int err; + +- err = damon_commit_target_regions(dst, src, src_min_sz_region); ++ err = damon_commit_target_regions(dst, src, src_min_region_sz); + if (err) + return err; + if (dst_has_pid) +@@ -1187,7 +1187,7 @@ static int damon_commit_targets( + err = damon_commit_target( + dst_target, damon_target_has_pid(dst), + src_target, damon_target_has_pid(src), +- src->min_sz_region); ++ src->min_region_sz); + if (err) + return err; + } else { +@@ -1214,7 +1214,7 @@ static int damon_commit_targets( + return -ENOMEM; + err = damon_commit_target(new_target, false, + src_target, damon_target_has_pid(src), +- src->min_sz_region); ++ src->min_region_sz); + if (err) { + damon_destroy_target(new_target, NULL); + return err; +@@ -1261,7 +1261,7 @@ int damon_commit_ctx(struct damon_ctx *d + } + dst->ops = src->ops; + dst->addr_unit = src->addr_unit; +- dst->min_sz_region = src->min_sz_region; ++ dst->min_region_sz = src->min_region_sz; + + return 0; + } +@@ -1294,8 +1294,8 @@ static unsigned long damon_region_sz_lim + + if (ctx->attrs.min_nr_regions) + sz /= ctx->attrs.min_nr_regions; +- if (sz < ctx->min_sz_region) +- sz = ctx->min_sz_region; ++ if (sz < ctx->min_region_sz) ++ sz = ctx->min_region_sz; + + return sz; + } +@@ -1673,7 +1673,7 @@ static bool damos_valid_target(struct da + * @t: The target of the region. + * @rp: The pointer to the region. + * @s: The scheme to be applied. +- * @min_sz_region: minimum region size. ++ * @min_region_sz: minimum region size. + * + * If a quota of a scheme has exceeded in a quota charge window, the scheme's + * action would applied to only a part of the target access pattern fulfilling +@@ -1691,7 +1691,8 @@ static bool damos_valid_target(struct da + * Return: true if the region should be entirely skipped, false otherwise. + */ + static bool damos_skip_charged_region(struct damon_target *t, +- struct damon_region **rp, struct damos *s, unsigned long min_sz_region) ++ struct damon_region **rp, struct damos *s, ++ unsigned long min_region_sz) + { + struct damon_region *r = *rp; + struct damos_quota *quota = &s->quota; +@@ -1713,11 +1714,11 @@ static bool damos_skip_charged_region(st + if (quota->charge_addr_from && r->ar.start < + quota->charge_addr_from) { + sz_to_skip = ALIGN_DOWN(quota->charge_addr_from - +- r->ar.start, min_sz_region); ++ r->ar.start, min_region_sz); + if (!sz_to_skip) { +- if (damon_sz_region(r) <= min_sz_region) ++ if (damon_sz_region(r) <= min_region_sz) + return true; +- sz_to_skip = min_sz_region; ++ sz_to_skip = min_region_sz; + } + damon_split_region_at(t, r, sz_to_skip); + r = damon_next_region(r); +@@ -1743,7 +1744,7 @@ static void damos_update_stat(struct dam + + static bool damos_filter_match(struct damon_ctx *ctx, struct damon_target *t, + struct damon_region *r, struct damos_filter *filter, +- unsigned long min_sz_region) ++ unsigned long min_region_sz) + { + bool matched = false; + struct damon_target *ti; +@@ -1760,8 +1761,8 @@ static bool damos_filter_match(struct da + matched = target_idx == filter->target_idx; + break; + case DAMOS_FILTER_TYPE_ADDR: +- start = ALIGN_DOWN(filter->addr_range.start, min_sz_region); +- end = ALIGN_DOWN(filter->addr_range.end, min_sz_region); ++ start = ALIGN_DOWN(filter->addr_range.start, min_region_sz); ++ end = ALIGN_DOWN(filter->addr_range.end, min_region_sz); + + /* inside the range */ + if (start <= r->ar.start && r->ar.end <= end) { +@@ -1797,7 +1798,7 @@ static bool damos_filter_out(struct damo + + s->core_filters_allowed = false; + damos_for_each_core_filter(filter, s) { +- if (damos_filter_match(ctx, t, r, filter, ctx->min_sz_region)) { ++ if (damos_filter_match(ctx, t, r, filter, ctx->min_region_sz)) { + if (filter->allow) + s->core_filters_allowed = true; + return !filter->allow; +@@ -1932,7 +1933,7 @@ static void damos_apply_scheme(struct da + if (c->ops.apply_scheme) { + if (quota->esz && quota->charged_sz + sz > quota->esz) { + sz = ALIGN_DOWN(quota->esz - quota->charged_sz, +- c->min_sz_region); ++ c->min_region_sz); + if (!sz) + goto update_stat; + damon_split_region_at(t, r, sz); +@@ -1980,7 +1981,7 @@ static void damon_do_apply_schemes(struc + if (quota->esz && quota->charged_sz >= quota->esz) + continue; + +- if (damos_skip_charged_region(t, &r, s, c->min_sz_region)) ++ if (damos_skip_charged_region(t, &r, s, c->min_region_sz)) + continue; + + if (!damos_valid_target(c, t, r, s)) +@@ -2429,7 +2430,7 @@ static void damon_split_region_at(struct + + /* Split every region in the given target into 'nr_subs' regions */ + static void damon_split_regions_of(struct damon_target *t, int nr_subs, +- unsigned long min_sz_region) ++ unsigned long min_region_sz) + { + struct damon_region *r, *next; + unsigned long sz_region, sz_sub = 0; +@@ -2439,13 +2440,13 @@ static void damon_split_regions_of(struc + sz_region = damon_sz_region(r); + + for (i = 0; i < nr_subs - 1 && +- sz_region > 2 * min_sz_region; i++) { ++ sz_region > 2 * min_region_sz; i++) { + /* + * Randomly select size of left sub-region to be at + * least 10 percent and at most 90% of original region + */ + sz_sub = ALIGN_DOWN(damon_rand(1, 10) * +- sz_region / 10, min_sz_region); ++ sz_region / 10, min_region_sz); + /* Do not allow blank region */ + if (sz_sub == 0 || sz_sub >= sz_region) + continue; +@@ -2485,7 +2486,7 @@ static void kdamond_split_regions(struct + nr_subregions = 3; + + damon_for_each_target(t, ctx) +- damon_split_regions_of(t, nr_subregions, ctx->min_sz_region); ++ damon_split_regions_of(t, nr_subregions, ctx->min_region_sz); + + last_nr_regions = nr_regions; + } +@@ -2855,7 +2856,7 @@ static bool damon_find_biggest_system_ra + * @t: The monitoring target to set the region. + * @start: The pointer to the start address of the region. + * @end: The pointer to the end address of the region. +- * @min_sz_region: Minimum region size. ++ * @min_region_sz: Minimum region size. + * + * This function sets the region of @t as requested by @start and @end. If the + * values of @start and @end are zero, however, this function finds the biggest +@@ -2867,7 +2868,7 @@ static bool damon_find_biggest_system_ra + */ + int damon_set_region_biggest_system_ram_default(struct damon_target *t, + unsigned long *start, unsigned long *end, +- unsigned long min_sz_region) ++ unsigned long min_region_sz) + { + struct damon_addr_range addr_range; + +@@ -2880,7 +2881,7 @@ int damon_set_region_biggest_system_ram_ + + addr_range.start = *start; + addr_range.end = *end; +- return damon_set_regions(t, &addr_range, 1, min_sz_region); ++ return damon_set_regions(t, &addr_range, 1, min_region_sz); + } + + /* +--- a/mm/damon/lru_sort.c ++++ b/mm/damon/lru_sort.c +@@ -212,7 +212,7 @@ static int damon_lru_sort_apply_paramete + if (!monitor_region_start && !monitor_region_end) + addr_unit = 1; + param_ctx->addr_unit = addr_unit; +- param_ctx->min_sz_region = max(DAMON_MIN_REGION_SZ / addr_unit, 1); ++ param_ctx->min_region_sz = max(DAMON_MIN_REGION_SZ / addr_unit, 1); + + if (!damon_lru_sort_mon_attrs.sample_interval) { + err = -EINVAL; +@@ -243,7 +243,7 @@ static int damon_lru_sort_apply_paramete + err = damon_set_region_biggest_system_ram_default(param_target, + &monitor_region_start, + &monitor_region_end, +- param_ctx->min_sz_region); ++ param_ctx->min_region_sz); + if (err) + goto out; + err = damon_commit_ctx(ctx, param_ctx); +--- a/mm/damon/reclaim.c ++++ b/mm/damon/reclaim.c +@@ -208,7 +208,7 @@ static int damon_reclaim_apply_parameter + if (!monitor_region_start && !monitor_region_end) + addr_unit = 1; + param_ctx->addr_unit = addr_unit; +- param_ctx->min_sz_region = max(DAMON_MIN_REGION_SZ / addr_unit, 1); ++ param_ctx->min_region_sz = max(DAMON_MIN_REGION_SZ / addr_unit, 1); + + if (!damon_reclaim_mon_attrs.aggr_interval) { + err = -EINVAL; +@@ -251,7 +251,7 @@ static int damon_reclaim_apply_parameter + err = damon_set_region_biggest_system_ram_default(param_target, + &monitor_region_start, + &monitor_region_end, +- param_ctx->min_sz_region); ++ param_ctx->min_region_sz); + if (err) + goto out; + err = damon_commit_ctx(ctx, param_ctx); +--- a/mm/damon/stat.c ++++ b/mm/damon/stat.c +@@ -189,7 +189,7 @@ static struct damon_ctx *damon_stat_buil + goto free_out; + damon_add_target(ctx, target); + if (damon_set_region_biggest_system_ram_default(target, &start, &end, +- ctx->min_sz_region)) ++ ctx->min_region_sz)) + goto free_out; + return ctx; + free_out: +--- a/mm/damon/sysfs.c ++++ b/mm/damon/sysfs.c +@@ -1365,7 +1365,7 @@ static int damon_sysfs_set_attrs(struct + + static int damon_sysfs_set_regions(struct damon_target *t, + struct damon_sysfs_regions *sysfs_regions, +- unsigned long min_sz_region) ++ unsigned long min_region_sz) + { + struct damon_addr_range *ranges = kmalloc_array(sysfs_regions->nr, + sizeof(*ranges), GFP_KERNEL | __GFP_NOWARN); +@@ -1387,7 +1387,7 @@ static int damon_sysfs_set_regions(struc + if (ranges[i - 1].end > ranges[i].start) + goto out; + } +- err = damon_set_regions(t, ranges, sysfs_regions->nr, min_sz_region); ++ err = damon_set_regions(t, ranges, sysfs_regions->nr, min_region_sz); + out: + kfree(ranges); + return err; +@@ -1409,7 +1409,8 @@ static int damon_sysfs_add_target(struct + return -EINVAL; + } + t->obsolete = sys_target->obsolete; +- return damon_sysfs_set_regions(t, sys_target->regions, ctx->min_sz_region); ++ return damon_sysfs_set_regions(t, sys_target->regions, ++ ctx->min_region_sz); + } + + static int damon_sysfs_add_targets(struct damon_ctx *ctx, +@@ -1469,7 +1470,7 @@ static int damon_sysfs_apply_inputs(stru + ctx->addr_unit = sys_ctx->addr_unit; + /* addr_unit is respected by only DAMON_OPS_PADDR */ + if (sys_ctx->ops_id == DAMON_OPS_PADDR) +- ctx->min_sz_region = max( ++ ctx->min_region_sz = max( + DAMON_MIN_REGION_SZ / sys_ctx->addr_unit, 1); + err = damon_sysfs_set_attrs(ctx, sys_ctx->attrs); + if (err) diff --git a/queue-6.19/series b/queue-6.19/series index 69dbec8c68..7d03de77c7 100644 --- a/queue-6.19/series +++ b/queue-6.19/series @@ -368,3 +368,10 @@ i3c-mipi-i3c-hci-restart-dma-ring-correctly-after-dequeue-abort.patch i3c-mipi-i3c-hci-add-missing-tid-field-to-no-op-command-descriptor.patch i3c-mipi-i3c-hci-fix-race-in-dma-ring-dequeue.patch i3c-mipi-i3c-hci-correct-ring_ctrl_abort-handling-in-dma-dequeue.patch +mm-damon-rename-damon_min_region-to-damon_min_region_sz.patch +mm-damon-rename-min_sz_region-of-damon_ctx-to-min_region_sz.patch +mm-damon-core-disallow-non-power-of-two-min_region_sz.patch +kvm-arm64-gic-set-vgic_model-before-initing-private-irqs.patch +kvm-arm64-eagerly-init-vgic-dist-redist-on-vgic-creation.patch +io_uring-ensure-ctx-rings-is-stable-for-task-work-flags-manipulation.patch +io_uring-eventfd-use-ctx-rings_rcu-for-flags-checking.patch