mm: Add functions to zero portions of a folio

These functions are wrappers around zero_user_segments(), which means
that zero_user_segments() can now be called for compound pages even when
CONFIG_TRANSPARENT_HUGEPAGE is disabled.

Use 'xend' as the name of the parameter to indicate that this is an
excluded end, not the more usual included end.  Excluding the end makes
more sense to the callers, but can cause confusion to readers who are
more used to seeing included ends.
Signed-off-by: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
parent ed2145c4
...@@ -230,10 +230,10 @@ static inline void tag_clear_highpage(struct page *page) ...@@ -230,10 +230,10 @@ static inline void tag_clear_highpage(struct page *page)
* If we pass in a base or tail page, we can zero up to PAGE_SIZE. * If we pass in a base or tail page, we can zero up to PAGE_SIZE.
* If we pass in a head page, we can zero up to the size of the compound page. * If we pass in a head page, we can zero up to the size of the compound page.
*/ */
#if defined(CONFIG_HIGHMEM) && defined(CONFIG_TRANSPARENT_HUGEPAGE) #ifdef CONFIG_HIGHMEM
void zero_user_segments(struct page *page, unsigned start1, unsigned end1, void zero_user_segments(struct page *page, unsigned start1, unsigned end1,
unsigned start2, unsigned end2); unsigned start2, unsigned end2);
#else /* !HIGHMEM || !TRANSPARENT_HUGEPAGE */ #else
static inline void zero_user_segments(struct page *page, static inline void zero_user_segments(struct page *page,
unsigned start1, unsigned end1, unsigned start1, unsigned end1,
unsigned start2, unsigned end2) unsigned start2, unsigned end2)
...@@ -253,7 +253,7 @@ static inline void zero_user_segments(struct page *page, ...@@ -253,7 +253,7 @@ static inline void zero_user_segments(struct page *page,
for (i = 0; i < compound_nr(page); i++) for (i = 0; i < compound_nr(page); i++)
flush_dcache_page(page + i); flush_dcache_page(page + i);
} }
#endif /* !HIGHMEM || !TRANSPARENT_HUGEPAGE */ #endif
static inline void zero_user_segment(struct page *page, static inline void zero_user_segment(struct page *page,
unsigned start, unsigned end) unsigned start, unsigned end)
...@@ -363,4 +363,42 @@ static inline void memzero_page(struct page *page, size_t offset, size_t len) ...@@ -363,4 +363,42 @@ static inline void memzero_page(struct page *page, size_t offset, size_t len)
kunmap_local(addr); kunmap_local(addr);
} }
/**
* folio_zero_segments() - Zero two byte ranges in a folio.
* @folio: The folio to write to.
* @start1: The first byte to zero.
* @xend1: One more than the last byte in the first range.
* @start2: The first byte to zero in the second range.
* @xend2: One more than the last byte in the second range.
*/
static inline void folio_zero_segments(struct folio *folio,
size_t start1, size_t xend1, size_t start2, size_t xend2)
{
zero_user_segments(&folio->page, start1, xend1, start2, xend2);
}
/**
* folio_zero_segment() - Zero a byte range in a folio.
* @folio: The folio to write to.
* @start: The first byte to zero.
* @xend: One more than the last byte to zero.
*/
static inline void folio_zero_segment(struct folio *folio,
size_t start, size_t xend)
{
zero_user_segments(&folio->page, start, xend, 0, 0);
}
/**
* folio_zero_range() - Zero a byte range in a folio.
* @folio: The folio to write to.
* @start: The first byte to zero.
* @length: The number of bytes to zero.
*/
static inline void folio_zero_range(struct folio *folio,
size_t start, size_t length)
{
zero_user_segments(&folio->page, start, start + length, 0, 0);
}
#endif /* _LINUX_HIGHMEM_H */ #endif /* _LINUX_HIGHMEM_H */
...@@ -359,7 +359,6 @@ void kunmap_high(struct page *page) ...@@ -359,7 +359,6 @@ void kunmap_high(struct page *page)
} }
EXPORT_SYMBOL(kunmap_high); EXPORT_SYMBOL(kunmap_high);
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
void zero_user_segments(struct page *page, unsigned start1, unsigned end1, void zero_user_segments(struct page *page, unsigned start1, unsigned end1,
unsigned start2, unsigned end2) unsigned start2, unsigned end2)
{ {
...@@ -416,7 +415,6 @@ void zero_user_segments(struct page *page, unsigned start1, unsigned end1, ...@@ -416,7 +415,6 @@ void zero_user_segments(struct page *page, unsigned start1, unsigned end1,
BUG_ON((start1 | start2 | end1 | end2) != 0); BUG_ON((start1 | start2 | end1 | end2) != 0);
} }
EXPORT_SYMBOL(zero_user_segments); EXPORT_SYMBOL(zero_user_segments);
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
#endif /* CONFIG_HIGHMEM */ #endif /* CONFIG_HIGHMEM */
#ifdef CONFIG_KMAP_LOCAL #ifdef CONFIG_KMAP_LOCAL
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment