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 union { 24 /* 25 * Structures only used by metadata 26 * 27 * @eb_refs should only be operated under private_lock, as it 28 * manages whether the subpage can be detached. 29 */ 30 atomic_t eb_refs; 31 /* Structures only used by data */ 32 struct { 33 atomic_t readers; 34 }; 35 }; 36 }; 37 38 enum btrfs_subpage_type { 39 BTRFS_SUBPAGE_METADATA, 40 BTRFS_SUBPAGE_DATA, 41 }; 42 43 int btrfs_attach_subpage(const struct btrfs_fs_info *fs_info, 44 struct page *page, enum btrfs_subpage_type type); 45 void btrfs_detach_subpage(const struct btrfs_fs_info *fs_info, 46 struct page *page); 47 48 /* Allocate additional data where page represents more than one sector */ 49 int btrfs_alloc_subpage(const struct btrfs_fs_info *fs_info, 50 struct btrfs_subpage **ret, 51 enum btrfs_subpage_type type); 52 void btrfs_free_subpage(struct btrfs_subpage *subpage); 53 54 void btrfs_page_inc_eb_refs(const struct btrfs_fs_info *fs_info, 55 struct page *page); 56 void btrfs_page_dec_eb_refs(const struct btrfs_fs_info *fs_info, 57 struct page *page); 58 59 void btrfs_subpage_start_reader(const struct btrfs_fs_info *fs_info, 60 struct page *page, u64 start, u32 len); 61 void btrfs_subpage_end_reader(const struct btrfs_fs_info *fs_info, 62 struct page *page, u64 start, u32 len); 63 64 /* 65 * Template for subpage related operations. 66 * 67 * btrfs_subpage_*() are for call sites where the page has subpage attached and 68 * the range is ensured to be inside the page. 69 * 70 * btrfs_page_*() are for call sites where the page can either be subpage 71 * specific or regular page. The function will handle both cases. 72 * But the range still needs to be inside the page. 73 */ 74 #define DECLARE_BTRFS_SUBPAGE_OPS(name) \ 75 void btrfs_subpage_set_##name(const struct btrfs_fs_info *fs_info, \ 76 struct page *page, u64 start, u32 len); \ 77 void btrfs_subpage_clear_##name(const struct btrfs_fs_info *fs_info, \ 78 struct page *page, u64 start, u32 len); \ 79 bool btrfs_subpage_test_##name(const struct btrfs_fs_info *fs_info, \ 80 struct page *page, u64 start, u32 len); \ 81 void btrfs_page_set_##name(const struct btrfs_fs_info *fs_info, \ 82 struct page *page, u64 start, u32 len); \ 83 void btrfs_page_clear_##name(const struct btrfs_fs_info *fs_info, \ 84 struct page *page, u64 start, u32 len); \ 85 bool btrfs_page_test_##name(const struct btrfs_fs_info *fs_info, \ 86 struct page *page, u64 start, u32 len); 87 88 DECLARE_BTRFS_SUBPAGE_OPS(uptodate); 89 DECLARE_BTRFS_SUBPAGE_OPS(error); 90 91 #endif 92