162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * NUMA memory policies for Linux. 462306a36Sopenharmony_ci * Copyright 2003,2004 Andi Kleen SuSE Labs 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#ifndef _LINUX_MEMPOLICY_H 762306a36Sopenharmony_ci#define _LINUX_MEMPOLICY_H 1 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/sched.h> 1062306a36Sopenharmony_ci#include <linux/mmzone.h> 1162306a36Sopenharmony_ci#include <linux/slab.h> 1262306a36Sopenharmony_ci#include <linux/rbtree.h> 1362306a36Sopenharmony_ci#include <linux/spinlock.h> 1462306a36Sopenharmony_ci#include <linux/nodemask.h> 1562306a36Sopenharmony_ci#include <linux/pagemap.h> 1662306a36Sopenharmony_ci#include <uapi/linux/mempolicy.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistruct mm_struct; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#ifdef CONFIG_NUMA 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* 2362306a36Sopenharmony_ci * Describe a memory policy. 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * A mempolicy can be either associated with a process or with a VMA. 2662306a36Sopenharmony_ci * For VMA related allocations the VMA policy is preferred, otherwise 2762306a36Sopenharmony_ci * the process policy is used. Interrupts ignore the memory policy 2862306a36Sopenharmony_ci * of the current process. 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * Locking policy for interleave: 3162306a36Sopenharmony_ci * In process context there is no locking because only the process accesses 3262306a36Sopenharmony_ci * its own state. All vma manipulation is somewhat protected by a down_read on 3362306a36Sopenharmony_ci * mmap_lock. 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * Freeing policy: 3662306a36Sopenharmony_ci * Mempolicy objects are reference counted. A mempolicy will be freed when 3762306a36Sopenharmony_ci * mpol_put() decrements the reference count to zero. 3862306a36Sopenharmony_ci * 3962306a36Sopenharmony_ci * Duplicating policy objects: 4062306a36Sopenharmony_ci * mpol_dup() allocates a new mempolicy and copies the specified mempolicy 4162306a36Sopenharmony_ci * to the new storage. The reference count of the new object is initialized 4262306a36Sopenharmony_ci * to 1, representing the caller of mpol_dup(). 4362306a36Sopenharmony_ci */ 4462306a36Sopenharmony_cistruct mempolicy { 4562306a36Sopenharmony_ci atomic_t refcnt; 4662306a36Sopenharmony_ci unsigned short mode; /* See MPOL_* above */ 4762306a36Sopenharmony_ci unsigned short flags; /* See set_mempolicy() MPOL_F_* above */ 4862306a36Sopenharmony_ci nodemask_t nodes; /* interleave/bind/perfer */ 4962306a36Sopenharmony_ci int home_node; /* Home node to use for MPOL_BIND and MPOL_PREFERRED_MANY */ 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci union { 5262306a36Sopenharmony_ci nodemask_t cpuset_mems_allowed; /* relative to these nodes */ 5362306a36Sopenharmony_ci nodemask_t user_nodemask; /* nodemask passed by user */ 5462306a36Sopenharmony_ci } w; 5562306a36Sopenharmony_ci}; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/* 5862306a36Sopenharmony_ci * Support for managing mempolicy data objects (clone, copy, destroy) 5962306a36Sopenharmony_ci * The default fast path of a NULL MPOL_DEFAULT policy is always inlined. 6062306a36Sopenharmony_ci */ 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ciextern void __mpol_put(struct mempolicy *pol); 6362306a36Sopenharmony_cistatic inline void mpol_put(struct mempolicy *pol) 6462306a36Sopenharmony_ci{ 6562306a36Sopenharmony_ci if (pol) 6662306a36Sopenharmony_ci __mpol_put(pol); 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci/* 7062306a36Sopenharmony_ci * Does mempolicy pol need explicit unref after use? 7162306a36Sopenharmony_ci * Currently only needed for shared policies. 7262306a36Sopenharmony_ci */ 7362306a36Sopenharmony_cistatic inline int mpol_needs_cond_ref(struct mempolicy *pol) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci return (pol && (pol->flags & MPOL_F_SHARED)); 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic inline void mpol_cond_put(struct mempolicy *pol) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci if (mpol_needs_cond_ref(pol)) 8162306a36Sopenharmony_ci __mpol_put(pol); 8262306a36Sopenharmony_ci} 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ciextern struct mempolicy *__mpol_dup(struct mempolicy *pol); 8562306a36Sopenharmony_cistatic inline struct mempolicy *mpol_dup(struct mempolicy *pol) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci if (pol) 8862306a36Sopenharmony_ci pol = __mpol_dup(pol); 8962306a36Sopenharmony_ci return pol; 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci#define vma_policy(vma) ((vma)->vm_policy) 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic inline void mpol_get(struct mempolicy *pol) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci if (pol) 9762306a36Sopenharmony_ci atomic_inc(&pol->refcnt); 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ciextern bool __mpol_equal(struct mempolicy *a, struct mempolicy *b); 10162306a36Sopenharmony_cistatic inline bool mpol_equal(struct mempolicy *a, struct mempolicy *b) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci if (a == b) 10462306a36Sopenharmony_ci return true; 10562306a36Sopenharmony_ci return __mpol_equal(a, b); 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci/* 10962306a36Sopenharmony_ci * Tree of shared policies for a shared memory region. 11062306a36Sopenharmony_ci * Maintain the policies in a pseudo mm that contains vmas. The vmas 11162306a36Sopenharmony_ci * carry the policy. As a special twist the pseudo mm is indexed in pages, not 11262306a36Sopenharmony_ci * bytes, so that we can work with shared memory segments bigger than 11362306a36Sopenharmony_ci * unsigned long. 11462306a36Sopenharmony_ci */ 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistruct sp_node { 11762306a36Sopenharmony_ci struct rb_node nd; 11862306a36Sopenharmony_ci unsigned long start, end; 11962306a36Sopenharmony_ci struct mempolicy *policy; 12062306a36Sopenharmony_ci}; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistruct shared_policy { 12362306a36Sopenharmony_ci struct rb_root root; 12462306a36Sopenharmony_ci rwlock_t lock; 12562306a36Sopenharmony_ci}; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ciint vma_dup_policy(struct vm_area_struct *src, struct vm_area_struct *dst); 12862306a36Sopenharmony_civoid mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol); 12962306a36Sopenharmony_ciint mpol_set_shared_policy(struct shared_policy *info, 13062306a36Sopenharmony_ci struct vm_area_struct *vma, 13162306a36Sopenharmony_ci struct mempolicy *new); 13262306a36Sopenharmony_civoid mpol_free_shared_policy(struct shared_policy *p); 13362306a36Sopenharmony_cistruct mempolicy *mpol_shared_policy_lookup(struct shared_policy *sp, 13462306a36Sopenharmony_ci unsigned long idx); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistruct mempolicy *get_task_policy(struct task_struct *p); 13762306a36Sopenharmony_cistruct mempolicy *__get_vma_policy(struct vm_area_struct *vma, 13862306a36Sopenharmony_ci unsigned long addr); 13962306a36Sopenharmony_cibool vma_policy_mof(struct vm_area_struct *vma); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ciextern void numa_default_policy(void); 14262306a36Sopenharmony_ciextern void numa_policy_init(void); 14362306a36Sopenharmony_ciextern void mpol_rebind_task(struct task_struct *tsk, const nodemask_t *new); 14462306a36Sopenharmony_ciextern void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ciextern int huge_node(struct vm_area_struct *vma, 14762306a36Sopenharmony_ci unsigned long addr, gfp_t gfp_flags, 14862306a36Sopenharmony_ci struct mempolicy **mpol, nodemask_t **nodemask); 14962306a36Sopenharmony_ciextern bool init_nodemask_of_mempolicy(nodemask_t *mask); 15062306a36Sopenharmony_ciextern bool mempolicy_in_oom_domain(struct task_struct *tsk, 15162306a36Sopenharmony_ci const nodemask_t *mask); 15262306a36Sopenharmony_ciextern nodemask_t *policy_nodemask(gfp_t gfp, struct mempolicy *policy); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ciextern unsigned int mempolicy_slab_node(void); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ciextern enum zone_type policy_zone; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cistatic inline void check_highest_zone(enum zone_type k) 15962306a36Sopenharmony_ci{ 16062306a36Sopenharmony_ci if (k > policy_zone && k != ZONE_MOVABLE) 16162306a36Sopenharmony_ci policy_zone = k; 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ciint do_migrate_pages(struct mm_struct *mm, const nodemask_t *from, 16562306a36Sopenharmony_ci const nodemask_t *to, int flags); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci#ifdef CONFIG_TMPFS 16962306a36Sopenharmony_ciextern int mpol_parse_str(char *str, struct mempolicy **mpol); 17062306a36Sopenharmony_ci#endif 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ciextern void mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci/* Check if a vma is migratable */ 17562306a36Sopenharmony_ciextern bool vma_migratable(struct vm_area_struct *vma); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ciextern int mpol_misplaced(struct page *, struct vm_area_struct *, unsigned long); 17862306a36Sopenharmony_ciextern void mpol_put_task_policy(struct task_struct *); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_cistatic inline bool mpol_is_preferred_many(struct mempolicy *pol) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci return (pol->mode == MPOL_PREFERRED_MANY); 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ciextern bool apply_policy_zone(struct mempolicy *policy, enum zone_type zone); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci#else 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistruct mempolicy {}; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cistatic inline bool mpol_equal(struct mempolicy *a, struct mempolicy *b) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci return true; 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistatic inline void mpol_put(struct mempolicy *p) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic inline void mpol_cond_put(struct mempolicy *pol) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci} 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic inline void mpol_get(struct mempolicy *pol) 20562306a36Sopenharmony_ci{ 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistruct shared_policy {}; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cistatic inline void mpol_shared_policy_init(struct shared_policy *sp, 21162306a36Sopenharmony_ci struct mempolicy *mpol) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistatic inline void mpol_free_shared_policy(struct shared_policy *p) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic inline struct mempolicy * 22062306a36Sopenharmony_cimpol_shared_policy_lookup(struct shared_policy *sp, unsigned long idx) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci return NULL; 22362306a36Sopenharmony_ci} 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci#define vma_policy(vma) NULL 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic inline int 22862306a36Sopenharmony_civma_dup_policy(struct vm_area_struct *src, struct vm_area_struct *dst) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci return 0; 23162306a36Sopenharmony_ci} 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_cistatic inline void numa_policy_init(void) 23462306a36Sopenharmony_ci{ 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic inline void numa_default_policy(void) 23862306a36Sopenharmony_ci{ 23962306a36Sopenharmony_ci} 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic inline void mpol_rebind_task(struct task_struct *tsk, 24262306a36Sopenharmony_ci const nodemask_t *new) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_cistatic inline void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_cistatic inline int huge_node(struct vm_area_struct *vma, 25162306a36Sopenharmony_ci unsigned long addr, gfp_t gfp_flags, 25262306a36Sopenharmony_ci struct mempolicy **mpol, nodemask_t **nodemask) 25362306a36Sopenharmony_ci{ 25462306a36Sopenharmony_ci *mpol = NULL; 25562306a36Sopenharmony_ci *nodemask = NULL; 25662306a36Sopenharmony_ci return 0; 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistatic inline bool init_nodemask_of_mempolicy(nodemask_t *m) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci return false; 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic inline int do_migrate_pages(struct mm_struct *mm, const nodemask_t *from, 26562306a36Sopenharmony_ci const nodemask_t *to, int flags) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci return 0; 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic inline void check_highest_zone(int k) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci#ifdef CONFIG_TMPFS 27562306a36Sopenharmony_cistatic inline int mpol_parse_str(char *str, struct mempolicy **mpol) 27662306a36Sopenharmony_ci{ 27762306a36Sopenharmony_ci return 1; /* error */ 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci#endif 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_cistatic inline int mpol_misplaced(struct page *page, struct vm_area_struct *vma, 28262306a36Sopenharmony_ci unsigned long address) 28362306a36Sopenharmony_ci{ 28462306a36Sopenharmony_ci return -1; /* no node preference */ 28562306a36Sopenharmony_ci} 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_cistatic inline void mpol_put_task_policy(struct task_struct *task) 28862306a36Sopenharmony_ci{ 28962306a36Sopenharmony_ci} 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_cistatic inline bool mpol_is_preferred_many(struct mempolicy *pol) 29262306a36Sopenharmony_ci{ 29362306a36Sopenharmony_ci return false; 29462306a36Sopenharmony_ci} 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci#endif /* CONFIG_NUMA */ 29762306a36Sopenharmony_ci#endif 298