summaryrefslogtreecommitdiff
path: root/volumes.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2010-12-15 16:00:23 -0500
committerChris Mason <chris.mason@oracle.com>2011-04-22 14:52:40 -0400
commit7cd060deeac7828c8d0d7468d9c246d6c7ef77b2 (patch)
tree2ceb9339f21074be3cfacf840bc36496695dc284 /volumes.c
parent375714fe1181d1cca400dcfbcdb4fc29c6dfa5d6 (diff)
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 <chris.mason@oracle.com>
Diffstat (limited to 'volumes.c')
-rw-r--r--volumes.c15
1 files changed, 13 insertions, 2 deletions
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);
}
}