forked from luck/tmp_suning_uos_patched
Two jbd2 bug fixes, one of which is a regression fix.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABCAAGBQJSD2uJAAoJENNvdpvBGATwPwEP/R1Yu0UReTDVSmRwn8MGbk5O M7QwPgUVnEdqr86v4qx7kqOmKtwSQKfSr7+07UGwEBVasPPI1ezXT5c2VAwz146z 5EClKIJoZoKIdWwM0NvUYxb7p5HgTLubho5RTsHmjOGIy37ju+5rFKZ44aHt9siY J3w5v1EruHdDXwjyiZcIeHFUBGV34x9zPtIGy3yY06gEPAUMeEXShiH/Uj3EroKH 50PkwECBvqFuO4HpunhSYfNc3csTir2ZAx4judaV0s5ebyxzyZ398ql581q73mvP m5KREYYVLQnN9VzCnsjLsnyZboh6XoTxmlmblNVOr0LihyKLS/Nof6pvrWEqgnBf 6NpR6Y8cPVUq+rhhXwFx/RIkVh2EIME0T5dZplr7fVaPxzI1ZKud8p18WifxMAix y3rbdZiEA//OuH5u5XqV0/zv3aJUP7XjdT8dia5iq3FazFOdyT1VfVXzAfaXyqZk JlFguSrOJbQe+vgk2gFLWLH8L4wsnGlSUv1AeDEboriushmZqYlAn10y6ENnM5yW IMFNA6Wyz35MghsKMKV57H7B05VS8em6NGtHZVhTBt7JoiFn7PBvic/KcK/czpDy W2Y8K8azhuscmQfa/RjuVDtwakbNwTu341e7hIUOy41qL/x9nNr07ZRAeF68Nesd p4uRmJxLSW9PReYp9n4V =OroQ -----END PGP SIGNATURE----- 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()
This commit is contained in:
commit
a08797e853
|
@ -2086,6 +2086,7 @@ extern int ext4_sync_inode(handle_t *, struct inode *);
|
|||
extern void ext4_dirty_inode(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_inode_attach_jinode(struct inode *inode);
|
||||
extern int ext4_can_truncate(struct inode *inode);
|
||||
extern void ext4_truncate(struct inode *);
|
||||
extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length);
|
||||
|
|
|
@ -255,10 +255,10 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
|
|||
set_buffer_prio(bh);
|
||||
if (ext4_handle_valid(handle)) {
|
||||
err = jbd2_journal_dirty_metadata(handle, bh);
|
||||
if (err) {
|
||||
/* Errors can only happen if there is a bug */
|
||||
handle->h_err = err;
|
||||
__ext4_journal_stop(where, line, handle);
|
||||
/* Errors can only happen if there is a bug */
|
||||
if (WARN_ON_ONCE(err)) {
|
||||
ext4_journal_abort_handle(where, line, __func__, bh,
|
||||
handle, err);
|
||||
}
|
||||
} else {
|
||||
if (inode)
|
||||
|
|
|
@ -219,7 +219,6 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
|
|||
{
|
||||
struct super_block *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 path path;
|
||||
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
|
||||
* writing and the journal is present
|
||||
*/
|
||||
if (sbi->s_journal && !ei->jinode && (filp->f_mode & FMODE_WRITE)) {
|
||||
struct jbd2_inode *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);
|
||||
if (filp->f_mode & FMODE_WRITE) {
|
||||
int ret = ext4_inode_attach_jinode(inode);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
return dquot_file_open(inode, filp);
|
||||
}
|
||||
|
|
|
@ -3533,6 +3533,18 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
|
|||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
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()
|
||||
*
|
||||
|
@ -3661,6 +3698,12 @@ void ext4_truncate(struct inode *inode)
|
|||
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))
|
||||
credits = ext4_writepage_trans_blocks(inode);
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue
Block a user