Skip to content

Commit 719da39

Browse files
committed
Merge branch 'misc-fixes-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux into for-linus-4.7
2 parents 4c52990 + 5f9e105 commit 719da39

File tree

6 files changed

+115
-18
lines changed

6 files changed

+115
-18
lines changed

fs/btrfs/disk-io.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4133,6 +4133,17 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
41334133
* Hint to catch really bogus numbers, bitflips or so, more exact checks are
41344134
* done later
41354135
*/
4136+
if (btrfs_super_bytes_used(sb) < 6 * btrfs_super_nodesize(sb)) {
4137+
btrfs_err(fs_info, "bytes_used is too small %llu",
4138+
btrfs_super_bytes_used(sb));
4139+
ret = -EINVAL;
4140+
}
4141+
if (!is_power_of_2(btrfs_super_stripesize(sb)) ||
4142+
btrfs_super_stripesize(sb) != sectorsize) {
4143+
btrfs_err(fs_info, "invalid stripesize %u",
4144+
btrfs_super_stripesize(sb));
4145+
ret = -EINVAL;
4146+
}
41364147
if (btrfs_super_num_devices(sb) > (1UL << 31))
41374148
printk(KERN_WARNING "BTRFS: suspicious number of devices: %llu\n",
41384149
btrfs_super_num_devices(sb));

fs/btrfs/hash.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ int __init btrfs_hash_init(void)
2424
return PTR_ERR_OR_ZERO(tfm);
2525
}
2626

27+
const char* btrfs_crc32c_impl(void)
28+
{
29+
return crypto_tfm_alg_driver_name(crypto_shash_tfm(tfm));
30+
}
31+
2732
void btrfs_hash_exit(void)
2833
{
2934
crypto_free_shash(tfm);

fs/btrfs/hash.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
int __init btrfs_hash_init(void);
2323

2424
void btrfs_hash_exit(void);
25+
const char* btrfs_crc32c_impl(void);
2526

2627
u32 btrfs_crc32c(u32 crc, const void *address, unsigned int length);
2728

fs/btrfs/super.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2303,7 +2303,7 @@ static void btrfs_interface_exit(void)
23032303

23042304
static void btrfs_print_mod_info(void)
23052305
{
2306-
printk(KERN_INFO "Btrfs loaded"
2306+
printk(KERN_INFO "Btrfs loaded, crc32c=%s"
23072307
#ifdef CONFIG_BTRFS_DEBUG
23082308
", debug=on"
23092309
#endif
@@ -2313,7 +2313,8 @@ static void btrfs_print_mod_info(void)
23132313
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
23142314
", integrity-checker=on"
23152315
#endif
2316-
"\n");
2316+
"\n",
2317+
btrfs_crc32c_impl());
23172318
}
23182319

23192320
static int btrfs_run_sanity_tests(void)

fs/btrfs/volumes.c

Lines changed: 94 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4241,6 +4241,7 @@ int btrfs_create_uuid_tree(struct btrfs_fs_info *fs_info)
42414241
if (IS_ERR(uuid_root)) {
42424242
ret = PTR_ERR(uuid_root);
42434243
btrfs_abort_transaction(trans, tree_root, ret);
4244+
btrfs_end_transaction(trans, tree_root);
42444245
return ret;
42454246
}
42464247

@@ -6258,27 +6259,23 @@ struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info,
62586259
return dev;
62596260
}
62606261

6261-
static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
6262-
struct extent_buffer *leaf,
6263-
struct btrfs_chunk *chunk)
6262+
/* Return -EIO if any error, otherwise return 0. */
6263+
static int btrfs_check_chunk_valid(struct btrfs_root *root,
6264+
struct extent_buffer *leaf,
6265+
struct btrfs_chunk *chunk, u64 logical)
62646266
{
6265-
struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree;
6266-
struct map_lookup *map;
6267-
struct extent_map *em;
6268-
u64 logical;
62696267
u64 length;
62706268
u64 stripe_len;
6271-
u64 devid;
6272-
u8 uuid[BTRFS_UUID_SIZE];
6273-
int num_stripes;
6274-
int ret;
6275-
int i;
6269+
u16 num_stripes;
6270+
u16 sub_stripes;
6271+
u64 type;
62766272

6277-
logical = key->offset;
62786273
length = btrfs_chunk_length(leaf, chunk);
62796274
stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
62806275
num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
6281-
/* Validation check */
6276+
sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
6277+
type = btrfs_chunk_type(leaf, chunk);
6278+
62826279
if (!num_stripes) {
62836280
btrfs_err(root->fs_info, "invalid chunk num_stripes: %u",
62846281
num_stripes);
@@ -6289,6 +6286,11 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
62896286
"invalid chunk logical %llu", logical);
62906287
return -EIO;
62916288
}
6289+
if (btrfs_chunk_sector_size(leaf, chunk) != root->sectorsize) {
6290+
btrfs_err(root->fs_info, "invalid chunk sectorsize %u",
6291+
btrfs_chunk_sector_size(leaf, chunk));
6292+
return -EIO;
6293+
}
62926294
if (!length || !IS_ALIGNED(length, root->sectorsize)) {
62936295
btrfs_err(root->fs_info,
62946296
"invalid chunk length %llu", length);
@@ -6300,13 +6302,54 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
63006302
return -EIO;
63016303
}
63026304
if (~(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_PROFILE_MASK) &
6303-
btrfs_chunk_type(leaf, chunk)) {
6305+
type) {
63046306
btrfs_err(root->fs_info, "unrecognized chunk type: %llu",
63056307
~(BTRFS_BLOCK_GROUP_TYPE_MASK |
63066308
BTRFS_BLOCK_GROUP_PROFILE_MASK) &
63076309
btrfs_chunk_type(leaf, chunk));
63086310
return -EIO;
63096311
}
6312+
if ((type & BTRFS_BLOCK_GROUP_RAID10 && sub_stripes != 2) ||
6313+
(type & BTRFS_BLOCK_GROUP_RAID1 && num_stripes < 1) ||
6314+
(type & BTRFS_BLOCK_GROUP_RAID5 && num_stripes < 2) ||
6315+
(type & BTRFS_BLOCK_GROUP_RAID6 && num_stripes < 3) ||
6316+
(type & BTRFS_BLOCK_GROUP_DUP && num_stripes > 2) ||
6317+
((type & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0 &&
6318+
num_stripes != 1)) {
6319+
btrfs_err(root->fs_info,
6320+
"invalid num_stripes:sub_stripes %u:%u for profile %llu",
6321+
num_stripes, sub_stripes,
6322+
type & BTRFS_BLOCK_GROUP_PROFILE_MASK);
6323+
return -EIO;
6324+
}
6325+
6326+
return 0;
6327+
}
6328+
6329+
static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
6330+
struct extent_buffer *leaf,
6331+
struct btrfs_chunk *chunk)
6332+
{
6333+
struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree;
6334+
struct map_lookup *map;
6335+
struct extent_map *em;
6336+
u64 logical;
6337+
u64 length;
6338+
u64 stripe_len;
6339+
u64 devid;
6340+
u8 uuid[BTRFS_UUID_SIZE];
6341+
int num_stripes;
6342+
int ret;
6343+
int i;
6344+
6345+
logical = key->offset;
6346+
length = btrfs_chunk_length(leaf, chunk);
6347+
stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
6348+
num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
6349+
6350+
ret = btrfs_check_chunk_valid(root, leaf, chunk, logical);
6351+
if (ret)
6352+
return ret;
63106353

63116354
read_lock(&map_tree->map_tree.lock);
63126355
em = lookup_extent_mapping(&map_tree->map_tree, logical, 1);
@@ -6554,6 +6597,7 @@ int btrfs_read_sys_array(struct btrfs_root *root)
65546597
u32 array_size;
65556598
u32 len = 0;
65566599
u32 cur_offset;
6600+
u64 type;
65576601
struct btrfs_key key;
65586602

65596603
ASSERT(BTRFS_SUPER_INFO_SIZE <= root->nodesize);
@@ -6620,6 +6664,15 @@ int btrfs_read_sys_array(struct btrfs_root *root)
66206664
break;
66216665
}
66226666

6667+
type = btrfs_chunk_type(sb, chunk);
6668+
if ((type & BTRFS_BLOCK_GROUP_SYSTEM) == 0) {
6669+
btrfs_err(root->fs_info,
6670+
"invalid chunk type %llu in sys_array at offset %u",
6671+
type, cur_offset);
6672+
ret = -EIO;
6673+
break;
6674+
}
6675+
66236676
len = btrfs_chunk_item_size(num_stripes);
66246677
if (cur_offset + len > array_size)
66256678
goto out_short_read;
@@ -6638,12 +6691,14 @@ int btrfs_read_sys_array(struct btrfs_root *root)
66386691
sb_array_offset += len;
66396692
cur_offset += len;
66406693
}
6694+
clear_extent_buffer_uptodate(sb);
66416695
free_extent_buffer_stale(sb);
66426696
return ret;
66436697

66446698
out_short_read:
66456699
printk(KERN_ERR "BTRFS: sys_array too short to read %u bytes at offset %u\n",
66466700
len, cur_offset);
6701+
clear_extent_buffer_uptodate(sb);
66476702
free_extent_buffer_stale(sb);
66486703
return -EIO;
66496704
}
@@ -6656,6 +6711,7 @@ int btrfs_read_chunk_tree(struct btrfs_root *root)
66566711
struct btrfs_key found_key;
66576712
int ret;
66586713
int slot;
6714+
u64 total_dev = 0;
66596715

66606716
root = root->fs_info->chunk_root;
66616717

@@ -6697,6 +6753,7 @@ int btrfs_read_chunk_tree(struct btrfs_root *root)
66976753
ret = read_one_dev(root, leaf, dev_item);
66986754
if (ret)
66996755
goto error;
6756+
total_dev++;
67006757
} else if (found_key.type == BTRFS_CHUNK_ITEM_KEY) {
67016758
struct btrfs_chunk *chunk;
67026759
chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
@@ -6706,6 +6763,28 @@ int btrfs_read_chunk_tree(struct btrfs_root *root)
67066763
}
67076764
path->slots[0]++;
67086765
}
6766+
6767+
/*
6768+
* After loading chunk tree, we've got all device information,
6769+
* do another round of validation checks.
6770+
*/
6771+
if (total_dev != root->fs_info->fs_devices->total_devices) {
6772+
btrfs_err(root->fs_info,
6773+
"super_num_devices %llu mismatch with num_devices %llu found here",
6774+
btrfs_super_num_devices(root->fs_info->super_copy),
6775+
total_dev);
6776+
ret = -EINVAL;
6777+
goto error;
6778+
}
6779+
if (btrfs_super_total_bytes(root->fs_info->super_copy) <
6780+
root->fs_info->fs_devices->total_rw_bytes) {
6781+
btrfs_err(root->fs_info,
6782+
"super_total_bytes %llu mismatch with fs_devices total_rw_bytes %llu",
6783+
btrfs_super_total_bytes(root->fs_info->super_copy),
6784+
root->fs_info->fs_devices->total_rw_bytes);
6785+
ret = -EINVAL;
6786+
goto error;
6787+
}
67096788
ret = 0;
67106789
error:
67116790
unlock_chunks(root);

include/uapi/linux/btrfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ struct btrfs_ioctl_vol_args_v2 {
118118
};
119119
union {
120120
char name[BTRFS_SUBVOL_NAME_MAX + 1];
121-
u64 devid;
121+
__u64 devid;
122122
};
123123
};
124124

0 commit comments

Comments
 (0)