1 /* SPDX-License-Identifier: GPL-2.0 */ 2 3 #ifndef BTRFS_SUBPAGE_H 4 #define BTRFS_SUBPAGE_H 5 6 #include <linux/spinlock.h> 7 8 /* 9 * Maximum page size we support is 64K, minimum sector size is 4K, u16 bitmap 10 * is sufficient. Regular bitmap_* is not used due to size reasons. 11 */ 12 #define BTRFS_SUBPAGE_BITMAP_SIZE 16 13 14 /* 15 * Structure to trace status of each sector inside a page, attached to 16 * page::private for both data and metadata inodes. 17 */ 18 struct btrfs_subpage { 19 /* Common members for both data and metadata pages */ 20 spinlock_t lock; 21 u16 uptodate_bitmap; 22 u16 error_bitmap; 23 u16 dirty_bitmap; 24 u16 writeback_bitmap; 25 union { 26 /* 27 * Structures only used by metadata 28 * 29 * @eb_refs should only be operated under private_lock, as it 30 * manages whether the subpage can be detached. 31 */ 32 atomic_t eb_refs; 33 /* Structures only used by data */ 34 struct { 35 atomic_t readers; 36 }; 37 }; 38 }; 39 40 enum btrfs_subpage_type { 41 BTRFS_SUBPAGE_METADATA, 42 BTRFS_SUBPAGE_DATA, 43 }; 44 45 int btrfs_attach_subpage(const struct btrfs_fs_info *fs_info, 46 struct page *page, enum btrfs_subpage_type type); 47 void btrfs_detach_subpage(const struct btrfs_fs_info *fs_info, 48 struct page *page); 49 50 /* Allocate additional data where page represents more than one sector */ 51 int btrfs_alloc_subpage(const struct btrfs_fs_info *fs_info, 52 struct btrfs_subpage **ret, 53 enum btrfs_subpage_type type); 54 void btrfs_free_subpage(struct btrfs_subpage *subpage); 55 56 void btrfs_page_inc_eb_refs(const struct btrfs_fs_info *fs_info, 57 struct page *page); 58 void btrfs_page_dec_eb_refs(const struct btrfs_fs_info *fs_info, 59 struct page *page); 60 61 void btrfs_subpage_start_reader(const struct btrfs_fs_info *fs_info, 62 struct page *page, u64 start, u32 len); 63 void btrfs_subpage_end_reader(const struct btrfs_fs_info *fs_info, 64 struct page *page, u64 start, u32 len); 65 66 /* 67 * Template for subpage related operations. 68 * 69 * btrfs_subpage_*() are for call sites where the page has subpage attached and 70 * the range is ensured to be inside the page. 71 * 72 * btrfs_page_*() are for call sites where the page can either be subpage 73 * specific or regular page. The function will handle both cases. 74 * But the range still needs to be inside the page. 75 */ 76 #define DECLARE_BTRFS_SUBPAGE_OPS(name) \ 77 void btrfs_subpage_set_##name(const struct btrfs_fs_info *fs_info, \ 78 struct page *page, u64 start, u32 len); \ 79 void btrfs_subpage_clear_##name(const struct btrfs_fs_info *fs_info, \ 80 struct page *page, u64 start, u32 len); \ 81 bool btrfs_subpage_test_##name(const struct btrfs_fs_info *fs_info, \ 82 struct page *page, u64 start, u32 len); \ 83 void btrfs_page_set_##name(const struct btrfs_fs_info *fs_info, \ 84 struct page *page, u64 start, u32 len); \ 85 void btrfs_page_clear_##name(const struct btrfs_fs_info *fs_info, \ 86 struct page *page, u64 start, u32 len); \ 87 bool btrfs_page_test_##name(const struct btrfs_fs_info *fs_info, \ 88 struct page *page, u64 start, u32 len); 89 90 DECLARE_BTRFS_SUBPAGE_OPS(uptodate); 91 DECLARE_BTRFS_SUBPAGE_OPS(error); 92 DECLARE_BTRFS_SUBPAGE_OPS(dirty); 93 DECLARE_BTRFS_SUBPAGE_OPS(writeback); 94 95 bool btrfs_subpage_clear_and_test_dirty(const struct btrfs_fs_info *fs_info, 96 struct page *page, u64 start, u32 len); 97 98 #endif 99