aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/delayed-ref.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/delayed-ref.c')
-rw-r--r--fs/btrfs/delayed-ref.c43
1 files changed, 25 insertions, 18 deletions
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
index a405db0320e8..ee181989d444 100644
--- a/fs/btrfs/delayed-ref.c
+++ b/fs/btrfs/delayed-ref.c
@@ -155,16 +155,22 @@ static struct btrfs_delayed_ref_node *tree_insert(struct rb_root *root,
155 155
156/* 156/*
157 * find an head entry based on bytenr. This returns the delayed ref 157 * find an head entry based on bytenr. This returns the delayed ref
158 * head if it was able to find one, or NULL if nothing was in that spot 158 * head if it was able to find one, or NULL if nothing was in that spot.
159 * If return_bigger is given, the next bigger entry is returned if no exact
160 * match is found.
159 */ 161 */
160static struct btrfs_delayed_ref_node *find_ref_head(struct rb_root *root, 162static struct btrfs_delayed_ref_node *find_ref_head(struct rb_root *root,
161 u64 bytenr, 163 u64 bytenr,
162 struct btrfs_delayed_ref_node **last) 164 struct btrfs_delayed_ref_node **last,
165 int return_bigger)
163{ 166{
164 struct rb_node *n = root->rb_node; 167 struct rb_node *n;
165 struct btrfs_delayed_ref_node *entry; 168 struct btrfs_delayed_ref_node *entry;
166 int cmp; 169 int cmp = 0;
167 170
171again:
172 n = root->rb_node;
173 entry = NULL;
168 while (n) { 174 while (n) {
169 entry = rb_entry(n, struct btrfs_delayed_ref_node, rb_node); 175 entry = rb_entry(n, struct btrfs_delayed_ref_node, rb_node);
170 WARN_ON(!entry->in_tree); 176 WARN_ON(!entry->in_tree);
@@ -187,6 +193,19 @@ static struct btrfs_delayed_ref_node *find_ref_head(struct rb_root *root,
187 else 193 else
188 return entry; 194 return entry;
189 } 195 }
196 if (entry && return_bigger) {
197 if (cmp > 0) {
198 n = rb_next(&entry->rb_node);
199 if (!n)
200 n = rb_first(root);
201 entry = rb_entry(n, struct btrfs_delayed_ref_node,
202 rb_node);
203 bytenr = entry->bytenr;
204 return_bigger = 0;
205 goto again;
206 }
207 return entry;
208 }
190 return NULL; 209 return NULL;
191} 210}
192 211
@@ -246,20 +265,8 @@ int btrfs_find_ref_cluster(struct btrfs_trans_handle *trans,
246 node = rb_first(&delayed_refs->root); 265 node = rb_first(&delayed_refs->root);
247 } else { 266 } else {
248 ref = NULL; 267 ref = NULL;
249 find_ref_head(&delayed_refs->root, start, &ref); 268 find_ref_head(&delayed_refs->root, start + 1, &ref, 1);
250 if (ref) { 269 if (ref) {
251 struct btrfs_delayed_ref_node *tmp;
252
253 node = rb_prev(&ref->rb_node);
254 while (node) {
255 tmp = rb_entry(node,
256 struct btrfs_delayed_ref_node,
257 rb_node);
258 if (tmp->bytenr < start)
259 break;
260 ref = tmp;
261 node = rb_prev(&ref->rb_node);
262 }
263 node = &ref->rb_node; 270 node = &ref->rb_node;
264 } else 271 } else
265 node = rb_first(&delayed_refs->root); 272 node = rb_first(&delayed_refs->root);
@@ -748,7 +755,7 @@ btrfs_find_delayed_ref_head(struct btrfs_trans_handle *trans, u64 bytenr)
748 struct btrfs_delayed_ref_root *delayed_refs; 755 struct btrfs_delayed_ref_root *delayed_refs;
749 756
750 delayed_refs = &trans->transaction->delayed_refs; 757 delayed_refs = &trans->transaction->delayed_refs;
751 ref = find_ref_head(&delayed_refs->root, bytenr, NULL); 758 ref = find_ref_head(&delayed_refs->root, bytenr, NULL, 0);
752 if (ref) 759 if (ref)
753 return btrfs_delayed_node_to_head(ref); 760 return btrfs_delayed_node_to_head(ref);
754 return NULL; 761 return NULL;