From 1f3b5458415efd586c9c45abfea48e59d6122cbc Mon Sep 17 00:00:00 2001 From: Lijun Fang Date: Mon, 13 May 2019 22:39:44 +0800 Subject: [PATCH] mm: Be allowed to alloc CDM node memory for MPOL_BIND euler inclusion category: feature bugzilla: 11082 CVE: NA ----------------- CDM nodes should not be part of mems_allowed, However, It must be allowed to alloc from CDM node, when mpol->mode was MPOL_BIND. Signed-off-by: Lijun Fang Reviewed-by: zhong jiang Signed-off-by: Yang Yingliang --- include/linux/mm.h | 8 ++++---- mm/hugetlb.c | 16 +++++++++++----- mm/internal.h | 4 ++++ mm/mempolicy.c | 6 +++++- mm/page_alloc.c | 12 ++++++++++-- 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 6d02e3b8a8a9..a7b322093ac4 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -204,10 +204,6 @@ extern unsigned int kobjsize(const void *objp); #define VM_NORESERVE 0x00200000 /* should the VM suppress accounting */ #define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */ -#ifdef CONFIG_COHERENT_DEVICE -#define VM_CDM 0x00800000 /* Contains coherent device memory */ -#endif - #define VM_SYNC 0x00800000 /* Synchronous page faults */ #define VM_ARCH_1 0x01000000 /* Architecture-specific flag */ #define VM_WIPEONFORK 0x02000000 /* Wipe VMA contents in child. */ @@ -224,6 +220,10 @@ extern unsigned int kobjsize(const void *objp); #define VM_NOHUGEPAGE 0x40000000 /* MADV_NOHUGEPAGE marked this vma */ #define VM_MERGEABLE 0x80000000 /* KSM may merge identical pages */ +#ifdef CONFIG_COHERENT_DEVICE +#define VM_CDM 0x100000000 /* Contains coherent device memory */ +#endif + #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/mm/hugetlb.c b/mm/hugetlb.c index d467046ed100..22f4bc889a28 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -881,13 +881,17 @@ static struct page *dequeue_huge_page_node_exact(struct hstate *h, int nid) } static struct page *dequeue_huge_page_nodemask(struct hstate *h, gfp_t gfp_mask, int nid, - nodemask_t *nmask) + nodemask_t *nmask, struct mempolicy *mpol) { unsigned int cpuset_mems_cookie; struct zonelist *zonelist; struct zone *zone; struct zoneref *z; int node = -1; + bool mbind_cdmnode = false; + + if (is_cdm_node(nid) && mpol != NULL && mpol->mode == MPOL_BIND) + mbind_cdmnode = true; zonelist = node_zonelist(nid, gfp_mask); @@ -896,7 +900,8 @@ static struct page *dequeue_huge_page_nodemask(struct hstate *h, gfp_t gfp_mask, for_each_zone_zonelist_nodemask(zone, z, zonelist, gfp_zone(gfp_mask), nmask) { struct page *page; - if (!cpuset_zone_allowed(zone, gfp_mask)) + if (!cpuset_zone_allowed(zone, gfp_mask) && + mbind_cdmnode == false) continue; /* * no need to ask again on the same node. Pool is node rather than @@ -951,7 +956,7 @@ static struct page *dequeue_huge_page_vma(struct hstate *h, gfp_mask = htlb_alloc_mask(h); nid = huge_node(vma, address, gfp_mask, &mpol, &nodemask); - page = dequeue_huge_page_nodemask(h, gfp_mask, nid, nodemask); + page = dequeue_huge_page_nodemask(h, gfp_mask, nid, nodemask, mpol); if (page && !avoid_reserve && vma_has_reserves(vma, chg)) { SetPagePrivate(page); h->resv_huge_pages--; @@ -1638,7 +1643,7 @@ struct page *alloc_huge_page_node(struct hstate *h, int nid) spin_lock(&hugetlb_lock); if (h->free_huge_pages - h->resv_huge_pages > 0) - page = dequeue_huge_page_nodemask(h, gfp_mask, nid, NULL); + page = dequeue_huge_page_nodemask(h, gfp_mask, nid, NULL, NULL); spin_unlock(&hugetlb_lock); if (!page) @@ -1657,7 +1662,8 @@ struct page *alloc_huge_page_nodemask(struct hstate *h, int preferred_nid, if (h->free_huge_pages - h->resv_huge_pages > 0) { struct page *page; - page = dequeue_huge_page_nodemask(h, gfp_mask, preferred_nid, nmask); + page = dequeue_huge_page_nodemask(h, gfp_mask, preferred_nid, + nmask, NULL); if (page) { spin_unlock(&hugetlb_lock); return page; diff --git a/mm/internal.h b/mm/internal.h index 87256ae1bef8..ca41b400b4e6 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -485,6 +485,10 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone, #define ALLOC_CPUSET 0x40 /* check for correct cpuset */ #define ALLOC_CMA 0x80 /* allow allocations from CMA areas */ +#ifdef CONFIG_COHERENT_DEVICE +#define ALLOC_CDM 0x100 +#endif + enum ttu_flags; struct tlbflush_unmap_batch; diff --git a/mm/mempolicy.c b/mm/mempolicy.c index f5e7cacc20cb..e3ab1d942dd4 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -248,6 +248,9 @@ static int mpol_set_nodemask(struct mempolicy *pol, nodes_and(nsc->mask1, cpuset_current_mems_allowed, node_states[N_MEMORY]); +#ifdef CONFIG_COHERENT_DEVICE + nodes_or(nsc->mask1, cdmmask, nsc->mask1); +#endif VM_BUG_ON(!nodes); if (pol->mode == MPOL_PREFERRED && nodes_empty(*nodes)) nodes = NULL; /* explicit local allocation */ @@ -1776,7 +1779,8 @@ static nodemask_t *policy_nodemask(gfp_t gfp, struct mempolicy *policy) /* Lower zones don't get a nodemask applied for MPOL_BIND */ if (unlikely(policy->mode == MPOL_BIND) && apply_policy_zone(policy, gfp_zone(gfp)) && - cpuset_nodemask_valid_mems_allowed(&policy->v.nodes)) + (cpuset_nodemask_valid_mems_allowed(&policy->v.nodes) || + nodemask_has_cdm(policy->v.nodes))) return &policy->v.nodes; return NULL; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index d95e47a388b1..d70fb097e15f 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3301,7 +3301,11 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags, if (cpusets_enabled() && (alloc_flags & ALLOC_CPUSET) && - !__cpuset_zone_allowed(zone, gfp_mask)) + !__cpuset_zone_allowed(zone, gfp_mask) +#ifdef CONFIG_COHERENT_DEVICE + && !(alloc_flags & ALLOC_CDM) +#endif + ) continue; /* * When allocating a page cache page for writing, we @@ -4343,8 +4347,12 @@ static inline bool prepare_alloc_pages(gfp_t gfp_mask, unsigned int order, *alloc_mask |= __GFP_HARDWALL; if (!ac->nodemask) ac->nodemask = &cpuset_current_mems_allowed; - else + else { *alloc_flags |= ALLOC_CPUSET; +#ifdef CONFIG_COHERENT_DEVICE + *alloc_flags |= ALLOC_CDM; +#endif + } } fs_reclaim_acquire(gfp_mask); -- GitLab