aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r--fs/ext4/inode.c63
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 */
3112int 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,
3129int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode) 3162int 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;