aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/ext4_jbd2.h56
-rw-r--r--fs/ext4/inode.c36
2 files changed, 51 insertions, 41 deletions
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index 5802fa1dab18..95af6f878501 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -261,43 +261,45 @@ static inline void ext4_update_inode_fsync_trans(handle_t *handle,
261/* super.c */ 261/* super.c */
262int ext4_force_commit(struct super_block *sb); 262int ext4_force_commit(struct super_block *sb);
263 263
264static inline int ext4_should_journal_data(struct inode *inode) 264/*
265 * Ext4 inode journal modes
266 */
267#define EXT4_INODE_JOURNAL_DATA_MODE 0x01 /* journal data mode */
268#define EXT4_INODE_ORDERED_DATA_MODE 0x02 /* ordered data mode */
269#define EXT4_INODE_WRITEBACK_DATA_MODE 0x04 /* writeback data mode */
270
271static inline int ext4_inode_journal_mode(struct inode *inode)
265{ 272{
266 if (EXT4_JOURNAL(inode) == NULL) 273 if (EXT4_JOURNAL(inode) == NULL)
267 return 0; 274 return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */
268 if (!S_ISREG(inode->i_mode)) 275 /* We do not support data journalling with delayed allocation */
269 return 1; 276 if (!S_ISREG(inode->i_mode) ||
270 if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) 277 test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
271 return 1; 278 return EXT4_INODE_JOURNAL_DATA_MODE; /* journal data */
272 if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA)) 279 if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
273 return 1; 280 !test_opt(inode->i_sb, DELALLOC))
274 return 0; 281 return EXT4_INODE_JOURNAL_DATA_MODE; /* journal data */
282 if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
283 return EXT4_INODE_ORDERED_DATA_MODE; /* ordered */
284 if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
285 return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */
286 else
287 BUG();
288}
289
290static inline int ext4_should_journal_data(struct inode *inode)
291{
292 return ext4_inode_journal_mode(inode) & EXT4_INODE_JOURNAL_DATA_MODE;
275} 293}
276 294
277static inline int ext4_should_order_data(struct inode *inode) 295static inline int ext4_should_order_data(struct inode *inode)
278{ 296{
279 if (EXT4_JOURNAL(inode) == NULL) 297 return ext4_inode_journal_mode(inode) & EXT4_INODE_ORDERED_DATA_MODE;
280 return 0;
281 if (!S_ISREG(inode->i_mode))
282 return 0;
283 if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
284 return 0;
285 if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
286 return 1;
287 return 0;
288} 298}
289 299
290static inline int ext4_should_writeback_data(struct inode *inode) 300static inline int ext4_should_writeback_data(struct inode *inode)
291{ 301{
292 if (EXT4_JOURNAL(inode) == NULL) 302 return ext4_inode_journal_mode(inode) & EXT4_INODE_WRITEBACK_DATA_MODE;
293 return 1;
294 if (!S_ISREG(inode->i_mode))
295 return 0;
296 if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
297 return 0;
298 if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
299 return 1;
300 return 0;
301} 303}
302 304
303/* 305/*
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index feaa82fe629d..a58812ef5ea3 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2482,13 +2482,14 @@ static int ext4_da_write_end(struct file *file,
2482 int write_mode = (int)(unsigned long)fsdata; 2482 int write_mode = (int)(unsigned long)fsdata;
2483 2483
2484 if (write_mode == FALL_BACK_TO_NONDELALLOC) { 2484 if (write_mode == FALL_BACK_TO_NONDELALLOC) {
2485 if (ext4_should_order_data(inode)) { 2485 switch (ext4_inode_journal_mode(inode)) {
2486 case EXT4_INODE_ORDERED_DATA_MODE:
2486 return ext4_ordered_write_end(file, mapping, pos, 2487 return ext4_ordered_write_end(file, mapping, pos,
2487 len, copied, page, fsdata); 2488 len, copied, page, fsdata);
2488 } else if (ext4_should_writeback_data(inode)) { 2489 case EXT4_INODE_WRITEBACK_DATA_MODE:
2489 return ext4_writeback_write_end(file, mapping, pos, 2490 return ext4_writeback_write_end(file, mapping, pos,
2490 len, copied, page, fsdata); 2491 len, copied, page, fsdata);
2491 } else { 2492 default:
2492 BUG(); 2493 BUG();
2493 } 2494 }
2494 } 2495 }
@@ -3086,18 +3087,25 @@ static const struct address_space_operations ext4_da_aops = {
3086 3087
3087void ext4_set_aops(struct inode *inode) 3088void ext4_set_aops(struct inode *inode)
3088{ 3089{
3089 if (ext4_should_order_data(inode) && 3090 switch (ext4_inode_journal_mode(inode)) {
3090 test_opt(inode->i_sb, DELALLOC)) 3091 case EXT4_INODE_ORDERED_DATA_MODE:
3091 inode->i_mapping->a_ops = &ext4_da_aops; 3092 if (test_opt(inode->i_sb, DELALLOC))
3092 else if (ext4_should_order_data(inode)) 3093 inode->i_mapping->a_ops = &ext4_da_aops;
3093 inode->i_mapping->a_ops = &ext4_ordered_aops; 3094 else
3094 else if (ext4_should_writeback_data(inode) && 3095 inode->i_mapping->a_ops = &ext4_ordered_aops;
3095 test_opt(inode->i_sb, DELALLOC)) 3096 break;
3096 inode->i_mapping->a_ops = &ext4_da_aops; 3097 case EXT4_INODE_WRITEBACK_DATA_MODE:
3097 else if (ext4_should_writeback_data(inode)) 3098 if (test_opt(inode->i_sb, DELALLOC))
3098 inode->i_mapping->a_ops = &ext4_writeback_aops; 3099 inode->i_mapping->a_ops = &ext4_da_aops;
3099 else 3100 else
3101 inode->i_mapping->a_ops = &ext4_writeback_aops;
3102 break;
3103 case EXT4_INODE_JOURNAL_DATA_MODE:
3100 inode->i_mapping->a_ops = &ext4_journalled_aops; 3104 inode->i_mapping->a_ops = &ext4_journalled_aops;
3105 break;
3106 default:
3107 BUG();
3108 }
3101} 3109}
3102 3110
3103 3111