diff options
Diffstat (limited to 'fs/btrfs/delayed-ref.h')
-rw-r--r-- | fs/btrfs/delayed-ref.h | 104 |
1 files changed, 91 insertions, 13 deletions
diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h index e287e3b0eab0..d8f244d94925 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 | ||
@@ -98,19 +101,15 @@ struct btrfs_delayed_ref_head { | |||
98 | 101 | ||
99 | struct btrfs_delayed_tree_ref { | 102 | struct btrfs_delayed_tree_ref { |
100 | struct btrfs_delayed_ref_node node; | 103 | struct btrfs_delayed_ref_node node; |
101 | union { | 104 | u64 root; |
102 | u64 root; | 105 | u64 parent; |
103 | u64 parent; | ||
104 | }; | ||
105 | int level; | 106 | int level; |
106 | }; | 107 | }; |
107 | 108 | ||
108 | struct btrfs_delayed_data_ref { | 109 | struct btrfs_delayed_data_ref { |
109 | struct btrfs_delayed_ref_node node; | 110 | struct btrfs_delayed_ref_node node; |
110 | union { | 111 | u64 root; |
111 | u64 root; | 112 | u64 parent; |
112 | u64 parent; | ||
113 | }; | ||
114 | u64 objectid; | 113 | u64 objectid; |
115 | u64 offset; | 114 | u64 offset; |
116 | }; | 115 | }; |
@@ -140,6 +139,26 @@ struct btrfs_delayed_ref_root { | |||
140 | int flushing; | 139 | int flushing; |
141 | 140 | ||
142 | 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; | ||
156 | |||
157 | /* | ||
158 | * when the only refs we have in the list must not be processed, we want | ||
159 | * to wait for more refs to show up or for the end of backref walking. | ||
160 | */ | ||
161 | wait_queue_head_t seq_wait; | ||
143 | }; | 162 | }; |
144 | 163 | ||
145 | static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref) | 164 | static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref) |
@@ -151,16 +170,21 @@ static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref) | |||
151 | } | 170 | } |
152 | } | 171 | } |
153 | 172 | ||
154 | int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans, | 173 | int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info, |
174 | struct btrfs_trans_handle *trans, | ||
155 | u64 bytenr, u64 num_bytes, u64 parent, | 175 | u64 bytenr, u64 num_bytes, u64 parent, |
156 | u64 ref_root, int level, int action, | 176 | u64 ref_root, int level, int action, |
157 | struct btrfs_delayed_extent_op *extent_op); | 177 | struct btrfs_delayed_extent_op *extent_op, |
158 | int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans, | 178 | int for_cow); |
179 | int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info, | ||
180 | struct btrfs_trans_handle *trans, | ||
159 | u64 bytenr, u64 num_bytes, | 181 | u64 bytenr, u64 num_bytes, |
160 | u64 parent, u64 ref_root, | 182 | u64 parent, u64 ref_root, |
161 | u64 owner, u64 offset, int action, | 183 | u64 owner, u64 offset, int action, |
162 | struct btrfs_delayed_extent_op *extent_op); | 184 | struct btrfs_delayed_extent_op *extent_op, |
163 | int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans, | 185 | int for_cow); |
186 | int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info, | ||
187 | struct btrfs_trans_handle *trans, | ||
164 | u64 bytenr, u64 num_bytes, | 188 | u64 bytenr, u64 num_bytes, |
165 | struct btrfs_delayed_extent_op *extent_op); | 189 | struct btrfs_delayed_extent_op *extent_op); |
166 | 190 | ||
@@ -170,6 +194,60 @@ int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans, | |||
170 | struct btrfs_delayed_ref_head *head); | 194 | struct btrfs_delayed_ref_head *head); |
171 | int btrfs_find_ref_cluster(struct btrfs_trans_handle *trans, | 195 | int btrfs_find_ref_cluster(struct btrfs_trans_handle *trans, |
172 | struct list_head *cluster, u64 search_start); | 196 | struct list_head *cluster, u64 search_start); |
197 | |||
198 | struct seq_list { | ||
199 | struct list_head list; | ||
200 | u64 seq; | ||
201 | }; | ||
202 | |||
203 | static inline u64 inc_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs) | ||
204 | { | ||
205 | assert_spin_locked(&delayed_refs->lock); | ||
206 | ++delayed_refs->seq; | ||
207 | return delayed_refs->seq; | ||
208 | } | ||
209 | |||
210 | static inline void | ||
211 | btrfs_get_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs, | ||
212 | struct seq_list *elem) | ||
213 | { | ||
214 | assert_spin_locked(&delayed_refs->lock); | ||
215 | elem->seq = delayed_refs->seq; | ||
216 | list_add_tail(&elem->list, &delayed_refs->seq_head); | ||
217 | } | ||
218 | |||
219 | static inline void | ||
220 | btrfs_put_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs, | ||
221 | struct seq_list *elem) | ||
222 | { | ||
223 | spin_lock(&delayed_refs->lock); | ||
224 | list_del(&elem->list); | ||
225 | wake_up(&delayed_refs->seq_wait); | ||
226 | spin_unlock(&delayed_refs->lock); | ||
227 | } | ||
228 | |||
229 | int btrfs_check_delayed_seq(struct btrfs_delayed_ref_root *delayed_refs, | ||
230 | u64 seq); | ||
231 | |||
232 | /* | ||
233 | * delayed refs with a ref_seq > 0 must be held back during backref walking. | ||
234 | * this only applies to items in one of the fs-trees. for_cow items never need | ||
235 | * to be held back, so they won't get a ref_seq number. | ||
236 | */ | ||
237 | static inline int need_ref_seq(int for_cow, u64 rootid) | ||
238 | { | ||
239 | if (for_cow) | ||
240 | return 0; | ||
241 | |||
242 | if (rootid == BTRFS_FS_TREE_OBJECTID) | ||
243 | return 1; | ||
244 | |||
245 | if ((s64)rootid >= (s64)BTRFS_FIRST_FREE_OBJECTID) | ||
246 | return 1; | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
173 | /* | 251 | /* |
174 | * a node might live in a head or a regular ref, this lets you | 252 | * a node might live in a head or a regular ref, this lets you |
175 | * test for the proper type to use. | 253 | * test for the proper type to use. |