aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/delayed-ref.h
diff options
context:
space:
mode:
authorArne Jansen <sensille@gmx.net>2011-09-14 06:37:00 -0400
committerJan Schmidt <list.btrfs@jan-o-sch.net>2012-01-04 10:12:42 -0500
commit00f04b88791ff49dc64ada18819d40a5b0671709 (patch)
treefd85a5f4b374aac035388b0cbf8ef572578d5578 /fs/btrfs/delayed-ref.h
parent5b25f70f4200766355cdabda604e131d2fb6010d (diff)
Btrfs: add sequence numbers to delayed refs
Sequence numbers are needed to reconstruct the backrefs of a given extent to a certain point in time. The total set of backrefs consist of the set of backrefs recorded on disk plus the enqueued delayed refs for it that existed at that moment. This patch also adds a list that records all delayed refs which are currently in the process of being added. When walking all refs of an extent in btrfs_find_all_roots(), we freeze the current state of delayed refs, honor anythinh up to this point and prevent processing newer delayed refs to assert consistency. Signed-off-by: Arne Jansen <sensille@gmx.net> Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Diffstat (limited to 'fs/btrfs/delayed-ref.h')
-rw-r--r--fs/btrfs/delayed-ref.h70
1 files changed, 70 insertions, 0 deletions
diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h
index a5fb2bc83732..174416f7882b 100644
--- a/fs/btrfs/delayed-ref.h
+++ b/fs/btrfs/delayed-ref.h
@@ -33,6 +33,9 @@ struct btrfs_delayed_ref_node {
33 /* the size of the extent */ 33 /* the size of the extent */
34 u64 num_bytes; 34 u64 num_bytes;
35 35
36 /* seq number to keep track of insertion order */
37 u64 seq;
38
36 /* ref count on this data structure */ 39 /* ref count on this data structure */
37 atomic_t refs; 40 atomic_t refs;
38 41
@@ -136,6 +139,20 @@ struct btrfs_delayed_ref_root {
136 int flushing; 139 int flushing;
137 140
138 u64 run_delayed_start; 141 u64 run_delayed_start;
142
143 /*
144 * seq number of delayed refs. We need to know if a backref was being
145 * added before the currently processed ref or afterwards.
146 */
147 u64 seq;
148
149 /*
150 * seq_list holds a list of all seq numbers that are currently being
151 * added to the list. While walking backrefs (btrfs_find_all_roots,
152 * qgroups), which might take some time, no newer ref must be processed,
153 * as it might influence the outcome of the walk.
154 */
155 struct list_head seq_head;
139}; 156};
140 157
141static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref) 158static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref)
@@ -171,6 +188,59 @@ int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans,
171 struct btrfs_delayed_ref_head *head); 188 struct btrfs_delayed_ref_head *head);
172int btrfs_find_ref_cluster(struct btrfs_trans_handle *trans, 189int btrfs_find_ref_cluster(struct btrfs_trans_handle *trans,
173 struct list_head *cluster, u64 search_start); 190 struct list_head *cluster, u64 search_start);
191
192struct seq_list {
193 struct list_head list;
194 u64 seq;
195};
196
197static inline u64 inc_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs)
198{
199 assert_spin_locked(&delayed_refs->lock);
200 ++delayed_refs->seq;
201 return delayed_refs->seq;
202}
203
204static inline void
205btrfs_get_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs,
206 struct seq_list *elem)
207{
208 assert_spin_locked(&delayed_refs->lock);
209 elem->seq = delayed_refs->seq;
210 list_add_tail(&elem->list, &delayed_refs->seq_head);
211}
212
213static inline void
214btrfs_put_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs,
215 struct seq_list *elem)
216{
217 spin_lock(&delayed_refs->lock);
218 list_del(&elem->list);
219 spin_unlock(&delayed_refs->lock);
220}
221
222int btrfs_check_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs,
223 u64 seq);
224
225/*
226 * delayed refs with a ref_seq > 0 must be held back during backref walking.
227 * this only applies to items in one of the fs-trees. for_cow items never need
228 * to be held back, so they won't get a ref_seq number.
229 */
230static inline int need_ref_seq(int for_cow, u64 rootid)
231{
232 if (for_cow)
233 return 0;
234
235 if (rootid == BTRFS_FS_TREE_OBJECTID)
236 return 1;
237
238 if ((s64)rootid >= (s64)BTRFS_FIRST_FREE_OBJECTID)
239 return 1;
240
241 return 0;
242}
243
174/* 244/*
175 * a node might live in a head or a regular ref, this lets you 245 * a node might live in a head or a regular ref, this lets you
176 * test for the proper type to use. 246 * test for the proper type to use.