diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-16 18:12:56 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-16 18:12:56 -0400 |
| commit | a18f8775419d3df282dd83efdb51c5a64d092f31 (patch) | |
| tree | 1e0abc5c1d30e8bc58dc23099017eca496992fd2 /fs/btrfs/delayed-ref.c | |
| parent | 3eb514866f20c5eb74637279774b6d73b855480a (diff) | |
| parent | e02d48eaaed77f6c36916a7aa65c451e1f9d9aab (diff) | |
Merge tag 'for-5.3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs updates from David Sterba:
"Highlights:
- chunks that have been trimmed and unchanged since last mount are
tracked and skipped on repeated trims
- use hw assissed crc32c on more arches, speedups if native
instructions or optimized implementation is available
- the RAID56 incompat bit is automatically removed when the last
block group of that type is removed
Fixes:
- fsync fix for reflink on NODATACOW files that could lead to ENOSPC
- fix data loss after inode eviction, renaming it, and fsync it
- fix fsync not persisting dentry deletions due to inode evictions
- update ctime/mtime/iversion after hole punching
- fix compression type validation (reported by KASAN)
- send won't be allowed to start when relocation is in progress, this
can cause spurious errors or produce incorrect send stream
Core:
- new tracepoints for space update
- tree-checker: better check for end of extents for some tree items
- preparatory work for more checksum algorithms
- run delayed iput at unlink time and don't push the work to cleaner
thread where it's not properly throttled
- wrap block mapping to structures and helpers, base for further
refactoring
- split large files, part 1:
- space info handling
- block group reservations
- delayed refs
- delayed allocation
- other cleanups and refactoring"
* tag 'for-5.3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: (103 commits)
btrfs: fix memory leak of path on error return path
btrfs: move the subvolume reservation stuff out of extent-tree.c
btrfs: migrate the delalloc space stuff to it's own home
btrfs: migrate btrfs_trans_release_chunk_metadata
btrfs: migrate the delayed refs rsv code
btrfs: Evaluate io_tree in find_lock_delalloc_range()
btrfs: migrate the global_block_rsv helpers to block-rsv.c
btrfs: migrate the block-rsv code to block-rsv.c
btrfs: stop using block_rsv_release_bytes everywhere
btrfs: cleanup the target logic in __btrfs_block_rsv_release
btrfs: export __btrfs_block_rsv_release
btrfs: export btrfs_block_rsv_add_bytes
btrfs: move btrfs_block_rsv definitions into it's own header
btrfs: Simplify update of space_info in __reserve_metadata_bytes()
btrfs: unexport can_overcommit
btrfs: move reserve_metadata_bytes and supporting code to space-info.c
btrfs: move dump_space_info to space-info.c
btrfs: export block_rsv_use_bytes
btrfs: move btrfs_space_info_add_*_bytes to space-info.c
btrfs: move the space info update macro to space-info.h
...
Diffstat (limited to 'fs/btrfs/delayed-ref.c')
| -rw-r--r-- | fs/btrfs/delayed-ref.c | 181 |
1 files changed, 178 insertions, 3 deletions
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c index a73fc23e2961..9a91d1eb0af4 100644 --- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "delayed-ref.h" | 10 | #include "delayed-ref.h" |
| 11 | #include "transaction.h" | 11 | #include "transaction.h" |
| 12 | #include "qgroup.h" | 12 | #include "qgroup.h" |
| 13 | #include "space-info.h" | ||
| 13 | 14 | ||
| 14 | struct kmem_cache *btrfs_delayed_ref_head_cachep; | 15 | struct kmem_cache *btrfs_delayed_ref_head_cachep; |
| 15 | struct kmem_cache *btrfs_delayed_tree_ref_cachep; | 16 | struct kmem_cache *btrfs_delayed_tree_ref_cachep; |
| @@ -24,6 +25,179 @@ struct kmem_cache *btrfs_delayed_extent_op_cachep; | |||
| 24 | * of hammering updates on the extent allocation tree. | 25 | * of hammering updates on the extent allocation tree. |
| 25 | */ | 26 | */ |
| 26 | 27 | ||
| 28 | bool btrfs_check_space_for_delayed_refs(struct btrfs_fs_info *fs_info) | ||
| 29 | { | ||
| 30 | struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv; | ||
| 31 | struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; | ||
| 32 | bool ret = false; | ||
| 33 | u64 reserved; | ||
| 34 | |||
| 35 | spin_lock(&global_rsv->lock); | ||
| 36 | reserved = global_rsv->reserved; | ||
| 37 | spin_unlock(&global_rsv->lock); | ||
| 38 | |||
| 39 | /* | ||
| 40 | * Since the global reserve is just kind of magic we don't really want | ||
| 41 | * to rely on it to save our bacon, so if our size is more than the | ||
| 42 | * delayed_refs_rsv and the global rsv then it's time to think about | ||
| 43 | * bailing. | ||
| 44 | */ | ||
| 45 | spin_lock(&delayed_refs_rsv->lock); | ||
| 46 | reserved += delayed_refs_rsv->reserved; | ||
| 47 | if (delayed_refs_rsv->size >= reserved) | ||
| 48 | ret = true; | ||
| 49 | spin_unlock(&delayed_refs_rsv->lock); | ||
| 50 | return ret; | ||
| 51 | } | ||
| 52 | |||
| 53 | int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans) | ||
| 54 | { | ||
| 55 | u64 num_entries = | ||
| 56 | atomic_read(&trans->transaction->delayed_refs.num_entries); | ||
| 57 | u64 avg_runtime; | ||
| 58 | u64 val; | ||
| 59 | |||
| 60 | smp_mb(); | ||
| 61 | avg_runtime = trans->fs_info->avg_delayed_ref_runtime; | ||
| 62 | val = num_entries * avg_runtime; | ||
| 63 | if (val >= NSEC_PER_SEC) | ||
| 64 | return 1; | ||
| 65 | if (val >= NSEC_PER_SEC / 2) | ||
| 66 | return 2; | ||
| 67 | |||
| 68 | return btrfs_check_space_for_delayed_refs(trans->fs_info); | ||
| 69 | } | ||
| 70 | |||
| 71 | /** | ||
| 72 | * btrfs_delayed_refs_rsv_release - release a ref head's reservation. | ||
| 73 | * @fs_info - the fs_info for our fs. | ||
| 74 | * @nr - the number of items to drop. | ||
| 75 | * | ||
| 76 | * This drops the delayed ref head's count from the delayed refs rsv and frees | ||
| 77 | * any excess reservation we had. | ||
| 78 | */ | ||
| 79 | void btrfs_delayed_refs_rsv_release(struct btrfs_fs_info *fs_info, int nr) | ||
| 80 | { | ||
| 81 | struct btrfs_block_rsv *block_rsv = &fs_info->delayed_refs_rsv; | ||
| 82 | u64 num_bytes = btrfs_calc_trans_metadata_size(fs_info, nr); | ||
| 83 | u64 released = 0; | ||
| 84 | |||
| 85 | released = __btrfs_block_rsv_release(fs_info, block_rsv, num_bytes, | ||
| 86 | NULL); | ||
| 87 | if (released) | ||
| 88 | trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", | ||
| 89 | 0, released, 0); | ||
| 90 | } | ||
| 91 | |||
| 92 | /* | ||
| 93 | * btrfs_update_delayed_refs_rsv - adjust the size of the delayed refs rsv | ||
| 94 | * @trans - the trans that may have generated delayed refs | ||
| 95 | * | ||
| 96 | * This is to be called anytime we may have adjusted trans->delayed_ref_updates, | ||
| 97 | * it'll calculate the additional size and add it to the delayed_refs_rsv. | ||
| 98 | */ | ||
| 99 | void btrfs_update_delayed_refs_rsv(struct btrfs_trans_handle *trans) | ||
| 100 | { | ||
| 101 | struct btrfs_fs_info *fs_info = trans->fs_info; | ||
| 102 | struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_refs_rsv; | ||
| 103 | u64 num_bytes; | ||
| 104 | |||
| 105 | if (!trans->delayed_ref_updates) | ||
| 106 | return; | ||
| 107 | |||
| 108 | num_bytes = btrfs_calc_trans_metadata_size(fs_info, | ||
| 109 | trans->delayed_ref_updates); | ||
| 110 | spin_lock(&delayed_rsv->lock); | ||
| 111 | delayed_rsv->size += num_bytes; | ||
| 112 | delayed_rsv->full = 0; | ||
| 113 | spin_unlock(&delayed_rsv->lock); | ||
| 114 | trans->delayed_ref_updates = 0; | ||
| 115 | } | ||
| 116 | |||
| 117 | /** | ||
| 118 | * btrfs_migrate_to_delayed_refs_rsv - transfer bytes to our delayed refs rsv. | ||
| 119 | * @fs_info - the fs info for our fs. | ||
| 120 | * @src - the source block rsv to transfer from. | ||
| 121 | * @num_bytes - the number of bytes to transfer. | ||
| 122 | * | ||
| 123 | * This transfers up to the num_bytes amount from the src rsv to the | ||
| 124 | * delayed_refs_rsv. Any extra bytes are returned to the space info. | ||
| 125 | */ | ||
| 126 | void btrfs_migrate_to_delayed_refs_rsv(struct btrfs_fs_info *fs_info, | ||
| 127 | struct btrfs_block_rsv *src, | ||
| 128 | u64 num_bytes) | ||
| 129 | { | ||
| 130 | struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv; | ||
| 131 | u64 to_free = 0; | ||
| 132 | |||
| 133 | spin_lock(&src->lock); | ||
| 134 | src->reserved -= num_bytes; | ||
| 135 | src->size -= num_bytes; | ||
| 136 | spin_unlock(&src->lock); | ||
| 137 | |||
| 138 | spin_lock(&delayed_refs_rsv->lock); | ||
| 139 | if (delayed_refs_rsv->size > delayed_refs_rsv->reserved) { | ||
| 140 | u64 delta = delayed_refs_rsv->size - | ||
| 141 | delayed_refs_rsv->reserved; | ||
| 142 | if (num_bytes > delta) { | ||
| 143 | to_free = num_bytes - delta; | ||
| 144 | num_bytes = delta; | ||
| 145 | } | ||
| 146 | } else { | ||
| 147 | to_free = num_bytes; | ||
| 148 | num_bytes = 0; | ||
| 149 | } | ||
| 150 | |||
| 151 | if (num_bytes) | ||
| 152 | delayed_refs_rsv->reserved += num_bytes; | ||
| 153 | if (delayed_refs_rsv->reserved >= delayed_refs_rsv->size) | ||
| 154 | delayed_refs_rsv->full = 1; | ||
| 155 | spin_unlock(&delayed_refs_rsv->lock); | ||
| 156 | |||
| 157 | if (num_bytes) | ||
| 158 | trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", | ||
| 159 | 0, num_bytes, 1); | ||
| 160 | if (to_free) | ||
| 161 | btrfs_space_info_add_old_bytes(fs_info, | ||
| 162 | delayed_refs_rsv->space_info, to_free); | ||
| 163 | } | ||
| 164 | |||
| 165 | /** | ||
| 166 | * btrfs_delayed_refs_rsv_refill - refill based on our delayed refs usage. | ||
| 167 | * @fs_info - the fs_info for our fs. | ||
| 168 | * @flush - control how we can flush for this reservation. | ||
| 169 | * | ||
| 170 | * This will refill the delayed block_rsv up to 1 items size worth of space and | ||
| 171 | * will return -ENOSPC if we can't make the reservation. | ||
| 172 | */ | ||
| 173 | int btrfs_delayed_refs_rsv_refill(struct btrfs_fs_info *fs_info, | ||
| 174 | enum btrfs_reserve_flush_enum flush) | ||
| 175 | { | ||
| 176 | struct btrfs_block_rsv *block_rsv = &fs_info->delayed_refs_rsv; | ||
| 177 | u64 limit = btrfs_calc_trans_metadata_size(fs_info, 1); | ||
| 178 | u64 num_bytes = 0; | ||
| 179 | int ret = -ENOSPC; | ||
| 180 | |||
| 181 | spin_lock(&block_rsv->lock); | ||
| 182 | if (block_rsv->reserved < block_rsv->size) { | ||
| 183 | num_bytes = block_rsv->size - block_rsv->reserved; | ||
| 184 | num_bytes = min(num_bytes, limit); | ||
| 185 | } | ||
| 186 | spin_unlock(&block_rsv->lock); | ||
| 187 | |||
| 188 | if (!num_bytes) | ||
| 189 | return 0; | ||
| 190 | |||
| 191 | ret = btrfs_reserve_metadata_bytes(fs_info->extent_root, block_rsv, | ||
| 192 | num_bytes, flush); | ||
| 193 | if (ret) | ||
| 194 | return ret; | ||
| 195 | btrfs_block_rsv_add_bytes(block_rsv, num_bytes, 0); | ||
| 196 | trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", | ||
| 197 | 0, num_bytes, 1); | ||
| 198 | return 0; | ||
| 199 | } | ||
| 200 | |||
| 27 | /* | 201 | /* |
| 28 | * compare two delayed tree backrefs with same bytenr and type | 202 | * compare two delayed tree backrefs with same bytenr and type |
| 29 | */ | 203 | */ |
| @@ -957,13 +1131,14 @@ int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans, | |||
| 957 | } | 1131 | } |
| 958 | 1132 | ||
| 959 | /* | 1133 | /* |
| 960 | * this does a simple search for the head node for a given extent. | 1134 | * This does a simple search for the head node for a given extent. Returns the |
| 961 | * It must be called with the delayed ref spinlock held, and it returns | 1135 | * head node if found, or NULL if not. |
| 962 | * the head node if any where found, or NULL if not. | ||
| 963 | */ | 1136 | */ |
| 964 | struct btrfs_delayed_ref_head * | 1137 | struct btrfs_delayed_ref_head * |
| 965 | btrfs_find_delayed_ref_head(struct btrfs_delayed_ref_root *delayed_refs, u64 bytenr) | 1138 | btrfs_find_delayed_ref_head(struct btrfs_delayed_ref_root *delayed_refs, u64 bytenr) |
| 966 | { | 1139 | { |
| 1140 | lockdep_assert_held(&delayed_refs->lock); | ||
| 1141 | |||
| 967 | return find_ref_head(delayed_refs, bytenr, false); | 1142 | return find_ref_head(delayed_refs, bytenr, false); |
| 968 | } | 1143 | } |
| 969 | 1144 | ||
