aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorYan Zheng <zheng.yan@oracle.com>2008-12-08 16:46:26 -0500
committerChris Mason <chris.mason@oracle.com>2008-12-08 16:46:26 -0500
commita512bbf855ff0af474257475f2e6da7acd854f52 (patch)
tree1b2cfcf4152e09f32a6cb0bcbd798d5dab2f5490 /fs/btrfs/volumes.c
parentd20f7043fa65659136c1a7c3c456eeeb5c6f431f (diff)
Btrfs: superblock duplication
This patch implements superblock duplication. Superblocks are stored at offset 16K, 64M and 256G on every devices. Spaces used by superblocks are preserved by the allocator, which uses a reverse mapping function to find the logical addresses that correspond to superblocks. Thank you, Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c107
1 files changed, 87 insertions, 20 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 2049d179ccd5..a79b3cc09e94 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -423,15 +423,11 @@ int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
423 } 423 }
424 set_blocksize(bdev, 4096); 424 set_blocksize(bdev, 4096);
425 425
426 bh = __bread(bdev, BTRFS_SUPER_INFO_OFFSET / 4096, 4096); 426 bh = btrfs_read_dev_super(bdev);
427 if (!bh) 427 if (!bh)
428 goto error_close; 428 goto error_close;
429 429
430 disk_super = (struct btrfs_super_block *)bh->b_data; 430 disk_super = (struct btrfs_super_block *)bh->b_data;
431 if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC,
432 sizeof(disk_super->magic)))
433 goto error_brelse;
434
435 devid = le64_to_cpu(disk_super->dev_item.devid); 431 devid = le64_to_cpu(disk_super->dev_item.devid);
436 if (devid != device->devid) 432 if (devid != device->devid)
437 goto error_brelse; 433 goto error_brelse;
@@ -529,17 +525,12 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
529 ret = set_blocksize(bdev, 4096); 525 ret = set_blocksize(bdev, 4096);
530 if (ret) 526 if (ret)
531 goto error_close; 527 goto error_close;
532 bh = __bread(bdev, BTRFS_SUPER_INFO_OFFSET / 4096, 4096); 528 bh = btrfs_read_dev_super(bdev);
533 if (!bh) { 529 if (!bh) {
534 ret = -EIO; 530 ret = -EIO;
535 goto error_close; 531 goto error_close;
536 } 532 }
537 disk_super = (struct btrfs_super_block *)bh->b_data; 533 disk_super = (struct btrfs_super_block *)bh->b_data;
538 if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC,
539 sizeof(disk_super->magic))) {
540 ret = -EINVAL;
541 goto error_brelse;
542 }
543 devid = le64_to_cpu(disk_super->dev_item.devid); 534 devid = le64_to_cpu(disk_super->dev_item.devid);
544 transid = btrfs_super_generation(disk_super); 535 transid = btrfs_super_generation(disk_super);
545 if (disk_super->label[0]) 536 if (disk_super->label[0])
@@ -553,7 +544,6 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
553 printk("devid %Lu transid %Lu %s\n", devid, transid, path); 544 printk("devid %Lu transid %Lu %s\n", devid, transid, path);
554 ret = device_list_add(path, disk_super, devid, fs_devices_ret); 545 ret = device_list_add(path, disk_super, devid, fs_devices_ret);
555 546
556error_brelse:
557 brelse(bh); 547 brelse(bh);
558error_close: 548error_close:
559 close_bdev_exclusive(bdev, flags); 549 close_bdev_exclusive(bdev, flags);
@@ -1016,17 +1006,12 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
1016 } 1006 }
1017 1007
1018 set_blocksize(bdev, 4096); 1008 set_blocksize(bdev, 4096);
1019 bh = __bread(bdev, BTRFS_SUPER_INFO_OFFSET / 4096, 4096); 1009 bh = btrfs_read_dev_super(bdev);
1020 if (!bh) { 1010 if (!bh) {
1021 ret = -EIO; 1011 ret = -EIO;
1022 goto error_close; 1012 goto error_close;
1023 } 1013 }
1024 disk_super = (struct btrfs_super_block *)bh->b_data; 1014 disk_super = (struct btrfs_super_block *)bh->b_data;
1025 if (strncmp((char *)(&disk_super->magic), BTRFS_MAGIC,
1026 sizeof(disk_super->magic))) {
1027 ret = -ENOENT;
1028 goto error_brelse;
1029 }
1030 devid = le64_to_cpu(disk_super->dev_item.devid); 1015 devid = le64_to_cpu(disk_super->dev_item.devid);
1031 dev_uuid = disk_super->dev_item.uuid; 1016 dev_uuid = disk_super->dev_item.uuid;
1032 device = btrfs_find_device(root, devid, dev_uuid, 1017 device = btrfs_find_device(root, devid, dev_uuid,
@@ -2563,6 +2548,88 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
2563 mirror_num, NULL); 2548 mirror_num, NULL);
2564} 2549}
2565 2550
2551int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
2552 u64 chunk_start, u64 physical, u64 devid,
2553 u64 **logical, int *naddrs, int *stripe_len)
2554{
2555 struct extent_map_tree *em_tree = &map_tree->map_tree;
2556 struct extent_map *em;
2557 struct map_lookup *map;
2558 u64 *buf;
2559 u64 bytenr;
2560 u64 length;
2561 u64 stripe_nr;
2562 int i, j, nr = 0;
2563
2564 spin_lock(&em_tree->lock);
2565 em = lookup_extent_mapping(em_tree, chunk_start, 1);
2566 spin_unlock(&em_tree->lock);
2567
2568 BUG_ON(!em || em->start != chunk_start);
2569 map = (struct map_lookup *)em->bdev;
2570
2571 length = em->len;
2572 if (map->type & BTRFS_BLOCK_GROUP_RAID10)
2573 do_div(length, map->num_stripes / map->sub_stripes);
2574 else if (map->type & BTRFS_BLOCK_GROUP_RAID0)
2575 do_div(length, map->num_stripes);
2576
2577 buf = kzalloc(sizeof(u64) * map->num_stripes, GFP_NOFS);
2578 BUG_ON(!buf);
2579
2580 for (i = 0; i < map->num_stripes; i++) {
2581 if (devid && map->stripes[i].dev->devid != devid)
2582 continue;
2583 if (map->stripes[i].physical > physical ||
2584 map->stripes[i].physical + length <= physical)
2585 continue;
2586
2587 stripe_nr = physical - map->stripes[i].physical;
2588 do_div(stripe_nr, map->stripe_len);
2589
2590 if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
2591 stripe_nr = stripe_nr * map->num_stripes + i;
2592 do_div(stripe_nr, map->sub_stripes);
2593 } else if (map->type & BTRFS_BLOCK_GROUP_RAID0) {
2594 stripe_nr = stripe_nr * map->num_stripes + i;
2595 }
2596 bytenr = chunk_start + stripe_nr * map->stripe_len;
2597 for (j = 0; j < nr; j++) {
2598 if (buf[j] == bytenr)
2599 break;
2600 }
2601 if (j == nr)
2602 buf[nr++] = bytenr;
2603 }
2604
2605 for (i = 0; i > nr; i++) {
2606 struct btrfs_multi_bio *multi;
2607 struct btrfs_bio_stripe *stripe;
2608 int ret;
2609
2610 length = 1;
2611 ret = btrfs_map_block(map_tree, WRITE, buf[i],
2612 &length, &multi, 0);
2613 BUG_ON(ret);
2614
2615 stripe = multi->stripes;
2616 for (j = 0; j < multi->num_stripes; j++) {
2617 if (stripe->physical >= physical &&
2618 physical < stripe->physical + length)
2619 break;
2620 }
2621 BUG_ON(j >= multi->num_stripes);
2622 kfree(multi);
2623 }
2624
2625 *logical = buf;
2626 *naddrs = nr;
2627 *stripe_len = map->stripe_len;
2628
2629 free_extent_map(em);
2630 return 0;
2631}
2632
2566int btrfs_unplug_page(struct btrfs_mapping_tree *map_tree, 2633int btrfs_unplug_page(struct btrfs_mapping_tree *map_tree,
2567 u64 logical, struct page *page) 2634 u64 logical, struct page *page)
2568{ 2635{
@@ -3003,7 +3070,7 @@ int btrfs_read_super_device(struct btrfs_root *root, struct extent_buffer *buf)
3003 return read_one_dev(root, buf, dev_item); 3070 return read_one_dev(root, buf, dev_item);
3004} 3071}
3005 3072
3006int btrfs_read_sys_array(struct btrfs_root *root) 3073int btrfs_read_sys_array(struct btrfs_root *root, u64 sb_bytenr)
3007{ 3074{
3008 struct btrfs_super_block *super_copy = &root->fs_info->super_copy; 3075 struct btrfs_super_block *super_copy = &root->fs_info->super_copy;
3009 struct extent_buffer *sb; 3076 struct extent_buffer *sb;
@@ -3018,7 +3085,7 @@ int btrfs_read_sys_array(struct btrfs_root *root)
3018 u32 cur; 3085 u32 cur;
3019 struct btrfs_key key; 3086 struct btrfs_key key;
3020 3087
3021 sb = btrfs_find_create_tree_block(root, BTRFS_SUPER_INFO_OFFSET, 3088 sb = btrfs_find_create_tree_block(root, sb_bytenr,
3022 BTRFS_SUPER_INFO_SIZE); 3089 BTRFS_SUPER_INFO_SIZE);
3023 if (!sb) 3090 if (!sb)
3024 return -ENOMEM; 3091 return -ENOMEM;