• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 Red Hat.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public
6  * License v2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public
14  * License along with this program; if not, write to the
15  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16  * Boston, MA 021110-1307, USA.
17  */
18 
19 #include <linux/sched.h>
20 #include "ctree.h"
21 
tree_insert_offset(struct rb_root * root,u64 offset,struct rb_node * node)22 static int tree_insert_offset(struct rb_root *root, u64 offset,
23 			      struct rb_node *node)
24 {
25 	struct rb_node **p = &root->rb_node;
26 	struct rb_node *parent = NULL;
27 	struct btrfs_free_space *info;
28 
29 	while (*p) {
30 		parent = *p;
31 		info = rb_entry(parent, struct btrfs_free_space, offset_index);
32 
33 		if (offset < info->offset)
34 			p = &(*p)->rb_left;
35 		else if (offset > info->offset)
36 			p = &(*p)->rb_right;
37 		else
38 			return -EEXIST;
39 	}
40 
41 	rb_link_node(node, parent, p);
42 	rb_insert_color(node, root);
43 
44 	return 0;
45 }
46 
tree_insert_bytes(struct rb_root * root,u64 bytes,struct rb_node * node)47 static int tree_insert_bytes(struct rb_root *root, u64 bytes,
48 			     struct rb_node *node)
49 {
50 	struct rb_node **p = &root->rb_node;
51 	struct rb_node *parent = NULL;
52 	struct btrfs_free_space *info;
53 
54 	while (*p) {
55 		parent = *p;
56 		info = rb_entry(parent, struct btrfs_free_space, bytes_index);
57 
58 		if (bytes < info->bytes)
59 			p = &(*p)->rb_left;
60 		else
61 			p = &(*p)->rb_right;
62 	}
63 
64 	rb_link_node(node, parent, p);
65 	rb_insert_color(node, root);
66 
67 	return 0;
68 }
69 
70 /*
71  * searches the tree for the given offset.  If contains is set we will return
72  * the free space that contains the given offset.  If contains is not set we
73  * will return the free space that starts at or after the given offset and is
74  * at least bytes long.
75  */
tree_search_offset(struct rb_root * root,u64 offset,u64 bytes,int contains)76 static struct btrfs_free_space *tree_search_offset(struct rb_root *root,
77 						   u64 offset, u64 bytes,
78 						   int contains)
79 {
80 	struct rb_node *n = root->rb_node;
81 	struct btrfs_free_space *entry, *ret = NULL;
82 
83 	while (n) {
84 		entry = rb_entry(n, struct btrfs_free_space, offset_index);
85 
86 		if (offset < entry->offset) {
87 			if (!contains &&
88 			    (!ret || entry->offset < ret->offset) &&
89 			    (bytes <= entry->bytes))
90 				ret = entry;
91 			n = n->rb_left;
92 		} else if (offset > entry->offset) {
93 			if ((entry->offset + entry->bytes - 1) >= offset &&
94 			    bytes <= entry->bytes) {
95 				ret = entry;
96 				break;
97 			}
98 			n = n->rb_right;
99 		} else {
100 			if (bytes > entry->bytes) {
101 				n = n->rb_right;
102 				continue;
103 			}
104 			ret = entry;
105 			break;
106 		}
107 	}
108 
109 	return ret;
110 }
111 
112 /*
113  * return a chunk at least bytes size, as close to offset that we can get.
114  */
tree_search_bytes(struct rb_root * root,u64 offset,u64 bytes)115 static struct btrfs_free_space *tree_search_bytes(struct rb_root *root,
116 						  u64 offset, u64 bytes)
117 {
118 	struct rb_node *n = root->rb_node;
119 	struct btrfs_free_space *entry, *ret = NULL;
120 
121 	while (n) {
122 		entry = rb_entry(n, struct btrfs_free_space, bytes_index);
123 
124 		if (bytes < entry->bytes) {
125 			/*
126 			 * We prefer to get a hole size as close to the size we
127 			 * are asking for so we don't take small slivers out of
128 			 * huge holes, but we also want to get as close to the
129 			 * offset as possible so we don't have a whole lot of
130 			 * fragmentation.
131 			 */
132 			if (offset <= entry->offset) {
133 				if (!ret)
134 					ret = entry;
135 				else if (entry->bytes < ret->bytes)
136 					ret = entry;
137 				else if (entry->offset < ret->offset)
138 					ret = entry;
139 			}
140 			n = n->rb_left;
141 		} else if (bytes > entry->bytes) {
142 			n = n->rb_right;
143 		} else {
144 			/*
145 			 * Ok we may have multiple chunks of the wanted size,
146 			 * so we don't want to take the first one we find, we
147 			 * want to take the one closest to our given offset, so
148 			 * keep searching just in case theres a better match.
149 			 */
150 			n = n->rb_right;
151 			if (offset > entry->offset)
152 				continue;
153 			else if (!ret || entry->offset < ret->offset)
154 				ret = entry;
155 		}
156 	}
157 
158 	return ret;
159 }
160 
unlink_free_space(struct btrfs_block_group_cache * block_group,struct btrfs_free_space * info)161 static void unlink_free_space(struct btrfs_block_group_cache *block_group,
162 			      struct btrfs_free_space *info)
163 {
164 	rb_erase(&info->offset_index, &block_group->free_space_offset);
165 	rb_erase(&info->bytes_index, &block_group->free_space_bytes);
166 }
167 
link_free_space(struct btrfs_block_group_cache * block_group,struct btrfs_free_space * info)168 static int link_free_space(struct btrfs_block_group_cache *block_group,
169 			   struct btrfs_free_space *info)
170 {
171 	int ret = 0;
172 
173 
174 	ret = tree_insert_offset(&block_group->free_space_offset, info->offset,
175 				 &info->offset_index);
176 	if (ret)
177 		return ret;
178 
179 	ret = tree_insert_bytes(&block_group->free_space_bytes, info->bytes,
180 				&info->bytes_index);
181 	if (ret)
182 		return ret;
183 
184 	return ret;
185 }
186 
__btrfs_add_free_space(struct btrfs_block_group_cache * block_group,u64 offset,u64 bytes)187 static int __btrfs_add_free_space(struct btrfs_block_group_cache *block_group,
188 				  u64 offset, u64 bytes)
189 {
190 	struct btrfs_free_space *right_info;
191 	struct btrfs_free_space *left_info;
192 	struct btrfs_free_space *info = NULL;
193 	struct btrfs_free_space *alloc_info;
194 	int ret = 0;
195 
196 	alloc_info = kzalloc(sizeof(struct btrfs_free_space), GFP_NOFS);
197 	if (!alloc_info)
198 		return -ENOMEM;
199 
200 	/*
201 	 * first we want to see if there is free space adjacent to the range we
202 	 * are adding, if there is remove that struct and add a new one to
203 	 * cover the entire range
204 	 */
205 	right_info = tree_search_offset(&block_group->free_space_offset,
206 					offset+bytes, 0, 1);
207 	left_info = tree_search_offset(&block_group->free_space_offset,
208 				       offset-1, 0, 1);
209 
210 	if (right_info && right_info->offset == offset+bytes) {
211 		unlink_free_space(block_group, right_info);
212 		info = right_info;
213 		info->offset = offset;
214 		info->bytes += bytes;
215 	} else if (right_info && right_info->offset != offset+bytes) {
216 		printk(KERN_ERR "btrfs adding space in the middle of an "
217 		       "existing free space area. existing: "
218 		       "offset=%llu, bytes=%llu. new: offset=%llu, "
219 		       "bytes=%llu\n", (unsigned long long)right_info->offset,
220 		       (unsigned long long)right_info->bytes,
221 		       (unsigned long long)offset,
222 		       (unsigned long long)bytes);
223 		BUG();
224 	}
225 
226 	if (left_info) {
227 		unlink_free_space(block_group, left_info);
228 
229 		if (unlikely((left_info->offset + left_info->bytes) !=
230 			     offset)) {
231 			printk(KERN_ERR "btrfs free space to the left "
232 			       "of new free space isn't "
233 			       "quite right. existing: offset=%llu, "
234 			       "bytes=%llu. new: offset=%llu, bytes=%llu\n",
235 			       (unsigned long long)left_info->offset,
236 			       (unsigned long long)left_info->bytes,
237 			       (unsigned long long)offset,
238 			       (unsigned long long)bytes);
239 			BUG();
240 		}
241 
242 		if (info) {
243 			info->offset = left_info->offset;
244 			info->bytes += left_info->bytes;
245 			kfree(left_info);
246 		} else {
247 			info = left_info;
248 			info->bytes += bytes;
249 		}
250 	}
251 
252 	if (info) {
253 		ret = link_free_space(block_group, info);
254 		if (!ret)
255 			info = NULL;
256 		goto out;
257 	}
258 
259 	info = alloc_info;
260 	alloc_info = NULL;
261 	info->offset = offset;
262 	info->bytes = bytes;
263 
264 	ret = link_free_space(block_group, info);
265 	if (ret)
266 		kfree(info);
267 out:
268 	if (ret) {
269 		printk(KERN_ERR "btrfs: unable to add free space :%d\n", ret);
270 		if (ret == -EEXIST)
271 			BUG();
272 	}
273 
274 	kfree(alloc_info);
275 
276 	return ret;
277 }
278 
279 static int
__btrfs_remove_free_space(struct btrfs_block_group_cache * block_group,u64 offset,u64 bytes)280 __btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
281 			  u64 offset, u64 bytes)
282 {
283 	struct btrfs_free_space *info;
284 	int ret = 0;
285 
286 	info = tree_search_offset(&block_group->free_space_offset, offset, 0,
287 				  1);
288 
289 	if (info && info->offset == offset) {
290 		if (info->bytes < bytes) {
291 			printk(KERN_ERR "Found free space at %llu, size %llu,"
292 			       "trying to use %llu\n",
293 			       (unsigned long long)info->offset,
294 			       (unsigned long long)info->bytes,
295 			       (unsigned long long)bytes);
296 			WARN_ON(1);
297 			ret = -EINVAL;
298 			goto out;
299 		}
300 		unlink_free_space(block_group, info);
301 
302 		if (info->bytes == bytes) {
303 			kfree(info);
304 			goto out;
305 		}
306 
307 		info->offset += bytes;
308 		info->bytes -= bytes;
309 
310 		ret = link_free_space(block_group, info);
311 		BUG_ON(ret);
312 	} else if (info && info->offset < offset &&
313 		   info->offset + info->bytes >= offset + bytes) {
314 		u64 old_start = info->offset;
315 		/*
316 		 * we're freeing space in the middle of the info,
317 		 * this can happen during tree log replay
318 		 *
319 		 * first unlink the old info and then
320 		 * insert it again after the hole we're creating
321 		 */
322 		unlink_free_space(block_group, info);
323 		if (offset + bytes < info->offset + info->bytes) {
324 			u64 old_end = info->offset + info->bytes;
325 
326 			info->offset = offset + bytes;
327 			info->bytes = old_end - info->offset;
328 			ret = link_free_space(block_group, info);
329 			BUG_ON(ret);
330 		} else {
331 			/* the hole we're creating ends at the end
332 			 * of the info struct, just free the info
333 			 */
334 			kfree(info);
335 		}
336 
337 		/* step two, insert a new info struct to cover anything
338 		 * before the hole
339 		 */
340 		ret = __btrfs_add_free_space(block_group, old_start,
341 					     offset - old_start);
342 		BUG_ON(ret);
343 	} else {
344 		WARN_ON(1);
345 	}
346 out:
347 	return ret;
348 }
349 
btrfs_add_free_space(struct btrfs_block_group_cache * block_group,u64 offset,u64 bytes)350 int btrfs_add_free_space(struct btrfs_block_group_cache *block_group,
351 			 u64 offset, u64 bytes)
352 {
353 	int ret;
354 	struct btrfs_free_space *sp;
355 
356 	mutex_lock(&block_group->alloc_mutex);
357 	ret = __btrfs_add_free_space(block_group, offset, bytes);
358 	sp = tree_search_offset(&block_group->free_space_offset, offset, 0, 1);
359 	BUG_ON(!sp);
360 	mutex_unlock(&block_group->alloc_mutex);
361 
362 	return ret;
363 }
364 
btrfs_add_free_space_lock(struct btrfs_block_group_cache * block_group,u64 offset,u64 bytes)365 int btrfs_add_free_space_lock(struct btrfs_block_group_cache *block_group,
366 			      u64 offset, u64 bytes)
367 {
368 	int ret;
369 	struct btrfs_free_space *sp;
370 
371 	ret = __btrfs_add_free_space(block_group, offset, bytes);
372 	sp = tree_search_offset(&block_group->free_space_offset, offset, 0, 1);
373 	BUG_ON(!sp);
374 
375 	return ret;
376 }
377 
btrfs_remove_free_space(struct btrfs_block_group_cache * block_group,u64 offset,u64 bytes)378 int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
379 			    u64 offset, u64 bytes)
380 {
381 	int ret = 0;
382 
383 	mutex_lock(&block_group->alloc_mutex);
384 	ret = __btrfs_remove_free_space(block_group, offset, bytes);
385 	mutex_unlock(&block_group->alloc_mutex);
386 
387 	return ret;
388 }
389 
btrfs_remove_free_space_lock(struct btrfs_block_group_cache * block_group,u64 offset,u64 bytes)390 int btrfs_remove_free_space_lock(struct btrfs_block_group_cache *block_group,
391 				 u64 offset, u64 bytes)
392 {
393 	int ret;
394 
395 	ret = __btrfs_remove_free_space(block_group, offset, bytes);
396 
397 	return ret;
398 }
399 
btrfs_dump_free_space(struct btrfs_block_group_cache * block_group,u64 bytes)400 void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group,
401 			   u64 bytes)
402 {
403 	struct btrfs_free_space *info;
404 	struct rb_node *n;
405 	int count = 0;
406 
407 	for (n = rb_first(&block_group->free_space_offset); n; n = rb_next(n)) {
408 		info = rb_entry(n, struct btrfs_free_space, offset_index);
409 		if (info->bytes >= bytes)
410 			count++;
411 	}
412 	printk(KERN_INFO "%d blocks of free space at or bigger than bytes is"
413 	       "\n", count);
414 }
415 
btrfs_block_group_free_space(struct btrfs_block_group_cache * block_group)416 u64 btrfs_block_group_free_space(struct btrfs_block_group_cache *block_group)
417 {
418 	struct btrfs_free_space *info;
419 	struct rb_node *n;
420 	u64 ret = 0;
421 
422 	for (n = rb_first(&block_group->free_space_offset); n;
423 	     n = rb_next(n)) {
424 		info = rb_entry(n, struct btrfs_free_space, offset_index);
425 		ret += info->bytes;
426 	}
427 
428 	return ret;
429 }
430 
btrfs_remove_free_space_cache(struct btrfs_block_group_cache * block_group)431 void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group)
432 {
433 	struct btrfs_free_space *info;
434 	struct rb_node *node;
435 
436 	mutex_lock(&block_group->alloc_mutex);
437 	while ((node = rb_last(&block_group->free_space_bytes)) != NULL) {
438 		info = rb_entry(node, struct btrfs_free_space, bytes_index);
439 		unlink_free_space(block_group, info);
440 		kfree(info);
441 		if (need_resched()) {
442 			mutex_unlock(&block_group->alloc_mutex);
443 			cond_resched();
444 			mutex_lock(&block_group->alloc_mutex);
445 		}
446 	}
447 	mutex_unlock(&block_group->alloc_mutex);
448 }
449 
450 #if 0
451 static struct btrfs_free_space *btrfs_find_free_space_offset(struct
452 						      btrfs_block_group_cache
453 						      *block_group, u64 offset,
454 						      u64 bytes)
455 {
456 	struct btrfs_free_space *ret;
457 
458 	mutex_lock(&block_group->alloc_mutex);
459 	ret = tree_search_offset(&block_group->free_space_offset, offset,
460 				 bytes, 0);
461 	mutex_unlock(&block_group->alloc_mutex);
462 
463 	return ret;
464 }
465 
466 static struct btrfs_free_space *btrfs_find_free_space_bytes(struct
467 						     btrfs_block_group_cache
468 						     *block_group, u64 offset,
469 						     u64 bytes)
470 {
471 	struct btrfs_free_space *ret;
472 
473 	mutex_lock(&block_group->alloc_mutex);
474 
475 	ret = tree_search_bytes(&block_group->free_space_bytes, offset, bytes);
476 	mutex_unlock(&block_group->alloc_mutex);
477 
478 	return ret;
479 }
480 #endif
481 
btrfs_find_free_space(struct btrfs_block_group_cache * block_group,u64 offset,u64 bytes)482 struct btrfs_free_space *btrfs_find_free_space(struct btrfs_block_group_cache
483 					       *block_group, u64 offset,
484 					       u64 bytes)
485 {
486 	struct btrfs_free_space *ret = NULL;
487 
488 	ret = tree_search_offset(&block_group->free_space_offset, offset,
489 				 bytes, 0);
490 	if (!ret)
491 		ret = tree_search_bytes(&block_group->free_space_bytes,
492 					offset, bytes);
493 
494 	return ret;
495 }
496