diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-05-13 13:46:40 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:03 -0400 |
commit | dfe25020689bb2d318782d2c9c7141203583fc70 (patch) | |
tree | e106059546d7755af0d3b86bf47c113ca8927d7d /fs/btrfs/disk-io.c | |
parent | 1259ab75c62462b8ffad90067b5e1f6312786a18 (diff) |
Btrfs: Add mount -o degraded to allow mounts to continue with missing devices
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 49 |
1 files changed, 29 insertions, 20 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 574b1245964e..38b0d9ecda6a 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -614,21 +614,6 @@ int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize, | |||
614 | return ret; | 614 | return ret; |
615 | } | 615 | } |
616 | 616 | ||
617 | static int close_all_devices(struct btrfs_fs_info *fs_info) | ||
618 | { | ||
619 | struct list_head *list; | ||
620 | struct list_head *next; | ||
621 | struct btrfs_device *device; | ||
622 | |||
623 | list = &fs_info->fs_devices->devices; | ||
624 | list_for_each(next, list) { | ||
625 | device = list_entry(next, struct btrfs_device, dev_list); | ||
626 | close_bdev_excl(device->bdev); | ||
627 | device->bdev = NULL; | ||
628 | } | ||
629 | return 0; | ||
630 | } | ||
631 | |||
632 | struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, | 617 | struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, |
633 | u64 bytenr, u32 blocksize) | 618 | u64 bytenr, u32 blocksize) |
634 | { | 619 | { |
@@ -927,6 +912,8 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits) | |||
927 | 912 | ||
928 | list_for_each(cur, &info->fs_devices->devices) { | 913 | list_for_each(cur, &info->fs_devices->devices) { |
929 | device = list_entry(cur, struct btrfs_device, dev_list); | 914 | device = list_entry(cur, struct btrfs_device, dev_list); |
915 | if (!device->bdev) | ||
916 | continue; | ||
930 | bdi = blk_get_backing_dev_info(device->bdev); | 917 | bdi = blk_get_backing_dev_info(device->bdev); |
931 | if (bdi && bdi_congested(bdi, bdi_bits)) { | 918 | if (bdi && bdi_congested(bdi, bdi_bits)) { |
932 | ret = 1; | 919 | ret = 1; |
@@ -1140,7 +1127,8 @@ static void btrfs_async_submit_work(struct work_struct *work) | |||
1140 | } | 1127 | } |
1141 | 1128 | ||
1142 | struct btrfs_root *open_ctree(struct super_block *sb, | 1129 | struct btrfs_root *open_ctree(struct super_block *sb, |
1143 | struct btrfs_fs_devices *fs_devices) | 1130 | struct btrfs_fs_devices *fs_devices, |
1131 | char *options) | ||
1144 | { | 1132 | { |
1145 | u32 sectorsize; | 1133 | u32 sectorsize; |
1146 | u32 nodesize; | 1134 | u32 nodesize; |
@@ -1276,12 +1264,19 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1276 | if (!btrfs_super_root(disk_super)) | 1264 | if (!btrfs_super_root(disk_super)) |
1277 | goto fail_sb_buffer; | 1265 | goto fail_sb_buffer; |
1278 | 1266 | ||
1279 | if (btrfs_super_num_devices(disk_super) != fs_devices->num_devices) { | 1267 | btrfs_parse_options(options, tree_root, NULL); |
1268 | |||
1269 | if (btrfs_super_num_devices(disk_super) > fs_devices->num_devices) { | ||
1280 | printk("Btrfs: wanted %llu devices, but found %llu\n", | 1270 | printk("Btrfs: wanted %llu devices, but found %llu\n", |
1281 | (unsigned long long)btrfs_super_num_devices(disk_super), | 1271 | (unsigned long long)btrfs_super_num_devices(disk_super), |
1282 | (unsigned long long)fs_devices->num_devices); | 1272 | (unsigned long long)fs_devices->num_devices); |
1283 | goto fail_sb_buffer; | 1273 | if (btrfs_test_opt(tree_root, DEGRADED)) |
1274 | printk("continuing in degraded mode\n"); | ||
1275 | else { | ||
1276 | goto fail_sb_buffer; | ||
1277 | } | ||
1284 | } | 1278 | } |
1279 | |||
1285 | fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super); | 1280 | fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super); |
1286 | 1281 | ||
1287 | nodesize = btrfs_super_nodesize(disk_super); | 1282 | nodesize = btrfs_super_nodesize(disk_super); |
@@ -1329,6 +1324,8 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1329 | ret = btrfs_read_chunk_tree(chunk_root); | 1324 | ret = btrfs_read_chunk_tree(chunk_root); |
1330 | BUG_ON(ret); | 1325 | BUG_ON(ret); |
1331 | 1326 | ||
1327 | btrfs_close_extra_devices(fs_devices); | ||
1328 | |||
1332 | blocksize = btrfs_level_size(tree_root, | 1329 | blocksize = btrfs_level_size(tree_root, |
1333 | btrfs_super_root_level(disk_super)); | 1330 | btrfs_super_root_level(disk_super)); |
1334 | 1331 | ||
@@ -1374,7 +1371,7 @@ fail_sb_buffer: | |||
1374 | fail_iput: | 1371 | fail_iput: |
1375 | iput(fs_info->btree_inode); | 1372 | iput(fs_info->btree_inode); |
1376 | fail: | 1373 | fail: |
1377 | close_all_devices(fs_info); | 1374 | btrfs_close_devices(fs_info->fs_devices); |
1378 | btrfs_mapping_tree_free(&fs_info->mapping_tree); | 1375 | btrfs_mapping_tree_free(&fs_info->mapping_tree); |
1379 | 1376 | ||
1380 | kfree(extent_root); | 1377 | kfree(extent_root); |
@@ -1429,6 +1426,13 @@ int write_all_supers(struct btrfs_root *root) | |||
1429 | dev_item = &sb->dev_item; | 1426 | dev_item = &sb->dev_item; |
1430 | list_for_each(cur, head) { | 1427 | list_for_each(cur, head) { |
1431 | dev = list_entry(cur, struct btrfs_device, dev_list); | 1428 | dev = list_entry(cur, struct btrfs_device, dev_list); |
1429 | if (!dev->bdev) { | ||
1430 | total_errors++; | ||
1431 | continue; | ||
1432 | } | ||
1433 | if (!dev->in_fs_metadata) | ||
1434 | continue; | ||
1435 | |||
1432 | btrfs_set_stack_device_type(dev_item, dev->type); | 1436 | btrfs_set_stack_device_type(dev_item, dev->type); |
1433 | btrfs_set_stack_device_id(dev_item, dev->devid); | 1437 | btrfs_set_stack_device_id(dev_item, dev->devid); |
1434 | btrfs_set_stack_device_total_bytes(dev_item, dev->total_bytes); | 1438 | btrfs_set_stack_device_total_bytes(dev_item, dev->total_bytes); |
@@ -1482,6 +1486,11 @@ int write_all_supers(struct btrfs_root *root) | |||
1482 | 1486 | ||
1483 | list_for_each(cur, head) { | 1487 | list_for_each(cur, head) { |
1484 | dev = list_entry(cur, struct btrfs_device, dev_list); | 1488 | dev = list_entry(cur, struct btrfs_device, dev_list); |
1489 | if (!dev->bdev) | ||
1490 | continue; | ||
1491 | if (!dev->in_fs_metadata) | ||
1492 | continue; | ||
1493 | |||
1485 | BUG_ON(!dev->pending_io); | 1494 | BUG_ON(!dev->pending_io); |
1486 | bh = dev->pending_io; | 1495 | bh = dev->pending_io; |
1487 | wait_on_buffer(bh); | 1496 | wait_on_buffer(bh); |
@@ -1631,7 +1640,7 @@ int close_ctree(struct btrfs_root *root) | |||
1631 | kfree(hasher); | 1640 | kfree(hasher); |
1632 | } | 1641 | } |
1633 | #endif | 1642 | #endif |
1634 | close_all_devices(fs_info); | 1643 | btrfs_close_devices(fs_info->fs_devices); |
1635 | btrfs_mapping_tree_free(&fs_info->mapping_tree); | 1644 | btrfs_mapping_tree_free(&fs_info->mapping_tree); |
1636 | 1645 | ||
1637 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) | 1646 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) |