blob: c69049e7daa9f6903b285a47522cd10ab243beee [file] [log] [blame]
Qu Wenruocac06d82021-01-26 16:33:47 +08001// SPDX-License-Identifier: GPL-2.0
2
3#include <linux/slab.h>
4#include "ctree.h"
5#include "subpage.h"
6
7int btrfs_attach_subpage(const struct btrfs_fs_info *fs_info,
8 struct page *page, enum btrfs_subpage_type type)
9{
Qu Wenruo760f9912021-01-26 16:33:48 +080010 struct btrfs_subpage *subpage = NULL;
11 int ret;
Qu Wenruocac06d82021-01-26 16:33:47 +080012
13 /*
14 * We have cases like a dummy extent buffer page, which is not mappped
15 * and doesn't need to be locked.
16 */
17 if (page->mapping)
18 ASSERT(PageLocked(page));
19 /* Either not subpage, or the page already has private attached */
20 if (fs_info->sectorsize == PAGE_SIZE || PagePrivate(page))
21 return 0;
22
Qu Wenruo760f9912021-01-26 16:33:48 +080023 ret = btrfs_alloc_subpage(fs_info, &subpage, type);
24 if (ret < 0)
25 return ret;
Qu Wenruocac06d82021-01-26 16:33:47 +080026 attach_page_private(page, subpage);
27 return 0;
28}
29
30void btrfs_detach_subpage(const struct btrfs_fs_info *fs_info,
31 struct page *page)
32{
33 struct btrfs_subpage *subpage;
34
35 /* Either not subpage, or already detached */
36 if (fs_info->sectorsize == PAGE_SIZE || !PagePrivate(page))
37 return;
38
39 subpage = (struct btrfs_subpage *)detach_page_private(page);
40 ASSERT(subpage);
Qu Wenruo760f9912021-01-26 16:33:48 +080041 btrfs_free_subpage(subpage);
42}
43
44int btrfs_alloc_subpage(const struct btrfs_fs_info *fs_info,
45 struct btrfs_subpage **ret,
46 enum btrfs_subpage_type type)
47{
48 if (fs_info->sectorsize == PAGE_SIZE)
49 return 0;
50
51 *ret = kzalloc(sizeof(struct btrfs_subpage), GFP_NOFS);
52 if (!*ret)
53 return -ENOMEM;
54 spin_lock_init(&(*ret)->lock);
Qu Wenruo8ff84662021-01-26 16:33:50 +080055 if (type == BTRFS_SUBPAGE_METADATA)
56 atomic_set(&(*ret)->eb_refs, 0);
Qu Wenruo92082d42021-02-02 10:28:36 +080057 else
58 atomic_set(&(*ret)->readers, 0);
Qu Wenruo760f9912021-01-26 16:33:48 +080059 return 0;
60}
61
62void btrfs_free_subpage(struct btrfs_subpage *subpage)
63{
Qu Wenruocac06d82021-01-26 16:33:47 +080064 kfree(subpage);
65}
Qu Wenruo8ff84662021-01-26 16:33:50 +080066
67/*
68 * Increase the eb_refs of current subpage.
69 *
70 * This is important for eb allocation, to prevent race with last eb freeing
71 * of the same page.
72 * With the eb_refs increased before the eb inserted into radix tree,
73 * detach_extent_buffer_page() won't detach the page private while we're still
74 * allocating the extent buffer.
75 */
76void btrfs_page_inc_eb_refs(const struct btrfs_fs_info *fs_info,
77 struct page *page)
78{
79 struct btrfs_subpage *subpage;
80
81 if (fs_info->sectorsize == PAGE_SIZE)
82 return;
83
84 ASSERT(PagePrivate(page) && page->mapping);
85 lockdep_assert_held(&page->mapping->private_lock);
86
87 subpage = (struct btrfs_subpage *)page->private;
88 atomic_inc(&subpage->eb_refs);
89}
90
91void btrfs_page_dec_eb_refs(const struct btrfs_fs_info *fs_info,
92 struct page *page)
93{
94 struct btrfs_subpage *subpage;
95
96 if (fs_info->sectorsize == PAGE_SIZE)
97 return;
98
99 ASSERT(PagePrivate(page) && page->mapping);
100 lockdep_assert_held(&page->mapping->private_lock);
101
102 subpage = (struct btrfs_subpage *)page->private;
103 ASSERT(atomic_read(&subpage->eb_refs));
104 atomic_dec(&subpage->eb_refs);
105}
Qu Wenruoa1d767c2021-01-26 16:33:52 +0800106
Qu Wenruo92082d42021-02-02 10:28:36 +0800107static void btrfs_subpage_assert(const struct btrfs_fs_info *fs_info,
108 struct page *page, u64 start, u32 len)
109{
110 /* Basic checks */
111 ASSERT(PagePrivate(page) && page->private);
112 ASSERT(IS_ALIGNED(start, fs_info->sectorsize) &&
113 IS_ALIGNED(len, fs_info->sectorsize));
114 /*
115 * The range check only works for mapped page, we can still have
116 * unmapped page like dummy extent buffer pages.
117 */
118 if (page->mapping)
119 ASSERT(page_offset(page) <= start &&
120 start + len <= page_offset(page) + PAGE_SIZE);
121}
122
123void btrfs_subpage_start_reader(const struct btrfs_fs_info *fs_info,
124 struct page *page, u64 start, u32 len)
125{
126 struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
127 const int nbits = len >> fs_info->sectorsize_bits;
128 int ret;
129
130 btrfs_subpage_assert(fs_info, page, start, len);
131
132 ret = atomic_add_return(nbits, &subpage->readers);
133 ASSERT(ret == nbits);
134}
135
136void btrfs_subpage_end_reader(const struct btrfs_fs_info *fs_info,
137 struct page *page, u64 start, u32 len)
138{
139 struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
140 const int nbits = len >> fs_info->sectorsize_bits;
141
142 btrfs_subpage_assert(fs_info, page, start, len);
143 ASSERT(atomic_read(&subpage->readers) >= nbits);
144 if (atomic_sub_and_test(nbits, &subpage->readers))
145 unlock_page(page);
146}
147
Qu Wenruoa1d767c2021-01-26 16:33:52 +0800148/*
149 * Convert the [start, start + len) range into a u16 bitmap
150 *
151 * For example: if start == page_offset() + 16K, len = 16K, we get 0x00f0.
152 */
153static u16 btrfs_subpage_calc_bitmap(const struct btrfs_fs_info *fs_info,
154 struct page *page, u64 start, u32 len)
155{
156 const int bit_start = offset_in_page(start) >> fs_info->sectorsize_bits;
157 const int nbits = len >> fs_info->sectorsize_bits;
158
Qu Wenruo92082d42021-02-02 10:28:36 +0800159 btrfs_subpage_assert(fs_info, page, start, len);
Qu Wenruoa1d767c2021-01-26 16:33:52 +0800160
161 /*
Qu Wenruoa1d767c2021-01-26 16:33:52 +0800162 * Here nbits can be 16, thus can go beyond u16 range. We make the
163 * first left shift to be calculate in unsigned long (at least u32),
164 * then truncate the result to u16.
165 */
166 return (u16)(((1UL << nbits) - 1) << bit_start);
167}
168
169void btrfs_subpage_set_uptodate(const struct btrfs_fs_info *fs_info,
170 struct page *page, u64 start, u32 len)
171{
172 struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
173 const u16 tmp = btrfs_subpage_calc_bitmap(fs_info, page, start, len);
174 unsigned long flags;
175
176 spin_lock_irqsave(&subpage->lock, flags);
177 subpage->uptodate_bitmap |= tmp;
178 if (subpage->uptodate_bitmap == U16_MAX)
179 SetPageUptodate(page);
180 spin_unlock_irqrestore(&subpage->lock, flags);
181}
182
183void btrfs_subpage_clear_uptodate(const struct btrfs_fs_info *fs_info,
184 struct page *page, u64 start, u32 len)
185{
186 struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
187 const u16 tmp = btrfs_subpage_calc_bitmap(fs_info, page, start, len);
188 unsigned long flags;
189
190 spin_lock_irqsave(&subpage->lock, flags);
191 subpage->uptodate_bitmap &= ~tmp;
192 ClearPageUptodate(page);
193 spin_unlock_irqrestore(&subpage->lock, flags);
194}
195
Qu Wenruo03a816b32021-01-26 16:33:53 +0800196void btrfs_subpage_set_error(const struct btrfs_fs_info *fs_info,
197 struct page *page, u64 start, u32 len)
198{
199 struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
200 const u16 tmp = btrfs_subpage_calc_bitmap(fs_info, page, start, len);
201 unsigned long flags;
202
203 spin_lock_irqsave(&subpage->lock, flags);
204 subpage->error_bitmap |= tmp;
205 SetPageError(page);
206 spin_unlock_irqrestore(&subpage->lock, flags);
207}
208
209void btrfs_subpage_clear_error(const struct btrfs_fs_info *fs_info,
210 struct page *page, u64 start, u32 len)
211{
212 struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private;
213 const u16 tmp = btrfs_subpage_calc_bitmap(fs_info, page, start, len);
214 unsigned long flags;
215
216 spin_lock_irqsave(&subpage->lock, flags);
217 subpage->error_bitmap &= ~tmp;
218 if (subpage->error_bitmap == 0)
219 ClearPageError(page);
220 spin_unlock_irqrestore(&subpage->lock, flags);
221}
222
Qu Wenruoa1d767c2021-01-26 16:33:52 +0800223/*
224 * Unlike set/clear which is dependent on each page status, for test all bits
225 * are tested in the same way.
226 */
227#define IMPLEMENT_BTRFS_SUBPAGE_TEST_OP(name) \
228bool btrfs_subpage_test_##name(const struct btrfs_fs_info *fs_info, \
229 struct page *page, u64 start, u32 len) \
230{ \
231 struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private; \
232 const u16 tmp = btrfs_subpage_calc_bitmap(fs_info, page, start, len); \
233 unsigned long flags; \
234 bool ret; \
235 \
236 spin_lock_irqsave(&subpage->lock, flags); \
237 ret = ((subpage->name##_bitmap & tmp) == tmp); \
238 spin_unlock_irqrestore(&subpage->lock, flags); \
239 return ret; \
240}
241IMPLEMENT_BTRFS_SUBPAGE_TEST_OP(uptodate);
Qu Wenruo03a816b32021-01-26 16:33:53 +0800242IMPLEMENT_BTRFS_SUBPAGE_TEST_OP(error);
Qu Wenruoa1d767c2021-01-26 16:33:52 +0800243
244/*
245 * Note that, in selftests (extent-io-tests), we can have empty fs_info passed
246 * in. We only test sectorsize == PAGE_SIZE cases so far, thus we can fall
247 * back to regular sectorsize branch.
248 */
249#define IMPLEMENT_BTRFS_PAGE_OPS(name, set_page_func, clear_page_func, \
250 test_page_func) \
251void btrfs_page_set_##name(const struct btrfs_fs_info *fs_info, \
252 struct page *page, u64 start, u32 len) \
253{ \
254 if (unlikely(!fs_info) || fs_info->sectorsize == PAGE_SIZE) { \
255 set_page_func(page); \
256 return; \
257 } \
258 btrfs_subpage_set_##name(fs_info, page, start, len); \
259} \
260void btrfs_page_clear_##name(const struct btrfs_fs_info *fs_info, \
261 struct page *page, u64 start, u32 len) \
262{ \
263 if (unlikely(!fs_info) || fs_info->sectorsize == PAGE_SIZE) { \
264 clear_page_func(page); \
265 return; \
266 } \
267 btrfs_subpage_clear_##name(fs_info, page, start, len); \
268} \
269bool btrfs_page_test_##name(const struct btrfs_fs_info *fs_info, \
270 struct page *page, u64 start, u32 len) \
271{ \
272 if (unlikely(!fs_info) || fs_info->sectorsize == PAGE_SIZE) \
273 return test_page_func(page); \
274 return btrfs_subpage_test_##name(fs_info, page, start, len); \
275}
276IMPLEMENT_BTRFS_PAGE_OPS(uptodate, SetPageUptodate, ClearPageUptodate,
277 PageUptodate);
Qu Wenruo03a816b32021-01-26 16:33:53 +0800278IMPLEMENT_BTRFS_PAGE_OPS(error, SetPageError, ClearPageError, PageError);