fs/btrfs/subpage.h

Source file repositories/reference/linux-study-clean/fs/btrfs/subpage.h

File Facts

System
Linux kernel
Corpus path
fs/btrfs/subpage.h
Extension
.h
Size
7131 bytes
Lines
194
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct btrfs_folio_state {
	/* Common members for both data and metadata pages */
	spinlock_t lock;
	union {
		/*
		 * Structures only used by metadata
		 *
		 * @eb_refs should only be operated under private_lock, as it
		 * manages whether the btrfs_folio_state can be detached.
		 */
		atomic_t eb_refs;

		/*
		 * Structures only used by data,
		 *
		 * How many sectors inside the page is locked.
		 */
		atomic_t nr_locked;
	};
	unsigned long bitmaps[];
};

enum btrfs_folio_type {
	BTRFS_SUBPAGE_METADATA,
	BTRFS_SUBPAGE_DATA,
};

/*
 * 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;
}
static inline bool btrfs_is_subpage(const struct btrfs_fs_info *fs_info,
				    struct folio *folio)
{
	if (folio->mapping && folio->mapping->host)
		ASSERT(is_data_inode(BTRFS_I(folio->mapping->host)));
	return fs_info->sectorsize < folio_size(folio);
}

int btrfs_attach_folio_state(const struct btrfs_fs_info *fs_info,
			     struct folio *folio, enum btrfs_folio_type type);
void btrfs_detach_folio_state(const struct btrfs_fs_info *fs_info, struct folio *folio,
			      enum btrfs_folio_type type);

/* Allocate additional data where page represents more than one sector */
struct btrfs_folio_state *btrfs_alloc_folio_state(const struct btrfs_fs_info *fs_info,
						  size_t fsize, enum btrfs_folio_type type);
static inline void btrfs_free_folio_state(struct btrfs_folio_state *bfs)
{
	kfree(bfs);
}

void btrfs_folio_inc_eb_refs(const struct btrfs_fs_info *fs_info, struct folio *folio);
void btrfs_folio_dec_eb_refs(const struct btrfs_fs_info *fs_info, struct folio *folio);

void btrfs_folio_end_lock(const struct btrfs_fs_info *fs_info,
			  struct folio *folio, u64 start, u32 len);
void btrfs_folio_set_lock(const struct btrfs_fs_info *fs_info,
			  struct folio *folio, u64 start, u32 len);
void btrfs_folio_end_lock_bitmap(const struct btrfs_fs_info *fs_info,
				 struct folio *folio, unsigned long *bitmap);
/*
 * Template for subpage related operations.
 *
 * btrfs_subpage_*() are for call sites where the folio has subpage attached and
 * the range is ensured to be inside the folio's single page.
 *
 * btrfs_folio_*() are for call sites where the page can either be subpage
 * specific or regular folios. The function will handle both cases.
 * But the range still needs to be inside one single page.
 *
 * btrfs_folio_clamp_*() are similar to btrfs_folio_*(), except the range doesn't
 * need to be inside the page. Those functions will truncate the range
 * automatically.
 *
 * Both btrfs_folio_*() and btrfs_folio_clamp_*() are for data folios.
 *
 * For metadata, one should use btrfs_meta_folio_*() helpers instead, and there
 * is no clamp version for metadata helpers, as we either go subpage
 * (nodesize < PAGE_SIZE) or go regular folio helpers (nodesize >= PAGE_SIZE,
 * and our folio is never larger than nodesize).

Annotation

Implementation Notes