@@ -111,6 +111,9 @@ void btrfs_init_subpage_info(struct btrfs_subpage_info *subpage_info, u32 sector
111
111
subpage_info -> checked_offset = cur ;
112
112
cur += nr_bits ;
113
113
114
+ subpage_info -> locked_offset = cur ;
115
+ cur += nr_bits ;
116
+
114
117
subpage_info -> total_nr_bits = cur ;
115
118
}
116
119
@@ -237,28 +240,58 @@ static void btrfs_subpage_assert(const struct btrfs_fs_info *fs_info,
237
240
start + len <= folio_pos (folio ) + PAGE_SIZE );
238
241
}
239
242
243
+ #define subpage_calc_start_bit (fs_info , folio , name , start , len ) \
244
+ ({ \
245
+ unsigned int start_bit; \
246
+ \
247
+ btrfs_subpage_assert(fs_info, folio, start, len); \
248
+ start_bit = offset_in_page(start) >> fs_info->sectorsize_bits; \
249
+ start_bit += fs_info->subpage_info->name##_offset; \
250
+ start_bit; \
251
+ })
252
+
240
253
void btrfs_subpage_start_reader (const struct btrfs_fs_info * fs_info ,
241
254
struct folio * folio , u64 start , u32 len )
242
255
{
243
256
struct btrfs_subpage * subpage = folio_get_private (folio );
257
+ const int start_bit = subpage_calc_start_bit (fs_info , folio , locked , start , len );
244
258
const int nbits = len >> fs_info -> sectorsize_bits ;
259
+ unsigned long flags ;
260
+
245
261
246
262
btrfs_subpage_assert (fs_info , folio , start , len );
247
263
264
+ spin_lock_irqsave (& subpage -> lock , flags );
265
+ /*
266
+ * Even though it's just for reading the page, no one should have
267
+ * locked the subpage range.
268
+ */
269
+ ASSERT (bitmap_test_range_all_zero (subpage -> bitmaps , start_bit , nbits ));
270
+ bitmap_set (subpage -> bitmaps , start_bit , nbits );
248
271
atomic_add (nbits , & subpage -> readers );
272
+ spin_unlock_irqrestore (& subpage -> lock , flags );
249
273
}
250
274
251
275
void btrfs_subpage_end_reader (const struct btrfs_fs_info * fs_info ,
252
276
struct folio * folio , u64 start , u32 len )
253
277
{
254
278
struct btrfs_subpage * subpage = folio_get_private (folio );
279
+ const int start_bit = subpage_calc_start_bit (fs_info , folio , locked , start , len );
255
280
const int nbits = len >> fs_info -> sectorsize_bits ;
281
+ unsigned long flags ;
256
282
bool is_data ;
257
283
bool last ;
258
284
259
285
btrfs_subpage_assert (fs_info , folio , start , len );
260
286
is_data = is_data_inode (folio -> mapping -> host );
287
+
288
+ spin_lock_irqsave (& subpage -> lock , flags );
289
+
290
+ /* The range should have already been locked. */
291
+ ASSERT (bitmap_test_range_all_set (subpage -> bitmaps , start_bit , nbits ));
261
292
ASSERT (atomic_read (& subpage -> readers ) >= nbits );
293
+
294
+ bitmap_clear (subpage -> bitmaps , start_bit , nbits );
262
295
last = atomic_sub_and_test (nbits , & subpage -> readers );
263
296
264
297
/*
@@ -270,6 +303,7 @@ void btrfs_subpage_end_reader(const struct btrfs_fs_info *fs_info,
270
303
*/
271
304
if (is_data && last )
272
305
folio_unlock (folio );
306
+ spin_unlock_irqrestore (& subpage -> lock , flags );
273
307
}
274
308
275
309
static void btrfs_subpage_clamp_range (struct folio * folio , u64 * start , u32 * len )
@@ -365,16 +399,6 @@ void btrfs_folio_end_writer_lock(const struct btrfs_fs_info *fs_info,
365
399
folio_unlock (folio );
366
400
}
367
401
368
- #define subpage_calc_start_bit (fs_info , folio , name , start , len ) \
369
- ({ \
370
- unsigned int start_bit; \
371
- \
372
- btrfs_subpage_assert(fs_info, folio, start, len); \
373
- start_bit = offset_in_page(start) >> fs_info->sectorsize_bits; \
374
- start_bit += fs_info->subpage_info->name##_offset; \
375
- start_bit; \
376
- })
377
-
378
402
#define subpage_test_bitmap_all_set (fs_info , subpage , name ) \
379
403
bitmap_test_range_all_set(subpage->bitmaps, \
380
404
fs_info->subpage_info->name##_offset, \
@@ -751,6 +775,7 @@ void __cold btrfs_subpage_dump_bitmap(const struct btrfs_fs_info *fs_info,
751
775
GET_SUBPAGE_BITMAP (subpage , subpage_info , writeback , & writeback_bitmap );
752
776
GET_SUBPAGE_BITMAP (subpage , subpage_info , ordered , & ordered_bitmap );
753
777
GET_SUBPAGE_BITMAP (subpage , subpage_info , checked , & checked_bitmap );
778
+ GET_SUBPAGE_BITMAP (subpage , subpage_info , locked , & checked_bitmap );
754
779
spin_unlock_irqrestore (& subpage -> lock , flags );
755
780
756
781
dump_page (folio_page (folio , 0 ), "btrfs subpage dump" );
0 commit comments