Skip to content

Commit

Permalink
Btrfs: Implement raid0 when multiple devices are present
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Mason <chris.mason@oracle.com>
  • Loading branch information
Chris Mason committed Sep 25, 2008
1 parent 8a4b83c commit 593060d
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 66 deletions.
3 changes: 3 additions & 0 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ struct btrfs_csum_item {
#define BTRFS_BLOCK_GROUP_DATA (1 << 0)
#define BTRFS_BLOCK_GROUP_SYSTEM (1 << 1)
#define BTRFS_BLOCK_GROUP_METADATA (1 << 2)
#define BTRFS_BLOCK_GROUP_RAID0 (1 << 3)


struct btrfs_block_group_item {
Expand Down Expand Up @@ -498,6 +499,8 @@ struct btrfs_fs_info {
u64 delalloc_bytes;
u64 last_alloc;
u64 last_data_alloc;
int extra_data_alloc_bits;
int extra_alloc_bits;
};

/*
Expand Down
2 changes: 2 additions & 0 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,8 @@ struct btrfs_root *open_ctree(struct super_block *sb,
fs_info->total_pinned = 0;
fs_info->last_alloc = 0;
fs_info->last_data_alloc = 0;
fs_info->extra_alloc_bits = 0;
fs_info->extra_data_alloc_bits = 0;

#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
INIT_WORK(&fs_info->trans_work, btrfs_transaction_cleaner, fs_info);
Expand Down
102 changes: 68 additions & 34 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(struct

static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits)
{
return (cache->flags & bits);
return (cache->flags & bits) == bits;
}

static int noinline find_search_start(struct btrfs_root *root,
Expand Down Expand Up @@ -1010,6 +1010,35 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,

}

static int update_space_info(struct btrfs_fs_info *info, u64 flags,
u64 total_bytes, u64 bytes_used,
struct btrfs_space_info **space_info)
{
struct btrfs_space_info *found;

found = __find_space_info(info, flags);
if (found) {
found->total_bytes += total_bytes;
found->bytes_used += bytes_used;
WARN_ON(found->total_bytes < found->bytes_used);
*space_info = found;
return 0;
}
found = kmalloc(sizeof(*found), GFP_NOFS);
if (!found)
return -ENOMEM;

list_add(&found->list, &info->space_info);
found->flags = flags;
found->total_bytes = total_bytes;
found->bytes_used = bytes_used;
found->bytes_pinned = 0;
found->full = 0;
*space_info = found;
return 0;
}


static int do_chunk_alloc(struct btrfs_trans_handle *trans,
struct btrfs_root *extent_root, u64 alloc_bytes,
u64 flags)
Expand All @@ -1021,6 +1050,11 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
int ret;

space_info = __find_space_info(extent_root->fs_info, flags);
if (!space_info) {
ret = update_space_info(extent_root->fs_info, flags,
0, 0, &space_info);
BUG_ON(ret);
}
BUG_ON(!space_info);

if (space_info->full)
Expand All @@ -1044,6 +1078,17 @@ printk("space info full %Lu\n", flags);
extent_root->fs_info->chunk_root->root_key.objectid,
start, num_bytes);
BUG_ON(ret);

if (flags & BTRFS_BLOCK_GROUP_RAID0) {
if (flags & BTRFS_BLOCK_GROUP_DATA) {
extent_root->fs_info->extra_data_alloc_bits =
BTRFS_BLOCK_GROUP_RAID0;
}
if (flags & BTRFS_BLOCK_GROUP_METADATA) {
extent_root->fs_info->extra_alloc_bits =
BTRFS_BLOCK_GROUP_RAID0;
}
}
return 0;
}

Expand Down Expand Up @@ -1655,24 +1700,31 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
struct btrfs_extent_ref *ref;
struct btrfs_path *path;
struct btrfs_key keys[2];
int extra_chunk_alloc_bits = 0;

if (data) {
data = BTRFS_BLOCK_GROUP_DATA;
data = BTRFS_BLOCK_GROUP_DATA | info->extra_data_alloc_bits;
} else if (root == root->fs_info->chunk_root) {
data = BTRFS_BLOCK_GROUP_SYSTEM;
} else {
data = BTRFS_BLOCK_GROUP_METADATA;
data = BTRFS_BLOCK_GROUP_METADATA | info->extra_alloc_bits;
}
if (btrfs_super_num_devices(&info->super_copy) > 1 &&
!(data & BTRFS_BLOCK_GROUP_SYSTEM))
extra_chunk_alloc_bits = BTRFS_BLOCK_GROUP_RAID0;

if (root->ref_cows) {
if (data != BTRFS_BLOCK_GROUP_METADATA) {
if (!(data & BTRFS_BLOCK_GROUP_METADATA)) {
ret = do_chunk_alloc(trans, root->fs_info->extent_root,
2 * 1024 * 1024,
BTRFS_BLOCK_GROUP_METADATA);
BTRFS_BLOCK_GROUP_METADATA |
info->extra_alloc_bits |
extra_chunk_alloc_bits);
BUG_ON(ret);
}
ret = do_chunk_alloc(trans, root->fs_info->extent_root,
num_bytes + 2 * 1024 * 1024, data);
num_bytes + 2 * 1024 * 1024, data |
extra_chunk_alloc_bits);
BUG_ON(ret);
}

Expand Down Expand Up @@ -2627,34 +2679,6 @@ int find_first_block_group(struct btrfs_root *root, struct btrfs_path *path,
return ret;
}

static int update_space_info(struct btrfs_fs_info *info, u64 flags,
u64 total_bytes, u64 bytes_used,
struct btrfs_space_info **space_info)
{
struct btrfs_space_info *found;

found = __find_space_info(info, flags);
if (found) {
found->total_bytes += total_bytes;
found->bytes_used += bytes_used;
WARN_ON(found->total_bytes < found->bytes_used);
*space_info = found;
return 0;
}
found = kmalloc(sizeof(*found), GFP_NOFS);
if (!found)
return -ENOMEM;

list_add(&found->list, &info->space_info);
found->flags = flags;
found->total_bytes = total_bytes;
found->bytes_used = bytes_used;
found->bytes_pinned = 0;
found->full = 0;
*space_info = found;
return 0;
}

int btrfs_read_block_groups(struct btrfs_root *root)
{
struct btrfs_path *path;
Expand Down Expand Up @@ -2712,6 +2736,16 @@ int btrfs_read_block_groups(struct btrfs_root *root)
} else if (cache->flags & BTRFS_BLOCK_GROUP_METADATA) {
bit = BLOCK_GROUP_METADATA;
}
if (cache->flags & BTRFS_BLOCK_GROUP_RAID0) {
if (cache->flags & BTRFS_BLOCK_GROUP_DATA) {
info->extra_data_alloc_bits =
BTRFS_BLOCK_GROUP_RAID0;
}
if (cache->flags & BTRFS_BLOCK_GROUP_METADATA) {
info->extra_alloc_bits =
BTRFS_BLOCK_GROUP_RAID0;
}
}

ret = update_space_info(info, cache->flags, found_key.offset,
btrfs_block_group_used(&cache->item),
Expand Down
2 changes: 0 additions & 2 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,6 @@ int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
map_length = length;
ret = btrfs_map_block(map_tree, logical, &physical, &map_length, &dev);
if (map_length < length + size) {
printk("merge bio hook logical %Lu bio len %Lu physical %Lu "
"len %Lu\n", logical, length, physical, map_length);
return 1;
}
return 0;
Expand Down
Loading

0 comments on commit 593060d

Please sign in to comment.