mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
synced 2026-10-30 13:52:50 +01:00
commitbda420b985("numa balancing: migrate on fault among multiple bound nodes") adds new flag MPOL_F_NUMA_BALANCING to enable NUMA balancing for MPOL_BIND memory policy. When the cpuset of tasks changes, the mempolicy of the task is rebound by mpol_rebind_nodemask(). When MPOL_F_STATIC_NODES and MPOL_F_RELATIVE_NODES are both not set, the behaviour of rebinding should be same whenever MPOL_F_NUMA_BALANCING is set or not. So, when an application calls set_mempolicy() with MPOL_F_NUMA_BALANCING set but both MPOL_F_STATIC_NODES and MPOL_F_RELATIVE_NODES cleared, mempolicy.w.cpuset_mems_allowed should be set to cpuset_current_mems_allowed nodemask. However, in current implementation, mpol_store_user_nodemask() wrongly returns true, causing mempolicy->w.user_nodemask to be incorrectly set to the user-specified nodemask. Later, when the cpuset of the application changes, mpol_rebind_nodemask() ends up rebinding based on the user-specified nodemask rather than the cpuset_mems_allowed nodemask as intended. I can reproduce with the following steps in qemu with 4 NUMA nodes: 1. echo '+cpuset' > /sys/fs/cgroup/cgroup.subtree_control 2. mkdir /sys/fs/cgroup/test 3. ./reproducer & 4. cat /proc/$pid/numa_maps, the task is bound to NUMA 1 5. echo $pid > /sys/fs/cgroup/test/cgroup.procs 6. cat /proc/$pid/numa_maps, the task is bound to NUMA 0 now. The reproducer code: int main() { struct bitmask *bmp; int ret; bmp = numa_parse_nodestring("1"); ret = set_mempolicy(MPOL_BIND | MPOL_F_NUMA_BALANCING, bmp->maskp, bmp->size + 1); if (ret < 0) { perror("Failed to call set_mempolicy"); exit(-1); } while (1); return 0; } If I call set_mempolicy() without MPOL_F_NUMA_BALANCING in the reproducer code. After step 5, the task is still bound to NUMA 1. To fix this, only set mempolicy->w.user_nodemask to the user-specified nodemask if MPOL_F_STATIC_NODES or MPOL_F_RELATIVE_NODES is present. Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Fixes:bda420b985("numa balancing: migrate on fault among multiple bound nodes") Signed-off-by: Jinjiang Tu <[email protected]> Reviewed-by: Gregory Price <[email protected]> Reviewed-by: Huang Ying <[email protected]> Acked-by: David Hildenbrand (Red Hat) <[email protected]> Cc: Alistair Popple <[email protected]> Cc: Byungchul Park <[email protected]> Cc: Joshua Hahn <[email protected]> Cc: Kefeng Wang <[email protected]> Cc: Mathew Brost <[email protected]> Cc: Mel Gorman <mgorman <[email protected]> Cc: Rakie Kim <[email protected]> Cc: Zi Yan <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
86 lines
3.0 KiB
C
86 lines
3.0 KiB
C
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
|
/*
|
|
* NUMA memory policies for Linux.
|
|
* Copyright 2003,2004 Andi Kleen SuSE Labs
|
|
*/
|
|
#ifndef _UAPI_LINUX_MEMPOLICY_H
|
|
#define _UAPI_LINUX_MEMPOLICY_H
|
|
|
|
#include <linux/errno.h>
|
|
|
|
|
|
/*
|
|
* Both the MPOL_* mempolicy mode and the MPOL_F_* optional mode flags are
|
|
* passed by the user to either set_mempolicy() or mbind() in an 'int' actual.
|
|
* The MPOL_MODE_FLAGS macro determines the legal set of optional mode flags.
|
|
*/
|
|
|
|
/* Policies */
|
|
enum {
|
|
MPOL_DEFAULT,
|
|
MPOL_PREFERRED,
|
|
MPOL_BIND,
|
|
MPOL_INTERLEAVE,
|
|
MPOL_LOCAL,
|
|
MPOL_PREFERRED_MANY,
|
|
MPOL_WEIGHTED_INTERLEAVE,
|
|
MPOL_MAX, /* always last member of enum */
|
|
};
|
|
|
|
/* Flags for set_mempolicy */
|
|
#define MPOL_F_STATIC_NODES (1 << 15)
|
|
#define MPOL_F_RELATIVE_NODES (1 << 14)
|
|
#define MPOL_F_NUMA_BALANCING (1 << 13) /* Optimize with NUMA balancing if possible */
|
|
|
|
/*
|
|
* MPOL_MODE_FLAGS is the union of all possible optional mode flags passed to
|
|
* either set_mempolicy() or mbind().
|
|
*/
|
|
#define MPOL_MODE_FLAGS \
|
|
(MPOL_F_STATIC_NODES | MPOL_F_RELATIVE_NODES | MPOL_F_NUMA_BALANCING)
|
|
|
|
/* Whether the nodemask is specified by users */
|
|
#define MPOL_USER_NODEMASK_FLAGS (MPOL_F_STATIC_NODES | MPOL_F_RELATIVE_NODES)
|
|
|
|
/* Flags for get_mempolicy */
|
|
#define MPOL_F_NODE (1<<0) /* return next IL mode instead of node mask */
|
|
#define MPOL_F_ADDR (1<<1) /* look up vma using address */
|
|
#define MPOL_F_MEMS_ALLOWED (1<<2) /* return allowed memories */
|
|
|
|
/* Flags for mbind */
|
|
#define MPOL_MF_STRICT (1<<0) /* Verify existing pages in the mapping */
|
|
#define MPOL_MF_MOVE (1<<1) /* Move pages owned by this process to conform
|
|
to policy */
|
|
#define MPOL_MF_MOVE_ALL (1<<2) /* Move every page to conform to policy */
|
|
#define MPOL_MF_LAZY (1<<3) /* UNSUPPORTED FLAG: Lazy migrate on fault */
|
|
#define MPOL_MF_INTERNAL (1<<4) /* Internal flags start here */
|
|
|
|
#define MPOL_MF_VALID (MPOL_MF_STRICT | \
|
|
MPOL_MF_MOVE | \
|
|
MPOL_MF_MOVE_ALL)
|
|
|
|
/*
|
|
* Internal flags that share the struct mempolicy flags word with
|
|
* "mode flags". These flags are allocated from bit 0 up, as they
|
|
* are never OR'ed into the mode in mempolicy API arguments.
|
|
*/
|
|
#define MPOL_F_SHARED (1 << 0) /* identify shared policies */
|
|
#define MPOL_F_MOF (1 << 3) /* this policy wants migrate on fault */
|
|
#define MPOL_F_MORON (1 << 4) /* Migrate On protnone Reference On Node */
|
|
|
|
/*
|
|
* Enabling zone reclaim means the page allocator will attempt to fulfill
|
|
* the allocation request on the current node by triggering reclaim and
|
|
* trying to shrink the current node.
|
|
* Fallback allocations on the next candidates in the zonelist are considered
|
|
* when reclaim fails to free up enough memory in the current node/zone.
|
|
*
|
|
* These bit locations are exposed in the vm.zone_reclaim_mode sysctl.
|
|
* New bits are OK, but existing bits should not be changed.
|
|
*/
|
|
#define RECLAIM_ZONE (1<<0) /* Enable zone reclaim */
|
|
#define RECLAIM_WRITE (1<<1) /* Writeout pages during reclaim */
|
|
#define RECLAIM_UNMAP (1<<2) /* Unmap pages during reclaim */
|
|
|
|
#endif /* _UAPI_LINUX_MEMPOLICY_H */
|