mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
btrfs: refactor extent buffer bitmaps operations
[BACKGROUND] Currently we handle extent bitmaps manually in extent_buffer_bitmap_set() and extent_buffer_bitmap_clear(). Although with various helpers like eb_bitmap_offset() it's still a little messy to read. The code seems to be a copy of bitmap_set(), but with all the cross-page handling embedded into the code. [ENHANCEMENT] This patch would enhance the readability by introducing two helpers: - memset_extent_buffer() To handle the byte aligned range, thus all the cross-page handling is done there. - extent_buffer_get_byte() This for the first and the last byte operations, which only need to grab one byte, thus no need for any cross-page handling. So we can split both extent_buffer_bitmap_set() and extent_buffer_bitmap_clear() into 3 parts: - Handle the first byte If the range fits inside the first byte, we can exit early. - Handle the byte aligned part This is the part which can have cross-page operations, and it would be handled by memset_extent_buffer(). - Handle the last byte This refactoring does not only make the code a little easier to read, but also makes later folio/page switch much easier, as the switch only needs to be done inside memset_extent_buffer() and extent_buffer_get_byte(). Reviewed-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me> Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
5864f1da6b
commit
cb22964f1d
1 changed files with 67 additions and 74 deletions
|
@ -4183,32 +4183,30 @@ void write_extent_buffer(const struct extent_buffer *eb, const void *srcv,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void memzero_extent_buffer(const struct extent_buffer *eb, unsigned long start,
|
static void memset_extent_buffer(const struct extent_buffer *eb, int c,
|
||||||
unsigned long len)
|
unsigned long start, unsigned long len)
|
||||||
{
|
{
|
||||||
size_t cur;
|
unsigned long cur = start;
|
||||||
size_t offset;
|
|
||||||
struct page *page;
|
|
||||||
char *kaddr;
|
|
||||||
unsigned long i = get_eb_page_index(start);
|
|
||||||
|
|
||||||
|
while (cur < start + len) {
|
||||||
|
unsigned long index = get_eb_page_index(cur);
|
||||||
|
unsigned int offset = get_eb_offset_in_page(eb, cur);
|
||||||
|
unsigned int cur_len = min(start + len - cur, PAGE_SIZE - offset);
|
||||||
|
struct page *page = eb->pages[index];
|
||||||
|
|
||||||
|
assert_eb_page_uptodate(eb, page);
|
||||||
|
memset(page_address(page) + offset, c, cur_len);
|
||||||
|
|
||||||
|
cur += cur_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void memzero_extent_buffer(const struct extent_buffer *eb, unsigned long start,
|
||||||
|
unsigned long len)
|
||||||
|
{
|
||||||
if (check_eb_range(eb, start, len))
|
if (check_eb_range(eb, start, len))
|
||||||
return;
|
return;
|
||||||
|
return memset_extent_buffer(eb, 0, start, len);
|
||||||
offset = get_eb_offset_in_page(eb, start);
|
|
||||||
|
|
||||||
while (len > 0) {
|
|
||||||
page = eb->pages[i];
|
|
||||||
assert_eb_page_uptodate(eb, page);
|
|
||||||
|
|
||||||
cur = min(len, PAGE_SIZE - offset);
|
|
||||||
kaddr = page_address(page);
|
|
||||||
memset(kaddr + offset, 0, cur);
|
|
||||||
|
|
||||||
len -= cur;
|
|
||||||
offset = 0;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy_extent_buffer_full(const struct extent_buffer *dst,
|
void copy_extent_buffer_full(const struct extent_buffer *dst,
|
||||||
|
@ -4325,6 +4323,15 @@ int extent_buffer_test_bit(const struct extent_buffer *eb, unsigned long start,
|
||||||
return 1U & (kaddr[offset] >> (nr & (BITS_PER_BYTE - 1)));
|
return 1U & (kaddr[offset] >> (nr & (BITS_PER_BYTE - 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u8 *extent_buffer_get_byte(const struct extent_buffer *eb, unsigned long bytenr)
|
||||||
|
{
|
||||||
|
unsigned long index = get_eb_page_index(bytenr);
|
||||||
|
|
||||||
|
if (check_eb_range(eb, bytenr, 1))
|
||||||
|
return NULL;
|
||||||
|
return page_address(eb->pages[index]) + get_eb_offset_in_page(eb, bytenr);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set an area of a bitmap to 1.
|
* Set an area of a bitmap to 1.
|
||||||
*
|
*
|
||||||
|
@ -4336,35 +4343,28 @@ int extent_buffer_test_bit(const struct extent_buffer *eb, unsigned long start,
|
||||||
void extent_buffer_bitmap_set(const struct extent_buffer *eb, unsigned long start,
|
void extent_buffer_bitmap_set(const struct extent_buffer *eb, unsigned long start,
|
||||||
unsigned long pos, unsigned long len)
|
unsigned long pos, unsigned long len)
|
||||||
{
|
{
|
||||||
|
unsigned int first_byte = start + BIT_BYTE(pos);
|
||||||
|
unsigned int last_byte = start + BIT_BYTE(pos + len - 1);
|
||||||
|
const bool same_byte = (first_byte == last_byte);
|
||||||
|
u8 mask = BITMAP_FIRST_BYTE_MASK(pos);
|
||||||
u8 *kaddr;
|
u8 *kaddr;
|
||||||
struct page *page;
|
|
||||||
unsigned long i;
|
|
||||||
size_t offset;
|
|
||||||
const unsigned int size = pos + len;
|
|
||||||
int bits_to_set = BITS_PER_BYTE - (pos % BITS_PER_BYTE);
|
|
||||||
u8 mask_to_set = BITMAP_FIRST_BYTE_MASK(pos);
|
|
||||||
|
|
||||||
eb_bitmap_offset(eb, start, pos, &i, &offset);
|
if (same_byte)
|
||||||
page = eb->pages[i];
|
mask &= BITMAP_LAST_BYTE_MASK(pos + len);
|
||||||
assert_eb_page_uptodate(eb, page);
|
|
||||||
kaddr = page_address(page);
|
|
||||||
|
|
||||||
while (len >= bits_to_set) {
|
/* Handle the first byte. */
|
||||||
kaddr[offset] |= mask_to_set;
|
kaddr = extent_buffer_get_byte(eb, first_byte);
|
||||||
len -= bits_to_set;
|
*kaddr |= mask;
|
||||||
bits_to_set = BITS_PER_BYTE;
|
if (same_byte)
|
||||||
mask_to_set = ~0;
|
return;
|
||||||
if (++offset >= PAGE_SIZE && len > 0) {
|
|
||||||
offset = 0;
|
/* Handle the byte aligned part. */
|
||||||
page = eb->pages[++i];
|
ASSERT(first_byte + 1 <= last_byte);
|
||||||
assert_eb_page_uptodate(eb, page);
|
memset_extent_buffer(eb, 0xff, first_byte + 1, last_byte - first_byte - 1);
|
||||||
kaddr = page_address(page);
|
|
||||||
}
|
/* Handle the last byte. */
|
||||||
}
|
kaddr = extent_buffer_get_byte(eb, last_byte);
|
||||||
if (len) {
|
*kaddr |= BITMAP_LAST_BYTE_MASK(pos + len);
|
||||||
mask_to_set &= BITMAP_LAST_BYTE_MASK(size);
|
|
||||||
kaddr[offset] |= mask_to_set;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4380,35 +4380,28 @@ void extent_buffer_bitmap_clear(const struct extent_buffer *eb,
|
||||||
unsigned long start, unsigned long pos,
|
unsigned long start, unsigned long pos,
|
||||||
unsigned long len)
|
unsigned long len)
|
||||||
{
|
{
|
||||||
|
unsigned int first_byte = start + BIT_BYTE(pos);
|
||||||
|
unsigned int last_byte = start + BIT_BYTE(pos + len - 1);
|
||||||
|
const bool same_byte = (first_byte == last_byte);
|
||||||
|
u8 mask = BITMAP_FIRST_BYTE_MASK(pos);
|
||||||
u8 *kaddr;
|
u8 *kaddr;
|
||||||
struct page *page;
|
|
||||||
unsigned long i;
|
|
||||||
size_t offset;
|
|
||||||
const unsigned int size = pos + len;
|
|
||||||
int bits_to_clear = BITS_PER_BYTE - (pos % BITS_PER_BYTE);
|
|
||||||
u8 mask_to_clear = BITMAP_FIRST_BYTE_MASK(pos);
|
|
||||||
|
|
||||||
eb_bitmap_offset(eb, start, pos, &i, &offset);
|
if (same_byte)
|
||||||
page = eb->pages[i];
|
mask &= BITMAP_LAST_BYTE_MASK(pos + len);
|
||||||
assert_eb_page_uptodate(eb, page);
|
|
||||||
kaddr = page_address(page);
|
|
||||||
|
|
||||||
while (len >= bits_to_clear) {
|
/* Handle the first byte. */
|
||||||
kaddr[offset] &= ~mask_to_clear;
|
kaddr = extent_buffer_get_byte(eb, first_byte);
|
||||||
len -= bits_to_clear;
|
*kaddr &= ~mask;
|
||||||
bits_to_clear = BITS_PER_BYTE;
|
if (same_byte)
|
||||||
mask_to_clear = ~0;
|
return;
|
||||||
if (++offset >= PAGE_SIZE && len > 0) {
|
|
||||||
offset = 0;
|
/* Handle the byte aligned part. */
|
||||||
page = eb->pages[++i];
|
ASSERT(first_byte + 1 <= last_byte);
|
||||||
assert_eb_page_uptodate(eb, page);
|
memset_extent_buffer(eb, 0, first_byte + 1, last_byte - first_byte - 1);
|
||||||
kaddr = page_address(page);
|
|
||||||
}
|
/* Handle the last byte. */
|
||||||
}
|
kaddr = extent_buffer_get_byte(eb, last_byte);
|
||||||
if (len) {
|
*kaddr &= ~BITMAP_LAST_BYTE_MASK(pos + len);
|
||||||
mask_to_clear &= BITMAP_LAST_BYTE_MASK(size);
|
|
||||||
kaddr[offset] &= ~mask_to_clear;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool areas_overlap(unsigned long src, unsigned long dst, unsigned long len)
|
static inline bool areas_overlap(unsigned long src, unsigned long dst, unsigned long len)
|
||||||
|
|
Loading…
Add table
Reference in a new issue