Pull ext4 fixes from Ted Ts'o: "Bug fixes and regressions for ext4, the most serious of which is a potential deadlock during directory renames that was introduced during the merge window discovered by a combination of syzbot and lockdep" * tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: zero i_disksize when initializing the bootloader inode ext4: make sure fs error flag setted before clear journal error ext4: commit super block if fs record error when journal record without error ext4, jbd2: add an optimized bmap for the journal inode ext4: fix WARNING in ext4_update_inline_data ext4: move where set the MAY_INLINE_DATA flag is set ext4: Fix deadlock during directory rename ext4: Fix comment about the 64BIT feature docs: ext4: modify the group desc size to 64 ext4: fix another off-by-one fsmap error on 1k block filesystems ext4: fix RENAME_WHITEOUT handling for inline directories ext4: make kobj_type structures constant ext4: fix cgroup writeback accounting with fs-layer encryption
Unified · Split
| @@ -105,9 +105,9 @@ descriptors. Instead, the superblock and a single block group descriptor · 104 unmodified lines | ||
| 105 | 105 | block is placed at the beginning of the first, second, and last block |
| 106 | 106 | groups in a meta-block group. A meta-block group is a collection of |
| 107 | 107 | block groups which can be described by a single block group descriptor |
| 108 | −block. Since the size of the block group descriptor structure is 32 | |
| 109 | −bytes, a meta-block group contains 32 block groups for filesystems with | |
| 110 | −a 1KB block size, and 128 block groups for filesystems with a 4KB | |
| 108 | +block. Since the size of the block group descriptor structure is 64 | |
| 109 | +bytes, a meta-block group contains 16 block groups for filesystems with | |
| 110 | +a 1KB block size, and 64 block groups for filesystems with a 4KB | |
| 111 | 111 | blocksize. Filesystems can either be created using this new block group |
| 112 | 112 | descriptor layout, or existing filesystems can be resized on-line, and |
| 113 | 113 | the field s_first_meta_bg in the superblock will indicate the first |
| @@ -1387,7 +1387,7 @@ struct ext4_super_block { · 1386 unmodified lines | ||
| 1387 | 1387 | __le32 s_first_meta_bg; /* First metablock block group */ |
| 1388 | 1388 | __le32 s_mkfs_time; /* When the filesystem was created */ |
| 1389 | 1389 | __le32 s_jnl_blocks[17]; /* Backup of the journal inode */ |
| 1390 | − /* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */ | |
| 1390 | + /* 64bit support valid if EXT4_FEATURE_INCOMPAT_64BIT */ | |
| 1391 | 1391 | /*150*/ __le32 s_blocks_count_hi; /* Blocks count */ |
| 1392 | 1392 | __le32 s_r_blocks_count_hi; /* Reserved blocks count */ |
| 1393 | 1393 | __le32 s_free_blocks_count_hi; /* Free blocks count */ |
| @@ -486,6 +486,8 @@ static int ext4_getfsmap_datadev(struct super_block *sb, · 485 unmodified lines | ||
| 486 | 486 | keys[0].fmr_physical = bofs; |
| 487 | 487 | if (keys[1].fmr_physical >= eofs) |
| 488 | 488 | keys[1].fmr_physical = eofs - 1; |
| 489 | + if (keys[1].fmr_physical < keys[0].fmr_physical) | |
| 490 | + return 0; | |
| 489 | 491 | start_fsb = keys[0].fmr_physical; |
| 490 | 492 | end_fsb = keys[1].fmr_physical; |
| 491 | 493 | |
| @@ -159,7 +159,6 @@ int ext4_find_inline_data_nolock(struct inode *inode) · 158 unmodified lines | ||
| 159 | 159 | (void *)ext4_raw_inode(&is.iloc)); |
| 160 | 160 | EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE + |
| 161 | 161 | le32_to_cpu(is.s.here->e_value_size); |
| 162 | − ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); | |
| 163 | 162 | } |
| 164 | 163 | out: |
| 165 | 164 | brelse(is.iloc.bh); |
| @@ -4797,8 +4797,13 @@ static inline int ext4_iget_extra_inode(struct inode *inode, · 4796 unmodified lines | ||
| 4797 | 4797 | |
| 4798 | 4798 | if (EXT4_INODE_HAS_XATTR_SPACE(inode) && |
| 4799 | 4799 | *magic == cpu_to_le32(EXT4_XATTR_MAGIC)) { |
| 4800 | + int err; | |
| 4801 | + | |
| 4800 | 4802 | ext4_set_inode_state(inode, EXT4_STATE_XATTR); |
| 4801 | − return ext4_find_inline_data_nolock(inode); | |
| 4803 | + err = ext4_find_inline_data_nolock(inode); | |
| 4804 | + if (!err && ext4_has_inline_data(inode)) | |
| 4805 | + ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); | |
| 4806 | + return err; | |
| 4802 | 4807 | } else |
| 4803 | 4808 | EXT4_I(inode)->i_inline_off = 0; |
| 4804 | 4809 | return 0; |
| @@ -431,6 +431,7 @@ static long swap_inode_boot_loader(struct super_block *sb, · 430 unmodified lines | ||
| 431 | 431 | ei_bl->i_flags = 0; |
| 432 | 432 | inode_set_iversion(inode_bl, 1); |
| 433 | 433 | i_size_write(inode_bl, 0); |
| 434 | + EXT4_I(inode_bl)->i_disksize = inode_bl->i_size; | |
| 434 | 435 | inode_bl->i_mode = S_IFREG; |
| 435 | 436 | if (ext4_has_feature_extents(sb)) { |
| 436 | 437 | ext4_set_inode_flag(inode_bl, EXT4_INODE_EXTENTS); |
| @@ -1595,11 +1595,10 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir, · 1594 unmodified lines | ||
| 1595 | 1595 | int has_inline_data = 1; |
| 1596 | 1596 | ret = ext4_find_inline_entry(dir, fname, res_dir, |
| 1597 | 1597 | &has_inline_data); |
| 1598 | − if (has_inline_data) { | |
| 1599 | − if (inlined) | |
| 1600 | − *inlined = 1; | |
| 1598 | + if (inlined) | |
| 1599 | + *inlined = has_inline_data; | |
| 1600 | + if (has_inline_data) | |
| 1601 | 1601 | goto cleanup_and_exit; |
| 1602 | − } | |
| 1603 | 1602 | } |
| 1604 | 1603 | |
| 1605 | 1604 | if ((namelen <= 2) && (name[0] == '.') && |
| @@ -3646,7 +3645,8 @@ static void ext4_resetent(handle_t *handle, struct ext4_renament *ent, · 2040 unmodified lines | ||
| 3646 | 3645 | * so the old->de may no longer valid and need to find it again |
| 3647 | 3646 | * before reset old inode info. |
| 3648 | 3647 | */ |
| 3649 | − old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL); | |
| 3648 | + old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, | |
| 3649 | + &old.inlined); | |
| 3650 | 3650 | if (IS_ERR(old.bh)) |
| 3651 | 3651 | retval = PTR_ERR(old.bh); |
| 3652 | 3652 | if (!old.bh) |
| @@ -3813,9 +3813,20 @@ static int ext4_rename(struct mnt_idmap *idmap, struct inode *old_dir, · 160 unmodified lines | ||
| 3813 | 3813 | return retval; |
| 3814 | 3814 | } |
| 3815 | 3815 | |
| 3816 | − old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL); | |
| 3817 | − if (IS_ERR(old.bh)) | |
| 3818 | − return PTR_ERR(old.bh); | |
| 3816 | + /* | |
| 3817 | + * We need to protect against old.inode directory getting converted | |
| 3818 | + * from inline directory format into a normal one. | |
| 3819 | + */ | |
| 3820 | + if (S_ISDIR(old.inode->i_mode)) | |
| 3821 | + inode_lock_nested(old.inode, I_MUTEX_NONDIR2); | |
| 3822 | + | |
| 3823 | + old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, | |
| 3824 | + &old.inlined); | |
| 3825 | + if (IS_ERR(old.bh)) { | |
| 3826 | + retval = PTR_ERR(old.bh); | |
| 3827 | + goto unlock_moved_dir; | |
| 3828 | + } | |
| 3829 | + | |
| 3819 | 3830 | /* |
| 3820 | 3831 | * Check for inode number is _not_ due to possible IO errors. |
| 3821 | 3832 | * We might rmdir the source, keep it as pwd of some process |
| @@ -3872,11 +3883,6 @@ static int ext4_rename(struct mnt_idmap *idmap, struct inode *old_dir, · 50 unmodified lines | ||
| 3872 | 3883 | if (new.dir != old.dir && EXT4_DIR_LINK_MAX(new.dir)) |
| 3873 | 3884 | goto end_rename; |
| 3874 | 3885 | } |
| 3875 | − /* | |
| 3876 | − * We need to protect against old.inode directory getting | |
| 3877 | − * converted from inline directory format into a normal one. | |
| 3878 | − */ | |
| 3879 | − inode_lock_nested(old.inode, I_MUTEX_NONDIR2); | |
| 3880 | 3886 | retval = ext4_rename_dir_prepare(handle, &old); |
| 3881 | 3887 | if (retval) { |
| 3882 | 3888 | inode_unlock(old.inode); |
| @@ -4013,12 +4019,15 @@ end_rename: · 130 unmodified lines | ||
| 4013 | 4019 | } else { |
| 4014 | 4020 | ext4_journal_stop(handle); |
| 4015 | 4021 | } |
| 4016 | − if (old.dir_bh) | |
| 4017 | − inode_unlock(old.inode); | |
| 4018 | 4022 | release_bh: |
| 4019 | 4023 | brelse(old.dir_bh); |
| 4020 | 4024 | brelse(old.bh); |
| 4021 | 4025 | brelse(new.bh); |
| 4026 | + | |
| 4027 | +unlock_moved_dir: | |
| 4028 | + if (S_ISDIR(old.inode->i_mode)) | |
| 4029 | + inode_unlock(old.inode); | |
| 4030 | + | |
| 4022 | 4031 | return retval; |
| 4023 | 4032 | } |
| 4024 | 4033 | |
| @@ -409,7 +409,8 @@ static void io_submit_init_bio(struct ext4_io_submit *io, · 408 unmodified lines | ||
| 409 | 409 | |
| 410 | 410 | static void io_submit_add_bh(struct ext4_io_submit *io, |
| 411 | 411 | struct inode *inode, |
| 412 | − struct page *page, | |
| 412 | + struct page *pagecache_page, | |
| 413 | + struct page *bounce_page, | |
| 413 | 414 | struct buffer_head *bh) |
| 414 | 415 | { |
| 415 | 416 | int ret; |
| @@ -421,10 +422,11 @@ submit_and_retry: · 5 unmodified lines | ||
| 421 | 422 | } |
| 422 | 423 | if (io->io_bio == NULL) |
| 423 | 424 | io_submit_init_bio(io, bh); |
| 424 | − ret = bio_add_page(io->io_bio, page, bh->b_size, bh_offset(bh)); | |
| 425 | + ret = bio_add_page(io->io_bio, bounce_page ?: pagecache_page, | |
| 426 | + bh->b_size, bh_offset(bh)); | |
| 425 | 427 | if (ret != bh->b_size) |
| 426 | 428 | goto submit_and_retry; |
| 427 | − wbc_account_cgroup_owner(io->io_wbc, page, bh->b_size); | |
| 429 | + wbc_account_cgroup_owner(io->io_wbc, pagecache_page, bh->b_size); | |
| 428 | 430 | io->io_next_block++; |
| 429 | 431 | } |
| 430 | 432 | |
| @@ -561,8 +563,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, · 130 unmodified lines | ||
| 561 | 563 | do { |
| 562 | 564 | if (!buffer_async_write(bh)) |
| 563 | 565 | continue; |
| 564 | − io_submit_add_bh(io, inode, | |
| 565 | − bounce_page ? bounce_page : page, bh); | |
| 566 | + io_submit_add_bh(io, inode, page, bounce_page, bh); | |
| 566 | 567 | } while ((bh = bh->b_this_page) != head); |
| 567 | 568 | unlock: |
| 568 | 569 | unlock_page(page); |
| @@ -5726,6 +5726,28 @@ static struct inode *ext4_get_journal_inode(struct super_block *sb, · 5725 unmodified lines | ||
| 5726 | 5726 | return journal_inode; |
| 5727 | 5727 | } |
| 5728 | 5728 | |
| 5729 | +static int ext4_journal_bmap(journal_t *journal, sector_t *block) | |
| 5730 | +{ | |
| 5731 | + struct ext4_map_blocks map; | |
| 5732 | + int ret; | |
| 5733 | + | |
| 5734 | + if (journal->j_inode == NULL) | |
| 5735 | + return 0; | |
| 5736 | + | |
| 5737 | + map.m_lblk = *block; | |
| 5738 | + map.m_len = 1; | |
| 5739 | + ret = ext4_map_blocks(NULL, journal->j_inode, &map, 0); | |
| 5740 | + if (ret <= 0) { | |
| 5741 | + ext4_msg(journal->j_inode->i_sb, KERN_CRIT, | |
| 5742 | + "journal bmap failed: block %llu ret %d\n", | |
| 5743 | + *block, ret); | |
| 5744 | + jbd2_journal_abort(journal, ret ? ret : -EIO); | |
| 5745 | + return ret; | |
| 5746 | + } | |
| 5747 | + *block = map.m_pblk; | |
| 5748 | + return 0; | |
| 5749 | +} | |
| 5750 | + | |
| 5729 | 5751 | static journal_t *ext4_get_journal(struct super_block *sb, |
| 5730 | 5752 | unsigned int journal_inum) |
| 5731 | 5753 | { |
| @@ -5746,6 +5768,7 @@ static journal_t *ext4_get_journal(struct super_block *sb, · 14 unmodified lines | ||
| 5746 | 5768 | return NULL; |
| 5747 | 5769 | } |
| 5748 | 5770 | journal->j_private = sb; |
| 5771 | + journal->j_bmap = ext4_journal_bmap; | |
| 5749 | 5772 | ext4_init_journal_params(sb, journal); |
| 5750 | 5773 | return journal; |
| 5751 | 5774 | } |
| @@ -5920,6 +5943,7 @@ static int ext4_load_journal(struct super_block *sb, · 168 unmodified lines | ||
| 5920 | 5943 | err = jbd2_journal_wipe(journal, !really_read_only); |
| 5921 | 5944 | if (!err) { |
| 5922 | 5945 | char *save = kmalloc(EXT4_S_ERR_LEN, GFP_KERNEL); |
| 5946 | + | |
| 5923 | 5947 | if (save) |
| 5924 | 5948 | memcpy(save, ((char *) es) + |
| 5925 | 5949 | EXT4_S_ERR_START, EXT4_S_ERR_LEN); |
| @@ -5928,6 +5952,14 @@ static int ext4_load_journal(struct super_block *sb, · 2 unmodified lines | ||
| 5928 | 5952 | memcpy(((char *) es) + EXT4_S_ERR_START, |
| 5929 | 5953 | save, EXT4_S_ERR_LEN); |
| 5930 | 5954 | kfree(save); |
| 5955 | + es->s_state |= cpu_to_le16(EXT4_SB(sb)->s_mount_state & | |
| 5956 | + EXT4_ERROR_FS); | |
| 5957 | + /* Write out restored error information to the superblock */ | |
| 5958 | + if (!bdev_read_only(sb->s_bdev)) { | |
| 5959 | + int err2; | |
| 5960 | + err2 = ext4_commit_super(sb); | |
| 5961 | + err = err ? : err2; | |
| 5962 | + } | |
| 5931 | 5963 | } |
| 5932 | 5964 | |
| 5933 | 5965 | if (err) { |
| @@ -6157,11 +6189,13 @@ static int ext4_clear_journal_err(struct super_block *sb, · 223 unmodified lines | ||
| 6157 | 6189 | errstr = ext4_decode_error(sb, j_errno, nbuf); |
| 6158 | 6190 | ext4_warning(sb, "Filesystem error recorded " |
| 6159 | 6191 | "from previous mount: %s", errstr); |
| 6160 | − ext4_warning(sb, "Marking fs in need of filesystem check."); | |
| 6161 | 6192 | |
| 6162 | 6193 | EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; |
| 6163 | 6194 | es->s_state |= cpu_to_le16(EXT4_ERROR_FS); |
| 6164 | − ext4_commit_super(sb); | |
| 6195 | + j_errno = ext4_commit_super(sb); | |
| 6196 | + if (j_errno) | |
| 6197 | + return j_errno; | |
| 6198 | + ext4_warning(sb, "Marked fs in need of filesystem check."); | |
| 6165 | 6199 | |
| 6166 | 6200 | jbd2_journal_clear_err(journal); |
| 6167 | 6201 | jbd2_journal_update_sb_errno(journal); |
| @@ -501,13 +501,13 @@ static const struct sysfs_ops ext4_attr_ops = { · 500 unmodified lines | ||
| 501 | 501 | .store = ext4_attr_store, |
| 502 | 502 | }; |
| 503 | 503 | |
| 504 | −static struct kobj_type ext4_sb_ktype = { | |
| 504 | +static const struct kobj_type ext4_sb_ktype = { | |
| 505 | 505 | .default_groups = ext4_groups, |
| 506 | 506 | .sysfs_ops = &ext4_attr_ops, |
| 507 | 507 | .release = ext4_sb_release, |
| 508 | 508 | }; |
| 509 | 509 | |
| 510 | −static struct kobj_type ext4_feat_ktype = { | |
| 510 | +static const struct kobj_type ext4_feat_ktype = { | |
| 511 | 511 | .default_groups = ext4_feat_groups, |
| 512 | 512 | .sysfs_ops = &ext4_attr_ops, |
| 513 | 513 | .release = ext4_feat_release, |
| @@ -2852,6 +2852,9 @@ shift: · 2851 unmodified lines | ||
| 2852 | 2852 | (void *)header, total_ino); |
| 2853 | 2853 | EXT4_I(inode)->i_extra_isize = new_extra_isize; |
| 2854 | 2854 | |
| 2855 | + if (ext4_has_inline_data(inode)) | |
| 2856 | + error = ext4_find_inline_data_nolock(inode); | |
| 2857 | + | |
| 2855 | 2858 | cleanup: |
| 2856 | 2859 | if (error && (mnt_count != le16_to_cpu(sbi->s_es->s_mnt_count))) { |
| 2857 | 2860 | ext4_warning(inode->i_sb, "Unable to expand inode %lu. Delete some EAs or run e2fsck.", |
| @@ -969,10 +969,13 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr, · 968 unmodified lines | ||
| 969 | 969 | { |
| 970 | 970 | int err = 0; |
| 971 | 971 | unsigned long long ret; |
| 972 | − sector_t block = 0; | |
| 972 | + sector_t block = blocknr; | |
| 973 | 973 | |
| 974 | − if (journal->j_inode) { | |
| 975 | − block = blocknr; | |
| 974 | + if (journal->j_bmap) { | |
| 975 | + err = journal->j_bmap(journal, &block); | |
| 976 | + if (err == 0) | |
| 977 | + *retp = block; | |
| 978 | + } else if (journal->j_inode) { | |
| 976 | 979 | ret = bmap(journal->j_inode, &block); |
| 977 | 980 | |
| 978 | 981 | if (ret || !block) { |
| @@ -1308,6 +1308,14 @@ struct journal_s · 1307 unmodified lines | ||
| 1308 | 1308 | struct buffer_head *bh, |
| 1309 | 1309 | enum passtype pass, int off, |
| 1310 | 1310 | tid_t expected_commit_id); |
| 1311 | + | |
| 1312 | + /** | |
| 1313 | + * @j_bmap: | |
| 1314 | + * | |
| 1315 | + * Bmap function that should be used instead of the generic | |
| 1316 | + * VFS bmap function. | |
| 1317 | + */ | |
| 1318 | + int (*j_bmap)(struct journal_s *journal, sector_t *block); | |
| 1311 | 1319 | }; |
| 1312 | 1320 | |
| 1313 | 1321 | #define jbd2_might_wait_for_commit(j) \ |