diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-04-15 15:41:47 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:01 -0400 |
commit | e17cade25ff8074101d653557a78df09c16ca276 (patch) | |
tree | c4bddc201bf77c9a460e726a5cdd5ca1add8c256 /fs/btrfs/volumes.c | |
parent | b248a4152956cbae1b23f4c70ef5b51d6ea2ecfb (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.c | 76 |
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); |
183 | printk("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; |
193 | printk("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 | ||
373 | int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, | 372 | int 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); |
406 | err: | 414 | err: |
@@ -408,17 +416,18 @@ err: | |||
408 | return ret; | 416 | return ret; |
409 | } | 417 | } |
410 | 418 | ||
411 | static int find_next_chunk(struct btrfs_root *root, u64 *objectid) | 419 | static 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; |
440 | error: | 456 | error: |
@@ -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; |
699 | printk("new chunk type %Lu start %Lu size %Lu\n", type, key.objectid, *num_bytes); | 721 | printk("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); |
714 | printk("alloc chunk start %Lu size %Lu from dev %Lu type %Lu\n", key.objectid, calc_size, device->devid, type); | 738 | printk("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) { |