diff options
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 70 |
1 files changed, 68 insertions, 2 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 28555f191b62..85404f15e53a 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -4174,6 +4174,65 @@ static int ext4_inode_blocks_set(handle_t *handle, | |||
4174 | return 0; | 4174 | return 0; |
4175 | } | 4175 | } |
4176 | 4176 | ||
4177 | struct other_inode { | ||
4178 | unsigned long orig_ino; | ||
4179 | struct ext4_inode *raw_inode; | ||
4180 | }; | ||
4181 | |||
4182 | static int other_inode_match(struct inode * inode, unsigned long ino, | ||
4183 | void *data) | ||
4184 | { | ||
4185 | struct other_inode *oi = (struct other_inode *) data; | ||
4186 | |||
4187 | if ((inode->i_ino != ino) || | ||
4188 | (inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW | | ||
4189 | I_DIRTY_SYNC | I_DIRTY_DATASYNC)) || | ||
4190 | ((inode->i_state & I_DIRTY_TIME) == 0)) | ||
4191 | return 0; | ||
4192 | spin_lock(&inode->i_lock); | ||
4193 | if (((inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW | | ||
4194 | I_DIRTY_SYNC | I_DIRTY_DATASYNC)) == 0) && | ||
4195 | (inode->i_state & I_DIRTY_TIME)) { | ||
4196 | struct ext4_inode_info *ei = EXT4_I(inode); | ||
4197 | |||
4198 | inode->i_state &= ~(I_DIRTY_TIME | I_DIRTY_TIME_EXPIRED); | ||
4199 | spin_unlock(&inode->i_lock); | ||
4200 | |||
4201 | spin_lock(&ei->i_raw_lock); | ||
4202 | EXT4_INODE_SET_XTIME(i_ctime, inode, oi->raw_inode); | ||
4203 | EXT4_INODE_SET_XTIME(i_mtime, inode, oi->raw_inode); | ||
4204 | EXT4_INODE_SET_XTIME(i_atime, inode, oi->raw_inode); | ||
4205 | ext4_inode_csum_set(inode, oi->raw_inode, ei); | ||
4206 | spin_unlock(&ei->i_raw_lock); | ||
4207 | trace_ext4_other_inode_update_time(inode, oi->orig_ino); | ||
4208 | return -1; | ||
4209 | } | ||
4210 | spin_unlock(&inode->i_lock); | ||
4211 | return -1; | ||
4212 | } | ||
4213 | |||
4214 | /* | ||
4215 | * Opportunistically update the other time fields for other inodes in | ||
4216 | * the same inode table block. | ||
4217 | */ | ||
4218 | static void ext4_update_other_inodes_time(struct super_block *sb, | ||
4219 | unsigned long orig_ino, char *buf) | ||
4220 | { | ||
4221 | struct other_inode oi; | ||
4222 | unsigned long ino; | ||
4223 | int i, inodes_per_block = EXT4_SB(sb)->s_inodes_per_block; | ||
4224 | int inode_size = EXT4_INODE_SIZE(sb); | ||
4225 | |||
4226 | oi.orig_ino = orig_ino; | ||
4227 | ino = orig_ino & ~(inodes_per_block - 1); | ||
4228 | for (i = 0; i < inodes_per_block; i++, ino++, buf += inode_size) { | ||
4229 | if (ino == orig_ino) | ||
4230 | continue; | ||
4231 | oi.raw_inode = (struct ext4_inode *) buf; | ||
4232 | (void) find_inode_nowait(sb, ino, other_inode_match, &oi); | ||
4233 | } | ||
4234 | } | ||
4235 | |||
4177 | /* | 4236 | /* |
4178 | * Post the struct inode info into an on-disk inode location in the | 4237 | * Post the struct inode info into an on-disk inode location in the |
4179 | * buffer-cache. This gobbles the caller's reference to the | 4238 | * buffer-cache. This gobbles the caller's reference to the |
@@ -4283,10 +4342,11 @@ static int ext4_do_update_inode(handle_t *handle, | |||
4283 | cpu_to_le16(ei->i_extra_isize); | 4342 | cpu_to_le16(ei->i_extra_isize); |
4284 | } | 4343 | } |
4285 | } | 4344 | } |
4286 | |||
4287 | ext4_inode_csum_set(inode, raw_inode, ei); | 4345 | ext4_inode_csum_set(inode, raw_inode, ei); |
4288 | |||
4289 | spin_unlock(&ei->i_raw_lock); | 4346 | spin_unlock(&ei->i_raw_lock); |
4347 | if (inode->i_sb->s_flags & MS_LAZYTIME) | ||
4348 | ext4_update_other_inodes_time(inode->i_sb, inode->i_ino, | ||
4349 | bh->b_data); | ||
4290 | 4350 | ||
4291 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); | 4351 | BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); |
4292 | rc = ext4_handle_dirty_metadata(handle, NULL, bh); | 4352 | rc = ext4_handle_dirty_metadata(handle, NULL, bh); |
@@ -4875,11 +4935,17 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode) | |||
4875 | * If the inode is marked synchronous, we don't honour that here - doing | 4935 | * If the inode is marked synchronous, we don't honour that here - doing |
4876 | * so would cause a commit on atime updates, which we don't bother doing. | 4936 | * so would cause a commit on atime updates, which we don't bother doing. |
4877 | * We handle synchronous inodes at the highest possible level. | 4937 | * We handle synchronous inodes at the highest possible level. |
4938 | * | ||
4939 | * If only the I_DIRTY_TIME flag is set, we can skip everything. If | ||
4940 | * I_DIRTY_TIME and I_DIRTY_SYNC is set, the only inode fields we need | ||
4941 | * to copy into the on-disk inode structure are the timestamp files. | ||
4878 | */ | 4942 | */ |
4879 | void ext4_dirty_inode(struct inode *inode, int flags) | 4943 | void ext4_dirty_inode(struct inode *inode, int flags) |
4880 | { | 4944 | { |
4881 | handle_t *handle; | 4945 | handle_t *handle; |
4882 | 4946 | ||
4947 | if (flags == I_DIRTY_TIME) | ||
4948 | return; | ||
4883 | handle = ext4_journal_start(inode, EXT4_HT_INODE, 2); | 4949 | handle = ext4_journal_start(inode, EXT4_HT_INODE, 2); |
4884 | if (IS_ERR(handle)) | 4950 | if (IS_ERR(handle)) |
4885 | goto out; | 4951 | goto out; |