1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _BCACHEFS_MOVE_H 3 #define _BCACHEFS_MOVE_H 4 5 #include "bbpos.h" 6 #include "bcachefs_ioctl.h" 7 #include "btree_iter.h" 8 #include "buckets.h" 9 #include "data_update.h" 10 #include "move_types.h" 11 12 struct bch_read_bio; 13 14 struct moving_context { 15 struct btree_trans *trans; 16 struct list_head list; 17 void *fn; 18 19 struct bch_ratelimit *rate; 20 struct bch_move_stats *stats; 21 struct write_point_specifier wp; 22 bool wait_on_copygc; 23 bool write_error; 24 25 /* For waiting on outstanding reads and writes: */ 26 struct closure cl; 27 28 struct mutex lock; 29 struct list_head reads; 30 struct list_head ios; 31 32 /* in flight sectors: */ 33 atomic_t read_sectors; 34 atomic_t write_sectors; 35 atomic_t read_ios; 36 atomic_t write_ios; 37 38 wait_queue_head_t wait; 39 }; 40 41 #define move_ctxt_wait_event_timeout(_ctxt, _cond, _timeout) \ 42 ({ \ 43 int _ret = 0; \ 44 while (true) { \ 45 bool cond_finished = false; \ 46 bch2_moving_ctxt_do_pending_writes(_ctxt); \ 47 \ 48 if (_cond) \ 49 break; \ 50 bch2_trans_unlock_long((_ctxt)->trans); \ 51 _ret = __wait_event_timeout((_ctxt)->wait, \ 52 bch2_moving_ctxt_next_pending_write(_ctxt) || \ 53 (cond_finished = (_cond)), _timeout); \ 54 if (_ret || ( cond_finished)) \ 55 break; \ 56 } \ 57 _ret; \ 58 }) 59 60 #define move_ctxt_wait_event(_ctxt, _cond) \ 61 do { \ 62 bool cond_finished = false; \ 63 bch2_moving_ctxt_do_pending_writes(_ctxt); \ 64 \ 65 if (_cond) \ 66 break; \ 67 bch2_trans_unlock_long((_ctxt)->trans); \ 68 __wait_event((_ctxt)->wait, \ 69 bch2_moving_ctxt_next_pending_write(_ctxt) || \ 70 (cond_finished = (_cond))); \ 71 if (cond_finished) \ 72 break; \ 73 } while (1) 74 75 typedef bool (*move_pred_fn)(struct bch_fs *, void *, struct bkey_s_c, 76 struct bch_io_opts *, struct data_update_opts *); 77 78 void bch2_moving_ctxt_exit(struct moving_context *); 79 void bch2_moving_ctxt_init(struct moving_context *, struct bch_fs *, 80 struct bch_ratelimit *, struct bch_move_stats *, 81 struct write_point_specifier, bool); 82 struct moving_io *bch2_moving_ctxt_next_pending_write(struct moving_context *); 83 void bch2_moving_ctxt_do_pending_writes(struct moving_context *); 84 void bch2_move_ctxt_wait_for_io(struct moving_context *); 85 int bch2_move_ratelimit(struct moving_context *); 86 87 /* Inodes in different snapshots may have different IO options: */ 88 struct snapshot_io_opts_entry { 89 u32 snapshot; 90 struct bch_io_opts io_opts; 91 }; 92 93 struct per_snapshot_io_opts { 94 u64 cur_inum; 95 struct bch_io_opts fs_io_opts; 96 DARRAY(struct snapshot_io_opts_entry) d; 97 }; 98 99 static inline void per_snapshot_io_opts_init(struct per_snapshot_io_opts *io_opts, struct bch_fs *c) 100 { 101 memset(io_opts, 0, sizeof(*io_opts)); 102 io_opts->fs_io_opts = bch2_opts_to_inode_opts(c->opts); 103 } 104 105 static inline void per_snapshot_io_opts_exit(struct per_snapshot_io_opts *io_opts) 106 { 107 darray_exit(&io_opts->d); 108 } 109 110 struct bch_io_opts *bch2_move_get_io_opts(struct btree_trans *, 111 struct per_snapshot_io_opts *, struct bkey_s_c); 112 int bch2_move_get_io_opts_one(struct btree_trans *, struct bch_io_opts *, struct bkey_s_c); 113 114 int bch2_scan_old_btree_nodes(struct bch_fs *, struct bch_move_stats *); 115 116 int bch2_move_extent(struct moving_context *, 117 struct move_bucket_in_flight *, 118 struct btree_iter *, 119 struct bkey_s_c, 120 struct bch_io_opts, 121 struct data_update_opts); 122 123 int __bch2_move_data(struct moving_context *, 124 struct bbpos, 125 struct bbpos, 126 move_pred_fn, void *); 127 int bch2_move_data(struct bch_fs *, 128 struct bbpos start, 129 struct bbpos end, 130 struct bch_ratelimit *, 131 struct bch_move_stats *, 132 struct write_point_specifier, 133 bool, 134 move_pred_fn, void *); 135 136 int __bch2_evacuate_bucket(struct moving_context *, 137 struct move_bucket_in_flight *, 138 struct bpos, int, 139 struct data_update_opts); 140 int bch2_evacuate_bucket(struct bch_fs *, struct bpos, int, 141 struct data_update_opts, 142 struct bch_ratelimit *, 143 struct bch_move_stats *, 144 struct write_point_specifier, 145 bool); 146 int bch2_data_job(struct bch_fs *, 147 struct bch_move_stats *, 148 struct bch_ioctl_data); 149 150 void bch2_move_stats_to_text(struct printbuf *, struct bch_move_stats *); 151 void bch2_move_stats_exit(struct bch_move_stats *, struct bch_fs *); 152 void bch2_move_stats_init(struct bch_move_stats *, char *); 153 154 void bch2_fs_moving_ctxts_to_text(struct printbuf *, struct bch_fs *); 155 156 void bch2_fs_move_init(struct bch_fs *); 157 158 #endif /* _BCACHEFS_MOVE_H */ 159