aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorIlya Dryomov <idryomov@gmail.com>2012-01-16 15:04:47 -0500
committerIlya Dryomov <idryomov@gmail.com>2012-01-16 15:04:47 -0500
commit10ea00f55a07f8f9536d9112b95108a86f700bab (patch)
tree83887f41d8a876d919f74f83cda26eb18b10deca /fs/btrfs/extent-tree.c
parenta46d11a8b06dd0431a3888fbc4856ea13a8e634f (diff)
Btrfs: make avail_*_alloc_bits fields dynamic
Currently when new chunks are created respective avail_alloc_bits field is updated to reflect profiles of all chunks present in the system. However when chunks are removed profile bits are never cleared. This patch clears profile bit of respective avail_alloc_bits field when the last chunk with that profile is removed. Restriper needs this to properly operate when "downgrading". Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 15a22949da17..946b0671c5d9 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -7469,6 +7469,22 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
7469 return 0; 7469 return 0;
7470} 7470}
7471 7471
7472static void clear_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
7473{
7474 u64 extra_flags = flags & BTRFS_BLOCK_GROUP_PROFILE_MASK;
7475
7476 /* chunk -> extended profile */
7477 if (extra_flags == 0)
7478 extra_flags = BTRFS_AVAIL_ALLOC_BIT_SINGLE;
7479
7480 if (flags & BTRFS_BLOCK_GROUP_DATA)
7481 fs_info->avail_data_alloc_bits &= ~extra_flags;
7482 if (flags & BTRFS_BLOCK_GROUP_METADATA)
7483 fs_info->avail_metadata_alloc_bits &= ~extra_flags;
7484 if (flags & BTRFS_BLOCK_GROUP_SYSTEM)
7485 fs_info->avail_system_alloc_bits &= ~extra_flags;
7486}
7487
7472int btrfs_remove_block_group(struct btrfs_trans_handle *trans, 7488int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
7473 struct btrfs_root *root, u64 group_start) 7489 struct btrfs_root *root, u64 group_start)
7474{ 7490{
@@ -7479,6 +7495,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
7479 struct btrfs_key key; 7495 struct btrfs_key key;
7480 struct inode *inode; 7496 struct inode *inode;
7481 int ret; 7497 int ret;
7498 int index;
7482 int factor; 7499 int factor;
7483 7500
7484 root = root->fs_info->extent_root; 7501 root = root->fs_info->extent_root;
@@ -7494,6 +7511,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
7494 free_excluded_extents(root, block_group); 7511 free_excluded_extents(root, block_group);
7495 7512
7496 memcpy(&key, &block_group->key, sizeof(key)); 7513 memcpy(&key, &block_group->key, sizeof(key));
7514 index = get_block_group_index(block_group);
7497 if (block_group->flags & (BTRFS_BLOCK_GROUP_DUP | 7515 if (block_group->flags & (BTRFS_BLOCK_GROUP_DUP |
7498 BTRFS_BLOCK_GROUP_RAID1 | 7516 BTRFS_BLOCK_GROUP_RAID1 |
7499 BTRFS_BLOCK_GROUP_RAID10)) 7517 BTRFS_BLOCK_GROUP_RAID10))
@@ -7568,6 +7586,8 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
7568 * are still on the list after taking the semaphore 7586 * are still on the list after taking the semaphore
7569 */ 7587 */
7570 list_del_init(&block_group->list); 7588 list_del_init(&block_group->list);
7589 if (list_empty(&block_group->space_info->block_groups[index]))
7590 clear_avail_alloc_bits(root->fs_info, block_group->flags);
7571 up_write(&block_group->space_info->groups_sem); 7591 up_write(&block_group->space_info->groups_sem);
7572 7592
7573 if (block_group->cached == BTRFS_CACHE_STARTED) 7593 if (block_group->cached == BTRFS_CACHE_STARTED)