diff options
Diffstat (limited to 'mm/util.c')
| -rw-r--r-- | mm/util.c | 111 | 
1 files changed, 66 insertions, 45 deletions
| diff --git a/mm/util.c b/mm/util.c index bacabe446906..e58151a61255 100644 --- a/mm/util.c +++ b/mm/util.c @@ -654,81 +654,78 @@ void *kvrealloc(const void *p, size_t oldsize, size_t newsize, gfp_t flags)  }  EXPORT_SYMBOL(kvrealloc); -static inline void *__page_rmapping(struct page *page) -{ -	unsigned long mapping; - -	mapping = (unsigned long)page->mapping; -	mapping &= ~PAGE_MAPPING_FLAGS; - -	return (void *)mapping; -} -  /* Neutral page->mapping pointer to address_space or anon_vma or other */  void *page_rmapping(struct page *page)  { -	page = compound_head(page); -	return __page_rmapping(page); +	return folio_raw_mapping(page_folio(page));  } -/* - * Return true if this page is mapped into pagetables. - * For compound page it returns true if any subpage of compound page is mapped. +/** + * folio_mapped - Is this folio mapped into userspace? + * @folio: The folio. + * + * Return: True if any page in this folio is referenced by user page tables.   */ -bool page_mapped(struct page *page) +bool folio_mapped(struct folio *folio)  { -	int i; +	long i, nr; -	if (likely(!PageCompound(page))) -		return atomic_read(&page->_mapcount) >= 0; -	page = compound_head(page); -	if (atomic_read(compound_mapcount_ptr(page)) >= 0) +	if (folio_test_single(folio)) +		return atomic_read(&folio->_mapcount) >= 0; +	if (atomic_read(folio_mapcount_ptr(folio)) >= 0)  		return true; -	if (PageHuge(page)) +	if (folio_test_hugetlb(folio))  		return false; -	for (i = 0; i < compound_nr(page); i++) { -		if (atomic_read(&page[i]._mapcount) >= 0) + +	nr = folio_nr_pages(folio); +	for (i = 0; i < nr; i++) { +		if (atomic_read(&folio_page(folio, i)->_mapcount) >= 0)  			return true;  	}  	return false;  } -EXPORT_SYMBOL(page_mapped); +EXPORT_SYMBOL(folio_mapped);  struct anon_vma *page_anon_vma(struct page *page)  { -	unsigned long mapping; +	struct folio *folio = page_folio(page); +	unsigned long mapping = (unsigned long)folio->mapping; -	page = compound_head(page); -	mapping = (unsigned long)page->mapping;  	if ((mapping & PAGE_MAPPING_FLAGS) != PAGE_MAPPING_ANON)  		return NULL; -	return __page_rmapping(page); +	return (void *)(mapping - PAGE_MAPPING_ANON);  } -struct address_space *page_mapping(struct page *page) +/** + * folio_mapping - Find the mapping where this folio is stored. + * @folio: The folio. + * + * For folios which are in the page cache, return the mapping that this + * page belongs to.  Folios in the swap cache return the swap mapping + * this page is stored in (which is different from the mapping for the + * swap file or swap device where the data is stored). + * + * You can call this for folios which aren't in the swap cache or page + * cache and it will return NULL. + */ +struct address_space *folio_mapping(struct folio *folio)  {  	struct address_space *mapping; -	page = compound_head(page); -  	/* This happens if someone calls flush_dcache_page on slab page */ -	if (unlikely(PageSlab(page))) +	if (unlikely(folio_test_slab(folio)))  		return NULL; -	if (unlikely(PageSwapCache(page))) { -		swp_entry_t entry; +	if (unlikely(folio_test_swapcache(folio))) +		return swap_address_space(folio_swap_entry(folio)); -		entry.val = page_private(page); -		return swap_address_space(entry); -	} - -	mapping = page->mapping; +	mapping = folio->mapping;  	if ((unsigned long)mapping & PAGE_MAPPING_ANON)  		return NULL;  	return (void *)((unsigned long)mapping & ~PAGE_MAPPING_FLAGS);  } -EXPORT_SYMBOL(page_mapping); +EXPORT_SYMBOL(folio_mapping);  /* Slow path of page_mapcount() for compound pages */  int __page_mapcount(struct page *page) @@ -750,13 +747,26 @@ int __page_mapcount(struct page *page)  }  EXPORT_SYMBOL_GPL(__page_mapcount); -void copy_huge_page(struct page *dst, struct page *src) +/** + * folio_copy - Copy the contents of one folio to another. + * @dst: Folio to copy to. + * @src: Folio to copy from. + * + * The bytes in the folio represented by @src are copied to @dst. + * Assumes the caller has validated that @dst is at least as large as @src. + * Can be called in atomic context for order-0 folios, but if the folio is + * larger, it may sleep. + */ +void folio_copy(struct folio *dst, struct folio *src)  { -	unsigned i, nr = compound_nr(src); +	long i = 0; +	long nr = folio_nr_pages(src); -	for (i = 0; i < nr; i++) { +	for (;;) { +		copy_highpage(folio_page(dst, i), folio_page(src, i)); +		if (++i == nr) +			break;  		cond_resched(); -		copy_highpage(nth_page(dst, i), nth_page(src, i));  	}  } @@ -1079,3 +1089,14 @@ void page_offline_end(void)  	up_write(&page_offline_rwsem);  }  EXPORT_SYMBOL(page_offline_end); + +#ifndef ARCH_IMPLEMENTS_FLUSH_DCACHE_FOLIO +void flush_dcache_folio(struct folio *folio) +{ +	long i, nr = folio_nr_pages(folio); + +	for (i = 0; i < nr; i++) +		flush_dcache_page(folio_page(folio, i)); +} +EXPORT_SYMBOL(flush_dcache_folio); +#endif |