aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDmitry Monakhov <dmonakhov@openvz.org>2014-08-23 17:48:28 -0400
committerTheodore Ts'o <tytso@mit.edu>2014-08-23 17:48:28 -0400
commit4631dbf677ded0419fee35ca7408285dabfaef1a (patch)
tree80976bb3bff717dbe00fb3d916deab9e237d1c37 /fs
parentc99d1e6e83b06744c75d9f5e491ed495a7086b7b (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.h16
-rw-r--r--fs/ext4/extents.c17
-rw-r--r--fs/ext4/inode.c34
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 */
2458static 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
2457struct ext4_group_info { 2473struct 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