mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 22:24:11 +08:00
mm: add folio_zero_tail() and use it in ext4
Patch series "Add folio_zero_tail() and folio_fill_tail()". I'm trying to make it easier for filesystems with tailpacking / stuffing / inline data to use folios. The primary function here is folio_fill_tail(). You give it a pointer to memory where the data currently is, and it takes care of copying it into the folio at that offset. That works for gfs2 & iomap. Then There's Ext4. Rather than gin up some kind of specialist "Here's a two pointers to two blocks of memory" routine, just let it do its current thing, and let it call folio_zero_tail(), which is also called by folio_fill_tail(). Other filesystems can be converted later; these ones seemed like good examples as they're already partly or completely converted to folios. This patch (of 3): Instead of unmapping the folio after copying the data to it, then mapping it again to zero the tail, provide folio_zero_tail() to zero the tail of an already-mapped folio. [akpm@linux-foundation.org: fix kerneldoc argument ordering] Link: https://lkml.kernel.org/r/20231107212643.3490372-1-willy@infradead.org Link: https://lkml.kernel.org/r/20231107212643.3490372-2-willy@infradead.org Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com> Cc: Darrick J. Wong <djwong@kernel.org> Cc: Theodore Ts'o <tytso@mit.edu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
600bca5805
commit
a4fc4a0c45
@ -502,9 +502,8 @@ static int ext4_read_inline_folio(struct inode *inode, struct folio *folio)
|
||||
BUG_ON(len > PAGE_SIZE);
|
||||
kaddr = kmap_local_folio(folio, 0);
|
||||
ret = ext4_read_inline_data(inode, kaddr, len, &iloc);
|
||||
flush_dcache_folio(folio);
|
||||
kaddr = folio_zero_tail(folio, len, kaddr + len);
|
||||
kunmap_local(kaddr);
|
||||
folio_zero_segment(folio, len, folio_size(folio));
|
||||
folio_mark_uptodate(folio);
|
||||
brelse(iloc.bh);
|
||||
|
||||
|
@ -483,6 +483,44 @@ static inline void memcpy_to_folio(struct folio *folio, size_t offset,
|
||||
flush_dcache_folio(folio);
|
||||
}
|
||||
|
||||
/**
|
||||
* folio_zero_tail - Zero the tail of a folio.
|
||||
* @folio: The folio to zero.
|
||||
* @offset: The byte offset in the folio to start zeroing at.
|
||||
* @kaddr: The address the folio is currently mapped to.
|
||||
*
|
||||
* If you have already used kmap_local_folio() to map a folio, written
|
||||
* some data to it and now need to zero the end of the folio (and flush
|
||||
* the dcache), you can use this function. If you do not have the
|
||||
* folio kmapped (eg the folio has been partially populated by DMA),
|
||||
* use folio_zero_range() or folio_zero_segment() instead.
|
||||
*
|
||||
* Return: An address which can be passed to kunmap_local().
|
||||
*/
|
||||
static inline __must_check void *folio_zero_tail(struct folio *folio,
|
||||
size_t offset, void *kaddr)
|
||||
{
|
||||
size_t len = folio_size(folio) - offset;
|
||||
|
||||
if (folio_test_highmem(folio)) {
|
||||
size_t max = PAGE_SIZE - offset_in_page(offset);
|
||||
|
||||
while (len > max) {
|
||||
memset(kaddr, 0, max);
|
||||
kunmap_local(kaddr);
|
||||
len -= max;
|
||||
offset += max;
|
||||
max = PAGE_SIZE;
|
||||
kaddr = kmap_local_folio(folio, offset);
|
||||
}
|
||||
}
|
||||
|
||||
memset(kaddr, 0, len);
|
||||
flush_dcache_folio(folio);
|
||||
|
||||
return kaddr;
|
||||
}
|
||||
|
||||
/**
|
||||
* memcpy_from_file_folio - Copy some bytes from a file folio.
|
||||
* @to: The destination buffer.
|
||||
|
Loading…
Reference in New Issue
Block a user