diff options
| -rw-r--r-- | fs/ext4/ext4.h | 1 | ||||
| -rw-r--r-- | fs/ext4/file.c | 21 | ||||
| -rw-r--r-- | fs/ext4/inode.c | 43 |
3 files changed, 48 insertions, 17 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 *); | |||
| 2086 | extern void ext4_dirty_inode(struct inode *, int); | 2086 | extern void ext4_dirty_inode(struct inode *, int); |
| 2087 | extern int ext4_change_inode_journal_flag(struct inode *, int); | 2087 | extern int ext4_change_inode_journal_flag(struct inode *, int); |
| 2088 | extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *); | 2088 | extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *); |
| 2089 | extern int ext4_inode_attach_jinode(struct inode *inode); | ||
| 2089 | extern int ext4_can_truncate(struct inode *inode); | 2090 | extern int ext4_can_truncate(struct inode *inode); |
| 2090 | extern void ext4_truncate(struct inode *); | 2091 | extern void ext4_truncate(struct inode *); |
| 2091 | extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length); | 2092 | extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length); |
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 | ||
| 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 | |||
| 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 |
