From: Fang Lijun fanglijun3@huawei.com
ascend inclusion category: bugfix bugzilla: NA CVE: NA
-------------------------------------------------
Dvpp use flags MAP_CHECKNODE to enable check node hugetlb. The global variable numanode will cause the mmap not be reenterable, so use the flags BITS[26:31] directly.
Fixes: cbdbfc7514ab ("mm: Check numa node hugepages enough when mmap hugetlb") Signed-off-by: Fang Lijun fanglijun3@huawei.com Reviewed-by: Ding Tianhong dingtianhong@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: Cheng Jian cj.chengjian@huawei.com --- fs/hugetlbfs/inode.c | 2 +- include/linux/mm.h | 2 ++ include/uapi/asm-generic/mman.h | 1 + mm/hugetlb.c | 2 +- mm/mmap.c | 28 ++++++++++++++++------------ 5 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 7a8994585b89..a878f009347c 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -211,7 +211,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) inode_lock(inode); file_accessed(file);
- if (is_set_cdmmask()) { + if (is_set_cdmmask() && (vma->vm_flags & VM_CHECKNODE)) { ret = hugetlb_checknode(vma, len >> huge_page_shift(h)); if (ret < 0) goto out; diff --git a/include/linux/mm.h b/include/linux/mm.h index 679860bb2238..7ea591ec38c4 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -234,6 +234,8 @@ extern unsigned int kobjsize(const void *objp); #define VM_CDM 0x100000000 /* Contains coherent device memory */ #endif
+#define VM_CHECKNODE 0x200000000 + #ifdef CONFIG_ARCH_USES_HIGH_VMA_FLAGS #define VM_HIGH_ARCH_BIT_0 32 /* bit only usable on 64-bit architectures */ #define VM_HIGH_ARCH_BIT_1 33 /* bit only usable on 64-bit architectures */ diff --git a/include/uapi/asm-generic/mman.h b/include/uapi/asm-generic/mman.h index 1915bcc107eb..233a5e82407c 100644 --- a/include/uapi/asm-generic/mman.h +++ b/include/uapi/asm-generic/mman.h @@ -5,6 +5,7 @@ #include <asm-generic/mman-common.h>
#define MAP_GROWSDOWN 0x0100 /* stack-like segment */ +#define MAP_CHECKNODE 0x0400 /* hugetlb numa node check */ #define MAP_DENYWRITE 0x0800 /* ETXTBSY */ #define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ #define MAP_LOCKED 0x2000 /* pages are locked */ diff --git a/mm/hugetlb.c b/mm/hugetlb.c index efb68abe9f35..327d24f0cf0d 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -970,7 +970,7 @@ static struct page *dequeue_huge_page_vma(struct hstate *h, if (page && !avoid_reserve && vma_has_reserves(vma, chg)) { SetPagePrivate(page); h->resv_huge_pages--; - if (is_set_cdmmask()) + if (is_set_cdmmask() && (vma->vm_flags & VM_CHECKNODE)) h->resv_huge_pages_node[vma->vm_flags >> CHECKNODE_BITS]--; }
diff --git a/mm/mmap.c b/mm/mmap.c index 00702331afc1..6197c5590ded 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -69,7 +69,6 @@ const int mmap_rnd_compat_bits_max = CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX; int mmap_rnd_compat_bits __read_mostly = CONFIG_ARCH_MMAP_RND_COMPAT_BITS; #endif
-static unsigned long numanode; static bool ignore_rlimit_data; core_param(ignore_rlimit_data, ignore_rlimit_data, bool, 0644);
@@ -1565,8 +1564,9 @@ unsigned long do_mmap(struct file *file, unsigned long addr, /* set numa node id into vm_flags, * hugetlbfs file mmap will use it to check node */ - if (is_set_cdmmask()) - vm_flags |= ((numanode << CHECKNODE_BITS) & CHECKNODE_MASK); + if (is_set_cdmmask() && (flags & MAP_CHECKNODE)) + vm_flags |= VM_CHECKNODE | ((((flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK) + << CHECKNODE_BITS) & CHECKNODE_MASK);
addr = mmap_region(file, addr, len, vm_flags, pgoff, uf); if (!IS_ERR_VALUE(addr) && @@ -1583,12 +1583,6 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len, struct file *file = NULL; unsigned long retval;
- /* get mmap numa node id */ - if (is_set_cdmmask()) { - numanode = (flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK; - flags &= ~(MAP_HUGE_MASK << MAP_HUGE_SHIFT); - } - if (!(flags & MAP_ANONYMOUS)) { audit_mmap_fd(fd, flags); file = fget(fd); @@ -1602,12 +1596,23 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len, } else if (flags & MAP_HUGETLB) { struct user_struct *user = NULL; struct hstate *hs; + int page_size_log;
- hs = hstate_sizelog((flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK); + /* + * If config cdm node, flags bits [26:31] used for + * mmap hugetlb check node + */ + if (is_set_cdmmask()) + page_size_log = 0; + else + page_size_log = (flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK; + + hs = hstate_sizelog(page_size_log); if (!hs) return -EINVAL;
len = ALIGN(len, huge_page_size(hs)); + /* * VM_NORESERVE is used because the reservations will be * taken when vm_ops->mmap() is called @@ -1616,8 +1621,7 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len, */ file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE, - &user, HUGETLB_ANONHUGE_INODE, - (flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK); + &user, HUGETLB_ANONHUGE_INODE, page_size_log); if (IS_ERR(file)) return PTR_ERR(file); }