diff options
-rw-r--r-- | fs/btrfs/ctree.h | 36 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 31 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 1 | ||||
-rw-r--r-- | fs/btrfs/super.c | 9 |
4 files changed, 65 insertions, 12 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 454eb88611bb..ef3583cf74d6 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -91,10 +91,12 @@ struct btrfs_super_block { | |||
91 | __le64 total_blocks; | 91 | __le64 total_blocks; |
92 | __le64 blocks_used; | 92 | __le64 blocks_used; |
93 | __le64 root_dir_objectid; | 93 | __le64 root_dir_objectid; |
94 | __le64 last_device_id; | ||
94 | /* fields below here vary with the underlying disk */ | 95 | /* fields below here vary with the underlying disk */ |
95 | __le64 device_block_start; | 96 | __le64 device_block_start; |
96 | __le64 device_num_blocks; | 97 | __le64 device_num_blocks; |
97 | __le64 device_root; | 98 | __le64 device_root; |
99 | __le64 device_id; | ||
98 | } __attribute__ ((__packed__)); | 100 | } __attribute__ ((__packed__)); |
99 | 101 | ||
100 | /* | 102 | /* |
@@ -230,6 +232,7 @@ struct btrfs_csum_item { | |||
230 | 232 | ||
231 | struct btrfs_device_item { | 233 | struct btrfs_device_item { |
232 | __le16 pathlen; | 234 | __le16 pathlen; |
235 | __le64 device_id; | ||
233 | } __attribute__ ((__packed__)); | 236 | } __attribute__ ((__packed__)); |
234 | 237 | ||
235 | struct crypto_hash; | 238 | struct crypto_hash; |
@@ -798,6 +801,28 @@ static inline void btrfs_set_super_root_dir(struct btrfs_super_block *s, u64 | |||
798 | s->root_dir_objectid = cpu_to_le64(val); | 801 | s->root_dir_objectid = cpu_to_le64(val); |
799 | } | 802 | } |
800 | 803 | ||
804 | static inline u64 btrfs_super_last_device_id(struct btrfs_super_block *s) | ||
805 | { | ||
806 | return le64_to_cpu(s->last_device_id); | ||
807 | } | ||
808 | |||
809 | static inline void btrfs_set_super_last_device_id(struct btrfs_super_block *s, | ||
810 | u64 val) | ||
811 | { | ||
812 | s->last_device_id = cpu_to_le64(val); | ||
813 | } | ||
814 | |||
815 | static inline u64 btrfs_super_device_id(struct btrfs_super_block *s) | ||
816 | { | ||
817 | return le64_to_cpu(s->device_id); | ||
818 | } | ||
819 | |||
820 | static inline void btrfs_set_super_device_id(struct btrfs_super_block *s, | ||
821 | u64 val) | ||
822 | { | ||
823 | s->device_id = cpu_to_le64(val); | ||
824 | } | ||
825 | |||
801 | static inline u64 btrfs_super_device_block_start(struct btrfs_super_block *s) | 826 | static inline u64 btrfs_super_device_block_start(struct btrfs_super_block *s) |
802 | { | 827 | { |
803 | return le64_to_cpu(s->device_block_start); | 828 | return le64_to_cpu(s->device_block_start); |
@@ -910,6 +935,17 @@ static inline void btrfs_set_device_pathlen(struct btrfs_device_item *d, | |||
910 | d->pathlen = cpu_to_le16(val); | 935 | d->pathlen = cpu_to_le16(val); |
911 | } | 936 | } |
912 | 937 | ||
938 | static inline u64 btrfs_device_id(struct btrfs_device_item *d) | ||
939 | { | ||
940 | return le64_to_cpu(d->device_id); | ||
941 | } | ||
942 | |||
943 | static inline void btrfs_set_device_id(struct btrfs_device_item *d, | ||
944 | u64 val) | ||
945 | { | ||
946 | d->device_id = cpu_to_le64(val); | ||
947 | } | ||
948 | |||
913 | static inline struct btrfs_root *btrfs_sb(struct super_block *sb) | 949 | static inline struct btrfs_root *btrfs_sb(struct super_block *sb) |
914 | { | 950 | { |
915 | return sb->s_fs_info; | 951 | return sb->s_fs_info; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 3ba4df20c913..06b969c14625 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -13,11 +13,13 @@ | |||
13 | struct dev_lookup { | 13 | struct dev_lookup { |
14 | u64 block_start; | 14 | u64 block_start; |
15 | u64 num_blocks; | 15 | u64 num_blocks; |
16 | u64 device_id; | ||
16 | struct block_device *bdev; | 17 | struct block_device *bdev; |
17 | }; | 18 | }; |
18 | 19 | ||
19 | int btrfs_insert_dev_radix(struct btrfs_root *root, | 20 | int btrfs_insert_dev_radix(struct btrfs_root *root, |
20 | struct block_device *bdev, | 21 | struct block_device *bdev, |
22 | u64 device_id, | ||
21 | u64 block_start, | 23 | u64 block_start, |
22 | u64 num_blocks) | 24 | u64 num_blocks) |
23 | { | 25 | { |
@@ -31,6 +33,7 @@ int btrfs_insert_dev_radix(struct btrfs_root *root, | |||
31 | lookup->block_start = block_start; | 33 | lookup->block_start = block_start; |
32 | lookup->num_blocks = num_blocks; | 34 | lookup->num_blocks = num_blocks; |
33 | lookup->bdev = bdev; | 35 | lookup->bdev = bdev; |
36 | lookup->device_id = device_id; | ||
34 | printk("inserting %s into dev radix %Lu %Lu\n", bdevname(bdev, b), block_start, num_blocks); | 37 | printk("inserting %s into dev radix %Lu %Lu\n", bdevname(bdev, b), block_start, num_blocks); |
35 | 38 | ||
36 | ret = radix_tree_insert(&root->fs_info->dev_radix, block_start + | 39 | ret = radix_tree_insert(&root->fs_info->dev_radix, block_start + |
@@ -418,17 +421,14 @@ printk("all worked\n"); | |||
418 | return root; | 421 | return root; |
419 | } | 422 | } |
420 | 423 | ||
421 | int btrfs_open_disk(struct btrfs_root *root, u64 block_start, u64 num_blocks, | 424 | static int btrfs_open_disk(struct btrfs_root *root, u64 device_id, |
422 | char *filename, int name_len) | 425 | u64 block_start, u64 num_blocks, |
426 | char *filename, int name_len) | ||
423 | { | 427 | { |
424 | char *null_filename; | 428 | char *null_filename; |
425 | struct block_device *bdev; | 429 | struct block_device *bdev; |
426 | int ret; | 430 | int ret; |
427 | 431 | ||
428 | if (block_start == 0) { | ||
429 | printk("skipping disk with block_start == 0\n"); | ||
430 | return 0; | ||
431 | } | ||
432 | null_filename = kmalloc(name_len + 1, GFP_NOFS); | 432 | null_filename = kmalloc(name_len + 1, GFP_NOFS); |
433 | if (!null_filename) | 433 | if (!null_filename) |
434 | return -ENOMEM; | 434 | return -ENOMEM; |
@@ -441,7 +441,8 @@ return 0; | |||
441 | goto out; | 441 | goto out; |
442 | } | 442 | } |
443 | set_blocksize(bdev, root->fs_info->sb->s_blocksize); | 443 | set_blocksize(bdev, root->fs_info->sb->s_blocksize); |
444 | ret = btrfs_insert_dev_radix(root, bdev, block_start, num_blocks); | 444 | ret = btrfs_insert_dev_radix(root, bdev, device_id, |
445 | block_start, num_blocks); | ||
445 | BUG_ON(ret); | 446 | BUG_ON(ret); |
446 | ret = 0; | 447 | ret = 0; |
447 | out: | 448 | out: |
@@ -490,10 +491,14 @@ static int read_device_info(struct btrfs_root *root) | |||
490 | } | 491 | } |
491 | dev_item = btrfs_item_ptr(leaf, slot, struct btrfs_device_item); | 492 | dev_item = btrfs_item_ptr(leaf, slot, struct btrfs_device_item); |
492 | printk("found key %Lu %Lu\n", key.objectid, key.offset); | 493 | printk("found key %Lu %Lu\n", key.objectid, key.offset); |
493 | ret = btrfs_open_disk(root, key.objectid, key.offset, | 494 | if (btrfs_device_id(dev_item) != |
494 | (char *)(dev_item + 1), | 495 | btrfs_super_device_id(root->fs_info->disk_super)) { |
495 | btrfs_device_pathlen(dev_item)); | 496 | ret = btrfs_open_disk(root, btrfs_device_id(dev_item), |
496 | BUG_ON(ret); | 497 | key.objectid, key.offset, |
498 | (char *)(dev_item + 1), | ||
499 | btrfs_device_pathlen(dev_item)); | ||
500 | BUG_ON(ret); | ||
501 | } | ||
497 | path->slots[0]++; | 502 | path->slots[0]++; |
498 | } | 503 | } |
499 | btrfs_free_path(path); | 504 | btrfs_free_path(path); |
@@ -556,6 +561,7 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
556 | dev_lookup->block_start = 0; | 561 | dev_lookup->block_start = 0; |
557 | dev_lookup->num_blocks = (u32)-2; | 562 | dev_lookup->num_blocks = (u32)-2; |
558 | dev_lookup->bdev = sb->s_bdev; | 563 | dev_lookup->bdev = sb->s_bdev; |
564 | dev_lookup->device_id = 0; | ||
559 | ret = radix_tree_insert(&fs_info->dev_radix, (u32)-2, dev_lookup); | 565 | ret = radix_tree_insert(&fs_info->dev_radix, (u32)-2, dev_lookup); |
560 | BUG_ON(ret); | 566 | BUG_ON(ret); |
561 | fs_info->sb_buffer = read_tree_block(tree_root, | 567 | fs_info->sb_buffer = read_tree_block(tree_root, |
@@ -575,6 +581,8 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
575 | radix_tree_delete(&fs_info->dev_radix, (u32)-2); | 581 | radix_tree_delete(&fs_info->dev_radix, (u32)-2); |
576 | dev_lookup->block_start = btrfs_super_device_block_start(disk_super); | 582 | dev_lookup->block_start = btrfs_super_device_block_start(disk_super); |
577 | dev_lookup->num_blocks = btrfs_super_device_num_blocks(disk_super); | 583 | dev_lookup->num_blocks = btrfs_super_device_num_blocks(disk_super); |
584 | dev_lookup->device_id = btrfs_super_device_id(disk_super); | ||
585 | |||
578 | ret = radix_tree_insert(&fs_info->dev_radix, | 586 | ret = radix_tree_insert(&fs_info->dev_radix, |
579 | dev_lookup->block_start + | 587 | dev_lookup->block_start + |
580 | dev_lookup->num_blocks - 1, dev_lookup); | 588 | dev_lookup->num_blocks - 1, dev_lookup); |
@@ -659,6 +667,7 @@ int del_fs_roots(struct btrfs_fs_info *fs_info) | |||
659 | } | 667 | } |
660 | return 0; | 668 | return 0; |
661 | } | 669 | } |
670 | |||
662 | static int free_dev_radix(struct btrfs_fs_info *fs_info) | 671 | static int free_dev_radix(struct btrfs_fs_info *fs_info) |
663 | { | 672 | { |
664 | struct dev_lookup *lookup[8]; | 673 | struct dev_lookup *lookup[8]; |
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index aa9f56c38419..444ebb0141ae 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
@@ -44,6 +44,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, | |||
44 | u64 bh_blocknr(struct buffer_head *bh); | 44 | u64 bh_blocknr(struct buffer_head *bh); |
45 | int btrfs_insert_dev_radix(struct btrfs_root *root, | 45 | int btrfs_insert_dev_radix(struct btrfs_root *root, |
46 | struct block_device *bdev, | 46 | struct block_device *bdev, |
47 | u64 device_id, | ||
47 | u64 block_start, | 48 | u64 block_start, |
48 | u64 num_blocks); | 49 | u64 num_blocks); |
49 | int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, | 50 | int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index c46d7eafcf62..8dcf600e39ef 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -1840,7 +1840,9 @@ static int add_disk(struct btrfs_root *root, char *name, int namelen) | |||
1840 | u16 item_size; | 1840 | u16 item_size; |
1841 | u64 num_blocks; | 1841 | u64 num_blocks; |
1842 | u64 new_blocks; | 1842 | u64 new_blocks; |
1843 | u64 device_id; | ||
1843 | int ret; | 1844 | int ret; |
1845 | |||
1844 | printk("adding disk %s\n", name); | 1846 | printk("adding disk %s\n", name); |
1845 | path = btrfs_alloc_path(); | 1847 | path = btrfs_alloc_path(); |
1846 | if (!path) | 1848 | if (!path) |
@@ -1875,9 +1877,14 @@ printk("insert failed %d\n", ret); | |||
1875 | path->slots[0], struct btrfs_device_item); | 1877 | path->slots[0], struct btrfs_device_item); |
1876 | btrfs_set_device_pathlen(dev_item, namelen); | 1878 | btrfs_set_device_pathlen(dev_item, namelen); |
1877 | memcpy(dev_item + 1, name, namelen); | 1879 | memcpy(dev_item + 1, name, namelen); |
1880 | |||
1881 | device_id = btrfs_super_last_device_id(root->fs_info->disk_super) + 1; | ||
1882 | btrfs_set_super_last_device_id(root->fs_info->disk_super, device_id); | ||
1883 | btrfs_set_device_id(dev_item, device_id); | ||
1878 | mark_buffer_dirty(path->nodes[0]); | 1884 | mark_buffer_dirty(path->nodes[0]); |
1879 | 1885 | ||
1880 | ret = btrfs_insert_dev_radix(root, bdev, num_blocks, new_blocks); | 1886 | ret = btrfs_insert_dev_radix(root, bdev, device_id, num_blocks, |
1887 | new_blocks); | ||
1881 | 1888 | ||
1882 | if (!ret) { | 1889 | if (!ret) { |
1883 | btrfs_set_super_total_blocks(root->fs_info->disk_super, | 1890 | btrfs_set_super_total_blocks(root->fs_info->disk_super, |