Skip to content

Commit 65989db

Browse files
committed
Merge tag 'ext4_for_linus-6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 updates from Ted Ts'o: "New ext4 features: - Add support so tune2fs can modify/update the superblock using an ioctl, without needing write access to the block device - Add support for 32-bit reserved uid's and gid's Bug fixes: - Fix potential warnings and other failures caused by corrupted / fuzzed file systems - Fail unaligned direct I/O write with EINVAL instead of silently falling back to buffered I/O - Correectly handle fsmap queries for metadata mappings - Avoid journal stalls caused by writeback throttling - Add some missing GFP_NOFAIL flags to avoid potential deadlocks under extremem memory pressure Cleanups: - Remove obsolete EXT3 Kconfigs" * tag 'ext4_for_linus-6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: fix checks for orphan inodes ext4: validate ea_ino and size in check_xattrs ext4: guard against EA inode refcount underflow in xattr update ext4: implemet new ioctls to set and get superblock parameters ext4: add support for 32-bit default reserved uid and gid values ext4: avoid potential buffer over-read in parse_apply_sb_mount_options() ext4: fix an off-by-one issue during moving extents ext4: increase i_disksize to offset + len in ext4_update_disksize_before_punch() ext4: verify orphan file size is not too big ext4: fail unaligned direct IO write with EINVAL ext4: correctly handle queries for metadata mappings ext4: increase IO priority of fastcommit ext4: remove obsolete EXT3 config options jbd2: increase IO priority of checkpoint ext4: fix potential null deref in ext4_mb_init() ext4: add ext4_sb_bread_nofail() helper function for ext4_free_branches() ext4: replace min/max nesting with clamp() fs: ext4: change GFP_KERNEL to GFP_NOFS to avoid deadlock
2 parents a4eb935 + acf943e commit 65989db

File tree

16 files changed

+467
-118
lines changed

16 files changed

+467
-118
lines changed

fs/ext4/Kconfig

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,4 @@
11
# SPDX-License-Identifier: GPL-2.0-only
2-
# Ext3 configs are here for backward compatibility with old configs which may
3-
# have EXT3_FS set but not EXT4_FS set and thus would result in non-bootable
4-
# kernels after the removal of ext3 driver.
5-
config EXT3_FS
6-
tristate "The Extended 3 (ext3) filesystem"
7-
select EXT4_FS
8-
help
9-
This config option is here only for backward compatibility. ext3
10-
filesystem is now handled by the ext4 driver.
11-
12-
config EXT3_FS_POSIX_ACL
13-
bool "Ext3 POSIX Access Control Lists"
14-
depends on EXT3_FS
15-
select EXT4_FS_POSIX_ACL
16-
select FS_POSIX_ACL
17-
help
18-
This config option is here only for backward compatibility. ext3
19-
filesystem is now handled by the ext4 driver.
20-
21-
config EXT3_FS_SECURITY
22-
bool "Ext3 Security Labels"
23-
depends on EXT3_FS
24-
select EXT4_FS_SECURITY
25-
help
26-
This config option is here only for backward compatibility. ext3
27-
filesystem is now handled by the ext4 driver.
28-
292
config EXT4_FS
303
tristate "The Extended 4 (ext4) filesystem"
314
select BUFFER_HEAD

fs/ext4/ext4.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1450,7 +1450,9 @@ struct ext4_super_block {
14501450
__le16 s_encoding; /* Filename charset encoding */
14511451
__le16 s_encoding_flags; /* Filename charset encoding flags */
14521452
__le32 s_orphan_file_inum; /* Inode for tracking orphan inodes */
1453-
__le32 s_reserved[94]; /* Padding to the end of the block */
1453+
__le16 s_def_resuid_hi;
1454+
__le16 s_def_resgid_hi;
1455+
__le32 s_reserved[93]; /* Padding to the end of the block */
14541456
__le32 s_checksum; /* crc32c(superblock) */
14551457
};
14561458

@@ -1820,6 +1822,18 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
18201822
ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
18211823
}
18221824

1825+
static inline int ext4_get_resuid(struct ext4_super_block *es)
1826+
{
1827+
return le16_to_cpu(es->s_def_resuid) |
1828+
le16_to_cpu(es->s_def_resuid_hi) << 16;
1829+
}
1830+
1831+
static inline int ext4_get_resgid(struct ext4_super_block *es)
1832+
{
1833+
return le16_to_cpu(es->s_def_resgid) |
1834+
le16_to_cpu(es->s_def_resgid_hi) << 16;
1835+
}
1836+
18231837
/*
18241838
* Returns: sbi->field[index]
18251839
* Used to access an array element from the following sbi fields which require
@@ -1989,6 +2003,16 @@ static inline bool ext4_verity_in_progress(struct inode *inode)
19892003

19902004
#define NEXT_ORPHAN(inode) EXT4_I(inode)->i_dtime
19912005

2006+
/*
2007+
* Check whether the inode is tracked as orphan (either in orphan file or
2008+
* orphan list).
2009+
*/
2010+
static inline bool ext4_inode_orphan_tracked(struct inode *inode)
2011+
{
2012+
return ext4_test_inode_state(inode, EXT4_STATE_ORPHAN_FILE) ||
2013+
!list_empty(&EXT4_I(inode)->i_orphan);
2014+
}
2015+
19922016
/*
19932017
* Codes for operating systems
19942018
*/
@@ -3142,6 +3166,8 @@ extern struct buffer_head *ext4_sb_bread(struct super_block *sb,
31423166
sector_t block, blk_opf_t op_flags);
31433167
extern struct buffer_head *ext4_sb_bread_unmovable(struct super_block *sb,
31443168
sector_t block);
3169+
extern struct buffer_head *ext4_sb_bread_nofail(struct super_block *sb,
3170+
sector_t block);
31453171
extern void ext4_read_bh_nowait(struct buffer_head *bh, blk_opf_t op_flags,
31463172
bh_end_io_t *end_io, bool simu_fail);
31473173
extern int ext4_read_bh(struct buffer_head *bh, blk_opf_t op_flags,

fs/ext4/fast_commit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,7 @@ void ext4_fc_track_range(handle_t *handle, struct inode *inode, ext4_lblk_t star
663663

664664
static void ext4_fc_submit_bh(struct super_block *sb, bool is_tail)
665665
{
666-
blk_opf_t write_flags = REQ_SYNC;
666+
blk_opf_t write_flags = JBD2_JOURNAL_REQ_FLAGS;
667667
struct buffer_head *bh = EXT4_SB(sb)->s_fc_bh;
668668

669669
/* Add REQ_FUA | REQ_PREFLUSH only its tail */

fs/ext4/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ static void ext4_inode_extension_cleanup(struct inode *inode, bool need_trunc)
354354
* to cleanup the orphan list in ext4_handle_inode_extension(). Do it
355355
* now.
356356
*/
357-
if (!list_empty(&EXT4_I(inode)->i_orphan) && inode->i_nlink) {
357+
if (ext4_inode_orphan_tracked(inode) && inode->i_nlink) {
358358
handle_t *handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
359359

360360
if (IS_ERR(handle)) {

fs/ext4/fsmap.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ static int ext4_getfsmap_dev_compare(const void *p1, const void *p2)
7474
static bool ext4_getfsmap_rec_before_low_key(struct ext4_getfsmap_info *info,
7575
struct ext4_fsmap *rec)
7676
{
77-
return rec->fmr_physical < info->gfi_low.fmr_physical;
77+
return rec->fmr_physical + rec->fmr_length <=
78+
info->gfi_low.fmr_physical;
7879
}
7980

8081
/*
@@ -200,15 +201,18 @@ static int ext4_getfsmap_meta_helper(struct super_block *sb,
200201
ext4_group_first_block_no(sb, agno));
201202
fs_end = fs_start + EXT4_C2B(sbi, len);
202203

203-
/* Return relevant extents from the meta_list */
204+
/*
205+
* Return relevant extents from the meta_list. We emit all extents that
206+
* partially/fully overlap with the query range
207+
*/
204208
list_for_each_entry_safe(p, tmp, &info->gfi_meta_list, fmr_list) {
205-
if (p->fmr_physical < info->gfi_next_fsblk) {
209+
if (p->fmr_physical + p->fmr_length <= info->gfi_next_fsblk) {
206210
list_del(&p->fmr_list);
207211
kfree(p);
208212
continue;
209213
}
210-
if (p->fmr_physical <= fs_start ||
211-
p->fmr_physical + p->fmr_length <= fs_end) {
214+
if (p->fmr_physical <= fs_end &&
215+
p->fmr_physical + p->fmr_length > fs_start) {
212216
/* Emit the retained free extent record if present */
213217
if (info->gfi_lastfree.fmr_owner) {
214218
error = ext4_getfsmap_helper(sb, info,

fs/ext4/indirect.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1025,7 +1025,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
10251025
}
10261026

10271027
/* Go read the buffer for the next level down */
1028-
bh = ext4_sb_bread(inode->i_sb, nr, 0);
1028+
bh = ext4_sb_bread_nofail(inode->i_sb, nr);
10291029

10301030
/*
10311031
* A read failure? Report error and clear slot

fs/ext4/inode.c

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3872,47 +3872,12 @@ static int ext4_iomap_overwrite_begin(struct inode *inode, loff_t offset,
38723872
return ret;
38733873
}
38743874

3875-
static inline bool ext4_want_directio_fallback(unsigned flags, ssize_t written)
3876-
{
3877-
/* must be a directio to fall back to buffered */
3878-
if ((flags & (IOMAP_WRITE | IOMAP_DIRECT)) !=
3879-
(IOMAP_WRITE | IOMAP_DIRECT))
3880-
return false;
3881-
3882-
/* atomic writes are all-or-nothing */
3883-
if (flags & IOMAP_ATOMIC)
3884-
return false;
3885-
3886-
/* can only try again if we wrote nothing */
3887-
return written == 0;
3888-
}
3889-
3890-
static int ext4_iomap_end(struct inode *inode, loff_t offset, loff_t length,
3891-
ssize_t written, unsigned flags, struct iomap *iomap)
3892-
{
3893-
/*
3894-
* Check to see whether an error occurred while writing out the data to
3895-
* the allocated blocks. If so, return the magic error code for
3896-
* non-atomic write so that we fallback to buffered I/O and attempt to
3897-
* complete the remainder of the I/O.
3898-
* For non-atomic writes, any blocks that may have been
3899-
* allocated in preparation for the direct I/O will be reused during
3900-
* buffered I/O. For atomic write, we never fallback to buffered-io.
3901-
*/
3902-
if (ext4_want_directio_fallback(flags, written))
3903-
return -ENOTBLK;
3904-
3905-
return 0;
3906-
}
3907-
39083875
const struct iomap_ops ext4_iomap_ops = {
39093876
.iomap_begin = ext4_iomap_begin,
3910-
.iomap_end = ext4_iomap_end,
39113877
};
39123878

39133879
const struct iomap_ops ext4_iomap_overwrite_ops = {
39143880
.iomap_begin = ext4_iomap_overwrite_begin,
3915-
.iomap_end = ext4_iomap_end,
39163881
};
39173882

39183883
static int ext4_iomap_begin_report(struct inode *inode, loff_t offset,
@@ -4287,7 +4252,11 @@ int ext4_can_truncate(struct inode *inode)
42874252
* We have to make sure i_disksize gets properly updated before we truncate
42884253
* page cache due to hole punching or zero range. Otherwise i_disksize update
42894254
* can get lost as it may have been postponed to submission of writeback but
4290-
* that will never happen after we truncate page cache.
4255+
* that will never happen if we remove the folio containing i_size from the
4256+
* page cache. Also if we punch hole within i_size but above i_disksize,
4257+
* following ext4_page_mkwrite() may mistakenly allocate written blocks over
4258+
* the hole and thus introduce allocated blocks beyond i_disksize which is
4259+
* not allowed (e2fsck would complain in case of crash).
42914260
*/
42924261
int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset,
42934262
loff_t len)
@@ -4298,9 +4267,11 @@ int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset,
42984267
loff_t size = i_size_read(inode);
42994268

43004269
WARN_ON(!inode_is_locked(inode));
4301-
if (offset > size || offset + len < size)
4270+
if (offset > size)
43024271
return 0;
43034272

4273+
if (offset + len < size)
4274+
size = offset + len;
43044275
if (EXT4_I(inode)->i_disksize >= size)
43054276
return 0;
43064277

@@ -4748,7 +4719,7 @@ static int ext4_fill_raw_inode(struct inode *inode, struct ext4_inode *raw_inode
47484719
* old inodes get re-used with the upper 16 bits of the
47494720
* uid/gid intact.
47504721
*/
4751-
if (ei->i_dtime && list_empty(&ei->i_orphan)) {
4722+
if (ei->i_dtime && !ext4_inode_orphan_tracked(inode)) {
47524723
raw_inode->i_uid_high = 0;
47534724
raw_inode->i_gid_high = 0;
47544725
} else {

0 commit comments

Comments
 (0)