1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _BCACHEFS_BTREE_UPDATE_H 3 #define _BCACHEFS_BTREE_UPDATE_H 4 5 #include "btree_iter.h" 6 #include "journal.h" 7 8 struct bch_fs; 9 struct btree; 10 11 void bch2_btree_node_prep_for_write(struct btree_trans *, 12 struct btree_path *, struct btree *); 13 bool bch2_btree_bset_insert_key(struct btree_trans *, struct btree_path *, 14 struct btree *, struct btree_node_iter *, 15 struct bkey_i *); 16 17 int bch2_btree_node_flush0(struct journal *, struct journal_entry_pin *, u64); 18 int bch2_btree_node_flush1(struct journal *, struct journal_entry_pin *, u64); 19 void bch2_btree_add_journal_pin(struct bch_fs *, struct btree *, u64); 20 21 void bch2_btree_insert_key_leaf(struct btree_trans *, struct btree_path *, 22 struct bkey_i *, u64); 23 24 #define BCH_TRANS_COMMIT_FLAGS() \ 25 x(no_enospc, "don't check for enospc") \ 26 x(no_check_rw, "don't attempt to take a ref on c->writes") \ 27 x(lazy_rw, "go read-write if we haven't yet - only for use in recovery") \ 28 x(no_journal_res, "don't take a journal reservation, instead " \ 29 "pin journal entry referred to by trans->journal_res.seq") \ 30 x(journal_reclaim, "operation required for journal reclaim; may return error" \ 31 "instead of deadlocking if BCH_WATERMARK_reclaim not specified")\ 32 33 enum __bch_trans_commit_flags { 34 /* First bits for bch_watermark: */ 35 __BCH_TRANS_COMMIT_FLAGS_START = BCH_WATERMARK_BITS, 36 #define x(n, ...) __BCH_TRANS_COMMIT_##n, 37 BCH_TRANS_COMMIT_FLAGS() 38 #undef x 39 }; 40 41 enum bch_trans_commit_flags { 42 #define x(n, ...) BCH_TRANS_COMMIT_##n = BIT(__BCH_TRANS_COMMIT_##n), 43 BCH_TRANS_COMMIT_FLAGS() 44 #undef x 45 }; 46 47 int bch2_btree_delete_extent_at(struct btree_trans *, struct btree_iter *, 48 unsigned, unsigned); 49 int bch2_btree_delete_at(struct btree_trans *, struct btree_iter *, unsigned); 50 int bch2_btree_delete(struct btree_trans *, enum btree_id, struct bpos, unsigned); 51 52 int bch2_btree_insert_nonextent(struct btree_trans *, enum btree_id, 53 struct bkey_i *, enum btree_update_flags); 54 55 int bch2_btree_insert_trans(struct btree_trans *, enum btree_id, struct bkey_i *, 56 enum btree_update_flags); 57 int bch2_btree_insert(struct bch_fs *, enum btree_id, struct bkey_i *, 58 struct disk_reservation *, int flags); 59 60 int bch2_btree_delete_range_trans(struct btree_trans *, enum btree_id, 61 struct bpos, struct bpos, unsigned, u64 *); 62 int bch2_btree_delete_range(struct bch_fs *, enum btree_id, 63 struct bpos, struct bpos, unsigned, u64 *); 64 65 int bch2_btree_bit_mod(struct btree_trans *, enum btree_id, struct bpos, bool); 66 67 static inline int bch2_btree_delete_at_buffered(struct btree_trans *trans, 68 enum btree_id btree, struct bpos pos) 69 { 70 return bch2_btree_bit_mod(trans, btree, pos, false); 71 } 72 73 int __bch2_insert_snapshot_whiteouts(struct btree_trans *, enum btree_id, 74 struct bpos, struct bpos); 75 76 /* 77 * For use when splitting extents in existing snapshots: 78 * 79 * If @old_pos is an interior snapshot node, iterate over descendent snapshot 80 * nodes: for every descendent snapshot in whiche @old_pos is overwritten and 81 * not visible, emit a whiteout at @new_pos. 82 */ 83 static inline int bch2_insert_snapshot_whiteouts(struct btree_trans *trans, 84 enum btree_id btree, 85 struct bpos old_pos, 86 struct bpos new_pos) 87 { 88 if (!btree_type_has_snapshots(btree) || 89 bkey_eq(old_pos, new_pos)) 90 return 0; 91 92 return __bch2_insert_snapshot_whiteouts(trans, btree, old_pos, new_pos); 93 } 94 95 int bch2_trans_update_extent_overwrite(struct btree_trans *, struct btree_iter *, 96 enum btree_update_flags, 97 struct bkey_s_c, struct bkey_s_c); 98 99 int bch2_bkey_get_empty_slot(struct btree_trans *, struct btree_iter *, 100 enum btree_id, struct bpos); 101 102 int __must_check bch2_trans_update(struct btree_trans *, struct btree_iter *, 103 struct bkey_i *, enum btree_update_flags); 104 105 struct jset_entry *__bch2_trans_jset_entry_alloc(struct btree_trans *, unsigned); 106 107 static inline struct jset_entry *btree_trans_journal_entries_top(struct btree_trans *trans) 108 { 109 return (void *) ((u64 *) trans->journal_entries + trans->journal_entries_u64s); 110 } 111 112 static inline struct jset_entry * 113 bch2_trans_jset_entry_alloc(struct btree_trans *trans, unsigned u64s) 114 { 115 if (!trans->journal_entries || 116 trans->journal_entries_u64s + u64s > trans->journal_entries_size) 117 return __bch2_trans_jset_entry_alloc(trans, u64s); 118 119 struct jset_entry *e = btree_trans_journal_entries_top(trans); 120 trans->journal_entries_u64s += u64s; 121 return e; 122 } 123 124 int bch2_btree_insert_clone_trans(struct btree_trans *, enum btree_id, struct bkey_i *); 125 126 static inline int __must_check bch2_trans_update_buffered(struct btree_trans *trans, 127 enum btree_id btree, 128 struct bkey_i *k) 129 { 130 if (unlikely(trans->journal_replay_not_finished)) 131 return bch2_btree_insert_clone_trans(trans, btree, k); 132 133 struct jset_entry *e = bch2_trans_jset_entry_alloc(trans, jset_u64s(k->k.u64s)); 134 int ret = PTR_ERR_OR_ZERO(e); 135 if (ret) 136 return ret; 137 138 journal_entry_init(e, BCH_JSET_ENTRY_write_buffer_keys, btree, 0, k->k.u64s); 139 bkey_copy(e->start, k); 140 return 0; 141 } 142 143 void bch2_trans_commit_hook(struct btree_trans *, 144 struct btree_trans_commit_hook *); 145 int __bch2_trans_commit(struct btree_trans *, unsigned); 146 147 __printf(2, 3) int bch2_fs_log_msg(struct bch_fs *, const char *, ...); 148 __printf(2, 3) int bch2_journal_log_msg(struct bch_fs *, const char *, ...); 149 150 /** 151 * bch2_trans_commit - insert keys at given iterator positions 152 * 153 * This is main entry point for btree updates. 154 * 155 * Return values: 156 * -EROFS: filesystem read only 157 * -EIO: journal or btree node IO error 158 */ 159 static inline int bch2_trans_commit(struct btree_trans *trans, 160 struct disk_reservation *disk_res, 161 u64 *journal_seq, 162 unsigned flags) 163 { 164 trans->disk_res = disk_res; 165 trans->journal_seq = journal_seq; 166 167 return __bch2_trans_commit(trans, flags); 168 } 169 170 #define commit_do(_trans, _disk_res, _journal_seq, _flags, _do) \ 171 lockrestart_do(_trans, _do ?: bch2_trans_commit(_trans, (_disk_res),\ 172 (_journal_seq), (_flags))) 173 174 #define nested_commit_do(_trans, _disk_res, _journal_seq, _flags, _do) \ 175 nested_lockrestart_do(_trans, _do ?: bch2_trans_commit(_trans, (_disk_res),\ 176 (_journal_seq), (_flags))) 177 178 #define bch2_trans_run(_c, _do) \ 179 ({ \ 180 struct btree_trans *trans = bch2_trans_get(_c); \ 181 int _ret = (_do); \ 182 bch2_trans_put(trans); \ 183 _ret; \ 184 }) 185 186 #define bch2_trans_do(_c, _disk_res, _journal_seq, _flags, _do) \ 187 bch2_trans_run(_c, commit_do(trans, _disk_res, _journal_seq, _flags, _do)) 188 189 #define trans_for_each_update(_trans, _i) \ 190 for (struct btree_insert_entry *_i = (_trans)->updates; \ 191 (_i) < (_trans)->updates + (_trans)->nr_updates; \ 192 (_i)++) 193 194 static inline void bch2_trans_reset_updates(struct btree_trans *trans) 195 { 196 trans_for_each_update(trans, i) 197 bch2_path_put(trans, i->path, true); 198 199 trans->nr_updates = 0; 200 trans->journal_entries_u64s = 0; 201 trans->hooks = NULL; 202 trans->extra_disk_res = 0; 203 204 if (trans->fs_usage_deltas) { 205 trans->fs_usage_deltas->used = 0; 206 memset((void *) trans->fs_usage_deltas + 207 offsetof(struct replicas_delta_list, memset_start), 0, 208 (void *) &trans->fs_usage_deltas->memset_end - 209 (void *) &trans->fs_usage_deltas->memset_start); 210 } 211 } 212 213 static inline struct bkey_i *__bch2_bkey_make_mut_noupdate(struct btree_trans *trans, struct bkey_s_c k, 214 unsigned type, unsigned min_bytes) 215 { 216 unsigned bytes = max_t(unsigned, min_bytes, bkey_bytes(k.k)); 217 struct bkey_i *mut; 218 219 if (type && k.k->type != type) 220 return ERR_PTR(-ENOENT); 221 222 mut = bch2_trans_kmalloc_nomemzero(trans, bytes); 223 if (!IS_ERR(mut)) { 224 bkey_reassemble(mut, k); 225 226 if (unlikely(bytes > bkey_bytes(k.k))) { 227 memset((void *) mut + bkey_bytes(k.k), 0, 228 bytes - bkey_bytes(k.k)); 229 mut->k.u64s = DIV_ROUND_UP(bytes, sizeof(u64)); 230 } 231 } 232 return mut; 233 } 234 235 static inline struct bkey_i *bch2_bkey_make_mut_noupdate(struct btree_trans *trans, struct bkey_s_c k) 236 { 237 return __bch2_bkey_make_mut_noupdate(trans, k, 0, 0); 238 } 239 240 #define bch2_bkey_make_mut_noupdate_typed(_trans, _k, _type) \ 241 bkey_i_to_##_type(__bch2_bkey_make_mut_noupdate(_trans, _k, \ 242 KEY_TYPE_##_type, sizeof(struct bkey_i_##_type))) 243 244 static inline struct bkey_i *__bch2_bkey_make_mut(struct btree_trans *trans, struct btree_iter *iter, 245 struct bkey_s_c *k, unsigned flags, 246 unsigned type, unsigned min_bytes) 247 { 248 struct bkey_i *mut = __bch2_bkey_make_mut_noupdate(trans, *k, type, min_bytes); 249 int ret; 250 251 if (IS_ERR(mut)) 252 return mut; 253 254 ret = bch2_trans_update(trans, iter, mut, flags); 255 if (ret) 256 return ERR_PTR(ret); 257 258 *k = bkey_i_to_s_c(mut); 259 return mut; 260 } 261 262 static inline struct bkey_i *bch2_bkey_make_mut(struct btree_trans *trans, struct btree_iter *iter, 263 struct bkey_s_c *k, unsigned flags) 264 { 265 return __bch2_bkey_make_mut(trans, iter, k, flags, 0, 0); 266 } 267 268 #define bch2_bkey_make_mut_typed(_trans, _iter, _k, _flags, _type) \ 269 bkey_i_to_##_type(__bch2_bkey_make_mut(_trans, _iter, _k, _flags,\ 270 KEY_TYPE_##_type, sizeof(struct bkey_i_##_type))) 271 272 static inline struct bkey_i *__bch2_bkey_get_mut_noupdate(struct btree_trans *trans, 273 struct btree_iter *iter, 274 unsigned btree_id, struct bpos pos, 275 unsigned flags, unsigned type, unsigned min_bytes) 276 { 277 struct bkey_s_c k = __bch2_bkey_get_iter(trans, iter, 278 btree_id, pos, flags|BTREE_ITER_INTENT, type); 279 struct bkey_i *ret = IS_ERR(k.k) 280 ? ERR_CAST(k.k) 281 : __bch2_bkey_make_mut_noupdate(trans, k, 0, min_bytes); 282 if (IS_ERR(ret)) 283 bch2_trans_iter_exit(trans, iter); 284 return ret; 285 } 286 287 static inline struct bkey_i *bch2_bkey_get_mut_noupdate(struct btree_trans *trans, 288 struct btree_iter *iter, 289 unsigned btree_id, struct bpos pos, 290 unsigned flags) 291 { 292 return __bch2_bkey_get_mut_noupdate(trans, iter, btree_id, pos, flags, 0, 0); 293 } 294 295 static inline struct bkey_i *__bch2_bkey_get_mut(struct btree_trans *trans, 296 struct btree_iter *iter, 297 unsigned btree_id, struct bpos pos, 298 unsigned flags, unsigned type, unsigned min_bytes) 299 { 300 struct bkey_i *mut = __bch2_bkey_get_mut_noupdate(trans, iter, 301 btree_id, pos, flags|BTREE_ITER_INTENT, type, min_bytes); 302 int ret; 303 304 if (IS_ERR(mut)) 305 return mut; 306 307 ret = bch2_trans_update(trans, iter, mut, flags); 308 if (ret) { 309 bch2_trans_iter_exit(trans, iter); 310 return ERR_PTR(ret); 311 } 312 313 return mut; 314 } 315 316 static inline struct bkey_i *bch2_bkey_get_mut_minsize(struct btree_trans *trans, 317 struct btree_iter *iter, 318 unsigned btree_id, struct bpos pos, 319 unsigned flags, unsigned min_bytes) 320 { 321 return __bch2_bkey_get_mut(trans, iter, btree_id, pos, flags, 0, min_bytes); 322 } 323 324 static inline struct bkey_i *bch2_bkey_get_mut(struct btree_trans *trans, 325 struct btree_iter *iter, 326 unsigned btree_id, struct bpos pos, 327 unsigned flags) 328 { 329 return __bch2_bkey_get_mut(trans, iter, btree_id, pos, flags, 0, 0); 330 } 331 332 #define bch2_bkey_get_mut_typed(_trans, _iter, _btree_id, _pos, _flags, _type)\ 333 bkey_i_to_##_type(__bch2_bkey_get_mut(_trans, _iter, \ 334 _btree_id, _pos, _flags, \ 335 KEY_TYPE_##_type, sizeof(struct bkey_i_##_type))) 336 337 static inline struct bkey_i *__bch2_bkey_alloc(struct btree_trans *trans, struct btree_iter *iter, 338 unsigned flags, unsigned type, unsigned val_size) 339 { 340 struct bkey_i *k = bch2_trans_kmalloc(trans, sizeof(*k) + val_size); 341 int ret; 342 343 if (IS_ERR(k)) 344 return k; 345 346 bkey_init(&k->k); 347 k->k.p = iter->pos; 348 k->k.type = type; 349 set_bkey_val_bytes(&k->k, val_size); 350 351 ret = bch2_trans_update(trans, iter, k, flags); 352 if (unlikely(ret)) 353 return ERR_PTR(ret); 354 return k; 355 } 356 357 #define bch2_bkey_alloc(_trans, _iter, _flags, _type) \ 358 bkey_i_to_##_type(__bch2_bkey_alloc(_trans, _iter, _flags, \ 359 KEY_TYPE_##_type, sizeof(struct bch_##_type))) 360 361 #endif /* _BCACHEFS_BTREE_UPDATE_H */ 362