aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2013-04-03 12:39:17 -0400
committerTheodore Ts'o <tytso@mit.edu>2013-04-03 12:39:17 -0400
commit74d553aad7926ed05e05d9d5cff516a7b31375fc (patch)
treeb18222cb547c2ce4e18a9538bc28f92e2978c600 /fs/ext4
parent8cde7ad17e4f4ff8d12ff60dd09c0a291cb0b61c (diff)
ext4: collapse handling of data=ordered and data=writeback codepaths
The only difference between how we handle data=ordered and data=writeback is a single call to ext4_jbd2_file_inode(). Eliminate code duplication by factoring out redundant the code paths. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Reviewed-by: Lukas Czerner <lczerner@redhat.com>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/ext4.h1
-rw-r--r--fs/ext4/inode.c125
2 files changed, 30 insertions, 96 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 3b83cd604796..f91e11bd9753 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1374,6 +1374,7 @@ enum {
1374 EXT4_STATE_DIOREAD_LOCK, /* Disable support for dio read 1374 EXT4_STATE_DIOREAD_LOCK, /* Disable support for dio read
1375 nolocking */ 1375 nolocking */
1376 EXT4_STATE_MAY_INLINE_DATA, /* may have in-inode data */ 1376 EXT4_STATE_MAY_INLINE_DATA, /* may have in-inode data */
1377 EXT4_STATE_ORDERED_MODE, /* data=ordered mode */
1377}; 1378};
1378 1379
1379#define EXT4_INODE_BIT_FNS(name, field, offset) \ 1380#define EXT4_INODE_BIT_FNS(name, field, offset) \
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index b3a5213bc73e..4ee69270a48a 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1145,77 +1145,36 @@ static int ext4_generic_write_end(struct file *file,
1145 * ext4 never places buffers on inode->i_mapping->private_list. metadata 1145 * ext4 never places buffers on inode->i_mapping->private_list. metadata
1146 * buffers are managed internally. 1146 * buffers are managed internally.
1147 */ 1147 */
1148static int ext4_ordered_write_end(struct file *file, 1148static int ext4_write_end(struct file *file,
1149 struct address_space *mapping, 1149 struct address_space *mapping,
1150 loff_t pos, unsigned len, unsigned copied, 1150 loff_t pos, unsigned len, unsigned copied,
1151 struct page *page, void *fsdata) 1151 struct page *page, void *fsdata)
1152{ 1152{
1153 handle_t *handle = ext4_journal_current_handle(); 1153 handle_t *handle = ext4_journal_current_handle();
1154 struct inode *inode = mapping->host; 1154 struct inode *inode = mapping->host;
1155 int ret = 0, ret2; 1155 int ret = 0, ret2;
1156 1156
1157 trace_ext4_ordered_write_end(inode, pos, len, copied); 1157 trace_ext4_write_end(inode, pos, len, copied);
1158 ret = ext4_jbd2_file_inode(handle, inode); 1158 if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) {
1159 1159 ret = ext4_jbd2_file_inode(handle, inode);
1160 if (ret == 0) { 1160 if (ret) {
1161 ret2 = ext4_generic_write_end(file, mapping, pos, len, copied, 1161 unlock_page(page);
1162 page, fsdata); 1162 page_cache_release(page);
1163 copied = ret2; 1163 goto errout;
1164 if (pos + len > inode->i_size && ext4_can_truncate(inode)) 1164 }
1165 /* if we have allocated more blocks and copied
1166 * less. We will have blocks allocated outside
1167 * inode->i_size. So truncate them
1168 */
1169 ext4_orphan_add(handle, inode);
1170 if (ret2 < 0)
1171 ret = ret2;
1172 } else {
1173 unlock_page(page);
1174 page_cache_release(page);
1175 }
1176
1177 ret2 = ext4_journal_stop(handle);
1178 if (!ret)
1179 ret = ret2;
1180
1181 if (pos + len > inode->i_size) {
1182 ext4_truncate_failed_write(inode);
1183 /*
1184 * If truncate failed early the inode might still be
1185 * on the orphan list; we need to make sure the inode
1186 * is removed from the orphan list in that case.
1187 */
1188 if (inode->i_nlink)
1189 ext4_orphan_del(NULL, inode);
1190 } 1165 }
1191 1166
1192 1167 copied = ext4_generic_write_end(file, mapping, pos, len, copied,
1193 return ret ? ret : copied; 1168 page, fsdata);
1194} 1169 if (copied < 0)
1195 1170 ret = copied;
1196static int ext4_writeback_write_end(struct file *file,
1197 struct address_space *mapping,
1198 loff_t pos, unsigned len, unsigned copied,
1199 struct page *page, void *fsdata)
1200{
1201 handle_t *handle = ext4_journal_current_handle();
1202 struct inode *inode = mapping->host;
1203 int ret = 0, ret2;
1204
1205 trace_ext4_writeback_write_end(inode, pos, len, copied);
1206 ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
1207 page, fsdata);
1208 copied = ret2;
1209 if (pos + len > inode->i_size && ext4_can_truncate(inode)) 1171 if (pos + len > inode->i_size && ext4_can_truncate(inode))
1210 /* if we have allocated more blocks and copied 1172 /* if we have allocated more blocks and copied
1211 * less. We will have blocks allocated outside 1173 * less. We will have blocks allocated outside
1212 * inode->i_size. So truncate them 1174 * inode->i_size. So truncate them
1213 */ 1175 */
1214 ext4_orphan_add(handle, inode); 1176 ext4_orphan_add(handle, inode);
1215 1177errout:
1216 if (ret2 < 0)
1217 ret = ret2;
1218
1219 ret2 = ext4_journal_stop(handle); 1178 ret2 = ext4_journal_stop(handle);
1220 if (!ret) 1179 if (!ret)
1221 ret = ret2; 1180 ret = ret2;
@@ -2818,18 +2777,9 @@ static int ext4_da_write_end(struct file *file,
2818 unsigned long start, end; 2777 unsigned long start, end;
2819 int write_mode = (int)(unsigned long)fsdata; 2778 int write_mode = (int)(unsigned long)fsdata;
2820 2779
2821 if (write_mode == FALL_BACK_TO_NONDELALLOC) { 2780 if (write_mode == FALL_BACK_TO_NONDELALLOC)
2822 switch (ext4_inode_journal_mode(inode)) { 2781 return ext4_write_end(file, mapping, pos,
2823 case EXT4_INODE_ORDERED_DATA_MODE: 2782 len, copied, page, fsdata);
2824 return ext4_ordered_write_end(file, mapping, pos,
2825 len, copied, page, fsdata);
2826 case EXT4_INODE_WRITEBACK_DATA_MODE:
2827 return ext4_writeback_write_end(file, mapping, pos,
2828 len, copied, page, fsdata);
2829 default:
2830 BUG();
2831 }
2832 }
2833 2783
2834 trace_ext4_da_write_end(inode, pos, len, copied); 2784 trace_ext4_da_write_end(inode, pos, len, copied);
2835 start = pos & (PAGE_CACHE_SIZE - 1); 2785 start = pos & (PAGE_CACHE_SIZE - 1);
@@ -3334,27 +3284,12 @@ static int ext4_journalled_set_page_dirty(struct page *page)
3334 return __set_page_dirty_nobuffers(page); 3284 return __set_page_dirty_nobuffers(page);
3335} 3285}
3336 3286
3337static const struct address_space_operations ext4_ordered_aops = { 3287static const struct address_space_operations ext4_aops = {
3338 .readpage = ext4_readpage, 3288 .readpage = ext4_readpage,
3339 .readpages = ext4_readpages, 3289 .readpages = ext4_readpages,
3340 .writepage = ext4_writepage, 3290 .writepage = ext4_writepage,
3341 .write_begin = ext4_write_begin, 3291 .write_begin = ext4_write_begin,
3342 .write_end = ext4_ordered_write_end, 3292 .write_end = ext4_write_end,
3343 .bmap = ext4_bmap,
3344 .invalidatepage = ext4_invalidatepage,
3345 .releasepage = ext4_releasepage,
3346 .direct_IO = ext4_direct_IO,
3347 .migratepage = buffer_migrate_page,
3348 .is_partially_uptodate = block_is_partially_uptodate,
3349 .error_remove_page = generic_error_remove_page,
3350};
3351
3352static const struct address_space_operations ext4_writeback_aops = {
3353 .readpage = ext4_readpage,
3354 .readpages = ext4_readpages,
3355 .writepage = ext4_writepage,
3356 .write_begin = ext4_write_begin,
3357 .write_end = ext4_writeback_write_end,
3358 .bmap = ext4_bmap, 3293 .bmap = ext4_bmap,
3359 .invalidatepage = ext4_invalidatepage, 3294 .invalidatepage = ext4_invalidatepage,
3360 .releasepage = ext4_releasepage, 3295 .releasepage = ext4_releasepage,
@@ -3399,23 +3334,21 @@ void ext4_set_aops(struct inode *inode)
3399{ 3334{
3400 switch (ext4_inode_journal_mode(inode)) { 3335 switch (ext4_inode_journal_mode(inode)) {
3401 case EXT4_INODE_ORDERED_DATA_MODE: 3336 case EXT4_INODE_ORDERED_DATA_MODE:
3402 if (test_opt(inode->i_sb, DELALLOC)) 3337 ext4_set_inode_state(inode, EXT4_STATE_ORDERED_MODE);
3403 inode->i_mapping->a_ops = &ext4_da_aops;
3404 else
3405 inode->i_mapping->a_ops = &ext4_ordered_aops;
3406 break; 3338 break;
3407 case EXT4_INODE_WRITEBACK_DATA_MODE: 3339 case EXT4_INODE_WRITEBACK_DATA_MODE:
3408 if (test_opt(inode->i_sb, DELALLOC)) 3340 ext4_clear_inode_state(inode, EXT4_STATE_ORDERED_MODE);
3409 inode->i_mapping->a_ops = &ext4_da_aops;
3410 else
3411 inode->i_mapping->a_ops = &ext4_writeback_aops;
3412 break; 3341 break;
3413 case EXT4_INODE_JOURNAL_DATA_MODE: 3342 case EXT4_INODE_JOURNAL_DATA_MODE:
3414 inode->i_mapping->a_ops = &ext4_journalled_aops; 3343 inode->i_mapping->a_ops = &ext4_journalled_aops;
3415 break; 3344 return;
3416 default: 3345 default:
3417 BUG(); 3346 BUG();
3418 } 3347 }
3348 if (test_opt(inode->i_sb, DELALLOC))
3349 inode->i_mapping->a_ops = &ext4_da_aops;
3350 else
3351 inode->i_mapping->a_ops = &ext4_aops;
3419} 3352}
3420 3353
3421 3354