xref: /kernel/linux/linux-6.6/fs/btrfs/subpage.h (revision 62306a36)
1/* SPDX-License-Identifier: GPL-2.0 */
2
3#ifndef BTRFS_SUBPAGE_H
4#define BTRFS_SUBPAGE_H
5
6#include <linux/spinlock.h>
7
8/*
9 * Extra info for subpapge bitmap.
10 *
11 * For subpage we pack all uptodate/dirty/writeback/ordered bitmaps into
12 * one larger bitmap.
13 *
14 * This structure records how they are organized in the bitmap:
15 *
16 * /- uptodate_offset	/- dirty_offset	/- ordered_offset
17 * |			|		|
18 * v			v		v
19 * |u|u|u|u|........|u|u|d|d|.......|d|d|o|o|.......|o|o|
20 * |<- bitmap_nr_bits ->|
21 * |<----------------- total_nr_bits ------------------>|
22 */
23struct btrfs_subpage_info {
24	/* Number of bits for each bitmap */
25	unsigned int bitmap_nr_bits;
26
27	/* Total number of bits for the whole bitmap */
28	unsigned int total_nr_bits;
29
30	/*
31	 * *_start indicates where the bitmap starts, the length is always
32	 * @bitmap_size, which is calculated from PAGE_SIZE / sectorsize.
33	 */
34	unsigned int uptodate_offset;
35	unsigned int dirty_offset;
36	unsigned int writeback_offset;
37	unsigned int ordered_offset;
38	unsigned int checked_offset;
39};
40
41/*
42 * Structure to trace status of each sector inside a page, attached to
43 * page::private for both data and metadata inodes.
44 */
45struct btrfs_subpage {
46	/* Common members for both data and metadata pages */
47	spinlock_t lock;
48	/*
49	 * Both data and metadata needs to track how many readers are for the
50	 * page.
51	 * Data relies on @readers to unlock the page when last reader finished.
52	 * While metadata doesn't need page unlock, it needs to prevent
53	 * page::private get cleared before the last end_page_read().
54	 */
55	atomic_t readers;
56	union {
57		/*
58		 * Structures only used by metadata
59		 *
60		 * @eb_refs should only be operated under private_lock, as it
61		 * manages whether the subpage can be detached.
62		 */
63		atomic_t eb_refs;
64
65		/* Structures only used by data */
66		atomic_t writers;
67	};
68	unsigned long bitmaps[];
69};
70
71enum btrfs_subpage_type {
72	BTRFS_SUBPAGE_METADATA,
73	BTRFS_SUBPAGE_DATA,
74};
75
76bool btrfs_is_subpage(const struct btrfs_fs_info *fs_info, struct page *page);
77
78void btrfs_init_subpage_info(struct btrfs_subpage_info *subpage_info, u32 sectorsize);
79int btrfs_attach_subpage(const struct btrfs_fs_info *fs_info,
80			 struct page *page, enum btrfs_subpage_type type);
81void btrfs_detach_subpage(const struct btrfs_fs_info *fs_info,
82			  struct page *page);
83
84/* Allocate additional data where page represents more than one sector */
85struct btrfs_subpage *btrfs_alloc_subpage(const struct btrfs_fs_info *fs_info,
86					  enum btrfs_subpage_type type);
87void btrfs_free_subpage(struct btrfs_subpage *subpage);
88
89void btrfs_page_inc_eb_refs(const struct btrfs_fs_info *fs_info,
90			    struct page *page);
91void btrfs_page_dec_eb_refs(const struct btrfs_fs_info *fs_info,
92			    struct page *page);
93
94void btrfs_subpage_start_reader(const struct btrfs_fs_info *fs_info,
95		struct page *page, u64 start, u32 len);
96void btrfs_subpage_end_reader(const struct btrfs_fs_info *fs_info,
97		struct page *page, u64 start, u32 len);
98
99void btrfs_subpage_start_writer(const struct btrfs_fs_info *fs_info,
100		struct page *page, u64 start, u32 len);
101bool btrfs_subpage_end_and_test_writer(const struct btrfs_fs_info *fs_info,
102		struct page *page, u64 start, u32 len);
103int btrfs_page_start_writer_lock(const struct btrfs_fs_info *fs_info,
104		struct page *page, u64 start, u32 len);
105void btrfs_page_end_writer_lock(const struct btrfs_fs_info *fs_info,
106		struct page *page, u64 start, u32 len);
107
108/*
109 * Template for subpage related operations.
110 *
111 * btrfs_subpage_*() are for call sites where the page has subpage attached and
112 * the range is ensured to be inside the page.
113 *
114 * btrfs_page_*() are for call sites where the page can either be subpage
115 * specific or regular page. The function will handle both cases.
116 * But the range still needs to be inside the page.
117 *
118 * btrfs_page_clamp_*() are similar to btrfs_page_*(), except the range doesn't
119 * need to be inside the page. Those functions will truncate the range
120 * automatically.
121 */
122#define DECLARE_BTRFS_SUBPAGE_OPS(name)					\
123void btrfs_subpage_set_##name(const struct btrfs_fs_info *fs_info,	\
124		struct page *page, u64 start, u32 len);			\
125void btrfs_subpage_clear_##name(const struct btrfs_fs_info *fs_info,	\
126		struct page *page, u64 start, u32 len);			\
127bool btrfs_subpage_test_##name(const struct btrfs_fs_info *fs_info,	\
128		struct page *page, u64 start, u32 len);			\
129void btrfs_page_set_##name(const struct btrfs_fs_info *fs_info,		\
130		struct page *page, u64 start, u32 len);			\
131void btrfs_page_clear_##name(const struct btrfs_fs_info *fs_info,	\
132		struct page *page, u64 start, u32 len);			\
133bool btrfs_page_test_##name(const struct btrfs_fs_info *fs_info,	\
134		struct page *page, u64 start, u32 len);			\
135void btrfs_page_clamp_set_##name(const struct btrfs_fs_info *fs_info,	\
136		struct page *page, u64 start, u32 len);			\
137void btrfs_page_clamp_clear_##name(const struct btrfs_fs_info *fs_info,	\
138		struct page *page, u64 start, u32 len);			\
139bool btrfs_page_clamp_test_##name(const struct btrfs_fs_info *fs_info,	\
140		struct page *page, u64 start, u32 len);
141
142DECLARE_BTRFS_SUBPAGE_OPS(uptodate);
143DECLARE_BTRFS_SUBPAGE_OPS(dirty);
144DECLARE_BTRFS_SUBPAGE_OPS(writeback);
145DECLARE_BTRFS_SUBPAGE_OPS(ordered);
146DECLARE_BTRFS_SUBPAGE_OPS(checked);
147
148bool btrfs_subpage_clear_and_test_dirty(const struct btrfs_fs_info *fs_info,
149		struct page *page, u64 start, u32 len);
150
151void btrfs_page_assert_not_dirty(const struct btrfs_fs_info *fs_info,
152				 struct page *page);
153void btrfs_page_unlock_writer(struct btrfs_fs_info *fs_info, struct page *page,
154			      u64 start, u32 len);
155void __cold btrfs_subpage_dump_bitmap(const struct btrfs_fs_info *fs_info,
156				      struct page *page, u64 start, u32 len);
157
158#endif
159