@@ -328,36 +328,53 @@ static void btrfs_subpage_start_writer(const struct btrfs_fs_info *fs_info,
328
328
struct folio * folio , u64 start , u32 len )
329
329
{
330
330
struct btrfs_subpage * subpage = folio_get_private (folio );
331
+ const int start_bit = subpage_calc_start_bit (fs_info , folio , locked , start , len );
331
332
const int nbits = (len >> fs_info -> sectorsize_bits );
333
+ unsigned long flags ;
332
334
int ret ;
333
335
334
336
btrfs_subpage_assert (fs_info , folio , start , len );
335
337
338
+ spin_lock_irqsave (& subpage -> lock , flags );
336
339
ASSERT (atomic_read (& subpage -> readers ) == 0 );
340
+ ASSERT (bitmap_test_range_all_zero (subpage -> bitmaps , start_bit , nbits ));
341
+ bitmap_set (subpage -> bitmaps , start_bit , nbits );
337
342
ret = atomic_add_return (nbits , & subpage -> writers );
338
343
ASSERT (ret == nbits );
344
+ spin_unlock_irqrestore (& subpage -> lock , flags );
339
345
}
340
346
341
347
static bool btrfs_subpage_end_and_test_writer (const struct btrfs_fs_info * fs_info ,
342
348
struct folio * folio , u64 start , u32 len )
343
349
{
344
350
struct btrfs_subpage * subpage = folio_get_private (folio );
351
+ const int start_bit = subpage_calc_start_bit (fs_info , folio , locked , start , len );
345
352
const int nbits = (len >> fs_info -> sectorsize_bits );
353
+ unsigned long flags ;
354
+ bool last ;
346
355
347
356
btrfs_subpage_assert (fs_info , folio , start , len );
348
357
358
+ spin_lock_irqsave (& subpage -> lock , flags );
349
359
/*
350
360
* We have call sites passing @lock_page into
351
361
* extent_clear_unlock_delalloc() for compression path.
352
362
*
353
363
* This @locked_page is locked by plain lock_page(), thus its
354
364
* subpage::writers is 0. Handle them in a special way.
355
365
*/
356
- if (atomic_read (& subpage -> writers ) == 0 )
366
+ if (atomic_read (& subpage -> writers ) == 0 ) {
367
+ spin_unlock_irqrestore (& subpage -> lock , flags );
357
368
return true;
369
+ }
358
370
359
371
ASSERT (atomic_read (& subpage -> writers ) >= nbits );
360
- return atomic_sub_and_test (nbits , & subpage -> writers );
372
+ /* The target range should have been locked. */
373
+ ASSERT (bitmap_test_range_all_set (subpage -> bitmaps , start_bit , nbits ));
374
+ bitmap_clear (subpage -> bitmaps , start_bit , nbits );
375
+ last = atomic_sub_and_test (nbits , & subpage -> writers );
376
+ spin_unlock_irqrestore (& subpage -> lock , flags );
377
+ return last ;
361
378
}
362
379
363
380
/*
0 commit comments