diff options
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 63 |
1 files changed, 62 insertions, 1 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index b83f91edebd1..f6d8528c4f55 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -3106,6 +3106,39 @@ ext4_reserve_inode_write(handle_t *handle, struct inode *inode, | |||
3106 | } | 3106 | } |
3107 | 3107 | ||
3108 | /* | 3108 | /* |
3109 | * Expand an inode by new_extra_isize bytes. | ||
3110 | * Returns 0 on success or negative error number on failure. | ||
3111 | */ | ||
3112 | int ext4_expand_extra_isize(struct inode *inode, unsigned int new_extra_isize, | ||
3113 | struct ext4_iloc iloc, handle_t *handle) | ||
3114 | { | ||
3115 | struct ext4_inode *raw_inode; | ||
3116 | struct ext4_xattr_ibody_header *header; | ||
3117 | struct ext4_xattr_entry *entry; | ||
3118 | |||
3119 | if (EXT4_I(inode)->i_extra_isize >= new_extra_isize) | ||
3120 | return 0; | ||
3121 | |||
3122 | raw_inode = ext4_raw_inode(&iloc); | ||
3123 | |||
3124 | header = IHDR(inode, raw_inode); | ||
3125 | entry = IFIRST(header); | ||
3126 | |||
3127 | /* No extended attributes present */ | ||
3128 | if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR) || | ||
3129 | header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) { | ||
3130 | memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE, 0, | ||
3131 | new_extra_isize); | ||
3132 | EXT4_I(inode)->i_extra_isize = new_extra_isize; | ||
3133 | return 0; | ||
3134 | } | ||
3135 | |||
3136 | /* try to expand with EAs present */ | ||
3137 | return ext4_expand_extra_isize_ea(inode, new_extra_isize, | ||
3138 | raw_inode, handle); | ||
3139 | } | ||
3140 | |||
3141 | /* | ||
3109 | * What we do here is to mark the in-core inode as clean with respect to inode | 3142 | * What we do here is to mark the in-core inode as clean with respect to inode |
3110 | * dirtiness (it may still be data-dirty). | 3143 | * dirtiness (it may still be data-dirty). |
3111 | * This means that the in-core inode may be reaped by prune_icache | 3144 | * This means that the in-core inode may be reaped by prune_icache |
@@ -3129,10 +3162,38 @@ ext4_reserve_inode_write(handle_t *handle, struct inode *inode, | |||
3129 | int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode) | 3162 | int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode) |
3130 | { | 3163 | { |
3131 | struct ext4_iloc iloc; | 3164 | struct ext4_iloc iloc; |
3132 | int err; | 3165 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
3166 | static unsigned int mnt_count; | ||
3167 | int err, ret; | ||
3133 | 3168 | ||
3134 | might_sleep(); | 3169 | might_sleep(); |
3135 | err = ext4_reserve_inode_write(handle, inode, &iloc); | 3170 | err = ext4_reserve_inode_write(handle, inode, &iloc); |
3171 | if (EXT4_I(inode)->i_extra_isize < sbi->s_want_extra_isize && | ||
3172 | !(EXT4_I(inode)->i_state & EXT4_STATE_NO_EXPAND)) { | ||
3173 | /* | ||
3174 | * We need extra buffer credits since we may write into EA block | ||
3175 | * with this same handle. If journal_extend fails, then it will | ||
3176 | * only result in a minor loss of functionality for that inode. | ||
3177 | * If this is felt to be critical, then e2fsck should be run to | ||
3178 | * force a large enough s_min_extra_isize. | ||
3179 | */ | ||
3180 | if ((jbd2_journal_extend(handle, | ||
3181 | EXT4_DATA_TRANS_BLOCKS(inode->i_sb))) == 0) { | ||
3182 | ret = ext4_expand_extra_isize(inode, | ||
3183 | sbi->s_want_extra_isize, | ||
3184 | iloc, handle); | ||
3185 | if (ret) { | ||
3186 | EXT4_I(inode)->i_state |= EXT4_STATE_NO_EXPAND; | ||
3187 | if (mnt_count != sbi->s_es->s_mnt_count) { | ||
3188 | ext4_warning(inode->i_sb, __FUNCTION__, | ||
3189 | "Unable to expand inode %lu. Delete" | ||
3190 | " some EAs or run e2fsck.", | ||
3191 | inode->i_ino); | ||
3192 | mnt_count = sbi->s_es->s_mnt_count; | ||
3193 | } | ||
3194 | } | ||
3195 | } | ||
3196 | } | ||
3136 | if (!err) | 3197 | if (!err) |
3137 | err = ext4_mark_iloc_dirty(handle, inode, &iloc); | 3198 | err = ext4_mark_iloc_dirty(handle, inode, &iloc); |
3138 | return err; | 3199 | return err; |