Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a08797e8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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()
parents 215b28a5 a361293f
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -2086,6 +2086,7 @@ extern int ext4_sync_inode(handle_t *, struct inode *);
extern void ext4_dirty_inode(struct inode *, int);
extern void ext4_dirty_inode(struct inode *, int);
extern int ext4_change_inode_journal_flag(struct inode *, int);
extern int ext4_change_inode_journal_flag(struct inode *, int);
extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *);
extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *);
extern int ext4_inode_attach_jinode(struct inode *inode);
extern int ext4_can_truncate(struct inode *inode);
extern int ext4_can_truncate(struct inode *inode);
extern void ext4_truncate(struct inode *);
extern void ext4_truncate(struct inode *);
extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length);
extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length);
+4 −4
Original line number Original line Diff line number Diff line
@@ -255,10 +255,10 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
	set_buffer_prio(bh);
	set_buffer_prio(bh);
	if (ext4_handle_valid(handle)) {
	if (ext4_handle_valid(handle)) {
		err = jbd2_journal_dirty_metadata(handle, bh);
		err = jbd2_journal_dirty_metadata(handle, bh);
		if (err) {
		/* Errors can only happen if there is a bug */
		/* Errors can only happen if there is a bug */
			handle->h_err = err;
		if (WARN_ON_ONCE(err)) {
			__ext4_journal_stop(where, line, handle);
			ext4_journal_abort_handle(where, line, __func__, bh,
						  handle, err);
		}
		}
	} else {
	} else {
		if (inode)
		if (inode)
+4 −17
Original line number Original line Diff line number Diff line
@@ -219,7 +219,6 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
{
{
	struct super_block *sb = inode->i_sb;
	struct super_block *sb = inode->i_sb;
	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
	struct ext4_inode_info *ei = EXT4_I(inode);
	struct vfsmount *mnt = filp->f_path.mnt;
	struct vfsmount *mnt = filp->f_path.mnt;
	struct path path;
	struct path path;
	char buf[64], *cp;
	char buf[64], *cp;
@@ -259,22 +258,10 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
	 * Set up the jbd2_inode if we are opening the inode for
	 * Set up the jbd2_inode if we are opening the inode for
	 * writing and the journal is present
	 * writing and the journal is present
	 */
	 */
	if (sbi->s_journal && !ei->jinode && (filp->f_mode & FMODE_WRITE)) {
	if (filp->f_mode & FMODE_WRITE) {
		struct jbd2_inode *jinode = jbd2_alloc_inode(GFP_KERNEL);
		int ret = ext4_inode_attach_jinode(inode);

		if (ret < 0)
		spin_lock(&inode->i_lock);
			return ret;
		if (!ei->jinode) {
			if (!jinode) {
				spin_unlock(&inode->i_lock);
				return -ENOMEM;
			}
			ei->jinode = jinode;
			jbd2_journal_init_jbd_inode(ei->jinode, inode);
			jinode = NULL;
		}
		spin_unlock(&inode->i_lock);
		if (unlikely(jinode != NULL))
			jbd2_free_inode(jinode);
	}
	}
	return dquot_file_open(inode, filp);
	return dquot_file_open(inode, filp);
}
}
+43 −0
Original line number Original line Diff line number Diff line
@@ -3533,6 +3533,18 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
		   offset;
		   offset;
	}
	}


	if (offset & (sb->s_blocksize - 1) ||
	    (offset + length) & (sb->s_blocksize - 1)) {
		/*
		 * Attach jinode to inode for jbd2 if we do any zeroing of
		 * partial block
		 */
		ret = ext4_inode_attach_jinode(inode);
		if (ret < 0)
			goto out_mutex;

	}

	first_block_offset = round_up(offset, sb->s_blocksize);
	first_block_offset = round_up(offset, sb->s_blocksize);
	last_block_offset = round_down((offset + length), sb->s_blocksize) - 1;
	last_block_offset = round_down((offset + length), sb->s_blocksize) - 1;


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


int ext4_inode_attach_jinode(struct inode *inode)
{
	struct ext4_inode_info *ei = EXT4_I(inode);
	struct jbd2_inode *jinode;

	if (ei->jinode || !EXT4_SB(inode->i_sb)->s_journal)
		return 0;

	jinode = jbd2_alloc_inode(GFP_KERNEL);
	spin_lock(&inode->i_lock);
	if (!ei->jinode) {
		if (!jinode) {
			spin_unlock(&inode->i_lock);
			return -ENOMEM;
		}
		ei->jinode = jinode;
		jbd2_journal_init_jbd_inode(ei->jinode, inode);
		jinode = NULL;
	}
	spin_unlock(&inode->i_lock);
	if (unlikely(jinode != NULL))
		jbd2_free_inode(jinode);
	return 0;
}

/*
/*
 * ext4_truncate()
 * ext4_truncate()
 *
 *
@@ -3661,6 +3698,12 @@ void ext4_truncate(struct inode *inode)
			return;
			return;
	}
	}


	/* If we zero-out tail of the page, we have to create jinode for jbd2 */
	if (inode->i_size & (inode->i_sb->s_blocksize - 1)) {
		if (ext4_inode_attach_jinode(inode) < 0)
			return;
	}

	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
	if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
		credits = ext4_writepage_trans_blocks(inode);
		credits = ext4_writepage_trans_blocks(inode);
	else
	else