18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci#ifndef BTRFS_SPACE_INFO_H 48c2ecf20Sopenharmony_ci#define BTRFS_SPACE_INFO_H 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_cistruct btrfs_space_info { 78c2ecf20Sopenharmony_ci spinlock_t lock; 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci u64 total_bytes; /* total bytes in the space, 108c2ecf20Sopenharmony_ci this doesn't take mirrors into account */ 118c2ecf20Sopenharmony_ci u64 bytes_used; /* total bytes used, 128c2ecf20Sopenharmony_ci this doesn't take mirrors into account */ 138c2ecf20Sopenharmony_ci u64 bytes_pinned; /* total bytes pinned, will be freed when the 148c2ecf20Sopenharmony_ci transaction finishes */ 158c2ecf20Sopenharmony_ci u64 bytes_reserved; /* total bytes the allocator has reserved for 168c2ecf20Sopenharmony_ci current allocations */ 178c2ecf20Sopenharmony_ci u64 bytes_may_use; /* number of bytes that may be used for 188c2ecf20Sopenharmony_ci delalloc/allocations */ 198c2ecf20Sopenharmony_ci u64 bytes_readonly; /* total bytes that are read only */ 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci u64 max_extent_size; /* This will hold the maximum extent size of 228c2ecf20Sopenharmony_ci the space info if we had an ENOSPC in the 238c2ecf20Sopenharmony_ci allocator. */ 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci unsigned int full:1; /* indicates that we cannot allocate any more 268c2ecf20Sopenharmony_ci chunks for this space */ 278c2ecf20Sopenharmony_ci unsigned int chunk_alloc:1; /* set if we are allocating a chunk */ 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci unsigned int flush:1; /* set if we are trying to make space */ 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci unsigned int force_alloc; /* set if we need to force a chunk 328c2ecf20Sopenharmony_ci alloc for this space */ 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci u64 disk_used; /* total bytes used on disk */ 358c2ecf20Sopenharmony_ci u64 disk_total; /* total bytes on disk, takes mirrors into 368c2ecf20Sopenharmony_ci account */ 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci u64 flags; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci /* 418c2ecf20Sopenharmony_ci * bytes_pinned is kept in line with what is actually pinned, as in 428c2ecf20Sopenharmony_ci * we've called update_block_group and dropped the bytes_used counter 438c2ecf20Sopenharmony_ci * and increased the bytes_pinned counter. However this means that 448c2ecf20Sopenharmony_ci * bytes_pinned does not reflect the bytes that will be pinned once the 458c2ecf20Sopenharmony_ci * delayed refs are flushed, so this counter is inc'ed every time we 468c2ecf20Sopenharmony_ci * call btrfs_free_extent so it is a realtime count of what will be 478c2ecf20Sopenharmony_ci * freed once the transaction is committed. It will be zeroed every 488c2ecf20Sopenharmony_ci * time the transaction commits. 498c2ecf20Sopenharmony_ci */ 508c2ecf20Sopenharmony_ci struct percpu_counter total_bytes_pinned; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci struct list_head list; 538c2ecf20Sopenharmony_ci /* Protected by the spinlock 'lock'. */ 548c2ecf20Sopenharmony_ci struct list_head ro_bgs; 558c2ecf20Sopenharmony_ci struct list_head priority_tickets; 568c2ecf20Sopenharmony_ci struct list_head tickets; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci /* 598c2ecf20Sopenharmony_ci * Size of space that needs to be reclaimed in order to satisfy pending 608c2ecf20Sopenharmony_ci * tickets 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_ci u64 reclaim_size; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci /* 658c2ecf20Sopenharmony_ci * tickets_id just indicates the next ticket will be handled, so note 668c2ecf20Sopenharmony_ci * it's not stored per ticket. 678c2ecf20Sopenharmony_ci */ 688c2ecf20Sopenharmony_ci u64 tickets_id; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci struct rw_semaphore groups_sem; 718c2ecf20Sopenharmony_ci /* for block groups in our same type */ 728c2ecf20Sopenharmony_ci struct list_head block_groups[BTRFS_NR_RAID_TYPES]; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci struct kobject kobj; 758c2ecf20Sopenharmony_ci struct kobject *block_group_kobjs[BTRFS_NR_RAID_TYPES]; 768c2ecf20Sopenharmony_ci}; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistruct reserve_ticket { 798c2ecf20Sopenharmony_ci u64 bytes; 808c2ecf20Sopenharmony_ci int error; 818c2ecf20Sopenharmony_ci bool steal; 828c2ecf20Sopenharmony_ci struct list_head list; 838c2ecf20Sopenharmony_ci wait_queue_head_t wait; 848c2ecf20Sopenharmony_ci}; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic inline bool btrfs_mixed_space_info(struct btrfs_space_info *space_info) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci return ((space_info->flags & BTRFS_BLOCK_GROUP_METADATA) && 898c2ecf20Sopenharmony_ci (space_info->flags & BTRFS_BLOCK_GROUP_DATA)); 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci/* 938c2ecf20Sopenharmony_ci * 948c2ecf20Sopenharmony_ci * Declare a helper function to detect underflow of various space info members 958c2ecf20Sopenharmony_ci */ 968c2ecf20Sopenharmony_ci#define DECLARE_SPACE_INFO_UPDATE(name, trace_name) \ 978c2ecf20Sopenharmony_cistatic inline void \ 988c2ecf20Sopenharmony_cibtrfs_space_info_update_##name(struct btrfs_fs_info *fs_info, \ 998c2ecf20Sopenharmony_ci struct btrfs_space_info *sinfo, \ 1008c2ecf20Sopenharmony_ci s64 bytes) \ 1018c2ecf20Sopenharmony_ci{ \ 1028c2ecf20Sopenharmony_ci const u64 abs_bytes = (bytes < 0) ? -bytes : bytes; \ 1038c2ecf20Sopenharmony_ci lockdep_assert_held(&sinfo->lock); \ 1048c2ecf20Sopenharmony_ci trace_update_##name(fs_info, sinfo, sinfo->name, bytes); \ 1058c2ecf20Sopenharmony_ci trace_btrfs_space_reservation(fs_info, trace_name, \ 1068c2ecf20Sopenharmony_ci sinfo->flags, abs_bytes, \ 1078c2ecf20Sopenharmony_ci bytes > 0); \ 1088c2ecf20Sopenharmony_ci if (bytes < 0 && sinfo->name < -bytes) { \ 1098c2ecf20Sopenharmony_ci WARN_ON(1); \ 1108c2ecf20Sopenharmony_ci sinfo->name = 0; \ 1118c2ecf20Sopenharmony_ci return; \ 1128c2ecf20Sopenharmony_ci } \ 1138c2ecf20Sopenharmony_ci sinfo->name += bytes; \ 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ciDECLARE_SPACE_INFO_UPDATE(bytes_may_use, "space_info"); 1178c2ecf20Sopenharmony_ciDECLARE_SPACE_INFO_UPDATE(bytes_pinned, "pinned"); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ciint btrfs_init_space_info(struct btrfs_fs_info *fs_info); 1208c2ecf20Sopenharmony_civoid btrfs_update_space_info(struct btrfs_fs_info *info, u64 flags, 1218c2ecf20Sopenharmony_ci u64 total_bytes, u64 bytes_used, 1228c2ecf20Sopenharmony_ci u64 bytes_readonly, 1238c2ecf20Sopenharmony_ci struct btrfs_space_info **space_info); 1248c2ecf20Sopenharmony_cistruct btrfs_space_info *btrfs_find_space_info(struct btrfs_fs_info *info, 1258c2ecf20Sopenharmony_ci u64 flags); 1268c2ecf20Sopenharmony_ciu64 __pure btrfs_space_info_used(struct btrfs_space_info *s_info, 1278c2ecf20Sopenharmony_ci bool may_use_included); 1288c2ecf20Sopenharmony_civoid btrfs_clear_space_info_full(struct btrfs_fs_info *info); 1298c2ecf20Sopenharmony_civoid btrfs_dump_space_info(struct btrfs_fs_info *fs_info, 1308c2ecf20Sopenharmony_ci struct btrfs_space_info *info, u64 bytes, 1318c2ecf20Sopenharmony_ci int dump_block_groups); 1328c2ecf20Sopenharmony_ciint btrfs_reserve_metadata_bytes(struct btrfs_root *root, 1338c2ecf20Sopenharmony_ci struct btrfs_block_rsv *block_rsv, 1348c2ecf20Sopenharmony_ci u64 orig_bytes, 1358c2ecf20Sopenharmony_ci enum btrfs_reserve_flush_enum flush); 1368c2ecf20Sopenharmony_civoid btrfs_try_granting_tickets(struct btrfs_fs_info *fs_info, 1378c2ecf20Sopenharmony_ci struct btrfs_space_info *space_info); 1388c2ecf20Sopenharmony_ciint btrfs_can_overcommit(struct btrfs_fs_info *fs_info, 1398c2ecf20Sopenharmony_ci struct btrfs_space_info *space_info, u64 bytes, 1408c2ecf20Sopenharmony_ci enum btrfs_reserve_flush_enum flush); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic inline void btrfs_space_info_free_bytes_may_use( 1438c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info, 1448c2ecf20Sopenharmony_ci struct btrfs_space_info *space_info, 1458c2ecf20Sopenharmony_ci u64 num_bytes) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci spin_lock(&space_info->lock); 1488c2ecf20Sopenharmony_ci btrfs_space_info_update_bytes_may_use(fs_info, space_info, -num_bytes); 1498c2ecf20Sopenharmony_ci btrfs_try_granting_tickets(fs_info, space_info); 1508c2ecf20Sopenharmony_ci spin_unlock(&space_info->lock); 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ciint btrfs_reserve_data_bytes(struct btrfs_fs_info *fs_info, u64 bytes, 1538c2ecf20Sopenharmony_ci enum btrfs_reserve_flush_enum flush); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic inline void __btrfs_mod_total_bytes_pinned( 1568c2ecf20Sopenharmony_ci struct btrfs_space_info *space_info, 1578c2ecf20Sopenharmony_ci s64 mod) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci percpu_counter_add_batch(&space_info->total_bytes_pinned, mod, 1608c2ecf20Sopenharmony_ci BTRFS_TOTAL_BYTES_PINNED_BATCH); 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cistatic inline void btrfs_mod_total_bytes_pinned(struct btrfs_fs_info *fs_info, 1648c2ecf20Sopenharmony_ci u64 flags, s64 mod) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci struct btrfs_space_info *space_info = btrfs_find_space_info(fs_info, flags); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci ASSERT(space_info); 1698c2ecf20Sopenharmony_ci __btrfs_mod_total_bytes_pinned(space_info, mod); 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci#endif /* BTRFS_SPACE_INFO_H */ 173