History

Merge tag 'ext4_for_linus-6.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4

Pull ext4 fixes from Ted Ts'o: "A few more miscellaneous ext4 bug fixes and cleanups including some syzbot failures and fixing a stale file handing refeencing an inode previously used as a regular file, but which has been deleted and reused as an ea_inode would result in ext4 erroneously considering this a case of fs corruption" * tag 'ext4_for_linus-6.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: fix off-by-one error in do_split ext4: make block validity check resistent to sb bh corruption ext4: avoid -Wflex-array-member-not-at-end warning Documentation: ext4: Add fields to ext4_super_block documentation ext4: don't treat fhandle lookup of ea_inode as FS corruption

Linus Torvalds committed 1 year ago

Commit 5aaaedb2 parents 051ea72 94824ac5 files · +77 −43Browse files

Unified · Split

5 files
  1. Documentation/filesystems/ext4/super.rst +14 −6
  2. fs/ext4/block_validity.c +2 −3
  3. fs/ext4/inode.c +52 −23
  4. fs/ext4/mballoc.c +8 −10
  5. fs/ext4/namei.c +1 −1
Documentation/filesystems/ext4/super.rst+14−6
@@ -328,9 +328,13 @@ The ext4 superblock is laid out as follows in · 327 unmodified lines
328 - s_checksum_type328 - s_checksum_type
329 - Metadata checksum algorithm type. The only valid value is 1 (crc32c).329 - Metadata checksum algorithm type. The only valid value is 1 (crc32c).
330 * - 0x176330 * - 0x176
331 - __le16331 - \_\_u8
332 - s_reserved_pad332 - s\_encryption\_level
333 -333 - Versioning level for encryption.
334 * - 0x177
335 - \_\_u8
336 - s\_reserved\_pad
337 - Padding to next 32bits.
334 * - 0x178338 * - 0x178
335 - __le64339 - __le64
336 - s_kbytes_written340 - s_kbytes_written
@@ -466,9 +470,13 @@ The ext4 superblock is laid out as follows in · 129 unmodified lines
466 - s_last_error_time_hi470 - s_last_error_time_hi
467 - Upper 8 bits of the s_last_error_time field.471 - Upper 8 bits of the s_last_error_time field.
468 * - 0x27A472 * - 0x27A
469 - __u8473 - \_\_u8
470 - s_pad[2]474 - s\_first\_error\_errcode
471 - Zero padding.475 -
476 * - 0x27B
477 - \_\_u8
478 - s\_last\_error\_errcode
479 -
472 * - 0x27C480 * - 0x27C
473 - __le16481 - __le16
474 - s_encoding482 - s_encoding
fs/ext4/block_validity.c+2−3
@@ -351,10 +351,9 @@ int ext4_check_blockref(const char *function, unsigned int line, · 350 unmodified lines
351{351{
352 __le32 *bref = p;352 __le32 *bref = p;
353 unsigned int blk;353 unsigned int blk;
354 journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
354 355
355 if (ext4_has_feature_journal(inode->i_sb) &&356 if (journal && inode == journal->j_inode)
356 (inode->i_ino ==
357 le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum)))
358 return 0;357 return 0;
359 358
360 while (bref < p+max) {359 while (bref < p+max) {
fs/ext4/inode.c+52−23
@@ -386,10 +386,11 @@ static int __check_block_validity(struct inode *inode, const char *func, · 385 unmodified lines
386 unsigned int line,386 unsigned int line,
387 struct ext4_map_blocks *map)387 struct ext4_map_blocks *map)
388{388{
389 if (ext4_has_feature_journal(inode->i_sb) &&389 journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
390 (inode->i_ino ==390
391 le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum)))391 if (journal && inode == journal->j_inode)
392 return 0;392 return 0;
393
393 if (!ext4_inode_block_valid(inode, map->m_pblk, map->m_len)) {394 if (!ext4_inode_block_valid(inode, map->m_pblk, map->m_len)) {
394 ext4_error_inode(inode, func, line, map->m_pblk,395 ext4_error_inode(inode, func, line, map->m_pblk,
395 "lblock %lu mapped to illegal pblock %llu "396 "lblock %lu mapped to illegal pblock %llu "
@@ -4724,22 +4725,43 @@ static inline void ext4_inode_set_iversion_queried(struct inode *inode, u64 val) · 4328 unmodified lines
4724 inode_set_iversion_queried(inode, val);4725 inode_set_iversion_queried(inode, val);
4725}4726}
4726 4727
4727static const char *check_igot_inode(struct inode *inode, ext4_iget_flags flags)4728static int check_igot_inode(struct inode *inode, ext4_iget_flags flags,
4728 4729 const char *function, unsigned int line)
4729{4730{
4731 const char *err_str;
4732
4730 if (flags & EXT4_IGET_EA_INODE) {4733 if (flags & EXT4_IGET_EA_INODE) {
4731 if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL))4734 if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) {
4732 return "missing EA_INODE flag";4735 err_str = "missing EA_INODE flag";
4736 goto error;
4737 }
4733 if (ext4_test_inode_state(inode, EXT4_STATE_XATTR) ||4738 if (ext4_test_inode_state(inode, EXT4_STATE_XATTR) ||
4734 EXT4_I(inode)->i_file_acl)4739 EXT4_I(inode)->i_file_acl) {
4735 return "ea_inode with extended attributes";4740 err_str = "ea_inode with extended attributes";
4741 goto error;
4742 }
4736 } else {4743 } else {
4737 if ((EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL))4744 if ((EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) {
4738 return "unexpected EA_INODE flag";4745 /*
4746 * open_by_handle_at() could provide an old inode number
4747 * that has since been reused for an ea_inode; this does
4748 * not indicate filesystem corruption
4749 */
4750 if (flags & EXT4_IGET_HANDLE)
4751 return -ESTALE;
4752 err_str = "unexpected EA_INODE flag";
4753 goto error;
4754 }
4755 }
4756 if (is_bad_inode(inode) && !(flags & EXT4_IGET_BAD)) {
4757 err_str = "unexpected bad inode w/o EXT4_IGET_BAD";
4758 goto error;
4739 }4759 }
4740 if (is_bad_inode(inode) && !(flags & EXT4_IGET_BAD))4760 return 0;
4741 return "unexpected bad inode w/o EXT4_IGET_BAD";4761
4742 return NULL;4762error:
4763 ext4_error_inode(inode, function, line, 0, err_str);
4764 return -EFSCORRUPTED;
4743}4765}
4744 4766
4745struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,4767struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
@@ -4751,7 +4773,6 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, · 5 unmodified lines
4751 struct ext4_inode_info *ei;4773 struct ext4_inode_info *ei;
4752 struct ext4_super_block *es = EXT4_SB(sb)->s_es;4774 struct ext4_super_block *es = EXT4_SB(sb)->s_es;
4753 struct inode *inode;4775 struct inode *inode;
4754 const char *err_str;
4755 journal_t *journal = EXT4_SB(sb)->s_journal;4776 journal_t *journal = EXT4_SB(sb)->s_journal;
4756 long ret;4777 long ret;
4757 loff_t size;4778 loff_t size;
@@ -4780,10 +4801,10 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, · 22 unmodified lines
4780 if (!inode)4801 if (!inode)
4781 return ERR_PTR(-ENOMEM);4802 return ERR_PTR(-ENOMEM);
4782 if (!(inode->i_state & I_NEW)) {4803 if (!(inode->i_state & I_NEW)) {
4783 if ((err_str = check_igot_inode(inode, flags)) != NULL) {4804 ret = check_igot_inode(inode, flags, function, line);
4784 ext4_error_inode(inode, function, line, 0, err_str);4805 if (ret) {
4785 iput(inode);4806 iput(inode);
4786 return ERR_PTR(-EFSCORRUPTED);4807 return ERR_PTR(ret);
4787 }4808 }
4788 return inode;4809 return inode;
4789 }4810 }
@@ -5065,13 +5086,21 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, · 275 unmodified lines
5065 ret = -EFSCORRUPTED;5086 ret = -EFSCORRUPTED;
5066 goto bad_inode;5087 goto bad_inode;
5067 }5088 }
5068 if ((err_str = check_igot_inode(inode, flags)) != NULL) {5089 ret = check_igot_inode(inode, flags, function, line);
5069 ext4_error_inode(inode, function, line, 0, err_str);5090 /*
5070 ret = -EFSCORRUPTED;5091 * -ESTALE here means there is nothing inherently wrong with the inode,
5071 goto bad_inode;5092 * it's just not an inode we can return for an fhandle lookup.
5093 */
5094 if (ret == -ESTALE) {
5095 brelse(iloc.bh);
5096 unlock_new_inode(inode);
5097 iput(inode);
5098 return ERR_PTR(-ESTALE);
5072 }5099 }
5073 5100 if (ret)
5101 goto bad_inode;
5074 brelse(iloc.bh);5102 brelse(iloc.bh);
5103
5075 unlock_new_inode(inode);5104 unlock_new_inode(inode);
5076 return inode;5105 return inode;
5077 5106
fs/ext4/mballoc.c+8−10
@@ -3037,10 +3037,8 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v) · 3036 unmodified lines
3037 unsigned char blocksize_bits = min_t(unsigned char,3037 unsigned char blocksize_bits = min_t(unsigned char,
3038 sb->s_blocksize_bits,3038 sb->s_blocksize_bits,
3039 EXT4_MAX_BLOCK_LOG_SIZE);3039 EXT4_MAX_BLOCK_LOG_SIZE);
3040 struct sg {3040 DEFINE_RAW_FLEX(struct ext4_group_info, sg, bb_counters,
3041 struct ext4_group_info info;3041 EXT4_MAX_BLOCK_LOG_SIZE + 2);
3042 ext4_grpblk_t counters[EXT4_MAX_BLOCK_LOG_SIZE + 2];
3043 } sg;
3044 3042
3045 group--;3043 group--;
3046 if (group == 0)3044 if (group == 0)
@@ -3048,7 +3046,7 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v) · 1 unmodified line
3048 " 2^0 2^1 2^2 2^3 2^4 2^5 2^6 "3046 " 2^0 2^1 2^2 2^3 2^4 2^5 2^6 "
3049 " 2^7 2^8 2^9 2^10 2^11 2^12 2^13 ]\n");3047 " 2^7 2^8 2^9 2^10 2^11 2^12 2^13 ]\n");
3050 3048
3051 i = (blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) +3049 i = (blocksize_bits + 2) * sizeof(sg->bb_counters[0]) +
3052 sizeof(struct ext4_group_info);3050 sizeof(struct ext4_group_info);
3053 3051
3054 grinfo = ext4_get_group_info(sb, group);3052 grinfo = ext4_get_group_info(sb, group);
@@ -3068,14 +3066,14 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v) · 13 unmodified lines
3068 * We care only about free space counters in the group info and3066 * We care only about free space counters in the group info and
3069 * these are safe to access even after the buddy has been unloaded3067 * these are safe to access even after the buddy has been unloaded
3070 */3068 */
3071 memcpy(&sg, grinfo, i);3069 memcpy(sg, grinfo, i);
3072 seq_printf(seq, "#%-5u: %-5u %-5u %-5u [", group, sg.info.bb_free,3070 seq_printf(seq, "#%-5u: %-5u %-5u %-5u [", group, sg->bb_free,
3073 sg.info.bb_fragments, sg.info.bb_first_free);3071 sg->bb_fragments, sg->bb_first_free);
3074 for (i = 0; i <= 13; i++)3072 for (i = 0; i <= 13; i++)
3075 seq_printf(seq, " %-5u", i <= blocksize_bits + 1 ?3073 seq_printf(seq, " %-5u", i <= blocksize_bits + 1 ?
3076 sg.info.bb_counters[i] : 0);3074 sg->bb_counters[i] : 0);
3077 seq_puts(seq, " ]");3075 seq_puts(seq, " ]");
3078 if (EXT4_MB_GRP_BBITMAP_CORRUPT(&sg.info))3076 if (EXT4_MB_GRP_BBITMAP_CORRUPT(sg))
3079 seq_puts(seq, " Block bitmap corrupted!");3077 seq_puts(seq, " Block bitmap corrupted!");
3080 seq_putc(seq, '\n');3078 seq_putc(seq, '\n');
3081 return 0;3079 return 0;
fs/ext4/namei.c+1−1
@@ -1971,7 +1971,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, · 1970 unmodified lines
1971 * split it in half by count; each resulting block will have at least1971 * split it in half by count; each resulting block will have at least
1972 * half the space free.1972 * half the space free.
1973 */1973 */
1974 if (i > 0)1974 if (i >= 0)
1975 split = count - move;1975 split = count - move;
1976 else1976 else
1977 split = count/2;1977 split = count/2;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t