From 7cd060deeac7828c8d0d7468d9c246d6c7ef77b2 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Wed, 15 Dec 2010 16:00:23 -0500 Subject: [PATCH] Fill missing devices so degraded filesystems can be read When a device is missing, the btrfs tools need to be able to read alternate copies from the remaining devices. This creates placeholder devices that always return -EIO so the tools can limp along. Signed-off-by: Chris Mason --- disk-io.c | 1 + volumes.c | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/disk-io.c b/disk-io.c index a6e1000d..fef3edab 100644 --- a/disk-io.c +++ b/disk-io.c @@ -204,6 +204,7 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, eb->dev_bytenr = multi->stripes[0].physical; kfree(multi); ret = read_extent_from_disk(eb); + if (ret == 0 && check_tree_block(root, eb) == 0 && csum_tree_block(root, eb, 1) == 0 && verify_parent_transid(eb->tree, eb, parent_transid) == 0) { diff --git a/volumes.c b/volumes.c index 76718550..b8f71673 100644 --- a/volumes.c +++ b/volumes.c @@ -1159,6 +1159,16 @@ int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset) return readonly; } +static struct btrfs_device *fill_missing_device(u64 devid) +{ + struct btrfs_device *device; + + device = kzalloc(sizeof(*device), GFP_NOFS); + device->devid = devid; + device->fd = -1; + return device; +} + static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, struct extent_buffer *leaf, struct btrfs_chunk *chunk) @@ -1209,8 +1219,9 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, map->stripes[i].dev = btrfs_find_device(root, devid, uuid, NULL); if (!map->stripes[i].dev) { - kfree(map); - return -EIO; + map->stripes[i].dev = fill_missing_device(devid); + printf("warning, device %llu is missing\n", + (unsigned long long)devid); } }