diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-18 13:04:09 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-18 13:04:09 -0500 |
| commit | 805937cf45f9a9933e6b8e5c6660406e977a9a23 (patch) | |
| tree | f7b6365b768a2a5f40ccdaf8625b2c4188eef2ce /fs | |
| parent | 87eeff7974ae665f6d4d74c2f97c04d4b180b5d6 (diff) | |
| parent | 92e3b40537707001d17bbad800d150ab04e53bf4 (diff) | |
Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 fixes from Ted Ts'o:
"Miscellaneous ext4 bug fixes for v3.14"
* tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
jbd2: fix use after free in jbd2_journal_start_reserved()
ext4: don't leave i_crtime.tv_sec uninitialized
ext4: fix online resize with a non-standard blocks per group setting
ext4: fix online resize with very large inode tables
ext4: don't try to modify s_flags if the the file system is read-only
ext4: fix error paths in swap_inode_boot_loader()
ext4: fix xfstest generic/299 block validity failures
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/ext4/ext4.h | 2 | ||||
| -rw-r--r-- | fs/ext4/extents.c | 1 | ||||
| -rw-r--r-- | fs/ext4/ioctl.c | 3 | ||||
| -rw-r--r-- | fs/ext4/resize.c | 34 | ||||
| -rw-r--r-- | fs/ext4/super.c | 20 | ||||
| -rw-r--r-- | fs/jbd2/transaction.c | 6 |
6 files changed, 43 insertions, 23 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index ece55565b9cd..d3a534fdc5ff 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
| @@ -771,6 +771,8 @@ do { \ | |||
| 771 | if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \ | 771 | if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \ |
| 772 | (einode)->xtime.tv_sec = \ | 772 | (einode)->xtime.tv_sec = \ |
| 773 | (signed)le32_to_cpu((raw_inode)->xtime); \ | 773 | (signed)le32_to_cpu((raw_inode)->xtime); \ |
| 774 | else \ | ||
| 775 | (einode)->xtime.tv_sec = 0; \ | ||
| 774 | if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra)) \ | 776 | if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra)) \ |
| 775 | ext4_decode_extra_time(&(einode)->xtime, \ | 777 | ext4_decode_extra_time(&(einode)->xtime, \ |
| 776 | raw_inode->xtime ## _extra); \ | 778 | raw_inode->xtime ## _extra); \ |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 10cff4736b11..74bc2d549c58 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -3906,6 +3906,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, | |||
| 3906 | } else | 3906 | } else |
| 3907 | err = ret; | 3907 | err = ret; |
| 3908 | map->m_flags |= EXT4_MAP_MAPPED; | 3908 | map->m_flags |= EXT4_MAP_MAPPED; |
| 3909 | map->m_pblk = newblock; | ||
| 3909 | if (allocated > map->m_len) | 3910 | if (allocated > map->m_len) |
| 3910 | allocated = map->m_len; | 3911 | allocated = map->m_len; |
| 3911 | map->m_len = allocated; | 3912 | map->m_len = allocated; |
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 6bea80614d77..a2a837f00407 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
| @@ -140,7 +140,7 @@ static long swap_inode_boot_loader(struct super_block *sb, | |||
| 140 | handle = ext4_journal_start(inode_bl, EXT4_HT_MOVE_EXTENTS, 2); | 140 | handle = ext4_journal_start(inode_bl, EXT4_HT_MOVE_EXTENTS, 2); |
| 141 | if (IS_ERR(handle)) { | 141 | if (IS_ERR(handle)) { |
| 142 | err = -EINVAL; | 142 | err = -EINVAL; |
| 143 | goto swap_boot_out; | 143 | goto journal_err_out; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | /* Protect extent tree against block allocations via delalloc */ | 146 | /* Protect extent tree against block allocations via delalloc */ |
| @@ -198,6 +198,7 @@ static long swap_inode_boot_loader(struct super_block *sb, | |||
| 198 | 198 | ||
| 199 | ext4_double_up_write_data_sem(inode, inode_bl); | 199 | ext4_double_up_write_data_sem(inode, inode_bl); |
| 200 | 200 | ||
| 201 | journal_err_out: | ||
| 201 | ext4_inode_resume_unlocked_dio(inode); | 202 | ext4_inode_resume_unlocked_dio(inode); |
| 202 | ext4_inode_resume_unlocked_dio(inode_bl); | 203 | ext4_inode_resume_unlocked_dio(inode_bl); |
| 203 | 204 | ||
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index c5adbb318a90..f3b84cd9de56 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
| @@ -243,6 +243,7 @@ static int ext4_alloc_group_tables(struct super_block *sb, | |||
| 243 | ext4_group_t group; | 243 | ext4_group_t group; |
| 244 | ext4_group_t last_group; | 244 | ext4_group_t last_group; |
| 245 | unsigned overhead; | 245 | unsigned overhead; |
| 246 | __u16 uninit_mask = (flexbg_size > 1) ? ~EXT4_BG_BLOCK_UNINIT : ~0; | ||
| 246 | 247 | ||
| 247 | BUG_ON(flex_gd->count == 0 || group_data == NULL); | 248 | BUG_ON(flex_gd->count == 0 || group_data == NULL); |
| 248 | 249 | ||
| @@ -266,7 +267,7 @@ next_group: | |||
| 266 | src_group++; | 267 | src_group++; |
| 267 | for (; src_group <= last_group; src_group++) { | 268 | for (; src_group <= last_group; src_group++) { |
| 268 | overhead = ext4_group_overhead_blocks(sb, src_group); | 269 | overhead = ext4_group_overhead_blocks(sb, src_group); |
| 269 | if (overhead != 0) | 270 | if (overhead == 0) |
| 270 | last_blk += group_data[src_group - group].blocks_count; | 271 | last_blk += group_data[src_group - group].blocks_count; |
| 271 | else | 272 | else |
| 272 | break; | 273 | break; |
| @@ -280,8 +281,7 @@ next_group: | |||
| 280 | group = ext4_get_group_number(sb, start_blk - 1); | 281 | group = ext4_get_group_number(sb, start_blk - 1); |
| 281 | group -= group_data[0].group; | 282 | group -= group_data[0].group; |
| 282 | group_data[group].free_blocks_count--; | 283 | group_data[group].free_blocks_count--; |
| 283 | if (flexbg_size > 1) | 284 | flex_gd->bg_flags[group] &= uninit_mask; |
| 284 | flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT; | ||
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | /* Allocate inode bitmaps */ | 287 | /* Allocate inode bitmaps */ |
| @@ -292,22 +292,30 @@ next_group: | |||
| 292 | group = ext4_get_group_number(sb, start_blk - 1); | 292 | group = ext4_get_group_number(sb, start_blk - 1); |
| 293 | group -= group_data[0].group; | 293 | group -= group_data[0].group; |
| 294 | group_data[group].free_blocks_count--; | 294 | group_data[group].free_blocks_count--; |
| 295 | if (flexbg_size > 1) | 295 | flex_gd->bg_flags[group] &= uninit_mask; |
| 296 | flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT; | ||
| 297 | } | 296 | } |
| 298 | 297 | ||
| 299 | /* Allocate inode tables */ | 298 | /* Allocate inode tables */ |
| 300 | for (; it_index < flex_gd->count; it_index++) { | 299 | for (; it_index < flex_gd->count; it_index++) { |
| 301 | if (start_blk + EXT4_SB(sb)->s_itb_per_group > last_blk) | 300 | unsigned int itb = EXT4_SB(sb)->s_itb_per_group; |
| 301 | ext4_fsblk_t next_group_start; | ||
| 302 | |||
| 303 | if (start_blk + itb > last_blk) | ||
| 302 | goto next_group; | 304 | goto next_group; |
| 303 | group_data[it_index].inode_table = start_blk; | 305 | group_data[it_index].inode_table = start_blk; |
| 304 | group = ext4_get_group_number(sb, start_blk - 1); | 306 | group = ext4_get_group_number(sb, start_blk); |
| 307 | next_group_start = ext4_group_first_block_no(sb, group + 1); | ||
| 305 | group -= group_data[0].group; | 308 | group -= group_data[0].group; |
| 306 | group_data[group].free_blocks_count -= | ||
| 307 | EXT4_SB(sb)->s_itb_per_group; | ||
| 308 | if (flexbg_size > 1) | ||
| 309 | flex_gd->bg_flags[group] &= ~EXT4_BG_BLOCK_UNINIT; | ||
| 310 | 309 | ||
| 310 | if (start_blk + itb > next_group_start) { | ||
| 311 | flex_gd->bg_flags[group + 1] &= uninit_mask; | ||
| 312 | overhead = start_blk + itb - next_group_start; | ||
| 313 | group_data[group + 1].free_blocks_count -= overhead; | ||
| 314 | itb -= overhead; | ||
| 315 | } | ||
| 316 | |||
| 317 | group_data[group].free_blocks_count -= itb; | ||
| 318 | flex_gd->bg_flags[group] &= uninit_mask; | ||
| 311 | start_blk += EXT4_SB(sb)->s_itb_per_group; | 319 | start_blk += EXT4_SB(sb)->s_itb_per_group; |
| 312 | } | 320 | } |
| 313 | 321 | ||
| @@ -401,7 +409,7 @@ static int set_flexbg_block_bitmap(struct super_block *sb, handle_t *handle, | |||
| 401 | start = ext4_group_first_block_no(sb, group); | 409 | start = ext4_group_first_block_no(sb, group); |
| 402 | group -= flex_gd->groups[0].group; | 410 | group -= flex_gd->groups[0].group; |
| 403 | 411 | ||
| 404 | count2 = sb->s_blocksize * 8 - (block - start); | 412 | count2 = EXT4_BLOCKS_PER_GROUP(sb) - (block - start); |
| 405 | if (count2 > count) | 413 | if (count2 > count) |
| 406 | count2 = count; | 414 | count2 = count; |
| 407 | 415 | ||
| @@ -620,7 +628,7 @@ handle_ib: | |||
| 620 | if (err) | 628 | if (err) |
| 621 | goto out; | 629 | goto out; |
| 622 | count = group_table_count[j]; | 630 | count = group_table_count[j]; |
| 623 | start = group_data[i].block_bitmap; | 631 | start = (&group_data[i].block_bitmap)[j]; |
| 624 | block = start; | 632 | block = start; |
| 625 | } | 633 | } |
| 626 | 634 | ||
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 1f7784de05b6..710fed2377d4 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -3695,16 +3695,22 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3695 | for (i = 0; i < 4; i++) | 3695 | for (i = 0; i < 4; i++) |
| 3696 | sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); | 3696 | sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); |
| 3697 | sbi->s_def_hash_version = es->s_def_hash_version; | 3697 | sbi->s_def_hash_version = es->s_def_hash_version; |
| 3698 | i = le32_to_cpu(es->s_flags); | 3698 | if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) { |
| 3699 | if (i & EXT2_FLAGS_UNSIGNED_HASH) | 3699 | i = le32_to_cpu(es->s_flags); |
| 3700 | sbi->s_hash_unsigned = 3; | 3700 | if (i & EXT2_FLAGS_UNSIGNED_HASH) |
| 3701 | else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) { | 3701 | sbi->s_hash_unsigned = 3; |
| 3702 | else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) { | ||
| 3702 | #ifdef __CHAR_UNSIGNED__ | 3703 | #ifdef __CHAR_UNSIGNED__ |
| 3703 | es->s_flags |= cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH); | 3704 | if (!(sb->s_flags & MS_RDONLY)) |
| 3704 | sbi->s_hash_unsigned = 3; | 3705 | es->s_flags |= |
| 3706 | cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH); | ||
| 3707 | sbi->s_hash_unsigned = 3; | ||
| 3705 | #else | 3708 | #else |
| 3706 | es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH); | 3709 | if (!(sb->s_flags & MS_RDONLY)) |
| 3710 | es->s_flags |= | ||
| 3711 | cpu_to_le32(EXT2_FLAGS_SIGNED_HASH); | ||
| 3707 | #endif | 3712 | #endif |
| 3713 | } | ||
| 3708 | } | 3714 | } |
| 3709 | 3715 | ||
| 3710 | /* Handle clustersize */ | 3716 | /* Handle clustersize */ |
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 8360674c85bc..60bb365f54a5 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
| @@ -514,11 +514,13 @@ int jbd2_journal_start_reserved(handle_t *handle, unsigned int type, | |||
| 514 | * similarly constrained call sites | 514 | * similarly constrained call sites |
| 515 | */ | 515 | */ |
| 516 | ret = start_this_handle(journal, handle, GFP_NOFS); | 516 | ret = start_this_handle(journal, handle, GFP_NOFS); |
| 517 | if (ret < 0) | 517 | if (ret < 0) { |
| 518 | jbd2_journal_free_reserved(handle); | 518 | jbd2_journal_free_reserved(handle); |
| 519 | return ret; | ||
| 520 | } | ||
| 519 | handle->h_type = type; | 521 | handle->h_type = type; |
| 520 | handle->h_line_no = line_no; | 522 | handle->h_line_no = line_no; |
| 521 | return ret; | 523 | return 0; |
| 522 | } | 524 | } |
| 523 | EXPORT_SYMBOL(jbd2_journal_start_reserved); | 525 | EXPORT_SYMBOL(jbd2_journal_start_reserved); |
| 524 | 526 | ||
