summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/fs/btrfs/btrfs.c49
-rw-r--r--core/fs/btrfs/btrfs.h2
2 files changed, 35 insertions, 16 deletions
diff --git a/core/fs/btrfs/btrfs.c b/core/fs/btrfs/btrfs.c
index 53e11050..58e1fe68 100644
--- a/core/fs/btrfs/btrfs.c
+++ b/core/fs/btrfs/btrfs.c
@@ -81,7 +81,8 @@ static int btrfs_comp_chunk_map(struct btrfs_chunk_map_item *m1,
}
/* insert a new chunk mapping item */
-static void insert_map(struct fs_info *fs, struct btrfs_chunk_map_item *item)
+static void insert_chunk_item(struct fs_info *fs,
+ struct btrfs_chunk_map_item *item)
{
struct btrfs_info * const bfs = fs->fs_info;
struct btrfs_chunk_map *chunk_map = &bfs->chunk_map;
@@ -113,6 +114,22 @@ static void insert_map(struct fs_info *fs, struct btrfs_chunk_map_item *item)
chunk_map->cur_length++;
}
+static inline void insert_map(struct fs_info *fs, struct btrfs_disk_key *key,
+ struct btrfs_chunk *chunk)
+{
+ struct btrfs_stripe *stripe = &chunk->stripe;
+ struct btrfs_stripe *stripe_end = stripe + chunk->num_stripes;
+ struct btrfs_chunk_map_item item;
+
+ item.logical = key->offset;
+ item.length = chunk->length;
+ for ( ; stripe < stripe_end; stripe++) {
+ item.devid = stripe->devid;
+ item.physical = stripe->offset;
+ insert_chunk_item(fs, &item);
+ }
+}
+
/*
* from sys_chunk_array or chunk_tree, we can convert a logical address to
* a physical address we can not support multi device case yet
@@ -330,7 +347,6 @@ static int next_slot(struct fs_info *fs, struct btrfs_disk_key *key,
static void btrfs_read_sys_chunk_array(struct fs_info *fs)
{
struct btrfs_info * const bfs = fs->fs_info;
- struct btrfs_chunk_map_item item;
struct btrfs_disk_key *key;
struct btrfs_chunk *chunk;
int cur;
@@ -342,12 +358,7 @@ static void btrfs_read_sys_chunk_array(struct fs_info *fs)
cur += sizeof(*key);
chunk = (struct btrfs_chunk *)(bfs->sb.sys_chunk_array + cur);
cur += btrfs_chunk_item_size(chunk->num_stripes);
- /* insert to mapping table, ignore multi stripes */
- item.logical = key->offset;
- item.length = chunk->length;
- item.devid = chunk->stripe.devid;
- item.physical = chunk->stripe.offset;/*ignore other stripes */
- insert_map(fs, &item);
+ insert_map(fs, key, chunk);
}
}
@@ -355,14 +366,18 @@ static void btrfs_read_sys_chunk_array(struct fs_info *fs)
static void btrfs_read_chunk_tree(struct fs_info *fs)
{
struct btrfs_info * const bfs = fs->fs_info;
+ struct btrfs_disk_key ignore_key;
struct btrfs_disk_key search_key;
struct btrfs_chunk *chunk;
- struct btrfs_chunk_map_item item;
struct btrfs_path path;
if (!(bfs->sb.flags & BTRFS_SUPER_FLAG_METADUMP)) {
if (bfs->sb.num_devices > 1)
printf("warning: only support single device btrfs\n");
+
+ ignore_key.objectid = BTRFS_DEV_ITEMS_OBJECTID;
+ ignore_key.type = BTRFS_DEV_ITEM_KEY;
+
/* read chunk from chunk_tree */
search_key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
search_key.type = BTRFS_CHUNK_ITEM_KEY;
@@ -371,16 +386,18 @@ static void btrfs_read_chunk_tree(struct fs_info *fs)
search_tree(fs, bfs->sb.chunk_root, &search_key, &path);
do {
do {
+ /* skip information about underlying block
+ * devices.
+ */
+ if (!btrfs_comp_keys_type(&ignore_key,
+ &path.item.key))
+ continue;
if (btrfs_comp_keys_type(&search_key,
- &path.item.key))
+ &path.item.key))
break;
+
chunk = (struct btrfs_chunk *)(path.data);
- /* insert to mapping table, ignore stripes */
- item.logical = path.item.key.offset;
- item.length = chunk->length;
- item.devid = chunk->stripe.devid;
- item.physical = chunk->stripe.offset;
- insert_map(fs, &item);
+ insert_map(fs, &path.item.key, chunk);
} while (!next_slot(fs, &search_key, &path));
if (btrfs_comp_keys_type(&search_key, &path.item.key))
break;
diff --git a/core/fs/btrfs/btrfs.h b/core/fs/btrfs/btrfs.h
index 8f519a9c..32e7c703 100644
--- a/core/fs/btrfs/btrfs.h
+++ b/core/fs/btrfs/btrfs.h
@@ -56,6 +56,8 @@ typedef u64 __le64;
#define BTRFS_MAX_LEVEL 8
#define BTRFS_MAX_CHUNK_ENTRIES 256
+#define BTRFS_DEV_ITEMS_OBJECTID 1ULL
+
#define BTRFS_FT_REG_FILE 1
#define BTRFS_FT_DIR 2
#define BTRFS_FT_SYMLINK 7