aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-03-24 15:01:59 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:01 -0400
commit6324fbf334f4586325057197da7752f4ffa409d3 (patch)
treeaf67d90c3a58f48b91f73ac23f753f4f3907a453 /fs/btrfs/volumes.c
parent0b86a832a1f38abec695864ec2eaedc9d2383f1b (diff)
Btrfs: Dynamic chunk and block group allocation
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c87
1 files changed, 53 insertions, 34 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 90a8d45dc6d7..a52a13f365d6 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -131,7 +131,7 @@ check_pending:
131 btrfs_release_path(root, path); 131 btrfs_release_path(root, path);
132 BUG_ON(*start < search_start); 132 BUG_ON(*start < search_start);
133 133
134 if (*start + num_bytes >= search_end) { 134 if (*start + num_bytes > search_end) {
135 ret = -ENOSPC; 135 ret = -ENOSPC;
136 goto error; 136 goto error;
137 } 137 }
@@ -159,8 +159,9 @@ int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
159 return -ENOMEM; 159 return -ENOMEM;
160 160
161 ret = find_free_dev_extent(trans, device, path, num_bytes, start); 161 ret = find_free_dev_extent(trans, device, path, num_bytes, start);
162 if (ret) 162 if (ret) {
163 goto err; 163 goto err;
164 }
164 165
165 key.objectid = device->devid; 166 key.objectid = device->devid;
166 key.offset = *start; 167 key.offset = *start;
@@ -214,22 +215,6 @@ error:
214 return ret; 215 return ret;
215} 216}
216 217
217static struct btrfs_device *next_device(struct list_head *head,
218 struct list_head *last)
219{
220 struct list_head *next = last->next;
221 struct btrfs_device *dev;
222
223 if (list_empty(head))
224 return NULL;
225
226 if (next == head)
227 next = next->next;
228
229 dev = list_entry(next, struct btrfs_device, dev_list);
230 return dev;
231}
232
233static int find_next_devid(struct btrfs_root *root, struct btrfs_path *path, 218static int find_next_devid(struct btrfs_root *root, struct btrfs_path *path,
234 u64 *objectid) 219 u64 *objectid)
235{ 220{
@@ -397,31 +382,63 @@ int btrfs_add_system_chunk(struct btrfs_trans_handle *trans,
397 382
398int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, 383int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
399 struct btrfs_root *extent_root, u64 *start, 384 struct btrfs_root *extent_root, u64 *start,
400 u64 *num_bytes, u32 type) 385 u64 *num_bytes, u64 type)
401{ 386{
402 u64 dev_offset; 387 u64 dev_offset;
403 struct btrfs_root *chunk_root = extent_root->fs_info->chunk_root; 388 struct btrfs_root *chunk_root = extent_root->fs_info->chunk_root;
404 struct btrfs_stripe *stripes; 389 struct btrfs_stripe *stripes;
405 struct btrfs_device *device = NULL; 390 struct btrfs_device *device = NULL;
406 struct btrfs_chunk *chunk; 391 struct btrfs_chunk *chunk;
392 struct list_head private_devs;
407 struct list_head *dev_list = &extent_root->fs_info->devices; 393 struct list_head *dev_list = &extent_root->fs_info->devices;
408 struct list_head *last_dev = extent_root->fs_info->last_device; 394 struct list_head *cur;
409 struct extent_map_tree *em_tree; 395 struct extent_map_tree *em_tree;
410 struct map_lookup *map; 396 struct map_lookup *map;
411 struct extent_map *em; 397 struct extent_map *em;
412 u64 physical; 398 u64 physical;
413 u64 calc_size = 1024 * 1024 * 1024; 399 u64 calc_size = 1024 * 1024 * 1024;
414 int num_stripes; 400 u64 avail;
401 u64 max_avail = 0;
402 int num_stripes = 1;
403 int looped = 0;
415 int ret; 404 int ret;
416 int index = 0; 405 int index;
417 struct btrfs_key key; 406 struct btrfs_key key;
418 407
408 if (list_empty(dev_list))
409 return -ENOSPC;
410again:
411 INIT_LIST_HEAD(&private_devs);
412 cur = dev_list->next;
413 index = 0;
414 /* build a private list of devices we will allocate from */
415 while(index < num_stripes) {
416 device = list_entry(cur, struct btrfs_device, dev_list);
417 avail = device->total_bytes - device->bytes_used;
418 cur = cur->next;
419 if (avail > max_avail)
420 max_avail = avail;
421 if (avail >= calc_size) {
422 list_move_tail(&device->dev_list, &private_devs);
423 index++;
424 }
425 if (cur == dev_list)
426 break;
427 }
428 if (index < num_stripes) {
429 list_splice(&private_devs, dev_list);
430 if (!looped && max_avail > 0) {
431 looped = 1;
432 calc_size = max_avail;
433 goto again;
434 }
435 return -ENOSPC;
436 }
419 437
420 ret = find_next_chunk(chunk_root, &key.objectid); 438 ret = find_next_chunk(chunk_root, &key.objectid);
421 if (ret) 439 if (ret)
422 return ret; 440 return ret;
423 441
424 num_stripes = 1;
425 chunk = kmalloc(btrfs_chunk_item_size(num_stripes), GFP_NOFS); 442 chunk = kmalloc(btrfs_chunk_item_size(num_stripes), GFP_NOFS);
426 if (!chunk) 443 if (!chunk)
427 return -ENOMEM; 444 return -ENOMEM;
@@ -429,11 +446,12 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
429 stripes = &chunk->stripe; 446 stripes = &chunk->stripe;
430 447
431 *num_bytes = calc_size; 448 *num_bytes = calc_size;
449 index = 0;
432 while(index < num_stripes) { 450 while(index < num_stripes) {
433 device = next_device(dev_list, last_dev); 451 BUG_ON(list_empty(&private_devs));
434 BUG_ON(!device); 452 cur = private_devs.next;
435 last_dev = &device->dev_list; 453 device = list_entry(cur, struct btrfs_device, dev_list);
436 extent_root->fs_info->last_device = last_dev; 454 list_move_tail(&device->dev_list, dev_list);
437 455
438 ret = btrfs_alloc_dev_extent(trans, device, 456 ret = btrfs_alloc_dev_extent(trans, device,
439 key.objectid, 457 key.objectid,
@@ -449,6 +467,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
449 physical = dev_offset; 467 physical = dev_offset;
450 index++; 468 index++;
451 } 469 }
470 BUG_ON(!list_empty(&private_devs));
452 471
453 /* key.objectid was set above */ 472 /* key.objectid was set above */
454 key.offset = *num_bytes; 473 key.offset = *num_bytes;
@@ -692,17 +711,17 @@ static int read_one_dev(struct btrfs_root *root, struct btrfs_key *key,
692 int ret; 711 int ret;
693 712
694 devid = btrfs_device_id(leaf, dev_item); 713 devid = btrfs_device_id(leaf, dev_item);
695 if (btrfs_find_device(root, devid)) 714 device = btrfs_find_device(root, devid);
696 return 0; 715 if (!device) {
697 716 device = kmalloc(sizeof(*device), GFP_NOFS);
698 device = kmalloc(sizeof(*device), GFP_NOFS); 717 if (!device)
699 if (!device) 718 return -ENOMEM;
700 return -ENOMEM; 719 list_add(&device->dev_list, &root->fs_info->devices);
720 }
701 721
702 fill_device_from_item(leaf, dev_item, device); 722 fill_device_from_item(leaf, dev_item, device);
703 device->dev_root = root->fs_info->dev_root; 723 device->dev_root = root->fs_info->dev_root;
704 device->bdev = root->fs_info->sb->s_bdev; 724 device->bdev = root->fs_info->sb->s_bdev;
705 list_add(&device->dev_list, &root->fs_info->devices);
706 memcpy(&device->dev_key, key, sizeof(*key)); 725 memcpy(&device->dev_key, key, sizeof(*key));
707 ret = 0; 726 ret = 0;
708#if 0 727#if 0