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