diff options
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) { |