Skip to content

Commit 7ce14f6

Browse files
committed
Merge branch 'for-linus-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason: "I fixed up a regression from 4.0 where conversion between different raid levels would sometimes bail out without converting. Filipe tracked down a race where it was possible to double allocate chunks on the drive. Mark has a fix for fiemap. All three will get bundled off for stable as well" * 'for-linus-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: Btrfs: fix regression in raid level conversion Btrfs: fix racy system chunk allocation when setting block group ro btrfs: clear 'ret' in btrfs_check_shared() loop
2 parents cf539cb + 153c35b commit 7ce14f6

File tree

3 files changed

+38
-0
lines changed

3 files changed

+38
-0
lines changed

fs/btrfs/backref.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -880,6 +880,8 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info,
880880
* indirect refs to their parent bytenr.
881881
* When roots are found, they're added to the roots list
882882
*
883+
* NOTE: This can return values > 0
884+
*
883885
* FIXME some caching might speed things up
884886
*/
885887
static int find_parent_nodes(struct btrfs_trans_handle *trans,
@@ -1198,6 +1200,19 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans,
11981200
return ret;
11991201
}
12001202

1203+
/**
1204+
* btrfs_check_shared - tell us whether an extent is shared
1205+
*
1206+
* @trans: optional trans handle
1207+
*
1208+
* btrfs_check_shared uses the backref walking code but will short
1209+
* circuit as soon as it finds a root or inode that doesn't match the
1210+
* one passed in. This provides a significant performance benefit for
1211+
* callers (such as fiemap) which want to know whether the extent is
1212+
* shared but do not need a ref count.
1213+
*
1214+
* Return: 0 if extent is not shared, 1 if it is shared, < 0 on error.
1215+
*/
12011216
int btrfs_check_shared(struct btrfs_trans_handle *trans,
12021217
struct btrfs_fs_info *fs_info, u64 root_objectid,
12031218
u64 inum, u64 bytenr)
@@ -1226,11 +1241,13 @@ int btrfs_check_shared(struct btrfs_trans_handle *trans,
12261241
ret = find_parent_nodes(trans, fs_info, bytenr, elem.seq, tmp,
12271242
roots, NULL, root_objectid, inum);
12281243
if (ret == BACKREF_FOUND_SHARED) {
1244+
/* this is the only condition under which we return 1 */
12291245
ret = 1;
12301246
break;
12311247
}
12321248
if (ret < 0 && ret != -ENOENT)
12331249
break;
1250+
ret = 0;
12341251
node = ulist_next(tmp, &uiter);
12351252
if (!node)
12361253
break;

fs/btrfs/extent-tree.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8829,6 +8829,24 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,
88298829
goto again;
88308830
}
88318831

8832+
/*
8833+
* if we are changing raid levels, try to allocate a corresponding
8834+
* block group with the new raid level.
8835+
*/
8836+
alloc_flags = update_block_group_flags(root, cache->flags);
8837+
if (alloc_flags != cache->flags) {
8838+
ret = do_chunk_alloc(trans, root, alloc_flags,
8839+
CHUNK_ALLOC_FORCE);
8840+
/*
8841+
* ENOSPC is allowed here, we may have enough space
8842+
* already allocated at the new raid level to
8843+
* carry on
8844+
*/
8845+
if (ret == -ENOSPC)
8846+
ret = 0;
8847+
if (ret < 0)
8848+
goto out;
8849+
}
88328850

88338851
ret = set_block_group_ro(cache, 0);
88348852
if (!ret)
@@ -8842,7 +8860,9 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,
88428860
out:
88438861
if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM) {
88448862
alloc_flags = update_block_group_flags(root, cache->flags);
8863+
lock_chunks(root->fs_info->chunk_root);
88458864
check_system_chunk(trans, root, alloc_flags);
8865+
unlock_chunks(root->fs_info->chunk_root);
88468866
}
88478867
mutex_unlock(&root->fs_info->ro_block_group_mutex);
88488868

fs/btrfs/volumes.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4625,6 +4625,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
46254625
{
46264626
u64 chunk_offset;
46274627

4628+
ASSERT(mutex_is_locked(&extent_root->fs_info->chunk_mutex));
46284629
chunk_offset = find_next_chunk(extent_root->fs_info);
46294630
return __btrfs_alloc_chunk(trans, extent_root, chunk_offset, type);
46304631
}

0 commit comments

Comments
 (0)