space-info.h (5032B)
1/* SPDX-License-Identifier: GPL-2.0 */ 2 3#ifndef BTRFS_SPACE_INFO_H 4#define BTRFS_SPACE_INFO_H 5 6#include "volumes.h" 7 8struct btrfs_space_info { 9 spinlock_t lock; 10 11 u64 total_bytes; /* total bytes in the space, 12 this doesn't take mirrors into account */ 13 u64 bytes_used; /* total bytes used, 14 this doesn't take mirrors into account */ 15 u64 bytes_pinned; /* total bytes pinned, will be freed when the 16 transaction finishes */ 17 u64 bytes_reserved; /* total bytes the allocator has reserved for 18 current allocations */ 19 u64 bytes_may_use; /* number of bytes that may be used for 20 delalloc/allocations */ 21 u64 bytes_readonly; /* total bytes that are read only */ 22 u64 bytes_zone_unusable; /* total bytes that are unusable until 23 resetting the device zone */ 24 25 u64 max_extent_size; /* This will hold the maximum extent size of 26 the space info if we had an ENOSPC in the 27 allocator. */ 28 29 /* 30 * Once a block group drops below this threshold (percents) we'll 31 * schedule it for reclaim. 32 */ 33 int bg_reclaim_threshold; 34 35 int clamp; /* Used to scale our threshold for preemptive 36 flushing. The value is >> clamp, so turns 37 out to be a 2^clamp divisor. */ 38 39 unsigned int full:1; /* indicates that we cannot allocate any more 40 chunks for this space */ 41 unsigned int chunk_alloc:1; /* set if we are allocating a chunk */ 42 43 unsigned int flush:1; /* set if we are trying to make space */ 44 45 unsigned int force_alloc; /* set if we need to force a chunk 46 alloc for this space */ 47 48 u64 disk_used; /* total bytes used on disk */ 49 u64 disk_total; /* total bytes on disk, takes mirrors into 50 account */ 51 52 u64 flags; 53 54 struct list_head list; 55 /* Protected by the spinlock 'lock'. */ 56 struct list_head ro_bgs; 57 struct list_head priority_tickets; 58 struct list_head tickets; 59 60 /* 61 * Size of space that needs to be reclaimed in order to satisfy pending 62 * tickets 63 */ 64 u64 reclaim_size; 65 66 /* 67 * tickets_id just indicates the next ticket will be handled, so note 68 * it's not stored per ticket. 69 */ 70 u64 tickets_id; 71 72 struct rw_semaphore groups_sem; 73 /* for block groups in our same type */ 74 struct list_head block_groups[BTRFS_NR_RAID_TYPES]; 75 76 struct kobject kobj; 77 struct kobject *block_group_kobjs[BTRFS_NR_RAID_TYPES]; 78}; 79 80struct reserve_ticket { 81 u64 bytes; 82 int error; 83 bool steal; 84 struct list_head list; 85 wait_queue_head_t wait; 86}; 87 88static inline bool btrfs_mixed_space_info(struct btrfs_space_info *space_info) 89{ 90 return ((space_info->flags & BTRFS_BLOCK_GROUP_METADATA) && 91 (space_info->flags & BTRFS_BLOCK_GROUP_DATA)); 92} 93 94/* 95 * 96 * Declare a helper function to detect underflow of various space info members 97 */ 98#define DECLARE_SPACE_INFO_UPDATE(name, trace_name) \ 99static inline void \ 100btrfs_space_info_update_##name(struct btrfs_fs_info *fs_info, \ 101 struct btrfs_space_info *sinfo, \ 102 s64 bytes) \ 103{ \ 104 const u64 abs_bytes = (bytes < 0) ? -bytes : bytes; \ 105 lockdep_assert_held(&sinfo->lock); \ 106 trace_update_##name(fs_info, sinfo, sinfo->name, bytes); \ 107 trace_btrfs_space_reservation(fs_info, trace_name, \ 108 sinfo->flags, abs_bytes, \ 109 bytes > 0); \ 110 if (bytes < 0 && sinfo->name < -bytes) { \ 111 WARN_ON(1); \ 112 sinfo->name = 0; \ 113 return; \ 114 } \ 115 sinfo->name += bytes; \ 116} 117 118DECLARE_SPACE_INFO_UPDATE(bytes_may_use, "space_info"); 119DECLARE_SPACE_INFO_UPDATE(bytes_pinned, "pinned"); 120 121int btrfs_init_space_info(struct btrfs_fs_info *fs_info); 122void btrfs_update_space_info(struct btrfs_fs_info *info, u64 flags, 123 u64 total_bytes, u64 bytes_used, 124 u64 bytes_readonly, u64 bytes_zone_unusable, 125 struct btrfs_space_info **space_info); 126struct btrfs_space_info *btrfs_find_space_info(struct btrfs_fs_info *info, 127 u64 flags); 128u64 __pure btrfs_space_info_used(struct btrfs_space_info *s_info, 129 bool may_use_included); 130void btrfs_clear_space_info_full(struct btrfs_fs_info *info); 131void btrfs_dump_space_info(struct btrfs_fs_info *fs_info, 132 struct btrfs_space_info *info, u64 bytes, 133 int dump_block_groups); 134int btrfs_reserve_metadata_bytes(struct btrfs_fs_info *fs_info, 135 struct btrfs_block_rsv *block_rsv, 136 u64 orig_bytes, 137 enum btrfs_reserve_flush_enum flush); 138void btrfs_try_granting_tickets(struct btrfs_fs_info *fs_info, 139 struct btrfs_space_info *space_info); 140int btrfs_can_overcommit(struct btrfs_fs_info *fs_info, 141 struct btrfs_space_info *space_info, u64 bytes, 142 enum btrfs_reserve_flush_enum flush); 143 144static inline void btrfs_space_info_free_bytes_may_use( 145 struct btrfs_fs_info *fs_info, 146 struct btrfs_space_info *space_info, 147 u64 num_bytes) 148{ 149 spin_lock(&space_info->lock); 150 btrfs_space_info_update_bytes_may_use(fs_info, space_info, -num_bytes); 151 btrfs_try_granting_tickets(fs_info, space_info); 152 spin_unlock(&space_info->lock); 153} 154int btrfs_reserve_data_bytes(struct btrfs_fs_info *fs_info, u64 bytes, 155 enum btrfs_reserve_flush_enum flush); 156#endif /* BTRFS_SPACE_INFO_H */