aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-04-15 15:41:47 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:01 -0400
commite17cade25ff8074101d653557a78df09c16ca276 (patch)
treec4bddc201bf77c9a460e726a5cdd5ca1add8c256 /fs/btrfs/volumes.c
parentb248a4152956cbae1b23f4c70ef5b51d6ea2ecfb (diff)
Btrfs: Add chunk uuids and update multi-device back references
Block headers now store the chunk tree uuid Chunk items records the device uuid for each stripes Device extent items record better back refs to the chunk tree Block groups record better back refs to the chunk tree The chunk tree format has also changed. The objectid of BTRFS_CHUNK_ITEM_KEY used to be the logical offset of the chunk. Now it is a chunk tree id, with the logical offset being stored in the offset field of the key. This allows a single chunk tree to record multiple logical address spaces, upping the number of bytes indexed by a chunk tree from 2^64 to 2^128. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c76
1 files changed, 50 insertions, 26 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index f81519f0e4a7..23ebd95b25e0 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -180,7 +180,7 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
180 list_for_each(cur, head) { 180 list_for_each(cur, head) {
181 device = list_entry(cur, struct btrfs_device, dev_list); 181 device = list_entry(cur, struct btrfs_device, dev_list);
182 bdev = open_bdev_excl(device->name, flags, holder); 182 bdev = open_bdev_excl(device->name, flags, holder);
183printk("opening %s devid %Lu\n", device->name, device->devid); 183
184 if (IS_ERR(bdev)) { 184 if (IS_ERR(bdev)) {
185 printk("open %s failed\n", device->name); 185 printk("open %s failed\n", device->name);
186 ret = PTR_ERR(bdev); 186 ret = PTR_ERR(bdev);
@@ -190,7 +190,6 @@ printk("opening %s devid %Lu\n", device->name, device->devid);
190 fs_devices->latest_bdev = bdev; 190 fs_devices->latest_bdev = bdev;
191 if (device->devid == fs_devices->lowest_devid) { 191 if (device->devid == fs_devices->lowest_devid) {
192 fs_devices->lowest_bdev = bdev; 192 fs_devices->lowest_bdev = bdev;
193printk("lowest bdev %s\n", device->name);
194 } 193 }
195 device->bdev = bdev; 194 device->bdev = bdev;
196 } 195 }
@@ -372,7 +371,9 @@ error:
372 371
373int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, 372int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
374 struct btrfs_device *device, 373 struct btrfs_device *device,
375 u64 owner, u64 num_bytes, u64 *start) 374 u64 chunk_tree, u64 chunk_objectid,
375 u64 chunk_offset,
376 u64 num_bytes, u64 *start)
376{ 377{
377 int ret; 378 int ret;
378 struct btrfs_path *path; 379 struct btrfs_path *path;
@@ -400,7 +401,14 @@ int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
400 leaf = path->nodes[0]; 401 leaf = path->nodes[0];
401 extent = btrfs_item_ptr(leaf, path->slots[0], 402 extent = btrfs_item_ptr(leaf, path->slots[0],
402 struct btrfs_dev_extent); 403 struct btrfs_dev_extent);
403 btrfs_set_dev_extent_owner(leaf, extent, owner); 404 btrfs_set_dev_extent_chunk_tree(leaf, extent, chunk_tree);
405 btrfs_set_dev_extent_chunk_objectid(leaf, extent, chunk_objectid);
406 btrfs_set_dev_extent_chunk_offset(leaf, extent, chunk_offset);
407
408 write_extent_buffer(leaf, root->fs_info->chunk_tree_uuid,
409 (unsigned long)btrfs_dev_extent_chunk_tree_uuid(extent),
410 BTRFS_UUID_SIZE);
411
404 btrfs_set_dev_extent_length(leaf, extent, num_bytes); 412 btrfs_set_dev_extent_length(leaf, extent, num_bytes);
405 btrfs_mark_buffer_dirty(leaf); 413 btrfs_mark_buffer_dirty(leaf);
406err: 414err:
@@ -408,17 +416,18 @@ err:
408 return ret; 416 return ret;
409} 417}
410 418
411static int find_next_chunk(struct btrfs_root *root, u64 *objectid) 419static int find_next_chunk(struct btrfs_root *root, u64 objectid, u64 *offset)
412{ 420{
413 struct btrfs_path *path; 421 struct btrfs_path *path;
414 int ret; 422 int ret;
415 struct btrfs_key key; 423 struct btrfs_key key;
424 struct btrfs_chunk *chunk;
416 struct btrfs_key found_key; 425 struct btrfs_key found_key;
417 426
418 path = btrfs_alloc_path(); 427 path = btrfs_alloc_path();
419 BUG_ON(!path); 428 BUG_ON(!path);
420 429
421 key.objectid = (u64)-1; 430 key.objectid = objectid;
422 key.offset = (u64)-1; 431 key.offset = (u64)-1;
423 key.type = BTRFS_CHUNK_ITEM_KEY; 432 key.type = BTRFS_CHUNK_ITEM_KEY;
424 433
@@ -430,11 +439,18 @@ static int find_next_chunk(struct btrfs_root *root, u64 *objectid)
430 439
431 ret = btrfs_previous_item(root, path, 0, BTRFS_CHUNK_ITEM_KEY); 440 ret = btrfs_previous_item(root, path, 0, BTRFS_CHUNK_ITEM_KEY);
432 if (ret) { 441 if (ret) {
433 *objectid = 0; 442 *offset = 0;
434 } else { 443 } else {
435 btrfs_item_key_to_cpu(path->nodes[0], &found_key, 444 btrfs_item_key_to_cpu(path->nodes[0], &found_key,
436 path->slots[0]); 445 path->slots[0]);
437 *objectid = found_key.objectid + found_key.offset; 446 if (found_key.objectid != objectid)
447 *offset = 0;
448 else {
449 chunk = btrfs_item_ptr(path->nodes[0], path->slots[0],
450 struct btrfs_chunk);
451 *offset = found_key.offset +
452 btrfs_chunk_length(path->nodes[0], chunk);
453 }
438 } 454 }
439 ret = 0; 455 ret = 0;
440error: 456error:
@@ -520,9 +536,12 @@ int btrfs_add_device(struct btrfs_trans_handle *trans,
520 btrfs_set_device_sector_size(leaf, dev_item, device->sector_size); 536 btrfs_set_device_sector_size(leaf, dev_item, device->sector_size);
521 btrfs_set_device_total_bytes(leaf, dev_item, device->total_bytes); 537 btrfs_set_device_total_bytes(leaf, dev_item, device->total_bytes);
522 btrfs_set_device_bytes_used(leaf, dev_item, device->bytes_used); 538 btrfs_set_device_bytes_used(leaf, dev_item, device->bytes_used);
539 btrfs_set_device_group(leaf, dev_item, 0);
540 btrfs_set_device_seek_speed(leaf, dev_item, 0);
541 btrfs_set_device_bandwidth(leaf, dev_item, 0);
523 542
524 ptr = (unsigned long)btrfs_device_uuid(dev_item); 543 ptr = (unsigned long)btrfs_device_uuid(dev_item);
525 write_extent_buffer(leaf, device->uuid, ptr, BTRFS_DEV_UUID_SIZE); 544 write_extent_buffer(leaf, device->uuid, ptr, BTRFS_UUID_SIZE);
526 btrfs_mark_buffer_dirty(leaf); 545 btrfs_mark_buffer_dirty(leaf);
527 ret = 0; 546 ret = 0;
528 547
@@ -674,7 +693,10 @@ again:
674 return -ENOSPC; 693 return -ENOSPC;
675 } 694 }
676 695
677 ret = find_next_chunk(chunk_root, &key.objectid); 696 key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
697 key.type = BTRFS_CHUNK_ITEM_KEY;
698 ret = find_next_chunk(chunk_root, BTRFS_FIRST_CHUNK_TREE_OBJECTID,
699 &key.offset);
678 if (ret) 700 if (ret)
679 return ret; 701 return ret;
680 702
@@ -696,8 +718,9 @@ again:
696 *num_bytes = calc_size * num_stripes; 718 *num_bytes = calc_size * num_stripes;
697 719
698 index = 0; 720 index = 0;
699printk("new chunk type %Lu start %Lu size %Lu\n", type, key.objectid, *num_bytes); 721printk("new chunk type %Lu start %Lu size %Lu\n", type, key.offset, *num_bytes);
700 while(index < num_stripes) { 722 while(index < num_stripes) {
723 struct btrfs_stripe *stripe;
701 BUG_ON(list_empty(&private_devs)); 724 BUG_ON(list_empty(&private_devs));
702 cur = private_devs.next; 725 cur = private_devs.next;
703 device = list_entry(cur, struct btrfs_device, dev_list); 726 device = list_entry(cur, struct btrfs_device, dev_list);
@@ -708,26 +731,28 @@ printk("new chunk type %Lu start %Lu size %Lu\n", type, key.objectid, *num_bytes
708 list_move_tail(&device->dev_list, dev_list); 731 list_move_tail(&device->dev_list, dev_list);
709 732
710 ret = btrfs_alloc_dev_extent(trans, device, 733 ret = btrfs_alloc_dev_extent(trans, device,
711 key.objectid, 734 info->chunk_root->root_key.objectid,
712 calc_size, &dev_offset); 735 BTRFS_FIRST_CHUNK_TREE_OBJECTID, key.offset,
736 calc_size, &dev_offset);
713 BUG_ON(ret); 737 BUG_ON(ret);
714printk("alloc chunk start %Lu size %Lu from dev %Lu type %Lu\n", key.objectid, calc_size, device->devid, type); 738printk("alloc chunk start %Lu size %Lu from dev %Lu type %Lu\n", key.offset, calc_size, device->devid, type);
715 device->bytes_used += calc_size; 739 device->bytes_used += calc_size;
716 ret = btrfs_update_device(trans, device); 740 ret = btrfs_update_device(trans, device);
717 BUG_ON(ret); 741 BUG_ON(ret);
718 742
719 map->stripes[index].dev = device; 743 map->stripes[index].dev = device;
720 map->stripes[index].physical = dev_offset; 744 map->stripes[index].physical = dev_offset;
721 btrfs_set_stack_stripe_devid(stripes + index, device->devid); 745 stripe = stripes + index;
722 btrfs_set_stack_stripe_offset(stripes + index, dev_offset); 746 btrfs_set_stack_stripe_devid(stripe, device->devid);
747 btrfs_set_stack_stripe_offset(stripe, dev_offset);
748 memcpy(stripe->dev_uuid, device->uuid, BTRFS_UUID_SIZE);
723 physical = dev_offset; 749 physical = dev_offset;
724 index++; 750 index++;
725 } 751 }
726 BUG_ON(!list_empty(&private_devs)); 752 BUG_ON(!list_empty(&private_devs));
727 753
728 /* key.objectid was set above */ 754 /* key was set above */
729 key.offset = *num_bytes; 755 btrfs_set_stack_chunk_length(chunk, *num_bytes);
730 key.type = BTRFS_CHUNK_ITEM_KEY;
731 btrfs_set_stack_chunk_owner(chunk, extent_root->root_key.objectid); 756 btrfs_set_stack_chunk_owner(chunk, extent_root->root_key.objectid);
732 btrfs_set_stack_chunk_stripe_len(chunk, stripe_len); 757 btrfs_set_stack_chunk_stripe_len(chunk, stripe_len);
733 btrfs_set_stack_chunk_type(chunk, type); 758 btrfs_set_stack_chunk_type(chunk, type);
@@ -745,14 +770,14 @@ printk("alloc chunk start %Lu size %Lu from dev %Lu type %Lu\n", key.objectid, c
745 ret = btrfs_insert_item(trans, chunk_root, &key, chunk, 770 ret = btrfs_insert_item(trans, chunk_root, &key, chunk,
746 btrfs_chunk_item_size(num_stripes)); 771 btrfs_chunk_item_size(num_stripes));
747 BUG_ON(ret); 772 BUG_ON(ret);
748 *start = key.objectid; 773 *start = key.offset;;
749 774
750 em = alloc_extent_map(GFP_NOFS); 775 em = alloc_extent_map(GFP_NOFS);
751 if (!em) 776 if (!em)
752 return -ENOMEM; 777 return -ENOMEM;
753 em->bdev = (struct block_device *)map; 778 em->bdev = (struct block_device *)map;
754 em->start = key.objectid; 779 em->start = key.offset;
755 em->len = key.offset; 780 em->len = *num_bytes;
756 em->block_start = 0; 781 em->block_start = 0;
757 782
758 kfree(chunk); 783 kfree(chunk);
@@ -1056,8 +1081,8 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
1056 int ret; 1081 int ret;
1057 int i; 1082 int i;
1058 1083
1059 logical = key->objectid; 1084 logical = key->offset;
1060 length = key->offset; 1085 length = btrfs_chunk_length(leaf, chunk);
1061 spin_lock(&map_tree->map_tree.lock); 1086 spin_lock(&map_tree->map_tree.lock);
1062 em = lookup_extent_mapping(&map_tree->map_tree, logical, 1); 1087 em = lookup_extent_mapping(&map_tree->map_tree, logical, 1);
1063 spin_unlock(&map_tree->map_tree.lock); 1088 spin_unlock(&map_tree->map_tree.lock);
@@ -1131,7 +1156,7 @@ static int fill_device_from_item(struct extent_buffer *leaf,
1131 device->sector_size = btrfs_device_sector_size(leaf, dev_item); 1156 device->sector_size = btrfs_device_sector_size(leaf, dev_item);
1132 1157
1133 ptr = (unsigned long)btrfs_device_uuid(dev_item); 1158 ptr = (unsigned long)btrfs_device_uuid(dev_item);
1134 read_extent_buffer(leaf, device->uuid, ptr, BTRFS_DEV_UUID_SIZE); 1159 read_extent_buffer(leaf, device->uuid, ptr, BTRFS_UUID_SIZE);
1135 1160
1136 return 0; 1161 return 0;
1137} 1162}
@@ -1143,7 +1168,6 @@ static int read_one_dev(struct btrfs_root *root,
1143 struct btrfs_device *device; 1168 struct btrfs_device *device;
1144 u64 devid; 1169 u64 devid;
1145 int ret; 1170 int ret;
1146
1147 devid = btrfs_device_id(leaf, dev_item); 1171 devid = btrfs_device_id(leaf, dev_item);
1148 device = btrfs_find_device(root, devid); 1172 device = btrfs_find_device(root, devid);
1149 if (!device) { 1173 if (!device) {