diff options
| -rw-r--r-- | fs/ext4/inode.c | 67 | ||||
| -rw-r--r-- | fs/ext4/xattr.c | 9 |
2 files changed, 36 insertions, 40 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 5dabbf276651..713b67e85f73 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -5706,21 +5706,35 @@ ext4_reserve_inode_write(handle_t *handle, struct inode *inode, | |||
| 5706 | * Expand an inode by new_extra_isize bytes. | 5706 | * Expand an inode by new_extra_isize bytes. |
| 5707 | * Returns 0 on success or negative error number on failure. | 5707 | * Returns 0 on success or negative error number on failure. |
| 5708 | */ | 5708 | */ |
| 5709 | static int ext4_expand_extra_isize(struct inode *inode, | 5709 | static int ext4_try_to_expand_extra_isize(struct inode *inode, |
| 5710 | unsigned int new_extra_isize, | 5710 | unsigned int new_extra_isize, |
| 5711 | struct ext4_iloc iloc, | 5711 | struct ext4_iloc iloc, |
| 5712 | handle_t *handle) | 5712 | handle_t *handle) |
| 5713 | { | 5713 | { |
| 5714 | struct ext4_inode *raw_inode; | 5714 | struct ext4_inode *raw_inode; |
| 5715 | struct ext4_xattr_ibody_header *header; | 5715 | struct ext4_xattr_ibody_header *header; |
| 5716 | int no_expand; | 5716 | int no_expand; |
| 5717 | int error; | 5717 | int error; |
| 5718 | 5718 | ||
| 5719 | if (EXT4_I(inode)->i_extra_isize >= new_extra_isize) | 5719 | if (ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND)) |
| 5720 | return 0; | 5720 | return -EOVERFLOW; |
| 5721 | |||
| 5722 | /* | ||
| 5723 | * In nojournal mode, we can immediately attempt to expand | ||
| 5724 | * the inode. When journaled, we first need to obtain extra | ||
| 5725 | * buffer credits since we may write into the EA block | ||
| 5726 | * with this same handle. If journal_extend fails, then it will | ||
| 5727 | * only result in a minor loss of functionality for that inode. | ||
| 5728 | * If this is felt to be critical, then e2fsck should be run to | ||
| 5729 | * force a large enough s_min_extra_isize. | ||
| 5730 | */ | ||
| 5731 | if (ext4_handle_valid(handle) && | ||
| 5732 | jbd2_journal_extend(handle, | ||
| 5733 | EXT4_DATA_TRANS_BLOCKS(inode->i_sb)) != 0) | ||
| 5734 | return -ENOSPC; | ||
| 5721 | 5735 | ||
| 5722 | if (ext4_write_trylock_xattr(inode, &no_expand) == 0) | 5736 | if (ext4_write_trylock_xattr(inode, &no_expand) == 0) |
| 5723 | return 0; | 5737 | return -EBUSY; |
| 5724 | 5738 | ||
| 5725 | raw_inode = ext4_raw_inode(&iloc); | 5739 | raw_inode = ext4_raw_inode(&iloc); |
| 5726 | 5740 | ||
| @@ -5747,6 +5761,7 @@ static int ext4_expand_extra_isize(struct inode *inode, | |||
| 5747 | no_expand = 1; | 5761 | no_expand = 1; |
| 5748 | } | 5762 | } |
| 5749 | ext4_write_unlock_xattr(inode, &no_expand); | 5763 | ext4_write_unlock_xattr(inode, &no_expand); |
| 5764 | |||
| 5750 | return error; | 5765 | return error; |
| 5751 | } | 5766 | } |
| 5752 | 5767 | ||
| @@ -5767,44 +5782,18 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode) | |||
| 5767 | { | 5782 | { |
| 5768 | struct ext4_iloc iloc; | 5783 | struct ext4_iloc iloc; |
| 5769 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | 5784 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
| 5770 | static unsigned int mnt_count; | 5785 | int err; |
| 5771 | int err, ret; | ||
| 5772 | 5786 | ||
| 5773 | might_sleep(); | 5787 | might_sleep(); |
| 5774 | trace_ext4_mark_inode_dirty(inode, _RET_IP_); | 5788 | trace_ext4_mark_inode_dirty(inode, _RET_IP_); |
| 5775 | err = ext4_reserve_inode_write(handle, inode, &iloc); | 5789 | err = ext4_reserve_inode_write(handle, inode, &iloc); |
| 5776 | if (err) | 5790 | if (err) |
| 5777 | return err; | 5791 | return err; |
| 5778 | if (EXT4_I(inode)->i_extra_isize < sbi->s_want_extra_isize && | 5792 | |
| 5779 | !ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND)) { | 5793 | if (EXT4_I(inode)->i_extra_isize < sbi->s_want_extra_isize) |
| 5780 | /* | 5794 | ext4_try_to_expand_extra_isize(inode, sbi->s_want_extra_isize, |
| 5781 | * In nojournal mode, we can immediately attempt to expand | 5795 | iloc, handle); |
| 5782 | * the inode. When journaled, we first need to obtain extra | 5796 | |
| 5783 | * buffer credits since we may write into the EA block | ||
| 5784 | * with this same handle. If journal_extend fails, then it will | ||
| 5785 | * only result in a minor loss of functionality for that inode. | ||
| 5786 | * If this is felt to be critical, then e2fsck should be run to | ||
| 5787 | * force a large enough s_min_extra_isize. | ||
| 5788 | */ | ||
| 5789 | if (!ext4_handle_valid(handle) || | ||
| 5790 | jbd2_journal_extend(handle, | ||
| 5791 | EXT4_DATA_TRANS_BLOCKS(inode->i_sb)) == 0) { | ||
| 5792 | ret = ext4_expand_extra_isize(inode, | ||
| 5793 | sbi->s_want_extra_isize, | ||
| 5794 | iloc, handle); | ||
| 5795 | if (ret) { | ||
| 5796 | if (mnt_count != | ||
| 5797 | le16_to_cpu(sbi->s_es->s_mnt_count)) { | ||
| 5798 | ext4_warning(inode->i_sb, | ||
| 5799 | "Unable to expand inode %lu. Delete" | ||
| 5800 | " some EAs or run e2fsck.", | ||
| 5801 | inode->i_ino); | ||
| 5802 | mnt_count = | ||
| 5803 | le16_to_cpu(sbi->s_es->s_mnt_count); | ||
| 5804 | } | ||
| 5805 | } | ||
| 5806 | } | ||
| 5807 | } | ||
| 5808 | return ext4_mark_iloc_dirty(handle, inode, &iloc); | 5797 | return ext4_mark_iloc_dirty(handle, inode, &iloc); |
| 5809 | } | 5798 | } |
| 5810 | 5799 | ||
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 862ba3891398..7f5f4b63782b 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
| @@ -2638,12 +2638,14 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, | |||
| 2638 | { | 2638 | { |
| 2639 | struct ext4_xattr_ibody_header *header; | 2639 | struct ext4_xattr_ibody_header *header; |
| 2640 | struct buffer_head *bh = NULL; | 2640 | struct buffer_head *bh = NULL; |
| 2641 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | ||
| 2642 | static unsigned int mnt_count; | ||
| 2641 | size_t min_offs; | 2643 | size_t min_offs; |
| 2642 | size_t ifree, bfree; | 2644 | size_t ifree, bfree; |
| 2643 | int total_ino; | 2645 | int total_ino; |
| 2644 | void *base, *end; | 2646 | void *base, *end; |
| 2645 | int error = 0, tried_min_extra_isize = 0; | 2647 | int error = 0, tried_min_extra_isize = 0; |
| 2646 | int s_min_extra_isize = le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize); | 2648 | int s_min_extra_isize = le16_to_cpu(sbi->s_es->s_min_extra_isize); |
| 2647 | int isize_diff; /* How much do we need to grow i_extra_isize */ | 2649 | int isize_diff; /* How much do we need to grow i_extra_isize */ |
| 2648 | 2650 | ||
| 2649 | retry: | 2651 | retry: |
| @@ -2731,6 +2733,11 @@ out: | |||
| 2731 | 2733 | ||
| 2732 | cleanup: | 2734 | cleanup: |
| 2733 | brelse(bh); | 2735 | brelse(bh); |
| 2736 | if (mnt_count != le16_to_cpu(sbi->s_es->s_mnt_count)) { | ||
| 2737 | ext4_warning(inode->i_sb, "Unable to expand inode %lu. Delete some EAs or run e2fsck.", | ||
| 2738 | inode->i_ino); | ||
| 2739 | mnt_count = le16_to_cpu(sbi->s_es->s_mnt_count); | ||
| 2740 | } | ||
| 2734 | return error; | 2741 | return error; |
| 2735 | } | 2742 | } |
| 2736 | 2743 | ||
