diff options
author | Theodore Ts'o <tytso@mit.edu> | 2013-04-03 12:39:17 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2013-04-03 12:39:17 -0400 |
commit | 74d553aad7926ed05e05d9d5cff516a7b31375fc (patch) | |
tree | b18222cb547c2ce4e18a9538bc28f92e2978c600 /fs/ext4 | |
parent | 8cde7ad17e4f4ff8d12ff60dd09c0a291cb0b61c (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.h | 1 | ||||
-rw-r--r-- | fs/ext4/inode.c | 125 |
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 | */ |
1148 | static int ext4_ordered_write_end(struct file *file, | 1148 | static 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; | |
1196 | static 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 | 1177 | errout: | |
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 | ||
3337 | static const struct address_space_operations ext4_ordered_aops = { | 3287 | static 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 | |||
3352 | static 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 | ||