diff options
-rw-r--r-- | fs/ext4/inode.c | 54 |
1 files changed, 40 insertions, 14 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 6253ecdac67f..d04c8428bde2 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -4538,7 +4538,8 @@ static int ext4_inode_blocks_set(handle_t *handle, | |||
4538 | */ | 4538 | */ |
4539 | static int ext4_do_update_inode(handle_t *handle, | 4539 | static int ext4_do_update_inode(handle_t *handle, |
4540 | struct inode *inode, | 4540 | struct inode *inode, |
4541 | struct ext4_iloc *iloc) | 4541 | struct ext4_iloc *iloc, |
4542 | int do_sync) | ||
4542 | { | 4543 | { |
4543 | struct ext4_inode *raw_inode = ext4_raw_inode(iloc); | 4544 | struct ext4_inode *raw_inode = ext4_raw_inode(iloc); |
4544 | struct ext4_inode_info *ei = EXT4_I(inode); | 4545 | struct ext4_inode_info *ei = EXT4_I(inode); |
@@ -4640,10 +4641,22 @@ static int ext4_do_update_inode(handle_t *handle, | |||
4640 | raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize); | 4641 | raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize); |
4641 | } | 4642 | } |
4642 | 4643 | ||
4643 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); | 4644 | /* |
4644 | rc = ext4_handle_dirty_metadata(handle, inode, bh); | 4645 | * If we're not using a journal and we were called from |
4645 | if (!err) | 4646 | * ext4_write_inode() to sync the inode (making do_sync true), |
4646 | err = rc; | 4647 | * we can just use sync_dirty_buffer() directly to do our dirty |
4648 | * work. Testing s_journal here is a bit redundant but it's | ||
4649 | * worth it to avoid potential future trouble. | ||
4650 | */ | ||
4651 | if (EXT4_SB(inode->i_sb)->s_journal == NULL && do_sync) { | ||
4652 | BUFFER_TRACE(bh, "call sync_dirty_buffer"); | ||
4653 | sync_dirty_buffer(bh); | ||
4654 | } else { | ||
4655 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); | ||
4656 | rc = ext4_handle_dirty_metadata(handle, inode, bh); | ||
4657 | if (!err) | ||
4658 | err = rc; | ||
4659 | } | ||
4647 | ei->i_state &= ~EXT4_STATE_NEW; | 4660 | ei->i_state &= ~EXT4_STATE_NEW; |
4648 | 4661 | ||
4649 | out_brelse: | 4662 | out_brelse: |
@@ -4689,19 +4702,32 @@ out_brelse: | |||
4689 | */ | 4702 | */ |
4690 | int ext4_write_inode(struct inode *inode, int wait) | 4703 | int ext4_write_inode(struct inode *inode, int wait) |
4691 | { | 4704 | { |
4705 | int err; | ||
4706 | |||
4692 | if (current->flags & PF_MEMALLOC) | 4707 | if (current->flags & PF_MEMALLOC) |
4693 | return 0; | 4708 | return 0; |
4694 | 4709 | ||
4695 | if (ext4_journal_current_handle()) { | 4710 | if (EXT4_SB(inode->i_sb)->s_journal) { |
4696 | jbd_debug(1, "called recursively, non-PF_MEMALLOC!\n"); | 4711 | if (ext4_journal_current_handle()) { |
4697 | dump_stack(); | 4712 | jbd_debug(1, "called recursively, non-PF_MEMALLOC!\n"); |
4698 | return -EIO; | 4713 | dump_stack(); |
4699 | } | 4714 | return -EIO; |
4715 | } | ||
4700 | 4716 | ||
4701 | if (!wait) | 4717 | if (!wait) |
4702 | return 0; | 4718 | return 0; |
4719 | |||
4720 | err = ext4_force_commit(inode->i_sb); | ||
4721 | } else { | ||
4722 | struct ext4_iloc iloc; | ||
4703 | 4723 | ||
4704 | return ext4_force_commit(inode->i_sb); | 4724 | err = ext4_get_inode_loc(inode, &iloc); |
4725 | if (err) | ||
4726 | return err; | ||
4727 | err = ext4_do_update_inode(EXT4_NOJOURNAL_HANDLE, | ||
4728 | inode, &iloc, wait); | ||
4729 | } | ||
4730 | return err; | ||
4705 | } | 4731 | } |
4706 | 4732 | ||
4707 | /* | 4733 | /* |
@@ -4995,7 +5021,7 @@ int ext4_mark_iloc_dirty(handle_t *handle, | |||
4995 | get_bh(iloc->bh); | 5021 | get_bh(iloc->bh); |
4996 | 5022 | ||
4997 | /* ext4_do_update_inode() does jbd2_journal_dirty_metadata */ | 5023 | /* ext4_do_update_inode() does jbd2_journal_dirty_metadata */ |
4998 | err = ext4_do_update_inode(handle, inode, iloc); | 5024 | err = ext4_do_update_inode(handle, inode, iloc, 0); |
4999 | put_bh(iloc->bh); | 5025 | put_bh(iloc->bh); |
5000 | return err; | 5026 | return err; |
5001 | } | 5027 | } |