mirror of
https://github.com/torvalds/linux.git
synced 2026-08-01 03:59:40 +02:00
btrfs: factor out metadata subpage detection into a dedicated helper
Currently we have only one btrfs_is_subpage() to cover both data and metadata. But there is a special case for metadata: - dummy extent buffer, sector size < PAGE_SIZE and node size >= PAGE_SIZE In such case, btrfs_is_subpage() will return true for extent buffer folio. But that is not correct, and that's exactly why we have some open-coded checks for functions like set_extent_buffer_uptodate() and clear_extent_buffer_uptodate(). Just extract the metadata specific checks into a helper, and replace those call sites. 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
619611e87f
commit
f64e818153
|
|
@ -836,7 +836,7 @@ static int attach_extent_buffer_folio(struct extent_buffer *eb,
|
|||
if (folio->mapping)
|
||||
lockdep_assert_held(&folio->mapping->i_private_lock);
|
||||
|
||||
if (fs_info->nodesize >= PAGE_SIZE) {
|
||||
if (!btrfs_meta_is_subpage(fs_info)) {
|
||||
if (!folio_test_private(folio))
|
||||
folio_attach_private(folio, eb);
|
||||
else
|
||||
|
|
@ -1797,7 +1797,7 @@ static noinline_for_stack void write_one_eb(struct extent_buffer *eb,
|
|||
wbc_init_bio(wbc, &bbio->bio);
|
||||
bbio->inode = BTRFS_I(eb->fs_info->btree_inode);
|
||||
bbio->file_offset = eb->start;
|
||||
if (fs_info->nodesize < PAGE_SIZE) {
|
||||
if (btrfs_meta_is_subpage(fs_info)) {
|
||||
struct folio *folio = eb->folios[0];
|
||||
bool ret;
|
||||
|
||||
|
|
@ -1939,7 +1939,7 @@ static int submit_eb_page(struct folio *folio, struct btrfs_eb_write_context *ct
|
|||
if (!folio_test_private(folio))
|
||||
return 0;
|
||||
|
||||
if (folio_to_fs_info(folio)->nodesize < PAGE_SIZE)
|
||||
if (btrfs_meta_is_subpage(folio_to_fs_info(folio)))
|
||||
return submit_eb_subpage(folio, wbc);
|
||||
|
||||
spin_lock(&mapping->i_private_lock);
|
||||
|
|
@ -2596,7 +2596,7 @@ static void detach_extent_buffer_folio(const struct extent_buffer *eb, struct fo
|
|||
return;
|
||||
}
|
||||
|
||||
if (fs_info->nodesize >= PAGE_SIZE) {
|
||||
if (!btrfs_meta_is_subpage(fs_info)) {
|
||||
/*
|
||||
* We do this since we'll remove the pages after we've
|
||||
* removed the eb from the radix tree, so we could race
|
||||
|
|
@ -2900,7 +2900,7 @@ static struct extent_buffer *grab_extent_buffer(struct btrfs_fs_info *fs_info,
|
|||
* don't try to insert two ebs for the same bytenr. So here we always
|
||||
* return NULL and just continue.
|
||||
*/
|
||||
if (fs_info->nodesize < PAGE_SIZE)
|
||||
if (btrfs_meta_is_subpage(fs_info))
|
||||
return NULL;
|
||||
|
||||
/* Page not yet attached to an extent buffer */
|
||||
|
|
@ -3003,7 +3003,7 @@ static int attach_eb_folio_to_filemap(struct extent_buffer *eb, int i,
|
|||
|
||||
finish:
|
||||
spin_lock(&mapping->i_private_lock);
|
||||
if (existing_folio && fs_info->nodesize < PAGE_SIZE) {
|
||||
if (existing_folio && btrfs_meta_is_subpage(fs_info)) {
|
||||
/* We're going to reuse the existing page, can drop our folio now. */
|
||||
__free_page(folio_page(eb->folios[i], 0));
|
||||
eb->folios[i] = existing_folio;
|
||||
|
|
@ -3094,7 +3094,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
|
|||
* The memory will be freed by attach_extent_buffer_page() or freed
|
||||
* manually if we exit earlier.
|
||||
*/
|
||||
if (fs_info->nodesize < PAGE_SIZE) {
|
||||
if (btrfs_meta_is_subpage(fs_info)) {
|
||||
prealloc = btrfs_alloc_subpage(fs_info, BTRFS_SUBPAGE_METADATA);
|
||||
if (IS_ERR(prealloc)) {
|
||||
ret = PTR_ERR(prealloc);
|
||||
|
|
@ -3395,7 +3395,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans,
|
|||
percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -eb->len,
|
||||
fs_info->dirty_metadata_batch);
|
||||
|
||||
if (eb->fs_info->nodesize < PAGE_SIZE)
|
||||
if (btrfs_meta_is_subpage(fs_info))
|
||||
return clear_subpage_extent_buffer_dirty(eb);
|
||||
|
||||
num_folios = num_extent_folios(eb);
|
||||
|
|
@ -3426,7 +3426,7 @@ void set_extent_buffer_dirty(struct extent_buffer *eb)
|
|||
WARN_ON(test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags));
|
||||
|
||||
if (!was_dirty) {
|
||||
bool subpage = eb->fs_info->nodesize < PAGE_SIZE;
|
||||
bool subpage = btrfs_meta_is_subpage(eb->fs_info);
|
||||
|
||||
/*
|
||||
* For subpage case, we can have other extent buffers in the
|
||||
|
|
@ -3472,7 +3472,7 @@ void clear_extent_buffer_uptodate(struct extent_buffer *eb)
|
|||
* This is special handling for metadata subpage, as regular
|
||||
* btrfs_is_subpage() can not handle cloned/dummy metadata.
|
||||
*/
|
||||
if (fs_info->nodesize >= PAGE_SIZE)
|
||||
if (!btrfs_meta_is_subpage(fs_info))
|
||||
folio_clear_uptodate(folio);
|
||||
else
|
||||
btrfs_subpage_clear_uptodate(fs_info, folio,
|
||||
|
|
@ -3493,7 +3493,7 @@ void set_extent_buffer_uptodate(struct extent_buffer *eb)
|
|||
* This is special handling for metadata subpage, as regular
|
||||
* btrfs_is_subpage() can not handle cloned/dummy metadata.
|
||||
*/
|
||||
if (fs_info->nodesize >= PAGE_SIZE)
|
||||
if (!btrfs_meta_is_subpage(fs_info))
|
||||
folio_mark_uptodate(folio);
|
||||
else
|
||||
btrfs_subpage_set_uptodate(fs_info, folio,
|
||||
|
|
@ -3583,7 +3583,7 @@ int read_extent_buffer_pages_nowait(struct extent_buffer *eb, int mirror_num,
|
|||
bbio->inode = BTRFS_I(eb->fs_info->btree_inode);
|
||||
bbio->file_offset = eb->start;
|
||||
memcpy(&bbio->parent_check, check, sizeof(*check));
|
||||
if (eb->fs_info->nodesize < PAGE_SIZE) {
|
||||
if (btrfs_meta_is_subpage(eb->fs_info)) {
|
||||
ret = bio_add_folio(&bbio->bio, eb->folios[0], eb->len,
|
||||
eb->start - folio_pos(eb->folios[0]));
|
||||
ASSERT(ret);
|
||||
|
|
@ -3784,7 +3784,7 @@ static void assert_eb_folio_uptodate(const struct extent_buffer *eb, int i)
|
|||
if (test_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags))
|
||||
return;
|
||||
|
||||
if (fs_info->nodesize < PAGE_SIZE) {
|
||||
if (btrfs_meta_is_subpage(fs_info)) {
|
||||
folio = eb->folios[0];
|
||||
ASSERT(i == 0);
|
||||
if (WARN_ON(!btrfs_subpage_test_uptodate(fs_info, folio,
|
||||
|
|
@ -4270,7 +4270,7 @@ int try_release_extent_buffer(struct folio *folio)
|
|||
{
|
||||
struct extent_buffer *eb;
|
||||
|
||||
if (folio_to_fs_info(folio)->nodesize < PAGE_SIZE)
|
||||
if (btrfs_meta_is_subpage(folio_to_fs_info(folio)))
|
||||
return try_release_subpage_extent_buffer(folio);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ void btrfs_folio_inc_eb_refs(const struct btrfs_fs_info *fs_info, struct folio *
|
|||
{
|
||||
struct btrfs_subpage *subpage;
|
||||
|
||||
if (!btrfs_is_subpage(fs_info, folio->mapping))
|
||||
if (!btrfs_meta_is_subpage(fs_info))
|
||||
return;
|
||||
|
||||
ASSERT(folio_test_private(folio) && folio->mapping);
|
||||
|
|
@ -183,7 +183,7 @@ void btrfs_folio_dec_eb_refs(const struct btrfs_fs_info *fs_info, struct folio *
|
|||
{
|
||||
struct btrfs_subpage *subpage;
|
||||
|
||||
if (!btrfs_is_subpage(fs_info, folio->mapping))
|
||||
if (!btrfs_meta_is_subpage(fs_info))
|
||||
return;
|
||||
|
||||
ASSERT(folio_test_private(folio) && folio->mapping);
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/sizes.h>
|
||||
#include "fs.h"
|
||||
|
||||
struct address_space;
|
||||
struct folio;
|
||||
struct btrfs_fs_info;
|
||||
|
||||
/*
|
||||
* Extra info for subpapge bitmap.
|
||||
|
|
@ -70,8 +70,25 @@ enum btrfs_subpage_type {
|
|||
};
|
||||
|
||||
#if PAGE_SIZE > SZ_4K
|
||||
/*
|
||||
* Subpage support for metadata is more complex, as we can have dummy extent
|
||||
* buffers, where folios have no mapping to determine the owning inode.
|
||||
*
|
||||
* Thankfully we only need to check if node size is smaller than page size.
|
||||
* Even with larger folio support, we will only allocate a folio as large as
|
||||
* node size.
|
||||
* Thus if nodesize < PAGE_SIZE, we know metadata needs need to subpage routine.
|
||||
*/
|
||||
static inline bool btrfs_meta_is_subpage(const struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
return fs_info->nodesize < PAGE_SIZE;
|
||||
}
|
||||
bool btrfs_is_subpage(const struct btrfs_fs_info *fs_info, struct address_space *mapping);
|
||||
#else
|
||||
static inline bool btrfs_meta_is_subpage(const struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline bool btrfs_is_subpage(const struct btrfs_fs_info *fs_info,
|
||||
struct address_space *mapping)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user