Skip to content

Commit

Permalink
Merge branch 'for-chris' of git://github.com/idryomov/btrfs-unstable …
Browse files Browse the repository at this point in the history
…into for-linus
  • Loading branch information
Chris Mason committed Mar 29, 2012
2 parents 1d4284b + 213e64d commit 1c691b3
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 139 deletions.
7 changes: 1 addition & 6 deletions fs/btrfs/backref.c
Original file line number Diff line number Diff line change
Expand Up @@ -1342,12 +1342,6 @@ int paths_from_inode(u64 inum, struct inode_fs_paths *ipath)
inode_to_path, ipath);
}

/*
* allocates space to return multiple file system paths for an inode.
* total_bytes to allocate are passed, note that space usable for actual path
* information will be total_bytes - sizeof(struct inode_fs_paths).
* the returned pointer must be freed with free_ipath() in the end.
*/
struct btrfs_data_container *init_data_container(u32 total_bytes)
{
struct btrfs_data_container *data;
Expand Down Expand Up @@ -1403,5 +1397,6 @@ struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root,

void free_ipath(struct inode_fs_paths *ipath)
{
kfree(ipath->fspath);
kfree(ipath);
}
33 changes: 15 additions & 18 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,21 @@ struct btrfs_csum_item {
*/
#define BTRFS_AVAIL_ALLOC_BIT_SINGLE (1ULL << 48)

#define BTRFS_EXTENDED_PROFILE_MASK (BTRFS_BLOCK_GROUP_PROFILE_MASK | \
BTRFS_AVAIL_ALLOC_BIT_SINGLE)

static inline u64 chunk_to_extended(u64 flags)
{
if ((flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0)
flags |= BTRFS_AVAIL_ALLOC_BIT_SINGLE;

return flags;
}
static inline u64 extended_to_chunk(u64 flags)
{
return flags & ~BTRFS_AVAIL_ALLOC_BIT_SINGLE;
}

struct btrfs_block_group_item {
__le64 used;
__le64 chunk_objectid;
Expand Down Expand Up @@ -2723,24 +2738,6 @@ static inline void free_fs_info(struct btrfs_fs_info *fs_info)
kfree(fs_info->super_for_commit);
kfree(fs_info);
}
/**
* profile_is_valid - tests whether a given profile is valid and reduced
* @flags: profile to validate
* @extended: if true @flags is treated as an extended profile
*/
static inline int profile_is_valid(u64 flags, int extended)
{
u64 mask = ~BTRFS_BLOCK_GROUP_PROFILE_MASK;

flags &= ~BTRFS_BLOCK_GROUP_TYPE_MASK;
if (extended)
mask &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE;

if (flags & mask)
return 0;
/* true if zero or exactly one bit set */
return (flags & (~flags + 1)) == flags;
}

/* root-item.c */
int btrfs_find_root_ref(struct btrfs_root *tree_root,
Expand Down
163 changes: 87 additions & 76 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -3138,11 +3138,8 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,

static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
{
u64 extra_flags = flags & BTRFS_BLOCK_GROUP_PROFILE_MASK;

/* chunk -> extended profile */
if (extra_flags == 0)
extra_flags = BTRFS_AVAIL_ALLOC_BIT_SINGLE;
u64 extra_flags = chunk_to_extended(flags) &
BTRFS_EXTENDED_PROFILE_MASK;

if (flags & BTRFS_BLOCK_GROUP_DATA)
fs_info->avail_data_alloc_bits |= extra_flags;
Expand All @@ -3152,6 +3149,35 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
fs_info->avail_system_alloc_bits |= extra_flags;
}

/*
* returns target flags in extended format or 0 if restripe for this
* chunk_type is not in progress
*/
static u64 get_restripe_target(struct btrfs_fs_info *fs_info, u64 flags)
{
struct btrfs_balance_control *bctl = fs_info->balance_ctl;
u64 target = 0;

BUG_ON(!mutex_is_locked(&fs_info->volume_mutex) &&
!spin_is_locked(&fs_info->balance_lock));

if (!bctl)
return 0;

if (flags & BTRFS_BLOCK_GROUP_DATA &&
bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) {
target = BTRFS_BLOCK_GROUP_DATA | bctl->data.target;
} else if (flags & BTRFS_BLOCK_GROUP_SYSTEM &&
bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
target = BTRFS_BLOCK_GROUP_SYSTEM | bctl->sys.target;
} else if (flags & BTRFS_BLOCK_GROUP_METADATA &&
bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) {
target = BTRFS_BLOCK_GROUP_METADATA | bctl->meta.target;
}

return target;
}

/*
* @flags: available profiles in extended format (see ctree.h)
*
Expand All @@ -3168,31 +3194,19 @@ u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
*/
u64 num_devices = root->fs_info->fs_devices->rw_devices +
root->fs_info->fs_devices->missing_devices;
u64 target;

/* pick restriper's target profile if it's available */
/*
* see if restripe for this chunk_type is in progress, if so
* try to reduce to the target profile
*/
spin_lock(&root->fs_info->balance_lock);
if (root->fs_info->balance_ctl) {
struct btrfs_balance_control *bctl = root->fs_info->balance_ctl;
u64 tgt = 0;

if ((flags & BTRFS_BLOCK_GROUP_DATA) &&
(bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
(flags & bctl->data.target)) {
tgt = BTRFS_BLOCK_GROUP_DATA | bctl->data.target;
} else if ((flags & BTRFS_BLOCK_GROUP_SYSTEM) &&
(bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
(flags & bctl->sys.target)) {
tgt = BTRFS_BLOCK_GROUP_SYSTEM | bctl->sys.target;
} else if ((flags & BTRFS_BLOCK_GROUP_METADATA) &&
(bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
(flags & bctl->meta.target)) {
tgt = BTRFS_BLOCK_GROUP_METADATA | bctl->meta.target;
}

if (tgt) {
target = get_restripe_target(root->fs_info, flags);
if (target) {
/* pick target profile only if it's already available */
if ((flags & target) & BTRFS_EXTENDED_PROFILE_MASK) {
spin_unlock(&root->fs_info->balance_lock);
flags = tgt;
goto out;
return extended_to_chunk(target);
}
}
spin_unlock(&root->fs_info->balance_lock);
Expand Down Expand Up @@ -3220,10 +3234,7 @@ u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
flags &= ~BTRFS_BLOCK_GROUP_RAID0;
}

out:
/* extended -> chunk profile */
flags &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE;
return flags;
return extended_to_chunk(flags);
}

static u64 get_alloc_profile(struct btrfs_root *root, u64 flags)
Expand Down Expand Up @@ -3445,8 +3456,6 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
int wait_for_alloc = 0;
int ret = 0;

BUG_ON(!profile_is_valid(flags, 0));

space_info = __find_space_info(extent_root->fs_info, flags);
if (!space_info) {
ret = update_space_info(extent_root->fs_info, flags,
Expand Down Expand Up @@ -5300,22 +5309,29 @@ wait_block_group_cache_done(struct btrfs_block_group_cache *cache)
return 0;
}

static int get_block_group_index(struct btrfs_block_group_cache *cache)
static int __get_block_group_index(u64 flags)
{
int index;
if (cache->flags & BTRFS_BLOCK_GROUP_RAID10)

if (flags & BTRFS_BLOCK_GROUP_RAID10)
index = 0;
else if (cache->flags & BTRFS_BLOCK_GROUP_RAID1)
else if (flags & BTRFS_BLOCK_GROUP_RAID1)
index = 1;
else if (cache->flags & BTRFS_BLOCK_GROUP_DUP)
else if (flags & BTRFS_BLOCK_GROUP_DUP)
index = 2;
else if (cache->flags & BTRFS_BLOCK_GROUP_RAID0)
else if (flags & BTRFS_BLOCK_GROUP_RAID0)
index = 3;
else
index = 4;

return index;
}

static int get_block_group_index(struct btrfs_block_group_cache *cache)
{
return __get_block_group_index(cache->flags);
}

enum btrfs_loop_type {
LOOP_CACHING_NOWAIT = 0,
LOOP_CACHING_WAIT = 1,
Expand Down Expand Up @@ -7011,31 +7027,15 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
{
u64 num_devices;
u64 stripped = BTRFS_BLOCK_GROUP_RAID0 |
BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10;

if (root->fs_info->balance_ctl) {
struct btrfs_balance_control *bctl = root->fs_info->balance_ctl;
u64 tgt = 0;

/* pick restriper's target profile and return */
if (flags & BTRFS_BLOCK_GROUP_DATA &&
bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) {
tgt = BTRFS_BLOCK_GROUP_DATA | bctl->data.target;
} else if (flags & BTRFS_BLOCK_GROUP_SYSTEM &&
bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
tgt = BTRFS_BLOCK_GROUP_SYSTEM | bctl->sys.target;
} else if (flags & BTRFS_BLOCK_GROUP_METADATA &&
bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) {
tgt = BTRFS_BLOCK_GROUP_METADATA | bctl->meta.target;
}
u64 stripped;

if (tgt) {
/* extended -> chunk profile */
tgt &= ~BTRFS_AVAIL_ALLOC_BIT_SINGLE;
return tgt;
}
}
/*
* if restripe for this chunk_type is on pick target profile and
* return, otherwise do the usual balance
*/
stripped = get_restripe_target(root->fs_info, flags);
if (stripped)
return extended_to_chunk(stripped);

/*
* we add in the count of missing devices because we want
Expand All @@ -7045,6 +7045,9 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
num_devices = root->fs_info->fs_devices->rw_devices +
root->fs_info->fs_devices->missing_devices;

stripped = BTRFS_BLOCK_GROUP_RAID0 |
BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10;

if (num_devices == 1) {
stripped |= BTRFS_BLOCK_GROUP_DUP;
stripped = flags & ~stripped;
Expand All @@ -7057,7 +7060,6 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
if (flags & (BTRFS_BLOCK_GROUP_RAID1 |
BTRFS_BLOCK_GROUP_RAID10))
return stripped | BTRFS_BLOCK_GROUP_DUP;
return flags;
} else {
/* they already had raid on here, just return */
if (flags & stripped)
Expand All @@ -7070,9 +7072,9 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
if (flags & BTRFS_BLOCK_GROUP_DUP)
return stripped | BTRFS_BLOCK_GROUP_RAID1;

/* turn single device chunks into raid0 */
return stripped | BTRFS_BLOCK_GROUP_RAID0;
/* this is drive concat, leave it alone */
}

return flags;
}

Expand Down Expand Up @@ -7253,6 +7255,7 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
u64 min_free;
u64 dev_min = 1;
u64 dev_nr = 0;
u64 target;
int index;
int full = 0;
int ret = 0;
Expand Down Expand Up @@ -7293,13 +7296,11 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
/*
* ok we don't have enough space, but maybe we have free space on our
* devices to allocate new chunks for relocation, so loop through our
* alloc devices and guess if we have enough space. However, if we
* were marked as full, then we know there aren't enough chunks, and we
* can just return.
* alloc devices and guess if we have enough space. if this block
* group is going to be restriped, run checks against the target
* profile instead of the current one.
*/
ret = -1;
if (full)
goto out;

/*
* index:
Expand All @@ -7309,7 +7310,20 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
* 3: raid0
* 4: single
*/
index = get_block_group_index(block_group);
target = get_restripe_target(root->fs_info, block_group->flags);
if (target) {
index = __get_block_group_index(extended_to_chunk(target));
} else {
/*
* this is just a balance, so if we were marked as full
* we know there is no space for a new chunk
*/
if (full)
goto out;

index = get_block_group_index(block_group);
}

if (index == 0) {
dev_min = 4;
/* Divide by 2 */
Expand Down Expand Up @@ -7720,11 +7734,8 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,

static void clear_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
{
u64 extra_flags = flags & BTRFS_BLOCK_GROUP_PROFILE_MASK;

/* chunk -> extended profile */
if (extra_flags == 0)
extra_flags = BTRFS_AVAIL_ALLOC_BIT_SINGLE;
u64 extra_flags = chunk_to_extended(flags) &
BTRFS_EXTENDED_PROFILE_MASK;

if (flags & BTRFS_BLOCK_GROUP_DATA)
fs_info->avail_data_alloc_bits &= ~extra_flags;
Expand Down
Loading

0 comments on commit 1c691b3

Please sign in to comment.