Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
  1/* SPDX-License-Identifier: GPL-2.0 */
  2#ifndef _BCACHEFS_SNAPSHOT_H
  3#define _BCACHEFS_SNAPSHOT_H
  4
  5enum bch_validate_flags;
  6
  7void bch2_snapshot_tree_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
  8int bch2_snapshot_tree_validate(struct bch_fs *, struct bkey_s_c,
  9			       enum bch_validate_flags);
 10
 11#define bch2_bkey_ops_snapshot_tree ((struct bkey_ops) {	\
 12	.key_validate	= bch2_snapshot_tree_validate,		\
 13	.val_to_text	= bch2_snapshot_tree_to_text,		\
 14	.min_val_size	= 8,					\
 15})
 16
 17struct bkey_i_snapshot_tree *__bch2_snapshot_tree_create(struct btree_trans *);
 18
 19int bch2_snapshot_tree_lookup(struct btree_trans *, u32, struct bch_snapshot_tree *);
 20
 21void bch2_snapshot_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
 22int bch2_snapshot_validate(struct bch_fs *, struct bkey_s_c, enum bch_validate_flags);
 23int bch2_mark_snapshot(struct btree_trans *, enum btree_id, unsigned,
 24		       struct bkey_s_c, struct bkey_s,
 25		       enum btree_iter_update_trigger_flags);
 26
 27#define bch2_bkey_ops_snapshot ((struct bkey_ops) {		\
 28	.key_validate	= bch2_snapshot_validate,		\
 29	.val_to_text	= bch2_snapshot_to_text,		\
 30	.trigger	= bch2_mark_snapshot,			\
 31	.min_val_size	= 24,					\
 32})
 33
 34static inline struct snapshot_t *__snapshot_t(struct snapshot_table *t, u32 id)
 35{
 36	u32 idx = U32_MAX - id;
 37
 38	return likely(t && idx < t->nr)
 39		? &t->s[idx]
 40		: NULL;
 41}
 42
 43static inline const struct snapshot_t *snapshot_t(struct bch_fs *c, u32 id)
 44{
 45	return __snapshot_t(rcu_dereference(c->snapshots), id);
 46}
 47
 48static inline u32 bch2_snapshot_tree(struct bch_fs *c, u32 id)
 49{
 50	rcu_read_lock();
 51	const struct snapshot_t *s = snapshot_t(c, id);
 52	id = s ? s->tree : 0;
 53	rcu_read_unlock();
 54
 55	return id;
 56}
 57
 58static inline u32 __bch2_snapshot_parent_early(struct bch_fs *c, u32 id)
 59{
 60	const struct snapshot_t *s = snapshot_t(c, id);
 61	return s ? s->parent : 0;
 62}
 63
 64static inline u32 bch2_snapshot_parent_early(struct bch_fs *c, u32 id)
 65{
 66	rcu_read_lock();
 67	id = __bch2_snapshot_parent_early(c, id);
 68	rcu_read_unlock();
 69
 70	return id;
 71}
 72
 73static inline u32 __bch2_snapshot_parent(struct bch_fs *c, u32 id)
 74{
 75	const struct snapshot_t *s = snapshot_t(c, id);
 76	if (!s)
 77		return 0;
 78
 79	u32 parent = s->parent;
 80	if (IS_ENABLED(CONFIG_BCACHEFS_DEBUG) &&
 81	    parent &&
 82	    s->depth != snapshot_t(c, parent)->depth + 1)
 83		panic("id %u depth=%u parent %u depth=%u\n",
 84		      id, snapshot_t(c, id)->depth,
 85		      parent, snapshot_t(c, parent)->depth);
 86
 87	return parent;
 88}
 89
 90static inline u32 bch2_snapshot_parent(struct bch_fs *c, u32 id)
 91{
 92	rcu_read_lock();
 93	id = __bch2_snapshot_parent(c, id);
 94	rcu_read_unlock();
 95
 96	return id;
 97}
 98
 99static inline u32 bch2_snapshot_nth_parent(struct bch_fs *c, u32 id, u32 n)
100{
101	rcu_read_lock();
102	while (n--)
103		id = __bch2_snapshot_parent(c, id);
104	rcu_read_unlock();
105
106	return id;
107}
108
109u32 bch2_snapshot_skiplist_get(struct bch_fs *, u32);
110
111static inline u32 bch2_snapshot_root(struct bch_fs *c, u32 id)
112{
113	u32 parent;
114
115	rcu_read_lock();
116	while ((parent = __bch2_snapshot_parent(c, id)))
117		id = parent;
118	rcu_read_unlock();
119
120	return id;
121}
122
123static inline u32 __bch2_snapshot_equiv(struct bch_fs *c, u32 id)
124{
125	const struct snapshot_t *s = snapshot_t(c, id);
126	return s ? s->equiv : 0;
127}
128
129static inline u32 bch2_snapshot_equiv(struct bch_fs *c, u32 id)
130{
131	rcu_read_lock();
132	id = __bch2_snapshot_equiv(c, id);
133	rcu_read_unlock();
134
135	return id;
136}
137
138static inline int bch2_snapshot_is_internal_node(struct bch_fs *c, u32 id)
139{
140	rcu_read_lock();
141	const struct snapshot_t *s = snapshot_t(c, id);
142	int ret = s ? s->children[0] : -BCH_ERR_invalid_snapshot_node;
143	rcu_read_unlock();
144
145	return ret;
146}
147
148static inline int bch2_snapshot_is_leaf(struct bch_fs *c, u32 id)
149{
150	int ret = bch2_snapshot_is_internal_node(c, id);
151	if (ret < 0)
152		return ret;
153	return !ret;
154}
155
156static inline u32 bch2_snapshot_depth(struct bch_fs *c, u32 parent)
157{
158	u32 depth;
159
160	rcu_read_lock();
161	depth = parent ? snapshot_t(c, parent)->depth + 1 : 0;
162	rcu_read_unlock();
163
164	return depth;
165}
166
167bool __bch2_snapshot_is_ancestor(struct bch_fs *, u32, u32);
168
169static inline bool bch2_snapshot_is_ancestor(struct bch_fs *c, u32 id, u32 ancestor)
170{
171	return id == ancestor
172		? true
173		: __bch2_snapshot_is_ancestor(c, id, ancestor);
174}
175
176static inline bool bch2_snapshot_has_children(struct bch_fs *c, u32 id)
177{
178	rcu_read_lock();
179	const struct snapshot_t *t = snapshot_t(c, id);
180	bool ret = t && (t->children[0]|t->children[1]) != 0;
181	rcu_read_unlock();
182
183	return ret;
184}
185
186static inline bool snapshot_list_has_id(snapshot_id_list *s, u32 id)
187{
188	darray_for_each(*s, i)
189		if (*i == id)
190			return true;
191	return false;
192}
193
194static inline bool snapshot_list_has_ancestor(struct bch_fs *c, snapshot_id_list *s, u32 id)
195{
196	darray_for_each(*s, i)
197		if (bch2_snapshot_is_ancestor(c, id, *i))
198			return true;
199	return false;
200}
201
202static inline int snapshot_list_add(struct bch_fs *c, snapshot_id_list *s, u32 id)
203{
204	BUG_ON(snapshot_list_has_id(s, id));
205	int ret = darray_push(s, id);
206	if (ret)
207		bch_err(c, "error reallocating snapshot_id_list (size %zu)", s->size);
208	return ret;
209}
210
211static inline int snapshot_list_add_nodup(struct bch_fs *c, snapshot_id_list *s, u32 id)
212{
213	int ret = snapshot_list_has_id(s, id)
214		? 0
215		: darray_push(s, id);
216	if (ret)
217		bch_err(c, "error reallocating snapshot_id_list (size %zu)", s->size);
218	return ret;
219}
220
221static inline int snapshot_list_merge(struct bch_fs *c, snapshot_id_list *dst, snapshot_id_list *src)
222{
223	darray_for_each(*src, i) {
224		int ret = snapshot_list_add_nodup(c, dst, *i);
225		if (ret)
226			return ret;
227	}
228
229	return 0;
230}
231
232int bch2_snapshot_lookup(struct btree_trans *trans, u32 id,
233			 struct bch_snapshot *s);
234int bch2_snapshot_get_subvol(struct btree_trans *, u32,
235			     struct bch_subvolume *);
236
237/* only exported for tests: */
238int bch2_snapshot_node_create(struct btree_trans *, u32,
239			      u32 *, u32 *, unsigned);
240
241int bch2_check_snapshot_trees(struct bch_fs *);
242int bch2_check_snapshots(struct bch_fs *);
243int bch2_reconstruct_snapshots(struct bch_fs *);
244int bch2_check_key_has_snapshot(struct btree_trans *, struct btree_iter *, struct bkey_s_c);
245
246int bch2_snapshot_node_set_deleted(struct btree_trans *, u32);
247void bch2_delete_dead_snapshots_work(struct work_struct *);
248
249int __bch2_key_has_snapshot_overwrites(struct btree_trans *, enum btree_id, struct bpos);
250
251static inline int bch2_key_has_snapshot_overwrites(struct btree_trans *trans,
252					  enum btree_id id,
253					  struct bpos pos)
254{
255	if (!btree_type_has_snapshots(id) ||
256	    bch2_snapshot_is_leaf(trans->c, pos.snapshot) > 0)
257		return 0;
258
259	return __bch2_key_has_snapshot_overwrites(trans, id, pos);
260}
261
262int bch2_snapshots_read(struct bch_fs *);
263void bch2_fs_snapshots_exit(struct bch_fs *);
264
265#endif /* _BCACHEFS_SNAPSHOT_H */