diff options
author | Yan Zheng <zheng.yan@oracle.com> | 2008-12-11 16:30:39 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-12-11 16:30:39 -0500 |
commit | d2fb3437e4d8d12c73c587615ad187d5288547ec (patch) | |
tree | 894e4c698970dd35226b2614b8a38fb8a96580e7 /fs/btrfs/inode.c | |
parent | cfc8ea87201dc9bb6aeb3fc80c61abee83e7cc06 (diff) |
Btrfs: fix leaking block group on balance
The block group structs are referenced in many different
places, and it's not safe to free while balancing. So, those block
group structs were simply leaked instead.
This patch replaces the block group pointer in the inode with the starting byte
offset of the block group and adds reference counting to the block group
struct.
Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 43 |
1 files changed, 13 insertions, 30 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 932d8c0b2c05..0a28b7706314 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -989,7 +989,6 @@ next_slot: | |||
989 | 989 | ||
990 | if (extent_type == BTRFS_FILE_EXTENT_REG || | 990 | if (extent_type == BTRFS_FILE_EXTENT_REG || |
991 | extent_type == BTRFS_FILE_EXTENT_PREALLOC) { | 991 | extent_type == BTRFS_FILE_EXTENT_PREALLOC) { |
992 | struct btrfs_block_group_cache *block_group; | ||
993 | disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); | 992 | disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); |
994 | extent_end = found_key.offset + | 993 | extent_end = found_key.offset + |
995 | btrfs_file_extent_num_bytes(leaf, fi); | 994 | btrfs_file_extent_num_bytes(leaf, fi); |
@@ -1007,9 +1006,7 @@ next_slot: | |||
1007 | goto out_check; | 1006 | goto out_check; |
1008 | if (btrfs_cross_ref_exist(trans, root, disk_bytenr)) | 1007 | if (btrfs_cross_ref_exist(trans, root, disk_bytenr)) |
1009 | goto out_check; | 1008 | goto out_check; |
1010 | block_group = btrfs_lookup_block_group(root->fs_info, | 1009 | if (btrfs_extent_readonly(root, disk_bytenr)) |
1011 | disk_bytenr); | ||
1012 | if (!block_group || block_group->ro) | ||
1013 | goto out_check; | 1010 | goto out_check; |
1014 | disk_bytenr += btrfs_file_extent_offset(leaf, fi); | 1011 | disk_bytenr += btrfs_file_extent_offset(leaf, fi); |
1015 | nocow = 1; | 1012 | nocow = 1; |
@@ -1969,16 +1966,11 @@ void btrfs_read_locked_inode(struct inode *inode) | |||
1969 | rdev = btrfs_inode_rdev(leaf, inode_item); | 1966 | rdev = btrfs_inode_rdev(leaf, inode_item); |
1970 | 1967 | ||
1971 | BTRFS_I(inode)->index_cnt = (u64)-1; | 1968 | BTRFS_I(inode)->index_cnt = (u64)-1; |
1969 | BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); | ||
1972 | 1970 | ||
1973 | alloc_group_block = btrfs_inode_block_group(leaf, inode_item); | 1971 | alloc_group_block = btrfs_inode_block_group(leaf, inode_item); |
1974 | BTRFS_I(inode)->block_group = btrfs_lookup_block_group(root->fs_info, | 1972 | BTRFS_I(inode)->block_group = btrfs_find_block_group(root, 0, |
1975 | alloc_group_block); | 1973 | alloc_group_block, 0); |
1976 | BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); | ||
1977 | if (!BTRFS_I(inode)->block_group) { | ||
1978 | BTRFS_I(inode)->block_group = btrfs_find_block_group(root, | ||
1979 | NULL, 0, | ||
1980 | BTRFS_BLOCK_GROUP_METADATA, 0); | ||
1981 | } | ||
1982 | btrfs_free_path(path); | 1974 | btrfs_free_path(path); |
1983 | inode_item = NULL; | 1975 | inode_item = NULL; |
1984 | 1976 | ||
@@ -2048,8 +2040,7 @@ static void fill_inode_item(struct btrfs_trans_handle *trans, | |||
2048 | btrfs_set_inode_transid(leaf, item, trans->transid); | 2040 | btrfs_set_inode_transid(leaf, item, trans->transid); |
2049 | btrfs_set_inode_rdev(leaf, item, inode->i_rdev); | 2041 | btrfs_set_inode_rdev(leaf, item, inode->i_rdev); |
2050 | btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags); | 2042 | btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags); |
2051 | btrfs_set_inode_block_group(leaf, item, | 2043 | btrfs_set_inode_block_group(leaf, item, BTRFS_I(inode)->block_group); |
2052 | BTRFS_I(inode)->block_group->key.objectid); | ||
2053 | } | 2044 | } |
2054 | 2045 | ||
2055 | /* | 2046 | /* |
@@ -3358,14 +3349,11 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
3358 | struct btrfs_root *root, | 3349 | struct btrfs_root *root, |
3359 | struct inode *dir, | 3350 | struct inode *dir, |
3360 | const char *name, int name_len, | 3351 | const char *name, int name_len, |
3361 | u64 ref_objectid, | 3352 | u64 ref_objectid, u64 objectid, |
3362 | u64 objectid, | 3353 | u64 alloc_hint, int mode, u64 *index) |
3363 | struct btrfs_block_group_cache *group, | ||
3364 | int mode, u64 *index) | ||
3365 | { | 3354 | { |
3366 | struct inode *inode; | 3355 | struct inode *inode; |
3367 | struct btrfs_inode_item *inode_item; | 3356 | struct btrfs_inode_item *inode_item; |
3368 | struct btrfs_block_group_cache *new_inode_group; | ||
3369 | struct btrfs_key *location; | 3357 | struct btrfs_key *location; |
3370 | struct btrfs_path *path; | 3358 | struct btrfs_path *path; |
3371 | struct btrfs_inode_ref *ref; | 3359 | struct btrfs_inode_ref *ref; |
@@ -3401,13 +3389,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
3401 | owner = 0; | 3389 | owner = 0; |
3402 | else | 3390 | else |
3403 | owner = 1; | 3391 | owner = 1; |
3404 | new_inode_group = btrfs_find_block_group(root, group, 0, | 3392 | BTRFS_I(inode)->block_group = |
3405 | BTRFS_BLOCK_GROUP_METADATA, owner); | 3393 | btrfs_find_block_group(root, 0, alloc_hint, owner); |
3406 | if (!new_inode_group) { | ||
3407 | printk("find_block group failed\n"); | ||
3408 | new_inode_group = group; | ||
3409 | } | ||
3410 | BTRFS_I(inode)->block_group = new_inode_group; | ||
3411 | 3394 | ||
3412 | key[0].objectid = objectid; | 3395 | key[0].objectid = objectid; |
3413 | btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY); | 3396 | btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY); |
@@ -4366,16 +4349,16 @@ out: | |||
4366 | /* | 4349 | /* |
4367 | * create a new subvolume directory/inode (helper for the ioctl). | 4350 | * create a new subvolume directory/inode (helper for the ioctl). |
4368 | */ | 4351 | */ |
4369 | int btrfs_create_subvol_root(struct btrfs_root *new_root, struct dentry *dentry, | 4352 | int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, |
4370 | struct btrfs_trans_handle *trans, u64 new_dirid, | 4353 | struct btrfs_root *new_root, struct dentry *dentry, |
4371 | struct btrfs_block_group_cache *block_group) | 4354 | u64 new_dirid, u64 alloc_hint) |
4372 | { | 4355 | { |
4373 | struct inode *inode; | 4356 | struct inode *inode; |
4374 | int error; | 4357 | int error; |
4375 | u64 index = 0; | 4358 | u64 index = 0; |
4376 | 4359 | ||
4377 | inode = btrfs_new_inode(trans, new_root, NULL, "..", 2, new_dirid, | 4360 | inode = btrfs_new_inode(trans, new_root, NULL, "..", 2, new_dirid, |
4378 | new_dirid, block_group, S_IFDIR | 0700, &index); | 4361 | new_dirid, alloc_hint, S_IFDIR | 0700, &index); |
4379 | if (IS_ERR(inode)) | 4362 | if (IS_ERR(inode)) |
4380 | return PTR_ERR(inode); | 4363 | return PTR_ERR(inode); |
4381 | inode->i_op = &btrfs_dir_inode_operations; | 4364 | inode->i_op = &btrfs_dir_inode_operations; |