Re: [sos-linux-ext-patches] [PATCH RFC 09/11] mm/migrate: thread migration policy through a control struct

From: Garg, Shivank

Date: Wed Sep 02 2026 - 07:34:27 EST


On Wed, 2026-09-02 at 10:52 +0000, Shivank Garg wrote:
> Migration mode and reason describe one migration invocation, but are passed
>

[...]

> @@ -2189,27 +2188,29 @@ static int migrate_folios_batch(struct list_head *from,
> */
> static int __migrate_lru_folios(struct list_head *from, new_folio_t get_new_folio,
> free_folio_t put_new_folio, unsigned long private,
> - enum migrate_mode mode, enum migrate_reason reason,
> - struct list_head *ret_folios,
> + const struct migrate_control *ctl, struct list_head *ret_folios,
> struct migrate_pages_stats *stats)
> {
> int rc, nr_failed = 0;
> LIST_HEAD(folios);
> LIST_HEAD(split_folios);
> struct migrate_pages_stats astats;
> + struct migrate_control async_ctl;
>
> - if (mode == MIGRATE_ASYNC) {
> + if (ctl->mode == MIGRATE_ASYNC) {
> rc = migrate_folios_batch(from, get_new_folio, put_new_folio,
> - private, mode, reason, ret_folios,
> + private, ctl, ret_folios,
> &split_folios, stats,
> NR_MAX_MIGRATE_PAGES_RETRY);
> goto out;
> }
>
> + async_ctl = *ctl;
> + async_ctl.mode = MIGRATE_ASYNC;
> memset(&astats, 0, sizeof(astats));
> /* Try to migrate in batch with MIGRATE_ASYNC mode firstly */



Sashiko:
Can this lead to an uninitialized stack variable being used?
If __migrate_lru_folios() is called with ctl->mode == MIGRATE_ASYNC, the
early check jumps directly to the out label, bypassing the initialization
of async_ctl. If large folios were split during that first pass, the
!list_empty(&split_folios) check will be true.
Could this cause migrate_folios_batch() to execute with garbage policy? For
example, it might interpret the uninitialized async_ctl.mode as MIGRATE_SYNC,
causing unintended blocking and sleeping during what should be an asynchronous
migration.
--

Yes, this is valid issue. I should initialize async_ctl early before it make
goto jump.

---
mm/migrate.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/mm/migrate.c b/mm/migrate.c
index 731836664a86..c75300e00388 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -2199,8 +2199,9 @@ static int __migrate_lru_folios(struct list_head *from, new_folio_t get_new_foli
LIST_HEAD(folios);
LIST_HEAD(split_folios);
struct migrate_pages_stats astats;
- struct migrate_control async_ctl;
+ struct migrate_control async_ctl = *ctl;

+ async_ctl.mode = MIGRATE_ASYNC;
if (ctl->mode == MIGRATE_ASYNC) {
rc = migrate_folios_batch(from, get_new_folio, put_new_folio,
private, ctl, ret_folios,
@@ -2209,8 +2210,6 @@ static int __migrate_lru_folios(struct list_head *from, new_folio_t get_new_foli
goto out;
}

- async_ctl = *ctl;
- async_ctl.mode = MIGRATE_ASYNC;
memset(&astats, 0, sizeof(astats));
/* Try to migrate in batch with MIGRATE_ASYNC mode firstly */
rc = migrate_folios_batch(from, get_new_folio, put_new_folio, private,
--
2.43.0