aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorYan Zheng <zheng.yan@oracle.com>2008-11-17 21:11:30 -0500
committerChris Mason <chris.mason@oracle.com>2008-11-17 21:11:30 -0500
commit2b82032c34ec40515d3c45c36cd1961f37977de8 (patch)
treefbdfe7b13dd51983dfca4aeb75983b37ee186ff9 /fs/btrfs/disk-io.c
parentc146afad2c7fea6a366d4945c1bab9b03880f526 (diff)
Btrfs: Seed device support
Seed device is a special btrfs with SEEDING super flag set and can only be mounted in read-only mode. Seed devices allow people to create new btrfs on top of it. The new FS contains the same contents as the seed device, but it can be mounted in read-write mode. This patch does the following: 1) split code in btrfs_alloc_chunk into two parts. The first part does makes the newly allocated chunk usable, but does not do any operation that modifies the chunk tree. The second part does the the chunk tree modifications. This division is for the bootstrap step of adding storage to the seed device. 2) Update device management code to handle seed device. The basic idea is: For an FS grown from seed devices, its seed devices are put into a list. Seed devices are opened on demand at mounting time. If any seed device is missing or has been changed, btrfs kernel module will refuse to mount the FS. 3) make btrfs_find_block_group not return NULL when all block groups are read-only. Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c56
1 files changed, 35 insertions, 21 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index c599f0ee997a..82833e5d84b6 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -345,6 +345,25 @@ out:
345 return 0; 345 return 0;
346} 346}
347 347
348static int check_tree_block_fsid(struct btrfs_root *root,
349 struct extent_buffer *eb)
350{
351 struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
352 u8 fsid[BTRFS_UUID_SIZE];
353 int ret = 1;
354
355 read_extent_buffer(eb, fsid, (unsigned long)btrfs_header_fsid(eb),
356 BTRFS_FSID_SIZE);
357 while (fs_devices) {
358 if (!memcmp(fsid, fs_devices->fsid, BTRFS_FSID_SIZE)) {
359 ret = 0;
360 break;
361 }
362 fs_devices = fs_devices->seed;
363 }
364 return ret;
365}
366
348int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, 367int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
349 struct extent_state *state) 368 struct extent_state *state)
350{ 369{
@@ -382,9 +401,7 @@ int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
382 ret = -EIO; 401 ret = -EIO;
383 goto err; 402 goto err;
384 } 403 }
385 if (memcmp_extent_buffer(eb, root->fs_info->fsid, 404 if (check_tree_block_fsid(root, eb)) {
386 (unsigned long)btrfs_header_fsid(eb),
387 BTRFS_FSID_SIZE)) {
388 printk("bad fsid on block %Lu\n", eb->start); 405 printk("bad fsid on block %Lu\n", eb->start);
389 ret = -EIO; 406 ret = -EIO;
390 goto err; 407 goto err;
@@ -1558,9 +1575,11 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1558 if (!btrfs_super_root(disk_super)) 1575 if (!btrfs_super_root(disk_super))
1559 goto fail_sb_buffer; 1576 goto fail_sb_buffer;
1560 1577
1561 err = btrfs_parse_options(tree_root, options); 1578 ret = btrfs_parse_options(tree_root, options);
1562 if (err) 1579 if (ret) {
1580 err = ret;
1563 goto fail_sb_buffer; 1581 goto fail_sb_buffer;
1582 }
1564 1583
1565 /* 1584 /*
1566 * we need to start all the end_io workers up front because the 1585 * we need to start all the end_io workers up front because the
@@ -1610,18 +1629,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1610 btrfs_start_workers(&fs_info->endio_write_workers, 1629 btrfs_start_workers(&fs_info->endio_write_workers,
1611 fs_info->thread_pool_size); 1630 fs_info->thread_pool_size);
1612 1631
1613 err = -EINVAL;
1614 if (btrfs_super_num_devices(disk_super) > fs_devices->open_devices) {
1615 printk("Btrfs: wanted %llu devices, but found %llu\n",
1616 (unsigned long long)btrfs_super_num_devices(disk_super),
1617 (unsigned long long)fs_devices->open_devices);
1618 if (btrfs_test_opt(tree_root, DEGRADED))
1619 printk("continuing in degraded mode\n");
1620 else {
1621 goto fail_sb_buffer;
1622 }
1623 }
1624
1625 fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super); 1632 fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super);
1626 fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages, 1633 fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages,
1627 4 * 1024 * 1024 / PAGE_CACHE_SIZE); 1634 4 * 1024 * 1024 / PAGE_CACHE_SIZE);
@@ -1672,7 +1679,10 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1672 mutex_lock(&fs_info->chunk_mutex); 1679 mutex_lock(&fs_info->chunk_mutex);
1673 ret = btrfs_read_chunk_tree(chunk_root); 1680 ret = btrfs_read_chunk_tree(chunk_root);
1674 mutex_unlock(&fs_info->chunk_mutex); 1681 mutex_unlock(&fs_info->chunk_mutex);
1675 BUG_ON(ret); 1682 if (ret) {
1683 printk("btrfs: failed to read chunk tree on %s\n", sb->s_id);
1684 goto fail_chunk_root;
1685 }
1676 1686
1677 btrfs_close_extra_devices(fs_devices); 1687 btrfs_close_extra_devices(fs_devices);
1678 1688
@@ -1684,7 +1694,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1684 btrfs_super_root(disk_super), 1694 btrfs_super_root(disk_super),
1685 blocksize, generation); 1695 blocksize, generation);
1686 if (!tree_root->node) 1696 if (!tree_root->node)
1687 goto fail_sb_buffer; 1697 goto fail_chunk_root;
1688 1698
1689 1699
1690 ret = find_and_setup_root(tree_root, fs_info, 1700 ret = find_and_setup_root(tree_root, fs_info,
@@ -1753,6 +1763,8 @@ fail_extent_root:
1753 free_extent_buffer(extent_root->node); 1763 free_extent_buffer(extent_root->node);
1754fail_tree_root: 1764fail_tree_root:
1755 free_extent_buffer(tree_root->node); 1765 free_extent_buffer(tree_root->node);
1766fail_chunk_root:
1767 free_extent_buffer(chunk_root->node);
1756fail_sys_array: 1768fail_sys_array:
1757fail_sb_buffer: 1769fail_sb_buffer:
1758 btrfs_stop_workers(&fs_info->fixup_workers); 1770 btrfs_stop_workers(&fs_info->fixup_workers);
@@ -1823,9 +1835,10 @@ int write_all_supers(struct btrfs_root *root)
1823 total_errors++; 1835 total_errors++;
1824 continue; 1836 continue;
1825 } 1837 }
1826 if (!dev->in_fs_metadata) 1838 if (!dev->in_fs_metadata || !dev->writeable)
1827 continue; 1839 continue;
1828 1840
1841 btrfs_set_stack_device_generation(dev_item, 0);
1829 btrfs_set_stack_device_type(dev_item, dev->type); 1842 btrfs_set_stack_device_type(dev_item, dev->type);
1830 btrfs_set_stack_device_id(dev_item, dev->devid); 1843 btrfs_set_stack_device_id(dev_item, dev->devid);
1831 btrfs_set_stack_device_total_bytes(dev_item, dev->total_bytes); 1844 btrfs_set_stack_device_total_bytes(dev_item, dev->total_bytes);
@@ -1834,6 +1847,7 @@ int write_all_supers(struct btrfs_root *root)
1834 btrfs_set_stack_device_io_width(dev_item, dev->io_width); 1847 btrfs_set_stack_device_io_width(dev_item, dev->io_width);
1835 btrfs_set_stack_device_sector_size(dev_item, dev->sector_size); 1848 btrfs_set_stack_device_sector_size(dev_item, dev->sector_size);
1836 memcpy(dev_item->uuid, dev->uuid, BTRFS_UUID_SIZE); 1849 memcpy(dev_item->uuid, dev->uuid, BTRFS_UUID_SIZE);
1850 memcpy(dev_item->fsid, dev->fs_devices->fsid, BTRFS_UUID_SIZE);
1837 flags = btrfs_super_flags(sb); 1851 flags = btrfs_super_flags(sb);
1838 btrfs_set_super_flags(sb, flags | BTRFS_HEADER_FLAG_WRITTEN); 1852 btrfs_set_super_flags(sb, flags | BTRFS_HEADER_FLAG_WRITTEN);
1839 1853
@@ -1881,7 +1895,7 @@ int write_all_supers(struct btrfs_root *root)
1881 dev = list_entry(cur, struct btrfs_device, dev_list); 1895 dev = list_entry(cur, struct btrfs_device, dev_list);
1882 if (!dev->bdev) 1896 if (!dev->bdev)
1883 continue; 1897 continue;
1884 if (!dev->in_fs_metadata) 1898 if (!dev->in_fs_metadata || !dev->writeable)
1885 continue; 1899 continue;
1886 1900
1887 BUG_ON(!dev->pending_io); 1901 BUG_ON(!dev->pending_io);