@@ -328,36 +328,53 @@ static void btrfs_subpage_start_writer(const struct btrfs_fs_info *fs_info,
328328 struct folio * folio , u64 start , u32 len )
329329{
330330 struct btrfs_subpage * subpage = folio_get_private (folio );
331+ const int start_bit = subpage_calc_start_bit (fs_info , folio , locked , start , len );
331332 const int nbits = (len >> fs_info -> sectorsize_bits );
333+ unsigned long flags ;
332334 int ret ;
333335
334336 btrfs_subpage_assert (fs_info , folio , start , len );
335337
338+ spin_lock_irqsave (& subpage -> lock , flags );
336339 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 );
337342 ret = atomic_add_return (nbits , & subpage -> writers );
338343 ASSERT (ret == nbits );
344+ spin_unlock_irqrestore (& subpage -> lock , flags );
339345}
340346
341347static bool btrfs_subpage_end_and_test_writer (const struct btrfs_fs_info * fs_info ,
342348 struct folio * folio , u64 start , u32 len )
343349{
344350 struct btrfs_subpage * subpage = folio_get_private (folio );
351+ const int start_bit = subpage_calc_start_bit (fs_info , folio , locked , start , len );
345352 const int nbits = (len >> fs_info -> sectorsize_bits );
353+ unsigned long flags ;
354+ bool last ;
346355
347356 btrfs_subpage_assert (fs_info , folio , start , len );
348357
358+ spin_lock_irqsave (& subpage -> lock , flags );
349359 /*
350360 * We have call sites passing @lock_page into
351361 * extent_clear_unlock_delalloc() for compression path.
352362 *
353363 * This @locked_page is locked by plain lock_page(), thus its
354364 * subpage::writers is 0. Handle them in a special way.
355365 */
356- if (atomic_read (& subpage -> writers ) == 0 )
366+ if (atomic_read (& subpage -> writers ) == 0 ) {
367+ spin_unlock_irqrestore (& subpage -> lock , flags );
357368 return true;
369+ }
358370
359371 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 ;
361378}
362379
363380/*
0 commit comments