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
328328 - s_checksum_type
329329 - Metadata checksum algorithm type. The only valid value is 1 (crc32c).
330330 * - 0x176
331− - __le16
332− - s_reserved_pad
333− -
331+ - \_\_u8
332+ - s\_encryption\_level
333+ - Versioning level for encryption.
334+ * - 0x177
335+ - \_\_u8
336+ - s\_reserved\_pad
337+ - Padding to next 32bits.
334338 * - 0x178
335339 - __le64
336340 - s_kbytes_written
@@ -466,9 +470,13 @@ The ext4 superblock is laid out as follows in · 129 unmodified lines
466470 - s_last_error_time_hi
467471 - Upper 8 bits of the s_last_error_time field.
468472 * - 0x27A
469− - __u8
470− - s_pad[2]
471− - Zero padding.
473+ - \_\_u8
474+ - s\_first\_error\_errcode
475+ -
476+ * - 0x27B
477+ - \_\_u8
478+ - s\_last\_error\_errcode
479+ -
472480 * - 0x27C
473481 - __le16
474482 - 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
351351 {
352352 __le32 *bref = p;
353353 unsigned int blk;
354+ journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
354355
355− if (ext4_has_feature_journal(inode->i_sb) &&
356− (inode->i_ino ==
357− le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum)))
356+ if (journal && inode == journal->j_inode)
358357 return 0;
359358
360359 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
386386 unsigned int line,
387387 struct ext4_map_blocks *map)
388388 {
389− if (ext4_has_feature_journal(inode->i_sb) &&
390− (inode->i_ino ==
391− le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum)))
389+ journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
390+
391+ if (journal && inode == journal->j_inode)
392392 return 0;
393+
393394 if (!ext4_inode_block_valid(inode, map->m_pblk, map->m_len)) {
394395 ext4_error_inode(inode, func, line, map->m_pblk,
395396 "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
47244725 inode_set_iversion_queried(inode, val);
47254726 }
47264727
4727−static const char *check_igot_inode(struct inode *inode, ext4_iget_flags flags)
4728−
4728+static int check_igot_inode(struct inode *inode, ext4_iget_flags flags,
4729+ const char *function, unsigned int line)
47294730 {
4731+ const char *err_str;
4732+
47304733 if (flags & EXT4_IGET_EA_INODE) {
4731− if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL))
4732− return "missing EA_INODE flag";
4734+ if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) {
4735+ err_str = "missing EA_INODE flag";
4736+ goto error;
4737+ }
47334738 if (ext4_test_inode_state(inode, EXT4_STATE_XATTR) ||
4734− EXT4_I(inode)->i_file_acl)
4735− return "ea_inode with extended attributes";
4739+ EXT4_I(inode)->i_file_acl) {
4740+ err_str = "ea_inode with extended attributes";
4741+ goto error;
4742+ }
47364743 } else {
4737− if ((EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL))
4738− return "unexpected EA_INODE flag";
4744+ if ((EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) {
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;
47394759 }
4740− if (is_bad_inode(inode) && !(flags & EXT4_IGET_BAD))
4741− return "unexpected bad inode w/o EXT4_IGET_BAD";
4742− return NULL;
4760+ return 0;
4761+
4762+error:
4763+ ext4_error_inode(inode, function, line, 0, err_str);
4764+ return -EFSCORRUPTED;
47434765 }
47444766
47454767 struct 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
47514773 struct ext4_inode_info *ei;
47524774 struct ext4_super_block *es = EXT4_SB(sb)->s_es;
47534775 struct inode *inode;
4754− const char *err_str;
47554776 journal_t *journal = EXT4_SB(sb)->s_journal;
47564777 long ret;
47574778 loff_t size;
@@ -4780,10 +4801,10 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, · 22 unmodified lines
47804801 if (!inode)
47814802 return ERR_PTR(-ENOMEM);
47824803 if (!(inode->i_state & I_NEW)) {
4783− if ((err_str = check_igot_inode(inode, flags)) != NULL) {
4784− ext4_error_inode(inode, function, line, 0, err_str);
4804+ ret = check_igot_inode(inode, flags, function, line);
4805+ if (ret) {
47854806 iput(inode);
4786− return ERR_PTR(-EFSCORRUPTED);
4807+ return ERR_PTR(ret);
47874808 }
47884809 return inode;
47894810 }
@@ -5065,13 +5086,21 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, · 275 unmodified lines
50655086 ret = -EFSCORRUPTED;
50665087 goto bad_inode;
50675088 }
5068− if ((err_str = check_igot_inode(inode, flags)) != NULL) {
5069− ext4_error_inode(inode, function, line, 0, err_str);
5070− ret = -EFSCORRUPTED;
5071− goto bad_inode;
5089+ ret = check_igot_inode(inode, flags, function, line);
5090+ /*
5091+ * -ESTALE here means there is nothing inherently wrong with the 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);
50725099 }
5073−
5100+ if (ret)
5101+ goto bad_inode;
50745102 brelse(iloc.bh);
5103+
50755104 unlock_new_inode(inode);
50765105 return inode;
50775106
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
30373037 unsigned char blocksize_bits = min_t(unsigned char,
30383038 sb->s_blocksize_bits,
30393039 EXT4_MAX_BLOCK_LOG_SIZE);
3040− struct sg {
3041− struct ext4_group_info info;
3042− ext4_grpblk_t counters[EXT4_MAX_BLOCK_LOG_SIZE + 2];
3043− } sg;
3040+ DEFINE_RAW_FLEX(struct ext4_group_info, sg, bb_counters,
3041+ EXT4_MAX_BLOCK_LOG_SIZE + 2);
30443042
30453043 group--;
30463044 if (group == 0)
@@ -3048,7 +3046,7 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v) · 1 unmodified line
30483046 " 2^0 2^1 2^2 2^3 2^4 2^5 2^6 "
30493047 " 2^7 2^8 2^9 2^10 2^11 2^12 2^13 ]\n");
30503048
3051− i = (blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) +
3049+ i = (blocksize_bits + 2) * sizeof(sg->bb_counters[0]) +
30523050 sizeof(struct ext4_group_info);
30533051
30543052 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
30683066 * We care only about free space counters in the group info and
30693067 * these are safe to access even after the buddy has been unloaded
30703068 */
3071− memcpy(&sg, grinfo, i);
3072− seq_printf(seq, "#%-5u: %-5u %-5u %-5u [", group, sg.info.bb_free,
3073− sg.info.bb_fragments, sg.info.bb_first_free);
3069+ memcpy(sg, grinfo, i);
3070+ seq_printf(seq, "#%-5u: %-5u %-5u %-5u [", group, sg->bb_free,
3071+ sg->bb_fragments, sg->bb_first_free);
30743072 for (i = 0; i <= 13; i++)
30753073 seq_printf(seq, " %-5u", i <= blocksize_bits + 1 ?
3076− sg.info.bb_counters[i] : 0);
3074+ sg->bb_counters[i] : 0);
30773075 seq_puts(seq, " ]");
3078− if (EXT4_MB_GRP_BBITMAP_CORRUPT(&sg.info))
3076+ if (EXT4_MB_GRP_BBITMAP_CORRUPT(sg))
30793077 seq_puts(seq, " Block bitmap corrupted!");
30803078 seq_putc(seq, '\n');
30813079 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
19711971 * split it in half by count; each resulting block will have at least
19721972 * half the space free.
19731973 */
1974− if (i > 0)
1974+ if (i >= 0)
19751975 split = count - move;
19761976 else
19771977 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