aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-08-17 13:43:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-08-17 13:43:19 -0400
commita08797e853e27fedb2468d4fd45459fd62902143 (patch)
treed6b2aa197ded9d9c4e81ef115540f5c76f1feb25 /fs
parent215b28a5308f3d332df2ee09ef11fda45d7e4a92 (diff)
parenta361293f5fedea0016a10599f409631a15d47ee7 (diff)
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()
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/ext4.h1
-rw-r--r--fs/ext4/ext4_jbd2.c8
-rw-r--r--fs/ext4/file.c21
-rw-r--r--fs/ext4/inode.c43
4 files changed, 52 insertions, 21 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index b577e45425b0..0ab26fbf3380 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2086,6 +2086,7 @@ extern int ext4_sync_inode(handle_t *, struct inode *);
2086extern void ext4_dirty_inode(struct inode *, int); 2086extern void ext4_dirty_inode(struct inode *, int);
2087extern int ext4_change_inode_journal_flag(struct inode *, int); 2087extern int ext4_change_inode_journal_flag(struct inode *, int);
2088extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *); 2088extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *);
2089extern int ext4_inode_attach_jinode(struct inode *inode);
2089extern int ext4_can_truncate(struct inode *inode); 2090extern int ext4_can_truncate(struct inode *inode);
2090extern void ext4_truncate(struct inode *); 2091extern void ext4_truncate(struct inode *);
2091extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length); 2092extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length);
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
index 72a3600aedbd..17ac112ab101 100644
--- a/fs/ext4/ext4_jbd2.c
+++ b/fs/ext4/ext4_jbd2.c
@@ -255,10 +255,10 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
255 set_buffer_prio(bh); 255 set_buffer_prio(bh);
256 if (ext4_handle_valid(handle)) { 256 if (ext4_handle_valid(handle)) {
257 err = jbd2_journal_dirty_metadata(handle, bh); 257 err = jbd2_journal_dirty_metadata(handle, bh);
258 if (err) { 258 /* Errors can only happen if there is a bug */
259 /* Errors can only happen if there is a bug */ 259 if (WARN_ON_ONCE(err)) {
260 handle->h_err = err; 260 ext4_journal_abort_handle(where, line, __func__, bh,
261 __ext4_journal_stop(where, line, handle); 261 handle, err);
262 } 262 }
263 } else { 263 } else {
264 if (inode) 264 if (inode)
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 6f4cc567c382..319c9d26279a 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -219,7 +219,6 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
219{ 219{
220 struct super_block *sb = inode->i_sb; 220 struct super_block *sb = inode->i_sb;
221 struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); 221 struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
222 struct ext4_inode_info *ei = EXT4_I(inode);
223 struct vfsmount *mnt = filp->f_path.mnt; 222 struct vfsmount *mnt = filp->f_path.mnt;
224 struct path path; 223 struct path path;
225 char buf[64], *cp; 224 char buf[64], *cp;
@@ -259,22 +258,10 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
259 * Set up the jbd2_inode if we are opening the inode for 258 * Set up the jbd2_inode if we are opening the inode for
260 * writing and the journal is present 259 * writing and the journal is present
261 */ 260 */
262 if (sbi->s_journal && !ei->jinode && (filp->f_mode & FMODE_WRITE)) { 261 if (filp->f_mode & FMODE_WRITE) {
263 struct jbd2_inode *jinode = jbd2_alloc_inode(GFP_KERNEL); 262 int ret = ext4_inode_attach_jinode(inode);
264 263 if (ret < 0)
265 spin_lock(&inode->i_lock); 264 return ret;
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);
278 } 265 }
279 return dquot_file_open(inode, filp); 266 return dquot_file_open(inode, filp);
280} 267}
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index dd32a2eacd0d..c2ca04e67a4f 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3533,6 +3533,18 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
3533 offset; 3533 offset;
3534 } 3534 }
3535 3535
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
3536 first_block_offset = round_up(offset, sb->s_blocksize); 3548 first_block_offset = round_up(offset, sb->s_blocksize);
3537 last_block_offset = round_down((offset + length), sb->s_blocksize) - 1; 3549 last_block_offset = round_down((offset + length), sb->s_blocksize) - 1;
3538 3550
@@ -3601,6 +3613,31 @@ out_mutex:
3601 return ret; 3613 return ret;
3602} 3614}
3603 3615
3616int 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
3604/* 3641/*
3605 * ext4_truncate() 3642 * ext4_truncate()
3606 * 3643 *
@@ -3661,6 +3698,12 @@ void ext4_truncate(struct inode *inode)
3661 return; 3698 return;
3662 } 3699 }
3663 3700
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
3664 if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) 3707 if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
3665 credits = ext4_writepage_trans_blocks(inode); 3708 credits = ext4_writepage_trans_blocks(inode);
3666 else 3709 else