aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r--fs/ext4/inode.c44
1 files changed, 16 insertions, 28 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 367a60c07cf0..3aa26e9117c4 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
@@ -2095,6 +2077,7 @@ static int mpage_map_and_submit_extent(handle_t *handle,
2095 struct ext4_map_blocks *map = &mpd->map; 2077 struct ext4_map_blocks *map = &mpd->map;
2096 int err; 2078 int err;
2097 loff_t disksize; 2079 loff_t disksize;
2080 int progress = 0;
2098 2081
2099 mpd->io_submit.io_end->offset = 2082 mpd->io_submit.io_end->offset =
2100 ((loff_t)map->m_lblk) << inode->i_blkbits; 2083 ((loff_t)map->m_lblk) << inode->i_blkbits;
@@ -2111,8 +2094,11 @@ static int mpage_map_and_submit_extent(handle_t *handle,
2111 * is non-zero, a commit should free up blocks. 2094 * is non-zero, a commit should free up blocks.
2112 */ 2095 */
2113 if ((err == -ENOMEM) || 2096 if ((err == -ENOMEM) ||
2114 (err == -ENOSPC && ext4_count_free_clusters(sb))) 2097 (err == -ENOSPC && ext4_count_free_clusters(sb))) {
2098 if (progress)
2099 goto update_disksize;
2115 return err; 2100 return err;
2101 }
2116 ext4_msg(sb, KERN_CRIT, 2102 ext4_msg(sb, KERN_CRIT,
2117 "Delayed block allocation failed for " 2103 "Delayed block allocation failed for "
2118 "inode %lu at logical offset %llu with" 2104 "inode %lu at logical offset %llu with"
@@ -2129,15 +2115,17 @@ static int mpage_map_and_submit_extent(handle_t *handle,
2129 *give_up_on_write = true; 2115 *give_up_on_write = true;
2130 return err; 2116 return err;
2131 } 2117 }
2118 progress = 1;
2132 /* 2119 /*
2133 * Update buffer state, submit mapped pages, and get us new 2120 * Update buffer state, submit mapped pages, and get us new
2134 * extent to map 2121 * extent to map
2135 */ 2122 */
2136 err = mpage_map_and_submit_buffers(mpd); 2123 err = mpage_map_and_submit_buffers(mpd);
2137 if (err < 0) 2124 if (err < 0)
2138 return err; 2125 goto update_disksize;
2139 } while (map->m_len); 2126 } while (map->m_len);
2140 2127
2128update_disksize:
2141 /* 2129 /*
2142 * Update on-disk size after IO is submitted. Races with 2130 * Update on-disk size after IO is submitted. Races with
2143 * truncate are avoided by checking i_size under i_data_sem. 2131 * truncate are avoided by checking i_size under i_data_sem.