diff options
author | Dmitry Monakhov <dmonakhov@openvz.org> | 2014-08-23 17:48:28 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2014-08-23 17:48:28 -0400 |
commit | 4631dbf677ded0419fee35ca7408285dabfaef1a (patch) | |
tree | 80976bb3bff717dbe00fb3d916deab9e237d1c37 /fs | |
parent | c99d1e6e83b06744c75d9f5e491ed495a7086b7b (diff) |
ext4: move i_size,i_disksize update routines to helper function
Cc: stable@vger.kernel.org # needed for bug fix patches
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/ext4.h | 16 | ||||
-rw-r--r-- | fs/ext4/extents.c | 17 | ||||
-rw-r--r-- | fs/ext4/inode.c | 34 |
3 files changed, 28 insertions, 39 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 4d95c3301775..b0c225cdb52c 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -2454,6 +2454,22 @@ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize) | |||
2454 | up_write(&EXT4_I(inode)->i_data_sem); | 2454 | up_write(&EXT4_I(inode)->i_data_sem); |
2455 | } | 2455 | } |
2456 | 2456 | ||
2457 | /* Update i_size, i_disksize. Requires i_mutex to avoid races with truncate */ | ||
2458 | static inline int ext4_update_inode_size(struct inode *inode, loff_t newsize) | ||
2459 | { | ||
2460 | int changed = 0; | ||
2461 | |||
2462 | if (newsize > inode->i_size) { | ||
2463 | i_size_write(inode, newsize); | ||
2464 | changed = 1; | ||
2465 | } | ||
2466 | if (newsize > EXT4_I(inode)->i_disksize) { | ||
2467 | ext4_update_i_disksize(inode, newsize); | ||
2468 | changed |= 2; | ||
2469 | } | ||
2470 | return changed; | ||
2471 | } | ||
2472 | |||
2457 | struct ext4_group_info { | 2473 | struct ext4_group_info { |
2458 | unsigned long bb_state; | 2474 | unsigned long bb_state; |
2459 | struct rb_root bb_free_root; | 2475 | struct rb_root bb_free_root; |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 76c2df382b7d..f0e6934291dd 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -4839,12 +4839,8 @@ static long ext4_zero_range(struct file *file, loff_t offset, | |||
4839 | } | 4839 | } |
4840 | 4840 | ||
4841 | inode->i_mtime = inode->i_ctime = ext4_current_time(inode); | 4841 | inode->i_mtime = inode->i_ctime = ext4_current_time(inode); |
4842 | |||
4843 | if (new_size) { | 4842 | if (new_size) { |
4844 | if (new_size > i_size_read(inode)) | 4843 | ext4_update_inode_size(inode, new_size); |
4845 | i_size_write(inode, new_size); | ||
4846 | if (new_size > EXT4_I(inode)->i_disksize) | ||
4847 | ext4_update_i_disksize(inode, new_size); | ||
4848 | } else { | 4844 | } else { |
4849 | /* | 4845 | /* |
4850 | * Mark that we allocate beyond EOF so the subsequent truncate | 4846 | * Mark that we allocate beyond EOF so the subsequent truncate |
@@ -4886,7 +4882,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) | |||
4886 | int ret = 0; | 4882 | int ret = 0; |
4887 | int flags; | 4883 | int flags; |
4888 | ext4_lblk_t lblk; | 4884 | ext4_lblk_t lblk; |
4889 | struct timespec tv; | ||
4890 | unsigned int blkbits = inode->i_blkbits; | 4885 | unsigned int blkbits = inode->i_blkbits; |
4891 | 4886 | ||
4892 | /* Return error if mode is not supported */ | 4887 | /* Return error if mode is not supported */ |
@@ -4945,15 +4940,11 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) | |||
4945 | if (IS_ERR(handle)) | 4940 | if (IS_ERR(handle)) |
4946 | goto out; | 4941 | goto out; |
4947 | 4942 | ||
4948 | tv = inode->i_ctime = ext4_current_time(inode); | 4943 | inode->i_ctime = ext4_current_time(inode); |
4949 | 4944 | ||
4950 | if (new_size) { | 4945 | if (new_size) { |
4951 | if (new_size > i_size_read(inode)) { | 4946 | if (ext4_update_inode_size(inode, new_size) & 0x1) |
4952 | i_size_write(inode, new_size); | 4947 | inode->i_mtime = inode->i_ctime; |
4953 | inode->i_mtime = tv; | ||
4954 | } | ||
4955 | if (new_size > EXT4_I(inode)->i_disksize) | ||
4956 | ext4_update_i_disksize(inode, new_size); | ||
4957 | } else { | 4948 | } else { |
4958 | /* | 4949 | /* |
4959 | * Mark that we allocate beyond EOF so the subsequent truncate | 4950 | * Mark that we allocate beyond EOF so the subsequent truncate |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 367a60c07cf0..b1ddd9352644 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1055,27 +1055,11 @@ static int ext4_write_end(struct file *file, | |||
1055 | } else | 1055 | } else |
1056 | copied = block_write_end(file, mapping, pos, | 1056 | copied = block_write_end(file, mapping, pos, |
1057 | len, copied, page, fsdata); | 1057 | len, copied, page, fsdata); |
1058 | |||
1059 | /* | 1058 | /* |
1060 | * No need to use i_size_read() here, the i_size | 1059 | * it's important to update i_size while still holding page lock: |
1061 | * cannot change under us because we hole i_mutex. | ||
1062 | * | ||
1063 | * But it's important to update i_size while still holding page lock: | ||
1064 | * page writeout could otherwise come in and zero beyond i_size. | 1060 | * page writeout could otherwise come in and zero beyond i_size. |
1065 | */ | 1061 | */ |
1066 | if (pos + copied > inode->i_size) { | 1062 | i_size_changed = ext4_update_inode_size(inode, pos + copied); |
1067 | i_size_write(inode, pos + copied); | ||
1068 | i_size_changed = 1; | ||
1069 | } | ||
1070 | |||
1071 | if (pos + copied > EXT4_I(inode)->i_disksize) { | ||
1072 | /* We need to mark inode dirty even if | ||
1073 | * new_i_size is less that inode->i_size | ||
1074 | * but greater than i_disksize. (hint delalloc) | ||
1075 | */ | ||
1076 | ext4_update_i_disksize(inode, (pos + copied)); | ||
1077 | i_size_changed = 1; | ||
1078 | } | ||
1079 | unlock_page(page); | 1063 | unlock_page(page); |
1080 | page_cache_release(page); | 1064 | page_cache_release(page); |
1081 | 1065 | ||
@@ -1123,7 +1107,7 @@ static int ext4_journalled_write_end(struct file *file, | |||
1123 | int ret = 0, ret2; | 1107 | int ret = 0, ret2; |
1124 | int partial = 0; | 1108 | int partial = 0; |
1125 | unsigned from, to; | 1109 | unsigned from, to; |
1126 | loff_t new_i_size; | 1110 | int size_changed = 0; |
1127 | 1111 | ||
1128 | trace_ext4_journalled_write_end(inode, pos, len, copied); | 1112 | trace_ext4_journalled_write_end(inode, pos, len, copied); |
1129 | from = pos & (PAGE_CACHE_SIZE - 1); | 1113 | from = pos & (PAGE_CACHE_SIZE - 1); |
@@ -1146,20 +1130,18 @@ static int ext4_journalled_write_end(struct file *file, | |||
1146 | if (!partial) | 1130 | if (!partial) |
1147 | SetPageUptodate(page); | 1131 | SetPageUptodate(page); |
1148 | } | 1132 | } |
1149 | new_i_size = pos + copied; | 1133 | size_changed = ext4_update_inode_size(inode, pos + copied); |
1150 | if (new_i_size > inode->i_size) | ||
1151 | i_size_write(inode, pos+copied); | ||
1152 | ext4_set_inode_state(inode, EXT4_STATE_JDATA); | 1134 | ext4_set_inode_state(inode, EXT4_STATE_JDATA); |
1153 | EXT4_I(inode)->i_datasync_tid = handle->h_transaction->t_tid; | 1135 | EXT4_I(inode)->i_datasync_tid = handle->h_transaction->t_tid; |
1154 | if (new_i_size > EXT4_I(inode)->i_disksize) { | 1136 | unlock_page(page); |
1155 | ext4_update_i_disksize(inode, new_i_size); | 1137 | page_cache_release(page); |
1138 | |||
1139 | if (size_changed) { | ||
1156 | ret2 = ext4_mark_inode_dirty(handle, inode); | 1140 | ret2 = ext4_mark_inode_dirty(handle, inode); |
1157 | if (!ret) | 1141 | if (!ret) |
1158 | ret = ret2; | 1142 | ret = ret2; |
1159 | } | 1143 | } |
1160 | 1144 | ||
1161 | unlock_page(page); | ||
1162 | page_cache_release(page); | ||
1163 | if (pos + len > inode->i_size && ext4_can_truncate(inode)) | 1145 | if (pos + len > inode->i_size && ext4_can_truncate(inode)) |
1164 | /* if we have allocated more blocks and copied | 1146 | /* if we have allocated more blocks and copied |
1165 | * less. We will have blocks allocated outside | 1147 | * less. We will have blocks allocated outside |