mm/numa: Allow override of kernel's default NUMA policy

Add numa_policy kernel argument to allow overriding the kernel's default
NUMA policy at boot time.

Syntax identical to what tmpfs accepts as it's mpol argument is accepted.

Some examples:

 numa_policy=interleave
 numa_policy=interleave=skip-interleave
 numa_policy=bind:0-3,5,7,9-15
 numa_policy=bind=static:1-2

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
This commit is contained in:
Tvrtko Ursulin
2024-05-22 17:12:16 +01:00
committed by Dom Cobley
parent e42c8ed4a8
commit a760844451

View File

@@ -3142,7 +3142,9 @@ void __init numa_policy_init(void)
/* Reset policy of current process to default */ /* Reset policy of current process to default */
void numa_default_policy(void) void numa_default_policy(void)
{ {
do_set_mempolicy(MPOL_DEFAULT, 0, NULL); struct mempolicy *pol = &default_policy;
do_set_mempolicy(pol->mode, pol->flags, &pol->nodes);
} }
/* /*
@@ -3159,7 +3161,6 @@ static const char * const policy_modes[] =
[MPOL_PREFERRED_MANY] = "prefer (many)", [MPOL_PREFERRED_MANY] = "prefer (many)",
}; };
#ifdef CONFIG_TMPFS
/** /**
* mpol_parse_str - parse string to mempolicy, for tmpfs mpol mount option. * mpol_parse_str - parse string to mempolicy, for tmpfs mpol mount option.
* @str: string containing mempolicy to parse * @str: string containing mempolicy to parse
@@ -3172,13 +3173,18 @@ static const char * const policy_modes[] =
*/ */
int mpol_parse_str(char *str, struct mempolicy **mpol) int mpol_parse_str(char *str, struct mempolicy **mpol)
{ {
struct mempolicy *new = NULL; struct mempolicy *new;
unsigned short mode_flags; unsigned short mode_flags;
nodemask_t nodes; nodemask_t nodes;
char *nodelist = strchr(str, ':'); char *nodelist = strchr(str, ':');
char *flags = strchr(str, '='); char *flags = strchr(str, '=');
int err = 1, mode; int err = 1, mode;
if (*mpol)
new = *mpol;
else
new = NULL;
if (flags) if (flags)
*flags++ = '\0'; /* terminate mode string */ *flags++ = '\0'; /* terminate mode string */
@@ -3258,9 +3264,16 @@ int mpol_parse_str(char *str, struct mempolicy **mpol)
goto out; goto out;
} }
new = mpol_new(mode, mode_flags, &nodes); if (!new) {
if (IS_ERR(new)) new = mpol_new(mode, mode_flags, &nodes);
goto out; if (IS_ERR(new))
goto out;
} else {
atomic_set(&new->refcnt, 1);
new->mode = mode;
new->flags = mode_flags;
new->home_node = NUMA_NO_NODE;
}
/* /*
* Save nodes for mpol_to_str() to show the tmpfs mount options * Save nodes for mpol_to_str() to show the tmpfs mount options
@@ -3293,7 +3306,29 @@ out:
*mpol = new; *mpol = new;
return err; return err;
} }
#endif /* CONFIG_TMPFS */
static int __init setup_numapolicy(char *str)
{
struct mempolicy pol = { }, *ppol = &pol;
char buf[128];
int ret;
if (str)
ret = mpol_parse_str(str, &ppol);
else
ret = -EINVAL;
if (!ret) {
default_policy = pol;
mpol_to_str(buf, sizeof(buf), &pol);
pr_info("NUMA default policy overridden to '%s'\n", buf);
} else {
pr_warn("Unable to parse numa_policy=\n");
}
return ret == 0;
}
__setup("numa_policy=", setup_numapolicy);
/** /**
* mpol_to_str - format a mempolicy structure for printing * mpol_to_str - format a mempolicy structure for printing