diff options
Diffstat (limited to 'include/linux/mm.h')
| -rw-r--r-- | include/linux/mm.h | 20 | 
1 files changed, 15 insertions, 5 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h index f28f46eade6a..c1b7414c7bef 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -175,7 +175,7 @@ extern unsigned int kobjsize(const void *objp);   * Special vmas that are non-mergable, non-mlock()able.   * Note: mm/huge_memory.c VM_NO_THP depends on this definition.   */ -#define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_PFNMAP) +#define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_PFNMAP | VM_MIXEDMAP)  /*   * mapping from the currently active vm_flags protection bits (the @@ -399,8 +399,18 @@ static inline void compound_unlock_irqrestore(struct page *page,  static inline struct page *compound_head(struct page *page)  { -	if (unlikely(PageTail(page))) -		return page->first_page; +	if (unlikely(PageTail(page))) { +		struct page *head = page->first_page; + +		/* +		 * page->first_page may be a dangling pointer to an old +		 * compound page, so recheck that it is still a tail +		 * page before returning. +		 */ +		smp_rmb(); +		if (likely(PageTail(page))) +			return head; +	}  	return page;  } @@ -757,7 +767,7 @@ static inline bool __cpupid_match_pid(pid_t task_pid, int cpupid)  #ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS  static inline int page_cpupid_xchg_last(struct page *page, int cpupid)  { -	return xchg(&page->_last_cpupid, cpupid); +	return xchg(&page->_last_cpupid, cpupid & LAST_CPUPID_MASK);  }  static inline int page_cpupid_last(struct page *page) @@ -766,7 +776,7 @@ static inline int page_cpupid_last(struct page *page)  }  static inline void page_cpupid_reset_last(struct page *page)  { -	page->_last_cpupid = -1; +	page->_last_cpupid = -1 & LAST_CPUPID_MASK;  }  #else  static inline int page_cpupid_last(struct page *page)  | 
