Skip to content

Commit a08797e

Browse files
committed
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull jbd2 bug fixes from Ted Ts'o: "Two jbd2 bug fixes, one of which is a regression fix" * tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: jbd2: Fix oops in jbd2_journal_file_inode() jbd2: Fix use after free after error in jbd2_journal_dirty_metadata()
2 parents 215b28a + a361293 commit a08797e

File tree

4 files changed

+52
-21
lines changed

4 files changed

+52
-21
lines changed

fs/ext4/ext4.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2086,6 +2086,7 @@ extern int ext4_sync_inode(handle_t *, struct inode *);
20862086
extern void ext4_dirty_inode(struct inode *, int);
20872087
extern int ext4_change_inode_journal_flag(struct inode *, int);
20882088
extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *);
2089+
extern int ext4_inode_attach_jinode(struct inode *inode);
20892090
extern int ext4_can_truncate(struct inode *inode);
20902091
extern void ext4_truncate(struct inode *);
20912092
extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length);

fs/ext4/ext4_jbd2.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,10 +255,10 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
255255
set_buffer_prio(bh);
256256
if (ext4_handle_valid(handle)) {
257257
err = jbd2_journal_dirty_metadata(handle, bh);
258-
if (err) {
259-
/* Errors can only happen if there is a bug */
260-
handle->h_err = err;
261-
__ext4_journal_stop(where, line, handle);
258+
/* Errors can only happen if there is a bug */
259+
if (WARN_ON_ONCE(err)) {
260+
ext4_journal_abort_handle(where, line, __func__, bh,
261+
handle, err);
262262
}
263263
} else {
264264
if (inode)

fs/ext4/file.c

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,6 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
219219
{
220220
struct super_block *sb = inode->i_sb;
221221
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
222-
struct ext4_inode_info *ei = EXT4_I(inode);
223222
struct vfsmount *mnt = filp->f_path.mnt;
224223
struct path path;
225224
char buf[64], *cp;
@@ -259,22 +258,10 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
259258
* Set up the jbd2_inode if we are opening the inode for
260259
* writing and the journal is present
261260
*/
262-
if (sbi->s_journal && !ei->jinode && (filp->f_mode & FMODE_WRITE)) {
263-
struct jbd2_inode *jinode = jbd2_alloc_inode(GFP_KERNEL);
264-
265-
spin_lock(&inode->i_lock);
266-
if (!ei->jinode) {
267-
if (!jinode) {
268-
spin_unlock(&inode->i_lock);
269-
return -ENOMEM;
270-
}
271-
ei->jinode = jinode;
272-
jbd2_journal_init_jbd_inode(ei->jinode, inode);
273-
jinode = NULL;
274-
}
275-
spin_unlock(&inode->i_lock);
276-
if (unlikely(jinode != NULL))
277-
jbd2_free_inode(jinode);
261+
if (filp->f_mode & FMODE_WRITE) {
262+
int ret = ext4_inode_attach_jinode(inode);
263+
if (ret < 0)
264+
return ret;
278265
}
279266
return dquot_file_open(inode, filp);
280267
}

fs/ext4/inode.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3533,6 +3533,18 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
35333533
offset;
35343534
}
35353535

3536+
if (offset & (sb->s_blocksize - 1) ||
3537+
(offset + length) & (sb->s_blocksize - 1)) {
3538+
/*
3539+
* Attach jinode to inode for jbd2 if we do any zeroing of
3540+
* partial block
3541+
*/
3542+
ret = ext4_inode_attach_jinode(inode);
3543+
if (ret < 0)
3544+
goto out_mutex;
3545+
3546+
}
3547+
35363548
first_block_offset = round_up(offset, sb->s_blocksize);
35373549
last_block_offset = round_down((offset + length), sb->s_blocksize) - 1;
35383550

@@ -3601,6 +3613,31 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
36013613
return ret;
36023614
}
36033615

3616+
int ext4_inode_attach_jinode(struct inode *inode)
3617+
{
3618+
struct ext4_inode_info *ei = EXT4_I(inode);
3619+
struct jbd2_inode *jinode;
3620+
3621+
if (ei->jinode || !EXT4_SB(inode->i_sb)->s_journal)
3622+
return 0;
3623+
3624+
jinode = jbd2_alloc_inode(GFP_KERNEL);
3625+
spin_lock(&inode->i_lock);
3626+
if (!ei->jinode) {
3627+
if (!jinode) {
3628+
spin_unlock(&inode->i_lock);
3629+
return -ENOMEM;
3630+
}
3631+
ei->jinode = jinode;
3632+
jbd2_journal_init_jbd_inode(ei->jinode, inode);
3633+
jinode = NULL;
3634+
}
3635+
spin_unlock(&inode->i_lock);
3636+
if (unlikely(jinode != NULL))
3637+
jbd2_free_inode(jinode);
3638+
return 0;
3639+
}
3640+
36043641
/*
36053642
* ext4_truncate()
36063643
*
@@ -3661,6 +3698,12 @@ void ext4_truncate(struct inode *inode)
36613698
return;
36623699
}
36633700

3701+
/* If we zero-out tail of the page, we have to create jinode for jbd2 */
3702+
if (inode->i_size & (inode->i_sb->s_blocksize - 1)) {
3703+
if (ext4_inode_attach_jinode(inode) < 0)
3704+
return;
3705+
}
3706+
36643707
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
36653708
credits = ext4_writepage_trans_blocks(inode);
36663709
else

0 commit comments

Comments
 (0)