btrfs: subpage: make writer lock utilize bitmap
[linux-2.6-microblaze.git] / fs / btrfs / subpage.c
index eae9e8a..54736f6 100644 (file)
@@ -328,24 +328,34 @@ static void btrfs_subpage_start_writer(const struct btrfs_fs_info *fs_info,
                                       struct folio *folio, u64 start, u32 len)
 {
        struct btrfs_subpage *subpage = folio_get_private(folio);
+       const int start_bit = subpage_calc_start_bit(fs_info, folio, locked, start, len);
        const int nbits = (len >> fs_info->sectorsize_bits);
+       unsigned long flags;
        int ret;
 
        btrfs_subpage_assert(fs_info, folio, start, len);
 
+       spin_lock_irqsave(&subpage->lock, flags);
        ASSERT(atomic_read(&subpage->readers) == 0);
+       ASSERT(bitmap_test_range_all_zero(subpage->bitmaps, start_bit, nbits));
+       bitmap_set(subpage->bitmaps, start_bit, nbits);
        ret = atomic_add_return(nbits, &subpage->writers);
        ASSERT(ret == nbits);
+       spin_unlock_irqrestore(&subpage->lock, flags);
 }
 
 static bool btrfs_subpage_end_and_test_writer(const struct btrfs_fs_info *fs_info,
                                              struct folio *folio, u64 start, u32 len)
 {
        struct btrfs_subpage *subpage = folio_get_private(folio);
+       const int start_bit = subpage_calc_start_bit(fs_info, folio, locked, start, len);
        const int nbits = (len >> fs_info->sectorsize_bits);
+       unsigned long flags;
+       bool last;
 
        btrfs_subpage_assert(fs_info, folio, start, len);
 
+       spin_lock_irqsave(&subpage->lock, flags);
        /*
         * We have call sites passing @lock_page into
         * extent_clear_unlock_delalloc() for compression path.
@@ -353,11 +363,18 @@ static bool btrfs_subpage_end_and_test_writer(const struct btrfs_fs_info *fs_inf
         * This @locked_page is locked by plain lock_page(), thus its
         * subpage::writers is 0.  Handle them in a special way.
         */
-       if (atomic_read(&subpage->writers) == 0)
+       if (atomic_read(&subpage->writers) == 0) {
+               spin_unlock_irqrestore(&subpage->lock, flags);
                return true;
+       }
 
        ASSERT(atomic_read(&subpage->writers) >= nbits);
-       return atomic_sub_and_test(nbits, &subpage->writers);
+       /* The target range should have been locked. */
+       ASSERT(bitmap_test_range_all_set(subpage->bitmaps, start_bit, nbits));
+       bitmap_clear(subpage->bitmaps, start_bit, nbits);
+       last = atomic_sub_and_test(nbits, &subpage->writers);
+       spin_unlock_irqrestore(&subpage->lock, flags);
+       return last;
 }
 
 /*