Commit 4631dbf6 authored by Dmitry Monakhov's avatar Dmitry Monakhov Committed by Theodore Ts'o

ext4: move i_size,i_disksize update routines to helper function

Cc: stable@vger.kernel.org # needed for bug fix patches
Signed-off-by: default avatarDmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent c99d1e6e
...@@ -2454,6 +2454,22 @@ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize) ...@@ -2454,6 +2454,22 @@ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize)
up_write(&EXT4_I(inode)->i_data_sem); up_write(&EXT4_I(inode)->i_data_sem);
} }
/* Update i_size, i_disksize. Requires i_mutex to avoid races with truncate */
static inline int ext4_update_inode_size(struct inode *inode, loff_t newsize)
{
int changed = 0;
if (newsize > inode->i_size) {
i_size_write(inode, newsize);
changed = 1;
}
if (newsize > EXT4_I(inode)->i_disksize) {
ext4_update_i_disksize(inode, newsize);
changed |= 2;
}
return changed;
}
struct ext4_group_info { struct ext4_group_info {
unsigned long bb_state; unsigned long bb_state;
struct rb_root bb_free_root; struct rb_root bb_free_root;
......
...@@ -4839,12 +4839,8 @@ static long ext4_zero_range(struct file *file, loff_t offset, ...@@ -4839,12 +4839,8 @@ static long ext4_zero_range(struct file *file, loff_t offset,
} }
inode->i_mtime = inode->i_ctime = ext4_current_time(inode); inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
if (new_size) { if (new_size) {
if (new_size > i_size_read(inode)) ext4_update_inode_size(inode, new_size);
i_size_write(inode, new_size);
if (new_size > EXT4_I(inode)->i_disksize)
ext4_update_i_disksize(inode, new_size);
} else { } else {
/* /*
* Mark that we allocate beyond EOF so the subsequent truncate * 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,7 +4882,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
int ret = 0; int ret = 0;
int flags; int flags;
ext4_lblk_t lblk; ext4_lblk_t lblk;
struct timespec tv;
unsigned int blkbits = inode->i_blkbits; unsigned int blkbits = inode->i_blkbits;
/* Return error if mode is not supported */ /* 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,15 +4940,11 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
if (IS_ERR(handle)) if (IS_ERR(handle))
goto out; goto out;
tv = inode->i_ctime = ext4_current_time(inode); inode->i_ctime = ext4_current_time(inode);
if (new_size) { if (new_size) {
if (new_size > i_size_read(inode)) { if (ext4_update_inode_size(inode, new_size) & 0x1)
i_size_write(inode, new_size); inode->i_mtime = inode->i_ctime;
inode->i_mtime = tv;
}
if (new_size > EXT4_I(inode)->i_disksize)
ext4_update_i_disksize(inode, new_size);
} else { } else {
/* /*
* Mark that we allocate beyond EOF so the subsequent truncate * Mark that we allocate beyond EOF so the subsequent truncate
......
...@@ -1055,27 +1055,11 @@ static int ext4_write_end(struct file *file, ...@@ -1055,27 +1055,11 @@ static int ext4_write_end(struct file *file,
} else } else
copied = block_write_end(file, mapping, pos, copied = block_write_end(file, mapping, pos,
len, copied, page, fsdata); len, copied, page, fsdata);
/* /*
* No need to use i_size_read() here, the i_size * it's important to update i_size while still holding page lock:
* cannot change under us because we hole i_mutex.
*
* But it's important to update i_size while still holding page lock:
* page writeout could otherwise come in and zero beyond i_size. * page writeout could otherwise come in and zero beyond i_size.
*/ */
if (pos + copied > inode->i_size) { i_size_changed = ext4_update_inode_size(inode, pos + copied);
i_size_write(inode, pos + copied);
i_size_changed = 1;
}
if (pos + copied > EXT4_I(inode)->i_disksize) {
/* We need to mark inode dirty even if
* new_i_size is less that inode->i_size
* but greater than i_disksize. (hint delalloc)
*/
ext4_update_i_disksize(inode, (pos + copied));
i_size_changed = 1;
}
unlock_page(page); unlock_page(page);
page_cache_release(page); page_cache_release(page);
...@@ -1123,7 +1107,7 @@ static int ext4_journalled_write_end(struct file *file, ...@@ -1123,7 +1107,7 @@ static int ext4_journalled_write_end(struct file *file,
int ret = 0, ret2; int ret = 0, ret2;
int partial = 0; int partial = 0;
unsigned from, to; unsigned from, to;
loff_t new_i_size; int size_changed = 0;
trace_ext4_journalled_write_end(inode, pos, len, copied); trace_ext4_journalled_write_end(inode, pos, len, copied);
from = pos & (PAGE_CACHE_SIZE - 1); from = pos & (PAGE_CACHE_SIZE - 1);
...@@ -1146,20 +1130,18 @@ static int ext4_journalled_write_end(struct file *file, ...@@ -1146,20 +1130,18 @@ static int ext4_journalled_write_end(struct file *file,
if (!partial) if (!partial)
SetPageUptodate(page); SetPageUptodate(page);
} }
new_i_size = pos + copied; size_changed = ext4_update_inode_size(inode, pos + copied);
if (new_i_size > inode->i_size)
i_size_write(inode, pos+copied);
ext4_set_inode_state(inode, EXT4_STATE_JDATA); ext4_set_inode_state(inode, EXT4_STATE_JDATA);
EXT4_I(inode)->i_datasync_tid = handle->h_transaction->t_tid; EXT4_I(inode)->i_datasync_tid = handle->h_transaction->t_tid;
if (new_i_size > EXT4_I(inode)->i_disksize) { unlock_page(page);
ext4_update_i_disksize(inode, new_i_size); page_cache_release(page);
if (size_changed) {
ret2 = ext4_mark_inode_dirty(handle, inode); ret2 = ext4_mark_inode_dirty(handle, inode);
if (!ret) if (!ret)
ret = ret2; ret = ret2;
} }
unlock_page(page);
page_cache_release(page);
if (pos + len > inode->i_size && ext4_can_truncate(inode)) if (pos + len > inode->i_size && ext4_can_truncate(inode))
/* if we have allocated more blocks and copied /* if we have allocated more blocks and copied
* less. We will have blocks allocated outside * less. We will have blocks allocated outside
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment