aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/ext4.h17
-rw-r--r--fs/ext4/inode.c16
2 files changed, 13 insertions, 20 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index f1c65dc7cc0a..66946aa62127 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2466,23 +2466,6 @@ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize)
2466 up_write(&EXT4_I(inode)->i_data_sem); 2466 up_write(&EXT4_I(inode)->i_data_sem);
2467} 2467}
2468 2468
2469/*
2470 * Update i_disksize after writeback has been started. Races with truncate
2471 * are avoided by checking i_size under i_data_sem.
2472 */
2473static inline void ext4_wb_update_i_disksize(struct inode *inode, loff_t newsize)
2474{
2475 loff_t i_size;
2476
2477 down_write(&EXT4_I(inode)->i_data_sem);
2478 i_size = i_size_read(inode);
2479 if (newsize > i_size)
2480 newsize = i_size;
2481 if (newsize > EXT4_I(inode)->i_disksize)
2482 EXT4_I(inode)->i_disksize = newsize;
2483 up_write(&EXT4_I(inode)->i_data_sem);
2484}
2485
2486struct ext4_group_info { 2469struct ext4_group_info {
2487 unsigned long bb_state; 2470 unsigned long bb_state;
2488 struct rb_root bb_free_root; 2471 struct rb_root bb_free_root;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 7b93df9aa182..f023f0cb46fc 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2247,13 +2247,23 @@ static int mpage_map_and_submit_extent(handle_t *handle,
2247 return err; 2247 return err;
2248 } while (map->m_len); 2248 } while (map->m_len);
2249 2249
2250 /* Update on-disk size after IO is submitted */ 2250 /*
2251 * Update on-disk size after IO is submitted. Races with
2252 * truncate are avoided by checking i_size under i_data_sem.
2253 */
2251 disksize = ((loff_t)mpd->first_page) << PAGE_CACHE_SHIFT; 2254 disksize = ((loff_t)mpd->first_page) << PAGE_CACHE_SHIFT;
2252 if (disksize > EXT4_I(inode)->i_disksize) { 2255 if (disksize > EXT4_I(inode)->i_disksize) {
2253 int err2; 2256 int err2;
2254 2257 loff_t i_size;
2255 ext4_wb_update_i_disksize(inode, disksize); 2258
2259 down_write(&EXT4_I(inode)->i_data_sem);
2260 i_size = i_size_read(inode);
2261 if (disksize > i_size)
2262 disksize = i_size;
2263 if (disksize > EXT4_I(inode)->i_disksize)
2264 EXT4_I(inode)->i_disksize = disksize;
2256 err2 = ext4_mark_inode_dirty(handle, inode); 2265 err2 = ext4_mark_inode_dirty(handle, inode);
2266 up_write(&EXT4_I(inode)->i_data_sem);
2257 if (err2) 2267 if (err2)
2258 ext4_error(inode->i_sb, 2268 ext4_error(inode->i_sb,
2259 "Failed to mark inode %lu dirty", 2269 "Failed to mark inode %lu dirty",