1cac06d84SQu Wenruo // SPDX-License-Identifier: GPL-2.0 2cac06d84SQu Wenruo 3cac06d84SQu Wenruo #include <linux/slab.h> 4cac06d84SQu Wenruo #include "ctree.h" 5cac06d84SQu Wenruo #include "subpage.h" 6cac06d84SQu Wenruo 7cac06d84SQu Wenruo int btrfs_attach_subpage(const struct btrfs_fs_info *fs_info, 8cac06d84SQu Wenruo struct page *page, enum btrfs_subpage_type type) 9cac06d84SQu Wenruo { 10760f991fSQu Wenruo struct btrfs_subpage *subpage = NULL; 11760f991fSQu Wenruo int ret; 12cac06d84SQu Wenruo 13cac06d84SQu Wenruo /* 14cac06d84SQu Wenruo * We have cases like a dummy extent buffer page, which is not mappped 15cac06d84SQu Wenruo * and doesn't need to be locked. 16cac06d84SQu Wenruo */ 17cac06d84SQu Wenruo if (page->mapping) 18cac06d84SQu Wenruo ASSERT(PageLocked(page)); 19cac06d84SQu Wenruo /* Either not subpage, or the page already has private attached */ 20cac06d84SQu Wenruo if (fs_info->sectorsize == PAGE_SIZE || PagePrivate(page)) 21cac06d84SQu Wenruo return 0; 22cac06d84SQu Wenruo 23760f991fSQu Wenruo ret = btrfs_alloc_subpage(fs_info, &subpage, type); 24760f991fSQu Wenruo if (ret < 0) 25760f991fSQu Wenruo return ret; 26cac06d84SQu Wenruo attach_page_private(page, subpage); 27cac06d84SQu Wenruo return 0; 28cac06d84SQu Wenruo } 29cac06d84SQu Wenruo 30cac06d84SQu Wenruo void btrfs_detach_subpage(const struct btrfs_fs_info *fs_info, 31cac06d84SQu Wenruo struct page *page) 32cac06d84SQu Wenruo { 33cac06d84SQu Wenruo struct btrfs_subpage *subpage; 34cac06d84SQu Wenruo 35cac06d84SQu Wenruo /* Either not subpage, or already detached */ 36cac06d84SQu Wenruo if (fs_info->sectorsize == PAGE_SIZE || !PagePrivate(page)) 37cac06d84SQu Wenruo return; 38cac06d84SQu Wenruo 39cac06d84SQu Wenruo subpage = (struct btrfs_subpage *)detach_page_private(page); 40cac06d84SQu Wenruo ASSERT(subpage); 41760f991fSQu Wenruo btrfs_free_subpage(subpage); 42760f991fSQu Wenruo } 43760f991fSQu Wenruo 44760f991fSQu Wenruo int btrfs_alloc_subpage(const struct btrfs_fs_info *fs_info, 45760f991fSQu Wenruo struct btrfs_subpage **ret, 46760f991fSQu Wenruo enum btrfs_subpage_type type) 47760f991fSQu Wenruo { 48760f991fSQu Wenruo if (fs_info->sectorsize == PAGE_SIZE) 49760f991fSQu Wenruo return 0; 50760f991fSQu Wenruo 51760f991fSQu Wenruo *ret = kzalloc(sizeof(struct btrfs_subpage), GFP_NOFS); 52760f991fSQu Wenruo if (!*ret) 53760f991fSQu Wenruo return -ENOMEM; 54760f991fSQu Wenruo spin_lock_init(&(*ret)->lock); 55*8ff8466dSQu Wenruo if (type == BTRFS_SUBPAGE_METADATA) 56*8ff8466dSQu Wenruo atomic_set(&(*ret)->eb_refs, 0); 57760f991fSQu Wenruo return 0; 58760f991fSQu Wenruo } 59760f991fSQu Wenruo 60760f991fSQu Wenruo void btrfs_free_subpage(struct btrfs_subpage *subpage) 61760f991fSQu Wenruo { 62cac06d84SQu Wenruo kfree(subpage); 63cac06d84SQu Wenruo } 64*8ff8466dSQu Wenruo 65*8ff8466dSQu Wenruo /* 66*8ff8466dSQu Wenruo * Increase the eb_refs of current subpage. 67*8ff8466dSQu Wenruo * 68*8ff8466dSQu Wenruo * This is important for eb allocation, to prevent race with last eb freeing 69*8ff8466dSQu Wenruo * of the same page. 70*8ff8466dSQu Wenruo * With the eb_refs increased before the eb inserted into radix tree, 71*8ff8466dSQu Wenruo * detach_extent_buffer_page() won't detach the page private while we're still 72*8ff8466dSQu Wenruo * allocating the extent buffer. 73*8ff8466dSQu Wenruo */ 74*8ff8466dSQu Wenruo void btrfs_page_inc_eb_refs(const struct btrfs_fs_info *fs_info, 75*8ff8466dSQu Wenruo struct page *page) 76*8ff8466dSQu Wenruo { 77*8ff8466dSQu Wenruo struct btrfs_subpage *subpage; 78*8ff8466dSQu Wenruo 79*8ff8466dSQu Wenruo if (fs_info->sectorsize == PAGE_SIZE) 80*8ff8466dSQu Wenruo return; 81*8ff8466dSQu Wenruo 82*8ff8466dSQu Wenruo ASSERT(PagePrivate(page) && page->mapping); 83*8ff8466dSQu Wenruo lockdep_assert_held(&page->mapping->private_lock); 84*8ff8466dSQu Wenruo 85*8ff8466dSQu Wenruo subpage = (struct btrfs_subpage *)page->private; 86*8ff8466dSQu Wenruo atomic_inc(&subpage->eb_refs); 87*8ff8466dSQu Wenruo } 88*8ff8466dSQu Wenruo 89*8ff8466dSQu Wenruo void btrfs_page_dec_eb_refs(const struct btrfs_fs_info *fs_info, 90*8ff8466dSQu Wenruo struct page *page) 91*8ff8466dSQu Wenruo { 92*8ff8466dSQu Wenruo struct btrfs_subpage *subpage; 93*8ff8466dSQu Wenruo 94*8ff8466dSQu Wenruo if (fs_info->sectorsize == PAGE_SIZE) 95*8ff8466dSQu Wenruo return; 96*8ff8466dSQu Wenruo 97*8ff8466dSQu Wenruo ASSERT(PagePrivate(page) && page->mapping); 98*8ff8466dSQu Wenruo lockdep_assert_held(&page->mapping->private_lock); 99*8ff8466dSQu Wenruo 100*8ff8466dSQu Wenruo subpage = (struct btrfs_subpage *)page->private; 101*8ff8466dSQu Wenruo ASSERT(atomic_read(&subpage->eb_refs)); 102*8ff8466dSQu Wenruo atomic_dec(&subpage->eb_refs); 103*8ff8466dSQu Wenruo } 104