diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-07-08 14:10:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-07-08 14:10:30 -0400 |
commit | 70a2dc6abc8af028b0c71af6b3520574ee09e814 (patch) | |
tree | 935075ce55d5091d5508ff9be533959703e25410 | |
parent | 8979319f2d361b5729b215e1d47cb5bbcaca9d76 (diff) | |
parent | a17712c8e4be4fa5404d20e9cd3b2b21eae7bc56 (diff) |
Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 bugfixes from Ted Ts'o:
"Bug fixes for ext4; most of which relate to vulnerabilities where a
maliciously crafted file system image can result in a kernel OOPS or
hang.
At least one fix addresses an inline data bug could be triggered by
userspace without the need of a crafted file system (although it does
require that the inline data feature be enabled)"
* tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
ext4: check superblock mapped prior to committing
ext4: add more mount time checks of the superblock
ext4: add more inode number paranoia checks
ext4: avoid running out of journal credits when appending to an inline file
jbd2: don't mark block as modified if the handle is out of credits
ext4: never move the system.data xattr out of the inode body
ext4: clear i_data in ext4_inode_info when removing inline data
ext4: include the illegal physical block in the bad map ext4_error msg
ext4: verify the depth of extent tree in ext4_find_extent()
ext4: only look at the bg_flags field if it is valid
ext4: make sure bitmaps and the inode table don't overlap with bg descriptors
ext4: always check block group bounds in ext4_init_block_bitmap()
ext4: always verify the magic number in xattr blocks
ext4: add corruption check in ext4_xattr_set_entry()
ext4: add warn_on_error mount option
-rw-r--r-- | fs/ext4/balloc.c | 21 | ||||
-rw-r--r-- | fs/ext4/ext4.h | 9 | ||||
-rw-r--r-- | fs/ext4/ext4_extents.h | 1 | ||||
-rw-r--r-- | fs/ext4/extents.c | 6 | ||||
-rw-r--r-- | fs/ext4/ialloc.c | 14 | ||||
-rw-r--r-- | fs/ext4/inline.c | 39 | ||||
-rw-r--r-- | fs/ext4/inode.c | 7 | ||||
-rw-r--r-- | fs/ext4/mballoc.c | 6 | ||||
-rw-r--r-- | fs/ext4/super.c | 99 | ||||
-rw-r--r-- | fs/ext4/xattr.c | 40 | ||||
-rw-r--r-- | fs/jbd2/transaction.c | 9 |
11 files changed, 155 insertions, 96 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index b00481c475cb..e68cefe08261 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -184,7 +184,6 @@ static int ext4_init_block_bitmap(struct super_block *sb, | |||
184 | unsigned int bit, bit_max; | 184 | unsigned int bit, bit_max; |
185 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 185 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
186 | ext4_fsblk_t start, tmp; | 186 | ext4_fsblk_t start, tmp; |
187 | int flex_bg = 0; | ||
188 | 187 | ||
189 | J_ASSERT_BH(bh, buffer_locked(bh)); | 188 | J_ASSERT_BH(bh, buffer_locked(bh)); |
190 | 189 | ||
@@ -207,22 +206,19 @@ static int ext4_init_block_bitmap(struct super_block *sb, | |||
207 | 206 | ||
208 | start = ext4_group_first_block_no(sb, block_group); | 207 | start = ext4_group_first_block_no(sb, block_group); |
209 | 208 | ||
210 | if (ext4_has_feature_flex_bg(sb)) | ||
211 | flex_bg = 1; | ||
212 | |||
213 | /* Set bits for block and inode bitmaps, and inode table */ | 209 | /* Set bits for block and inode bitmaps, and inode table */ |
214 | tmp = ext4_block_bitmap(sb, gdp); | 210 | tmp = ext4_block_bitmap(sb, gdp); |
215 | if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) | 211 | if (ext4_block_in_group(sb, tmp, block_group)) |
216 | ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); | 212 | ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); |
217 | 213 | ||
218 | tmp = ext4_inode_bitmap(sb, gdp); | 214 | tmp = ext4_inode_bitmap(sb, gdp); |
219 | if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) | 215 | if (ext4_block_in_group(sb, tmp, block_group)) |
220 | ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); | 216 | ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); |
221 | 217 | ||
222 | tmp = ext4_inode_table(sb, gdp); | 218 | tmp = ext4_inode_table(sb, gdp); |
223 | for (; tmp < ext4_inode_table(sb, gdp) + | 219 | for (; tmp < ext4_inode_table(sb, gdp) + |
224 | sbi->s_itb_per_group; tmp++) { | 220 | sbi->s_itb_per_group; tmp++) { |
225 | if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) | 221 | if (ext4_block_in_group(sb, tmp, block_group)) |
226 | ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); | 222 | ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); |
227 | } | 223 | } |
228 | 224 | ||
@@ -442,7 +438,16 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) | |||
442 | goto verify; | 438 | goto verify; |
443 | } | 439 | } |
444 | ext4_lock_group(sb, block_group); | 440 | ext4_lock_group(sb, block_group); |
445 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { | 441 | if (ext4_has_group_desc_csum(sb) && |
442 | (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { | ||
443 | if (block_group == 0) { | ||
444 | ext4_unlock_group(sb, block_group); | ||
445 | unlock_buffer(bh); | ||
446 | ext4_error(sb, "Block bitmap for bg 0 marked " | ||
447 | "uninitialized"); | ||
448 | err = -EFSCORRUPTED; | ||
449 | goto out; | ||
450 | } | ||
446 | err = ext4_init_block_bitmap(sb, bh, block_group, desc); | 451 | err = ext4_init_block_bitmap(sb, bh, block_group, desc); |
447 | set_bitmap_uptodate(bh); | 452 | set_bitmap_uptodate(bh); |
448 | set_buffer_uptodate(bh); | 453 | set_buffer_uptodate(bh); |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 0b127853c584..7c7123f265c2 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1114,6 +1114,7 @@ struct ext4_inode_info { | |||
1114 | #define EXT4_MOUNT_DIOREAD_NOLOCK 0x400000 /* Enable support for dio read nolocking */ | 1114 | #define EXT4_MOUNT_DIOREAD_NOLOCK 0x400000 /* Enable support for dio read nolocking */ |
1115 | #define EXT4_MOUNT_JOURNAL_CHECKSUM 0x800000 /* Journal checksums */ | 1115 | #define EXT4_MOUNT_JOURNAL_CHECKSUM 0x800000 /* Journal checksums */ |
1116 | #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */ | 1116 | #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */ |
1117 | #define EXT4_MOUNT_WARN_ON_ERROR 0x2000000 /* Trigger WARN_ON on error */ | ||
1117 | #define EXT4_MOUNT_DELALLOC 0x8000000 /* Delalloc support */ | 1118 | #define EXT4_MOUNT_DELALLOC 0x8000000 /* Delalloc support */ |
1118 | #define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000 /* Abort on file data write */ | 1119 | #define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000 /* Abort on file data write */ |
1119 | #define EXT4_MOUNT_BLOCK_VALIDITY 0x20000000 /* Block validity checking */ | 1120 | #define EXT4_MOUNT_BLOCK_VALIDITY 0x20000000 /* Block validity checking */ |
@@ -1507,11 +1508,6 @@ static inline struct ext4_inode_info *EXT4_I(struct inode *inode) | |||
1507 | static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) | 1508 | static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) |
1508 | { | 1509 | { |
1509 | return ino == EXT4_ROOT_INO || | 1510 | return ino == EXT4_ROOT_INO || |
1510 | ino == EXT4_USR_QUOTA_INO || | ||
1511 | ino == EXT4_GRP_QUOTA_INO || | ||
1512 | ino == EXT4_BOOT_LOADER_INO || | ||
1513 | ino == EXT4_JOURNAL_INO || | ||
1514 | ino == EXT4_RESIZE_INO || | ||
1515 | (ino >= EXT4_FIRST_INO(sb) && | 1511 | (ino >= EXT4_FIRST_INO(sb) && |
1516 | ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)); | 1512 | ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)); |
1517 | } | 1513 | } |
@@ -3018,9 +3014,6 @@ extern int ext4_inline_data_fiemap(struct inode *inode, | |||
3018 | struct iomap; | 3014 | struct iomap; |
3019 | extern int ext4_inline_data_iomap(struct inode *inode, struct iomap *iomap); | 3015 | extern int ext4_inline_data_iomap(struct inode *inode, struct iomap *iomap); |
3020 | 3016 | ||
3021 | extern int ext4_try_to_evict_inline_data(handle_t *handle, | ||
3022 | struct inode *inode, | ||
3023 | int needed); | ||
3024 | extern int ext4_inline_data_truncate(struct inode *inode, int *has_inline); | 3017 | extern int ext4_inline_data_truncate(struct inode *inode, int *has_inline); |
3025 | 3018 | ||
3026 | extern int ext4_convert_inline_data(struct inode *inode); | 3019 | extern int ext4_convert_inline_data(struct inode *inode); |
diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h index 98fb0c119c68..adf6668b596f 100644 --- a/fs/ext4/ext4_extents.h +++ b/fs/ext4/ext4_extents.h | |||
@@ -91,6 +91,7 @@ struct ext4_extent_header { | |||
91 | }; | 91 | }; |
92 | 92 | ||
93 | #define EXT4_EXT_MAGIC cpu_to_le16(0xf30a) | 93 | #define EXT4_EXT_MAGIC cpu_to_le16(0xf30a) |
94 | #define EXT4_MAX_EXTENT_DEPTH 5 | ||
94 | 95 | ||
95 | #define EXT4_EXTENT_TAIL_OFFSET(hdr) \ | 96 | #define EXT4_EXTENT_TAIL_OFFSET(hdr) \ |
96 | (sizeof(struct ext4_extent_header) + \ | 97 | (sizeof(struct ext4_extent_header) + \ |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 0057fe3f248d..8ce6fd5b10dd 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -869,6 +869,12 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block, | |||
869 | 869 | ||
870 | eh = ext_inode_hdr(inode); | 870 | eh = ext_inode_hdr(inode); |
871 | depth = ext_depth(inode); | 871 | depth = ext_depth(inode); |
872 | if (depth < 0 || depth > EXT4_MAX_EXTENT_DEPTH) { | ||
873 | EXT4_ERROR_INODE(inode, "inode has invalid extent depth: %d", | ||
874 | depth); | ||
875 | ret = -EFSCORRUPTED; | ||
876 | goto err; | ||
877 | } | ||
872 | 878 | ||
873 | if (path) { | 879 | if (path) { |
874 | ext4_ext_drop_refs(path); | 880 | ext4_ext_drop_refs(path); |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index f525f909b559..fb83750c1a14 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -150,7 +150,16 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) | |||
150 | } | 150 | } |
151 | 151 | ||
152 | ext4_lock_group(sb, block_group); | 152 | ext4_lock_group(sb, block_group); |
153 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { | 153 | if (ext4_has_group_desc_csum(sb) && |
154 | (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT))) { | ||
155 | if (block_group == 0) { | ||
156 | ext4_unlock_group(sb, block_group); | ||
157 | unlock_buffer(bh); | ||
158 | ext4_error(sb, "Inode bitmap for bg 0 marked " | ||
159 | "uninitialized"); | ||
160 | err = -EFSCORRUPTED; | ||
161 | goto out; | ||
162 | } | ||
154 | memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8); | 163 | memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8); |
155 | ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), | 164 | ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), |
156 | sb->s_blocksize * 8, bh->b_data); | 165 | sb->s_blocksize * 8, bh->b_data); |
@@ -994,7 +1003,8 @@ got: | |||
994 | 1003 | ||
995 | /* recheck and clear flag under lock if we still need to */ | 1004 | /* recheck and clear flag under lock if we still need to */ |
996 | ext4_lock_group(sb, group); | 1005 | ext4_lock_group(sb, group); |
997 | if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { | 1006 | if (ext4_has_group_desc_csum(sb) && |
1007 | (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { | ||
998 | gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); | 1008 | gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); |
999 | ext4_free_group_clusters_set(sb, gdp, | 1009 | ext4_free_group_clusters_set(sb, gdp, |
1000 | ext4_free_clusters_after_init(sb, group, gdp)); | 1010 | ext4_free_clusters_after_init(sb, group, gdp)); |
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 285ed1588730..e55a8bc870bd 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c | |||
@@ -437,6 +437,7 @@ static int ext4_destroy_inline_data_nolock(handle_t *handle, | |||
437 | 437 | ||
438 | memset((void *)ext4_raw_inode(&is.iloc)->i_block, | 438 | memset((void *)ext4_raw_inode(&is.iloc)->i_block, |
439 | 0, EXT4_MIN_INLINE_DATA_SIZE); | 439 | 0, EXT4_MIN_INLINE_DATA_SIZE); |
440 | memset(ei->i_data, 0, EXT4_MIN_INLINE_DATA_SIZE); | ||
440 | 441 | ||
441 | if (ext4_has_feature_extents(inode->i_sb)) { | 442 | if (ext4_has_feature_extents(inode->i_sb)) { |
442 | if (S_ISDIR(inode->i_mode) || | 443 | if (S_ISDIR(inode->i_mode) || |
@@ -886,11 +887,11 @@ retry_journal: | |||
886 | flags |= AOP_FLAG_NOFS; | 887 | flags |= AOP_FLAG_NOFS; |
887 | 888 | ||
888 | if (ret == -ENOSPC) { | 889 | if (ret == -ENOSPC) { |
890 | ext4_journal_stop(handle); | ||
889 | ret = ext4_da_convert_inline_data_to_extent(mapping, | 891 | ret = ext4_da_convert_inline_data_to_extent(mapping, |
890 | inode, | 892 | inode, |
891 | flags, | 893 | flags, |
892 | fsdata); | 894 | fsdata); |
893 | ext4_journal_stop(handle); | ||
894 | if (ret == -ENOSPC && | 895 | if (ret == -ENOSPC && |
895 | ext4_should_retry_alloc(inode->i_sb, &retries)) | 896 | ext4_should_retry_alloc(inode->i_sb, &retries)) |
896 | goto retry_journal; | 897 | goto retry_journal; |
@@ -1890,42 +1891,6 @@ out: | |||
1890 | return (error < 0 ? error : 0); | 1891 | return (error < 0 ? error : 0); |
1891 | } | 1892 | } |
1892 | 1893 | ||
1893 | /* | ||
1894 | * Called during xattr set, and if we can sparse space 'needed', | ||
1895 | * just create the extent tree evict the data to the outer block. | ||
1896 | * | ||
1897 | * We use jbd2 instead of page cache to move data to the 1st block | ||
1898 | * so that the whole transaction can be committed as a whole and | ||
1899 | * the data isn't lost because of the delayed page cache write. | ||
1900 | */ | ||
1901 | int ext4_try_to_evict_inline_data(handle_t *handle, | ||
1902 | struct inode *inode, | ||
1903 | int needed) | ||
1904 | { | ||
1905 | int error; | ||
1906 | struct ext4_xattr_entry *entry; | ||
1907 | struct ext4_inode *raw_inode; | ||
1908 | struct ext4_iloc iloc; | ||
1909 | |||
1910 | error = ext4_get_inode_loc(inode, &iloc); | ||
1911 | if (error) | ||
1912 | return error; | ||
1913 | |||
1914 | raw_inode = ext4_raw_inode(&iloc); | ||
1915 | entry = (struct ext4_xattr_entry *)((void *)raw_inode + | ||
1916 | EXT4_I(inode)->i_inline_off); | ||
1917 | if (EXT4_XATTR_LEN(entry->e_name_len) + | ||
1918 | EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)) < needed) { | ||
1919 | error = -ENOSPC; | ||
1920 | goto out; | ||
1921 | } | ||
1922 | |||
1923 | error = ext4_convert_inline_data_nolock(handle, inode, &iloc); | ||
1924 | out: | ||
1925 | brelse(iloc.bh); | ||
1926 | return error; | ||
1927 | } | ||
1928 | |||
1929 | int ext4_inline_data_truncate(struct inode *inode, int *has_inline) | 1894 | int ext4_inline_data_truncate(struct inode *inode, int *has_inline) |
1930 | { | 1895 | { |
1931 | handle_t *handle; | 1896 | handle_t *handle; |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 2ea07efbe016..7d6c10017bdf 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -402,9 +402,9 @@ static int __check_block_validity(struct inode *inode, const char *func, | |||
402 | if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk, | 402 | if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk, |
403 | map->m_len)) { | 403 | map->m_len)) { |
404 | ext4_error_inode(inode, func, line, map->m_pblk, | 404 | ext4_error_inode(inode, func, line, map->m_pblk, |
405 | "lblock %lu mapped to illegal pblock " | 405 | "lblock %lu mapped to illegal pblock %llu " |
406 | "(length %d)", (unsigned long) map->m_lblk, | 406 | "(length %d)", (unsigned long) map->m_lblk, |
407 | map->m_len); | 407 | map->m_pblk, map->m_len); |
408 | return -EFSCORRUPTED; | 408 | return -EFSCORRUPTED; |
409 | } | 409 | } |
410 | return 0; | 410 | return 0; |
@@ -4506,7 +4506,8 @@ static int __ext4_get_inode_loc(struct inode *inode, | |||
4506 | int inodes_per_block, inode_offset; | 4506 | int inodes_per_block, inode_offset; |
4507 | 4507 | ||
4508 | iloc->bh = NULL; | 4508 | iloc->bh = NULL; |
4509 | if (!ext4_valid_inum(sb, inode->i_ino)) | 4509 | if (inode->i_ino < EXT4_ROOT_INO || |
4510 | inode->i_ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)) | ||
4510 | return -EFSCORRUPTED; | 4511 | return -EFSCORRUPTED; |
4511 | 4512 | ||
4512 | iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb); | 4513 | iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb); |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 6eae2b91aafa..f7ab34088162 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -2423,7 +2423,8 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group, | |||
2423 | * initialize bb_free to be able to skip | 2423 | * initialize bb_free to be able to skip |
2424 | * empty groups without initialization | 2424 | * empty groups without initialization |
2425 | */ | 2425 | */ |
2426 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { | 2426 | if (ext4_has_group_desc_csum(sb) && |
2427 | (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { | ||
2427 | meta_group_info[i]->bb_free = | 2428 | meta_group_info[i]->bb_free = |
2428 | ext4_free_clusters_after_init(sb, group, desc); | 2429 | ext4_free_clusters_after_init(sb, group, desc); |
2429 | } else { | 2430 | } else { |
@@ -2989,7 +2990,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, | |||
2989 | #endif | 2990 | #endif |
2990 | ext4_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start, | 2991 | ext4_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start, |
2991 | ac->ac_b_ex.fe_len); | 2992 | ac->ac_b_ex.fe_len); |
2992 | if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { | 2993 | if (ext4_has_group_desc_csum(sb) && |
2994 | (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { | ||
2993 | gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); | 2995 | gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); |
2994 | ext4_free_group_clusters_set(sb, gdp, | 2996 | ext4_free_group_clusters_set(sb, gdp, |
2995 | ext4_free_clusters_after_init(sb, | 2997 | ext4_free_clusters_after_init(sb, |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 0c4c2201b3aa..ba2396a7bd04 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -405,6 +405,9 @@ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn) | |||
405 | 405 | ||
406 | static void ext4_handle_error(struct super_block *sb) | 406 | static void ext4_handle_error(struct super_block *sb) |
407 | { | 407 | { |
408 | if (test_opt(sb, WARN_ON_ERROR)) | ||
409 | WARN_ON_ONCE(1); | ||
410 | |||
408 | if (sb_rdonly(sb)) | 411 | if (sb_rdonly(sb)) |
409 | return; | 412 | return; |
410 | 413 | ||
@@ -740,6 +743,9 @@ __acquires(bitlock) | |||
740 | va_end(args); | 743 | va_end(args); |
741 | } | 744 | } |
742 | 745 | ||
746 | if (test_opt(sb, WARN_ON_ERROR)) | ||
747 | WARN_ON_ONCE(1); | ||
748 | |||
743 | if (test_opt(sb, ERRORS_CONT)) { | 749 | if (test_opt(sb, ERRORS_CONT)) { |
744 | ext4_commit_super(sb, 0); | 750 | ext4_commit_super(sb, 0); |
745 | return; | 751 | return; |
@@ -1371,7 +1377,8 @@ enum { | |||
1371 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota, | 1377 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota, |
1372 | Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err, | 1378 | Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err, |
1373 | Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_i_version, Opt_dax, | 1379 | Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_i_version, Opt_dax, |
1374 | Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_mblk_io_submit, | 1380 | Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_warn_on_error, |
1381 | Opt_nowarn_on_error, Opt_mblk_io_submit, | ||
1375 | Opt_lazytime, Opt_nolazytime, Opt_debug_want_extra_isize, | 1382 | Opt_lazytime, Opt_nolazytime, Opt_debug_want_extra_isize, |
1376 | Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, | 1383 | Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, |
1377 | Opt_inode_readahead_blks, Opt_journal_ioprio, | 1384 | Opt_inode_readahead_blks, Opt_journal_ioprio, |
@@ -1438,6 +1445,8 @@ static const match_table_t tokens = { | |||
1438 | {Opt_dax, "dax"}, | 1445 | {Opt_dax, "dax"}, |
1439 | {Opt_stripe, "stripe=%u"}, | 1446 | {Opt_stripe, "stripe=%u"}, |
1440 | {Opt_delalloc, "delalloc"}, | 1447 | {Opt_delalloc, "delalloc"}, |
1448 | {Opt_warn_on_error, "warn_on_error"}, | ||
1449 | {Opt_nowarn_on_error, "nowarn_on_error"}, | ||
1441 | {Opt_lazytime, "lazytime"}, | 1450 | {Opt_lazytime, "lazytime"}, |
1442 | {Opt_nolazytime, "nolazytime"}, | 1451 | {Opt_nolazytime, "nolazytime"}, |
1443 | {Opt_debug_want_extra_isize, "debug_want_extra_isize=%u"}, | 1452 | {Opt_debug_want_extra_isize, "debug_want_extra_isize=%u"}, |
@@ -1602,6 +1611,8 @@ static const struct mount_opts { | |||
1602 | MOPT_EXT4_ONLY | MOPT_SET | MOPT_EXPLICIT}, | 1611 | MOPT_EXT4_ONLY | MOPT_SET | MOPT_EXPLICIT}, |
1603 | {Opt_nodelalloc, EXT4_MOUNT_DELALLOC, | 1612 | {Opt_nodelalloc, EXT4_MOUNT_DELALLOC, |
1604 | MOPT_EXT4_ONLY | MOPT_CLEAR}, | 1613 | MOPT_EXT4_ONLY | MOPT_CLEAR}, |
1614 | {Opt_warn_on_error, EXT4_MOUNT_WARN_ON_ERROR, MOPT_SET}, | ||
1615 | {Opt_nowarn_on_error, EXT4_MOUNT_WARN_ON_ERROR, MOPT_CLEAR}, | ||
1605 | {Opt_nojournal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM, | 1616 | {Opt_nojournal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM, |
1606 | MOPT_EXT4_ONLY | MOPT_CLEAR}, | 1617 | MOPT_EXT4_ONLY | MOPT_CLEAR}, |
1607 | {Opt_journal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM, | 1618 | {Opt_journal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM, |
@@ -2331,6 +2342,7 @@ static int ext4_check_descriptors(struct super_block *sb, | |||
2331 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 2342 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
2332 | ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block); | 2343 | ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block); |
2333 | ext4_fsblk_t last_block; | 2344 | ext4_fsblk_t last_block; |
2345 | ext4_fsblk_t last_bg_block = sb_block + ext4_bg_num_gdb(sb, 0) + 1; | ||
2334 | ext4_fsblk_t block_bitmap; | 2346 | ext4_fsblk_t block_bitmap; |
2335 | ext4_fsblk_t inode_bitmap; | 2347 | ext4_fsblk_t inode_bitmap; |
2336 | ext4_fsblk_t inode_table; | 2348 | ext4_fsblk_t inode_table; |
@@ -2363,6 +2375,14 @@ static int ext4_check_descriptors(struct super_block *sb, | |||
2363 | if (!sb_rdonly(sb)) | 2375 | if (!sb_rdonly(sb)) |
2364 | return 0; | 2376 | return 0; |
2365 | } | 2377 | } |
2378 | if (block_bitmap >= sb_block + 1 && | ||
2379 | block_bitmap <= last_bg_block) { | ||
2380 | ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " | ||
2381 | "Block bitmap for group %u overlaps " | ||
2382 | "block group descriptors", i); | ||
2383 | if (!sb_rdonly(sb)) | ||
2384 | return 0; | ||
2385 | } | ||
2366 | if (block_bitmap < first_block || block_bitmap > last_block) { | 2386 | if (block_bitmap < first_block || block_bitmap > last_block) { |
2367 | ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " | 2387 | ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " |
2368 | "Block bitmap for group %u not in group " | 2388 | "Block bitmap for group %u not in group " |
@@ -2377,6 +2397,14 @@ static int ext4_check_descriptors(struct super_block *sb, | |||
2377 | if (!sb_rdonly(sb)) | 2397 | if (!sb_rdonly(sb)) |
2378 | return 0; | 2398 | return 0; |
2379 | } | 2399 | } |
2400 | if (inode_bitmap >= sb_block + 1 && | ||
2401 | inode_bitmap <= last_bg_block) { | ||
2402 | ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " | ||
2403 | "Inode bitmap for group %u overlaps " | ||
2404 | "block group descriptors", i); | ||
2405 | if (!sb_rdonly(sb)) | ||
2406 | return 0; | ||
2407 | } | ||
2380 | if (inode_bitmap < first_block || inode_bitmap > last_block) { | 2408 | if (inode_bitmap < first_block || inode_bitmap > last_block) { |
2381 | ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " | 2409 | ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " |
2382 | "Inode bitmap for group %u not in group " | 2410 | "Inode bitmap for group %u not in group " |
@@ -2391,6 +2419,14 @@ static int ext4_check_descriptors(struct super_block *sb, | |||
2391 | if (!sb_rdonly(sb)) | 2419 | if (!sb_rdonly(sb)) |
2392 | return 0; | 2420 | return 0; |
2393 | } | 2421 | } |
2422 | if (inode_table >= sb_block + 1 && | ||
2423 | inode_table <= last_bg_block) { | ||
2424 | ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " | ||
2425 | "Inode table for group %u overlaps " | ||
2426 | "block group descriptors", i); | ||
2427 | if (!sb_rdonly(sb)) | ||
2428 | return 0; | ||
2429 | } | ||
2394 | if (inode_table < first_block || | 2430 | if (inode_table < first_block || |
2395 | inode_table + sbi->s_itb_per_group - 1 > last_block) { | 2431 | inode_table + sbi->s_itb_per_group - 1 > last_block) { |
2396 | ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " | 2432 | ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " |
@@ -3097,13 +3133,22 @@ static ext4_group_t ext4_has_uninit_itable(struct super_block *sb) | |||
3097 | ext4_group_t group, ngroups = EXT4_SB(sb)->s_groups_count; | 3133 | ext4_group_t group, ngroups = EXT4_SB(sb)->s_groups_count; |
3098 | struct ext4_group_desc *gdp = NULL; | 3134 | struct ext4_group_desc *gdp = NULL; |
3099 | 3135 | ||
3136 | if (!ext4_has_group_desc_csum(sb)) | ||
3137 | return ngroups; | ||
3138 | |||
3100 | for (group = 0; group < ngroups; group++) { | 3139 | for (group = 0; group < ngroups; group++) { |
3101 | gdp = ext4_get_group_desc(sb, group, NULL); | 3140 | gdp = ext4_get_group_desc(sb, group, NULL); |
3102 | if (!gdp) | 3141 | if (!gdp) |
3103 | continue; | 3142 | continue; |
3104 | 3143 | ||
3105 | if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))) | 3144 | if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED)) |
3145 | continue; | ||
3146 | if (group != 0) | ||
3106 | break; | 3147 | break; |
3148 | ext4_error(sb, "Inode table for bg 0 marked as " | ||
3149 | "needing zeroing"); | ||
3150 | if (sb_rdonly(sb)) | ||
3151 | return ngroups; | ||
3107 | } | 3152 | } |
3108 | 3153 | ||
3109 | return group; | 3154 | return group; |
@@ -3742,6 +3787,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3742 | le32_to_cpu(es->s_log_block_size)); | 3787 | le32_to_cpu(es->s_log_block_size)); |
3743 | goto failed_mount; | 3788 | goto failed_mount; |
3744 | } | 3789 | } |
3790 | if (le32_to_cpu(es->s_log_cluster_size) > | ||
3791 | (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) { | ||
3792 | ext4_msg(sb, KERN_ERR, | ||
3793 | "Invalid log cluster size: %u", | ||
3794 | le32_to_cpu(es->s_log_cluster_size)); | ||
3795 | goto failed_mount; | ||
3796 | } | ||
3745 | 3797 | ||
3746 | if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (blocksize / 4)) { | 3798 | if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (blocksize / 4)) { |
3747 | ext4_msg(sb, KERN_ERR, | 3799 | ext4_msg(sb, KERN_ERR, |
@@ -3806,6 +3858,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3806 | } else { | 3858 | } else { |
3807 | sbi->s_inode_size = le16_to_cpu(es->s_inode_size); | 3859 | sbi->s_inode_size = le16_to_cpu(es->s_inode_size); |
3808 | sbi->s_first_ino = le32_to_cpu(es->s_first_ino); | 3860 | sbi->s_first_ino = le32_to_cpu(es->s_first_ino); |
3861 | if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) { | ||
3862 | ext4_msg(sb, KERN_ERR, "invalid first ino: %u", | ||
3863 | sbi->s_first_ino); | ||
3864 | goto failed_mount; | ||
3865 | } | ||
3809 | if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) || | 3866 | if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) || |
3810 | (!is_power_of_2(sbi->s_inode_size)) || | 3867 | (!is_power_of_2(sbi->s_inode_size)) || |
3811 | (sbi->s_inode_size > blocksize)) { | 3868 | (sbi->s_inode_size > blocksize)) { |
@@ -3882,13 +3939,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3882 | "block size (%d)", clustersize, blocksize); | 3939 | "block size (%d)", clustersize, blocksize); |
3883 | goto failed_mount; | 3940 | goto failed_mount; |
3884 | } | 3941 | } |
3885 | if (le32_to_cpu(es->s_log_cluster_size) > | ||
3886 | (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) { | ||
3887 | ext4_msg(sb, KERN_ERR, | ||
3888 | "Invalid log cluster size: %u", | ||
3889 | le32_to_cpu(es->s_log_cluster_size)); | ||
3890 | goto failed_mount; | ||
3891 | } | ||
3892 | sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) - | 3942 | sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) - |
3893 | le32_to_cpu(es->s_log_block_size); | 3943 | le32_to_cpu(es->s_log_block_size); |
3894 | sbi->s_clusters_per_group = | 3944 | sbi->s_clusters_per_group = |
@@ -3909,10 +3959,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3909 | } | 3959 | } |
3910 | } else { | 3960 | } else { |
3911 | if (clustersize != blocksize) { | 3961 | if (clustersize != blocksize) { |
3912 | ext4_warning(sb, "fragment/cluster size (%d) != " | 3962 | ext4_msg(sb, KERN_ERR, |
3913 | "block size (%d)", clustersize, | 3963 | "fragment/cluster size (%d) != " |
3914 | blocksize); | 3964 | "block size (%d)", clustersize, blocksize); |
3915 | clustersize = blocksize; | 3965 | goto failed_mount; |
3916 | } | 3966 | } |
3917 | if (sbi->s_blocks_per_group > blocksize * 8) { | 3967 | if (sbi->s_blocks_per_group > blocksize * 8) { |
3918 | ext4_msg(sb, KERN_ERR, | 3968 | ext4_msg(sb, KERN_ERR, |
@@ -3966,6 +4016,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3966 | ext4_blocks_count(es)); | 4016 | ext4_blocks_count(es)); |
3967 | goto failed_mount; | 4017 | goto failed_mount; |
3968 | } | 4018 | } |
4019 | if ((es->s_first_data_block == 0) && (es->s_log_block_size == 0) && | ||
4020 | (sbi->s_cluster_ratio == 1)) { | ||
4021 | ext4_msg(sb, KERN_WARNING, "bad geometry: first data " | ||
4022 | "block is 0 with a 1k block and cluster size"); | ||
4023 | goto failed_mount; | ||
4024 | } | ||
4025 | |||
3969 | blocks_count = (ext4_blocks_count(es) - | 4026 | blocks_count = (ext4_blocks_count(es) - |
3970 | le32_to_cpu(es->s_first_data_block) + | 4027 | le32_to_cpu(es->s_first_data_block) + |
3971 | EXT4_BLOCKS_PER_GROUP(sb) - 1); | 4028 | EXT4_BLOCKS_PER_GROUP(sb) - 1); |
@@ -4001,6 +4058,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
4001 | ret = -ENOMEM; | 4058 | ret = -ENOMEM; |
4002 | goto failed_mount; | 4059 | goto failed_mount; |
4003 | } | 4060 | } |
4061 | if (((u64)sbi->s_groups_count * sbi->s_inodes_per_group) != | ||
4062 | le32_to_cpu(es->s_inodes_count)) { | ||
4063 | ext4_msg(sb, KERN_ERR, "inodes count not valid: %u vs %llu", | ||
4064 | le32_to_cpu(es->s_inodes_count), | ||
4065 | ((u64)sbi->s_groups_count * sbi->s_inodes_per_group)); | ||
4066 | ret = -EINVAL; | ||
4067 | goto failed_mount; | ||
4068 | } | ||
4004 | 4069 | ||
4005 | bgl_lock_init(sbi->s_blockgroup_lock); | 4070 | bgl_lock_init(sbi->s_blockgroup_lock); |
4006 | 4071 | ||
@@ -4736,6 +4801,14 @@ static int ext4_commit_super(struct super_block *sb, int sync) | |||
4736 | 4801 | ||
4737 | if (!sbh || block_device_ejected(sb)) | 4802 | if (!sbh || block_device_ejected(sb)) |
4738 | return error; | 4803 | return error; |
4804 | |||
4805 | /* | ||
4806 | * The superblock bh should be mapped, but it might not be if the | ||
4807 | * device was hot-removed. Not much we can do but fail the I/O. | ||
4808 | */ | ||
4809 | if (!buffer_mapped(sbh)) | ||
4810 | return error; | ||
4811 | |||
4739 | /* | 4812 | /* |
4740 | * If the file system is mounted read-only, don't update the | 4813 | * If the file system is mounted read-only, don't update the |
4741 | * superblock write time. This avoids updating the superblock | 4814 | * superblock write time. This avoids updating the superblock |
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index fc4ced59c565..723df14f4084 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -230,12 +230,12 @@ __ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh, | |||
230 | { | 230 | { |
231 | int error = -EFSCORRUPTED; | 231 | int error = -EFSCORRUPTED; |
232 | 232 | ||
233 | if (buffer_verified(bh)) | ||
234 | return 0; | ||
235 | |||
236 | if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) || | 233 | if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) || |
237 | BHDR(bh)->h_blocks != cpu_to_le32(1)) | 234 | BHDR(bh)->h_blocks != cpu_to_le32(1)) |
238 | goto errout; | 235 | goto errout; |
236 | if (buffer_verified(bh)) | ||
237 | return 0; | ||
238 | |||
239 | error = -EFSBADCRC; | 239 | error = -EFSBADCRC; |
240 | if (!ext4_xattr_block_csum_verify(inode, bh)) | 240 | if (!ext4_xattr_block_csum_verify(inode, bh)) |
241 | goto errout; | 241 | goto errout; |
@@ -1560,7 +1560,7 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i, | |||
1560 | handle_t *handle, struct inode *inode, | 1560 | handle_t *handle, struct inode *inode, |
1561 | bool is_block) | 1561 | bool is_block) |
1562 | { | 1562 | { |
1563 | struct ext4_xattr_entry *last; | 1563 | struct ext4_xattr_entry *last, *next; |
1564 | struct ext4_xattr_entry *here = s->here; | 1564 | struct ext4_xattr_entry *here = s->here; |
1565 | size_t min_offs = s->end - s->base, name_len = strlen(i->name); | 1565 | size_t min_offs = s->end - s->base, name_len = strlen(i->name); |
1566 | int in_inode = i->in_inode; | 1566 | int in_inode = i->in_inode; |
@@ -1595,7 +1595,13 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i, | |||
1595 | 1595 | ||
1596 | /* Compute min_offs and last. */ | 1596 | /* Compute min_offs and last. */ |
1597 | last = s->first; | 1597 | last = s->first; |
1598 | for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { | 1598 | for (; !IS_LAST_ENTRY(last); last = next) { |
1599 | next = EXT4_XATTR_NEXT(last); | ||
1600 | if ((void *)next >= s->end) { | ||
1601 | EXT4_ERROR_INODE(inode, "corrupted xattr entries"); | ||
1602 | ret = -EFSCORRUPTED; | ||
1603 | goto out; | ||
1604 | } | ||
1599 | if (!last->e_value_inum && last->e_value_size) { | 1605 | if (!last->e_value_inum && last->e_value_size) { |
1600 | size_t offs = le16_to_cpu(last->e_value_offs); | 1606 | size_t offs = le16_to_cpu(last->e_value_offs); |
1601 | if (offs < min_offs) | 1607 | if (offs < min_offs) |
@@ -2206,23 +2212,8 @@ int ext4_xattr_ibody_inline_set(handle_t *handle, struct inode *inode, | |||
2206 | if (EXT4_I(inode)->i_extra_isize == 0) | 2212 | if (EXT4_I(inode)->i_extra_isize == 0) |
2207 | return -ENOSPC; | 2213 | return -ENOSPC; |
2208 | error = ext4_xattr_set_entry(i, s, handle, inode, false /* is_block */); | 2214 | error = ext4_xattr_set_entry(i, s, handle, inode, false /* is_block */); |
2209 | if (error) { | 2215 | if (error) |
2210 | if (error == -ENOSPC && | 2216 | return error; |
2211 | ext4_has_inline_data(inode)) { | ||
2212 | error = ext4_try_to_evict_inline_data(handle, inode, | ||
2213 | EXT4_XATTR_LEN(strlen(i->name) + | ||
2214 | EXT4_XATTR_SIZE(i->value_len))); | ||
2215 | if (error) | ||
2216 | return error; | ||
2217 | error = ext4_xattr_ibody_find(inode, i, is); | ||
2218 | if (error) | ||
2219 | return error; | ||
2220 | error = ext4_xattr_set_entry(i, s, handle, inode, | ||
2221 | false /* is_block */); | ||
2222 | } | ||
2223 | if (error) | ||
2224 | return error; | ||
2225 | } | ||
2226 | header = IHDR(inode, ext4_raw_inode(&is->iloc)); | 2217 | header = IHDR(inode, ext4_raw_inode(&is->iloc)); |
2227 | if (!IS_LAST_ENTRY(s->first)) { | 2218 | if (!IS_LAST_ENTRY(s->first)) { |
2228 | header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC); | 2219 | header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC); |
@@ -2651,6 +2642,11 @@ static int ext4_xattr_make_inode_space(handle_t *handle, struct inode *inode, | |||
2651 | last = IFIRST(header); | 2642 | last = IFIRST(header); |
2652 | /* Find the entry best suited to be pushed into EA block */ | 2643 | /* Find the entry best suited to be pushed into EA block */ |
2653 | for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { | 2644 | for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { |
2645 | /* never move system.data out of the inode */ | ||
2646 | if ((last->e_name_len == 4) && | ||
2647 | (last->e_name_index == EXT4_XATTR_INDEX_SYSTEM) && | ||
2648 | !memcmp(last->e_name, "data", 4)) | ||
2649 | continue; | ||
2654 | total_size = EXT4_XATTR_LEN(last->e_name_len); | 2650 | total_size = EXT4_XATTR_LEN(last->e_name_len); |
2655 | if (!last->e_value_inum) | 2651 | if (!last->e_value_inum) |
2656 | total_size += EXT4_XATTR_SIZE( | 2652 | total_size += EXT4_XATTR_SIZE( |
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 51dd68e67b0f..c0b66a7a795b 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
@@ -1361,6 +1361,13 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) | |||
1361 | if (jh->b_transaction == transaction && | 1361 | if (jh->b_transaction == transaction && |
1362 | jh->b_jlist != BJ_Metadata) { | 1362 | jh->b_jlist != BJ_Metadata) { |
1363 | jbd_lock_bh_state(bh); | 1363 | jbd_lock_bh_state(bh); |
1364 | if (jh->b_transaction == transaction && | ||
1365 | jh->b_jlist != BJ_Metadata) | ||
1366 | pr_err("JBD2: assertion failure: h_type=%u " | ||
1367 | "h_line_no=%u block_no=%llu jlist=%u\n", | ||
1368 | handle->h_type, handle->h_line_no, | ||
1369 | (unsigned long long) bh->b_blocknr, | ||
1370 | jh->b_jlist); | ||
1364 | J_ASSERT_JH(jh, jh->b_transaction != transaction || | 1371 | J_ASSERT_JH(jh, jh->b_transaction != transaction || |
1365 | jh->b_jlist == BJ_Metadata); | 1372 | jh->b_jlist == BJ_Metadata); |
1366 | jbd_unlock_bh_state(bh); | 1373 | jbd_unlock_bh_state(bh); |
@@ -1380,11 +1387,11 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) | |||
1380 | * of the transaction. This needs to be done | 1387 | * of the transaction. This needs to be done |
1381 | * once a transaction -bzzz | 1388 | * once a transaction -bzzz |
1382 | */ | 1389 | */ |
1383 | jh->b_modified = 1; | ||
1384 | if (handle->h_buffer_credits <= 0) { | 1390 | if (handle->h_buffer_credits <= 0) { |
1385 | ret = -ENOSPC; | 1391 | ret = -ENOSPC; |
1386 | goto out_unlock_bh; | 1392 | goto out_unlock_bh; |
1387 | } | 1393 | } |
1394 | jh->b_modified = 1; | ||
1388 | handle->h_buffer_credits--; | 1395 | handle->h_buffer_credits--; |
1389 | } | 1396 | } |
1390 | 1397 | ||