Skip to content

Commit 40d0c09

Browse files
committed
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: "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
2 parents e730408 + f5361da commit 40d0c09

File tree

13 files changed

+98
-33
lines changed

13 files changed

+98
-33
lines changed

Documentation/filesystems/ext4/blockgroup.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ descriptors. Instead, the superblock and a single block group descriptor
105105
block is placed at the beginning of the first, second, and last block
106106
groups in a meta-block group. A meta-block group is a collection of
107107
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
111111
blocksize. Filesystems can either be created using this new block group
112112
descriptor layout, or existing filesystems can be resized on-line, and
113113
the field s_first_meta_bg in the superblock will indicate the first

fs/ext4/ext4.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1387,7 +1387,7 @@ struct ext4_super_block {
13871387
__le32 s_first_meta_bg; /* First metablock block group */
13881388
__le32 s_mkfs_time; /* When the filesystem was created */
13891389
__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 */
13911391
/*150*/ __le32 s_blocks_count_hi; /* Blocks count */
13921392
__le32 s_r_blocks_count_hi; /* Reserved blocks count */
13931393
__le32 s_free_blocks_count_hi; /* Free blocks count */

fs/ext4/fsmap.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,8 @@ static int ext4_getfsmap_datadev(struct super_block *sb,
486486
keys[0].fmr_physical = bofs;
487487
if (keys[1].fmr_physical >= eofs)
488488
keys[1].fmr_physical = eofs - 1;
489+
if (keys[1].fmr_physical < keys[0].fmr_physical)
490+
return 0;
489491
start_fsb = keys[0].fmr_physical;
490492
end_fsb = keys[1].fmr_physical;
491493

fs/ext4/inline.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ int ext4_find_inline_data_nolock(struct inode *inode)
159159
(void *)ext4_raw_inode(&is.iloc));
160160
EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE +
161161
le32_to_cpu(is.s.here->e_value_size);
162-
ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
163162
}
164163
out:
165164
brelse(is.iloc.bh);

fs/ext4/inode.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4797,8 +4797,13 @@ static inline int ext4_iget_extra_inode(struct inode *inode,
47974797

47984798
if (EXT4_INODE_HAS_XATTR_SPACE(inode) &&
47994799
*magic == cpu_to_le32(EXT4_XATTR_MAGIC)) {
4800+
int err;
4801+
48004802
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;
48024807
} else
48034808
EXT4_I(inode)->i_inline_off = 0;
48044809
return 0;

fs/ext4/ioctl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ static long swap_inode_boot_loader(struct super_block *sb,
431431
ei_bl->i_flags = 0;
432432
inode_set_iversion(inode_bl, 1);
433433
i_size_write(inode_bl, 0);
434+
EXT4_I(inode_bl)->i_disksize = inode_bl->i_size;
434435
inode_bl->i_mode = S_IFREG;
435436
if (ext4_has_feature_extents(sb)) {
436437
ext4_set_inode_flag(inode_bl, EXT4_INODE_EXTENTS);

fs/ext4/namei.c

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,11 +1595,10 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir,
15951595
int has_inline_data = 1;
15961596
ret = ext4_find_inline_entry(dir, fname, res_dir,
15971597
&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)
16011601
goto cleanup_and_exit;
1602-
}
16031602
}
16041603

16051604
if ((namelen <= 2) && (name[0] == '.') &&
@@ -3646,7 +3645,8 @@ static void ext4_resetent(handle_t *handle, struct ext4_renament *ent,
36463645
* so the old->de may no longer valid and need to find it again
36473646
* before reset old inode info.
36483647
*/
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);
36503650
if (IS_ERR(old.bh))
36513651
retval = PTR_ERR(old.bh);
36523652
if (!old.bh)
@@ -3813,9 +3813,20 @@ static int ext4_rename(struct mnt_idmap *idmap, struct inode *old_dir,
38133813
return retval;
38143814
}
38153815

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+
38193830
/*
38203831
* Check for inode number is _not_ due to possible IO errors.
38213832
* 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,
38723883
if (new.dir != old.dir && EXT4_DIR_LINK_MAX(new.dir))
38733884
goto end_rename;
38743885
}
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);
38803886
retval = ext4_rename_dir_prepare(handle, &old);
38813887
if (retval) {
38823888
inode_unlock(old.inode);
@@ -4013,12 +4019,15 @@ static int ext4_rename(struct mnt_idmap *idmap, struct inode *old_dir,
40134019
} else {
40144020
ext4_journal_stop(handle);
40154021
}
4016-
if (old.dir_bh)
4017-
inode_unlock(old.inode);
40184022
release_bh:
40194023
brelse(old.dir_bh);
40204024
brelse(old.bh);
40214025
brelse(new.bh);
4026+
4027+
unlock_moved_dir:
4028+
if (S_ISDIR(old.inode->i_mode))
4029+
inode_unlock(old.inode);
4030+
40224031
return retval;
40234032
}
40244033

fs/ext4/page-io.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,8 @@ static void io_submit_init_bio(struct ext4_io_submit *io,
409409

410410
static void io_submit_add_bh(struct ext4_io_submit *io,
411411
struct inode *inode,
412-
struct page *page,
412+
struct page *pagecache_page,
413+
struct page *bounce_page,
413414
struct buffer_head *bh)
414415
{
415416
int ret;
@@ -421,10 +422,11 @@ static void io_submit_add_bh(struct ext4_io_submit *io,
421422
}
422423
if (io->io_bio == NULL)
423424
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));
425427
if (ret != bh->b_size)
426428
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);
428430
io->io_next_block++;
429431
}
430432

@@ -561,8 +563,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
561563
do {
562564
if (!buffer_async_write(bh))
563565
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);
566567
} while ((bh = bh->b_this_page) != head);
567568
unlock:
568569
unlock_page(page);

fs/ext4/super.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5726,6 +5726,28 @@ static struct inode *ext4_get_journal_inode(struct super_block *sb,
57265726
return journal_inode;
57275727
}
57285728

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+
57295751
static journal_t *ext4_get_journal(struct super_block *sb,
57305752
unsigned int journal_inum)
57315753
{
@@ -5746,6 +5768,7 @@ static journal_t *ext4_get_journal(struct super_block *sb,
57465768
return NULL;
57475769
}
57485770
journal->j_private = sb;
5771+
journal->j_bmap = ext4_journal_bmap;
57495772
ext4_init_journal_params(sb, journal);
57505773
return journal;
57515774
}
@@ -5920,6 +5943,7 @@ static int ext4_load_journal(struct super_block *sb,
59205943
err = jbd2_journal_wipe(journal, !really_read_only);
59215944
if (!err) {
59225945
char *save = kmalloc(EXT4_S_ERR_LEN, GFP_KERNEL);
5946+
59235947
if (save)
59245948
memcpy(save, ((char *) es) +
59255949
EXT4_S_ERR_START, EXT4_S_ERR_LEN);
@@ -5928,6 +5952,14 @@ static int ext4_load_journal(struct super_block *sb,
59285952
memcpy(((char *) es) + EXT4_S_ERR_START,
59295953
save, EXT4_S_ERR_LEN);
59305954
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+
}
59315963
}
59325964

59335965
if (err) {
@@ -6157,11 +6189,13 @@ static int ext4_clear_journal_err(struct super_block *sb,
61576189
errstr = ext4_decode_error(sb, j_errno, nbuf);
61586190
ext4_warning(sb, "Filesystem error recorded "
61596191
"from previous mount: %s", errstr);
6160-
ext4_warning(sb, "Marking fs in need of filesystem check.");
61616192

61626193
EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
61636194
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.");
61656199

61666200
jbd2_journal_clear_err(journal);
61676201
jbd2_journal_update_sb_errno(journal);

fs/ext4/sysfs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -501,13 +501,13 @@ static const struct sysfs_ops ext4_attr_ops = {
501501
.store = ext4_attr_store,
502502
};
503503

504-
static struct kobj_type ext4_sb_ktype = {
504+
static const struct kobj_type ext4_sb_ktype = {
505505
.default_groups = ext4_groups,
506506
.sysfs_ops = &ext4_attr_ops,
507507
.release = ext4_sb_release,
508508
};
509509

510-
static struct kobj_type ext4_feat_ktype = {
510+
static const struct kobj_type ext4_feat_ktype = {
511511
.default_groups = ext4_feat_groups,
512512
.sysfs_ops = &ext4_attr_ops,
513513
.release = ext4_feat_release,

0 commit comments

Comments
 (0)