mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 20:14:06 +02:00
6 hotfixes. 2 are cc:stable. All are for MM.
All are singletons - please see the changelogs for details. -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQTTMBEPP41GrTpTJgfdBJ7gKXxAjgUCacHhYgAKCRDdBJ7gKXxA jqnKAPwLWHOazW6WB43goV605aA42anjBRm8kHg7E36X53OUJgD+L8KV2IXeDzGE cFe9TxqtdhYg6/JRiwEE5eDYT/uWaAk= =G0UF -----END PGP SIGNATURE----- Merge tag 'mm-hotfixes-stable-2026-03-23-17-56' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm Pull MM fixes from Andrew Morton: "6 hotfixes. 2 are cc:stable. All are for MM. All are singletons - please see the changelogs for details" * tag 'mm-hotfixes-stable-2026-03-23-17-56' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: mm/damon/stat: monitor all System RAM resources mm/zswap: add missing kunmap_local() mailmap: update email address for Muhammad Usama Anjum zram: do not slot_free() written-back slots mm/damon/core: avoid use of half-online-committed context mm/rmap: clear vma->anon_vma on error
This commit is contained in:
commit
e3c33bc767
1
.mailmap
1
.mailmap
|
|
@ -587,6 +587,7 @@ Morten Welinder <terra@gnome.org>
|
|||
Morten Welinder <welinder@anemone.rentec.com>
|
||||
Morten Welinder <welinder@darter.rentec.com>
|
||||
Morten Welinder <welinder@troll.com>
|
||||
Muhammad Usama Anjum <usama.anjum@arm.com> <usama.anjum@collabora.com>
|
||||
Mukesh Ojha <quic_mojha@quicinc.com> <mojha@codeaurora.org>
|
||||
Muna Sinada <quic_msinada@quicinc.com> <msinada@codeaurora.org>
|
||||
Murali Nalajala <quic_mnalajal@quicinc.com> <mnalajal@codeaurora.org>
|
||||
|
|
|
|||
|
|
@ -917,9 +917,8 @@ static void zram_account_writeback_submit(struct zram *zram)
|
|||
|
||||
static int zram_writeback_complete(struct zram *zram, struct zram_wb_req *req)
|
||||
{
|
||||
u32 size, index = req->pps->index;
|
||||
int err, prio;
|
||||
bool huge;
|
||||
u32 index = req->pps->index;
|
||||
int err;
|
||||
|
||||
err = blk_status_to_errno(req->bio.bi_status);
|
||||
if (err) {
|
||||
|
|
@ -946,28 +945,13 @@ static int zram_writeback_complete(struct zram *zram, struct zram_wb_req *req)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (zram->compressed_wb) {
|
||||
/*
|
||||
* ZRAM_WB slots get freed, we need to preserve data required
|
||||
* for read decompression.
|
||||
*/
|
||||
size = get_slot_size(zram, index);
|
||||
prio = get_slot_comp_priority(zram, index);
|
||||
huge = test_slot_flag(zram, index, ZRAM_HUGE);
|
||||
}
|
||||
|
||||
slot_free(zram, index);
|
||||
set_slot_flag(zram, index, ZRAM_WB);
|
||||
clear_slot_flag(zram, index, ZRAM_IDLE);
|
||||
if (test_slot_flag(zram, index, ZRAM_HUGE))
|
||||
atomic64_dec(&zram->stats.huge_pages);
|
||||
atomic64_sub(get_slot_size(zram, index), &zram->stats.compr_data_size);
|
||||
zs_free(zram->mem_pool, get_slot_handle(zram, index));
|
||||
set_slot_handle(zram, index, req->blk_idx);
|
||||
|
||||
if (zram->compressed_wb) {
|
||||
if (huge)
|
||||
set_slot_flag(zram, index, ZRAM_HUGE);
|
||||
set_slot_size(zram, index, size);
|
||||
set_slot_comp_priority(zram, index, prio);
|
||||
}
|
||||
|
||||
atomic64_inc(&zram->stats.pages_stored);
|
||||
set_slot_flag(zram, index, ZRAM_WB);
|
||||
|
||||
out:
|
||||
slot_unlock(zram, index);
|
||||
|
|
@ -2010,8 +1994,13 @@ static void slot_free(struct zram *zram, u32 index)
|
|||
set_slot_comp_priority(zram, index, 0);
|
||||
|
||||
if (test_slot_flag(zram, index, ZRAM_HUGE)) {
|
||||
/*
|
||||
* Writeback completion decrements ->huge_pages but keeps
|
||||
* ZRAM_HUGE flag for deferred decompression path.
|
||||
*/
|
||||
if (!test_slot_flag(zram, index, ZRAM_WB))
|
||||
atomic64_dec(&zram->stats.huge_pages);
|
||||
clear_slot_flag(zram, index, ZRAM_HUGE);
|
||||
atomic64_dec(&zram->stats.huge_pages);
|
||||
}
|
||||
|
||||
if (test_slot_flag(zram, index, ZRAM_WB)) {
|
||||
|
|
|
|||
|
|
@ -810,6 +810,12 @@ struct damon_ctx {
|
|||
struct damos_walk_control *walk_control;
|
||||
struct mutex walk_control_lock;
|
||||
|
||||
/*
|
||||
* indicate if this may be corrupted. Currentonly this is set only for
|
||||
* damon_commit_ctx() failure.
|
||||
*/
|
||||
bool maybe_corrupted;
|
||||
|
||||
/* Working thread of the given DAMON context */
|
||||
struct task_struct *kdamond;
|
||||
/* Protects @kdamond field access */
|
||||
|
|
|
|||
|
|
@ -1252,6 +1252,7 @@ int damon_commit_ctx(struct damon_ctx *dst, struct damon_ctx *src)
|
|||
{
|
||||
int err;
|
||||
|
||||
dst->maybe_corrupted = true;
|
||||
if (!is_power_of_2(src->min_region_sz))
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -1277,6 +1278,7 @@ int damon_commit_ctx(struct damon_ctx *dst, struct damon_ctx *src)
|
|||
dst->addr_unit = src->addr_unit;
|
||||
dst->min_region_sz = src->min_region_sz;
|
||||
|
||||
dst->maybe_corrupted = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2678,6 +2680,8 @@ static void kdamond_call(struct damon_ctx *ctx, bool cancel)
|
|||
complete(&control->completion);
|
||||
else if (control->canceled && control->dealloc_on_cancel)
|
||||
kfree(control);
|
||||
if (!cancel && ctx->maybe_corrupted)
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_lock(&ctx->call_controls_lock);
|
||||
|
|
@ -2707,6 +2711,8 @@ static int kdamond_wait_activation(struct damon_ctx *ctx)
|
|||
kdamond_usleep(min_wait_time);
|
||||
|
||||
kdamond_call(ctx, false);
|
||||
if (ctx->maybe_corrupted)
|
||||
return -EINVAL;
|
||||
damos_walk_cancel(ctx);
|
||||
}
|
||||
return -EBUSY;
|
||||
|
|
@ -2790,6 +2796,8 @@ static int kdamond_fn(void *data)
|
|||
* kdamond_merge_regions() if possible, to reduce overhead
|
||||
*/
|
||||
kdamond_call(ctx, false);
|
||||
if (ctx->maybe_corrupted)
|
||||
break;
|
||||
if (!list_empty(&ctx->schemes))
|
||||
kdamond_apply_schemes(ctx);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -145,12 +145,59 @@ static int damon_stat_damon_call_fn(void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct damon_stat_system_ram_range_walk_arg {
|
||||
bool walked;
|
||||
struct resource res;
|
||||
};
|
||||
|
||||
static int damon_stat_system_ram_walk_fn(struct resource *res, void *arg)
|
||||
{
|
||||
struct damon_stat_system_ram_range_walk_arg *a = arg;
|
||||
|
||||
if (!a->walked) {
|
||||
a->walked = true;
|
||||
a->res.start = res->start;
|
||||
}
|
||||
a->res.end = res->end;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long damon_stat_res_to_core_addr(resource_size_t ra,
|
||||
unsigned long addr_unit)
|
||||
{
|
||||
/*
|
||||
* Use div_u64() for avoiding linking errors related with __udivdi3,
|
||||
* __aeabi_uldivmod, or similar problems. This should also improve the
|
||||
* performance optimization (read div_u64() comment for the detail).
|
||||
*/
|
||||
if (sizeof(ra) == 8 && sizeof(addr_unit) == 4)
|
||||
return div_u64(ra, addr_unit);
|
||||
return ra / addr_unit;
|
||||
}
|
||||
|
||||
static int damon_stat_set_monitoring_region(struct damon_target *t,
|
||||
unsigned long addr_unit, unsigned long min_region_sz)
|
||||
{
|
||||
struct damon_addr_range addr_range;
|
||||
struct damon_stat_system_ram_range_walk_arg arg = {};
|
||||
|
||||
walk_system_ram_res(0, -1, &arg, damon_stat_system_ram_walk_fn);
|
||||
if (!arg.walked)
|
||||
return -EINVAL;
|
||||
addr_range.start = damon_stat_res_to_core_addr(
|
||||
arg.res.start, addr_unit);
|
||||
addr_range.end = damon_stat_res_to_core_addr(
|
||||
arg.res.end + 1, addr_unit);
|
||||
if (addr_range.end <= addr_range.start)
|
||||
return -EINVAL;
|
||||
return damon_set_regions(t, &addr_range, 1, min_region_sz);
|
||||
}
|
||||
|
||||
static struct damon_ctx *damon_stat_build_ctx(void)
|
||||
{
|
||||
struct damon_ctx *ctx;
|
||||
struct damon_attrs attrs;
|
||||
struct damon_target *target;
|
||||
unsigned long start = 0, end = 0;
|
||||
|
||||
ctx = damon_new_ctx();
|
||||
if (!ctx)
|
||||
|
|
@ -180,8 +227,8 @@ static struct damon_ctx *damon_stat_build_ctx(void)
|
|||
if (!target)
|
||||
goto free_out;
|
||||
damon_add_target(ctx, target);
|
||||
if (damon_set_region_biggest_system_ram_default(target, &start, &end,
|
||||
ctx->min_region_sz))
|
||||
if (damon_stat_set_monitoring_region(target, ctx->addr_unit,
|
||||
ctx->min_region_sz))
|
||||
goto free_out;
|
||||
return ctx;
|
||||
free_out:
|
||||
|
|
|
|||
|
|
@ -457,6 +457,13 @@ static void cleanup_partial_anon_vmas(struct vm_area_struct *vma)
|
|||
list_del(&avc->same_vma);
|
||||
anon_vma_chain_free(avc);
|
||||
}
|
||||
|
||||
/*
|
||||
* The anon_vma assigned to this VMA is no longer valid, as we were not
|
||||
* able to correctly clone AVC state. Avoid inconsistent anon_vma tree
|
||||
* state by resetting.
|
||||
*/
|
||||
vma->anon_vma = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -942,9 +942,15 @@ static bool zswap_decompress(struct zswap_entry *entry, struct folio *folio)
|
|||
|
||||
/* zswap entries of length PAGE_SIZE are not compressed. */
|
||||
if (entry->length == PAGE_SIZE) {
|
||||
void *dst;
|
||||
|
||||
WARN_ON_ONCE(input->length != PAGE_SIZE);
|
||||
memcpy_from_sglist(kmap_local_folio(folio, 0), input, 0, PAGE_SIZE);
|
||||
|
||||
dst = kmap_local_folio(folio, 0);
|
||||
memcpy_from_sglist(dst, input, 0, PAGE_SIZE);
|
||||
dlen = PAGE_SIZE;
|
||||
kunmap_local(dst);
|
||||
flush_dcache_folio(folio);
|
||||
} else {
|
||||
sg_init_table(&output, 1);
|
||||
sg_set_folio(&output, folio, PAGE_SIZE, 0);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user