Commit 74d553aa authored by Theodore Ts'o's avatar Theodore Ts'o

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: default avatar"Theodore Ts'o" <tytso@mit.edu>
Reviewed-by: default avatarLukas Czerner <lczerner@redhat.com>
parent 8cde7ad1
...@@ -1374,6 +1374,7 @@ enum { ...@@ -1374,6 +1374,7 @@ enum {
EXT4_STATE_DIOREAD_LOCK, /* Disable support for dio read EXT4_STATE_DIOREAD_LOCK, /* Disable support for dio read
nolocking */ nolocking */
EXT4_STATE_MAY_INLINE_DATA, /* may have in-inode data */ EXT4_STATE_MAY_INLINE_DATA, /* may have in-inode data */
EXT4_STATE_ORDERED_MODE, /* data=ordered mode */
}; };
#define EXT4_INODE_BIT_FNS(name, field, offset) \ #define EXT4_INODE_BIT_FNS(name, field, offset) \
......
...@@ -1145,77 +1145,36 @@ static int ext4_generic_write_end(struct file *file, ...@@ -1145,77 +1145,36 @@ static int ext4_generic_write_end(struct file *file,
* ext4 never places buffers on inode->i_mapping->private_list. metadata * ext4 never places buffers on inode->i_mapping->private_list. metadata
* buffers are managed internally. * buffers are managed internally.
*/ */
static int ext4_ordered_write_end(struct file *file, static int ext4_write_end(struct file *file,
struct address_space *mapping, struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied, loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata) struct page *page, void *fsdata)
{ {
handle_t *handle = ext4_journal_current_handle(); handle_t *handle = ext4_journal_current_handle();
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
int ret = 0, ret2; int ret = 0, ret2;
trace_ext4_ordered_write_end(inode, pos, len, copied); trace_ext4_write_end(inode, pos, len, copied);
ret = ext4_jbd2_file_inode(handle, inode); if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) {
ret = ext4_jbd2_file_inode(handle, inode);
if (ret == 0) { if (ret) {
ret2 = ext4_generic_write_end(file, mapping, pos, len, copied, unlock_page(page);
page, fsdata); page_cache_release(page);
copied = ret2; goto errout;
if (pos + len > inode->i_size && ext4_can_truncate(inode)) }
/* if we have allocated more blocks and copied
* less. We will have blocks allocated outside
* inode->i_size. So truncate them
*/
ext4_orphan_add(handle, inode);
if (ret2 < 0)
ret = ret2;
} else {
unlock_page(page);
page_cache_release(page);
}
ret2 = ext4_journal_stop(handle);
if (!ret)
ret = ret2;
if (pos + len > inode->i_size) {
ext4_truncate_failed_write(inode);
/*
* If truncate failed early the inode might still be
* on the orphan list; we need to make sure the inode
* is removed from the orphan list in that case.
*/
if (inode->i_nlink)
ext4_orphan_del(NULL, inode);
} }
copied = ext4_generic_write_end(file, mapping, pos, len, copied,
return ret ? ret : copied; page, fsdata);
} if (copied < 0)
ret = copied;
static int ext4_writeback_write_end(struct file *file,
struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata)
{
handle_t *handle = ext4_journal_current_handle();
struct inode *inode = mapping->host;
int ret = 0, ret2;
trace_ext4_writeback_write_end(inode, pos, len, copied);
ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
page, fsdata);
copied = ret2;
if (pos + len > inode->i_size && ext4_can_truncate(inode)) if (pos + len > inode->i_size && ext4_can_truncate(inode))
/* if we have allocated more blocks and copied /* if we have allocated more blocks and copied
* less. We will have blocks allocated outside * less. We will have blocks allocated outside
* inode->i_size. So truncate them * inode->i_size. So truncate them
*/ */
ext4_orphan_add(handle, inode); ext4_orphan_add(handle, inode);
errout:
if (ret2 < 0)
ret = ret2;
ret2 = ext4_journal_stop(handle); ret2 = ext4_journal_stop(handle);
if (!ret) if (!ret)
ret = ret2; ret = ret2;
...@@ -2818,18 +2777,9 @@ static int ext4_da_write_end(struct file *file, ...@@ -2818,18 +2777,9 @@ static int ext4_da_write_end(struct file *file,
unsigned long start, end; unsigned long start, end;
int write_mode = (int)(unsigned long)fsdata; int write_mode = (int)(unsigned long)fsdata;
if (write_mode == FALL_BACK_TO_NONDELALLOC) { if (write_mode == FALL_BACK_TO_NONDELALLOC)
switch (ext4_inode_journal_mode(inode)) { return ext4_write_end(file, mapping, pos,
case EXT4_INODE_ORDERED_DATA_MODE: len, copied, page, fsdata);
return ext4_ordered_write_end(file, mapping, pos,
len, copied, page, fsdata);
case EXT4_INODE_WRITEBACK_DATA_MODE:
return ext4_writeback_write_end(file, mapping, pos,
len, copied, page, fsdata);
default:
BUG();
}
}
trace_ext4_da_write_end(inode, pos, len, copied); trace_ext4_da_write_end(inode, pos, len, copied);
start = pos & (PAGE_CACHE_SIZE - 1); start = pos & (PAGE_CACHE_SIZE - 1);
...@@ -3334,27 +3284,12 @@ static int ext4_journalled_set_page_dirty(struct page *page) ...@@ -3334,27 +3284,12 @@ static int ext4_journalled_set_page_dirty(struct page *page)
return __set_page_dirty_nobuffers(page); return __set_page_dirty_nobuffers(page);
} }
static const struct address_space_operations ext4_ordered_aops = { static const struct address_space_operations ext4_aops = {
.readpage = ext4_readpage, .readpage = ext4_readpage,
.readpages = ext4_readpages, .readpages = ext4_readpages,
.writepage = ext4_writepage, .writepage = ext4_writepage,
.write_begin = ext4_write_begin, .write_begin = ext4_write_begin,
.write_end = ext4_ordered_write_end, .write_end = ext4_write_end,
.bmap = ext4_bmap,
.invalidatepage = ext4_invalidatepage,
.releasepage = ext4_releasepage,
.direct_IO = ext4_direct_IO,
.migratepage = buffer_migrate_page,
.is_partially_uptodate = block_is_partially_uptodate,
.error_remove_page = generic_error_remove_page,
};
static const struct address_space_operations ext4_writeback_aops = {
.readpage = ext4_readpage,
.readpages = ext4_readpages,
.writepage = ext4_writepage,
.write_begin = ext4_write_begin,
.write_end = ext4_writeback_write_end,
.bmap = ext4_bmap, .bmap = ext4_bmap,
.invalidatepage = ext4_invalidatepage, .invalidatepage = ext4_invalidatepage,
.releasepage = ext4_releasepage, .releasepage = ext4_releasepage,
...@@ -3399,23 +3334,21 @@ void ext4_set_aops(struct inode *inode) ...@@ -3399,23 +3334,21 @@ void ext4_set_aops(struct inode *inode)
{ {
switch (ext4_inode_journal_mode(inode)) { switch (ext4_inode_journal_mode(inode)) {
case EXT4_INODE_ORDERED_DATA_MODE: case EXT4_INODE_ORDERED_DATA_MODE:
if (test_opt(inode->i_sb, DELALLOC)) ext4_set_inode_state(inode, EXT4_STATE_ORDERED_MODE);
inode->i_mapping->a_ops = &ext4_da_aops;
else
inode->i_mapping->a_ops = &ext4_ordered_aops;
break; break;
case EXT4_INODE_WRITEBACK_DATA_MODE: case EXT4_INODE_WRITEBACK_DATA_MODE:
if (test_opt(inode->i_sb, DELALLOC)) ext4_clear_inode_state(inode, EXT4_STATE_ORDERED_MODE);
inode->i_mapping->a_ops = &ext4_da_aops;
else
inode->i_mapping->a_ops = &ext4_writeback_aops;
break; break;
case EXT4_INODE_JOURNAL_DATA_MODE: case EXT4_INODE_JOURNAL_DATA_MODE:
inode->i_mapping->a_ops = &ext4_journalled_aops; inode->i_mapping->a_ops = &ext4_journalled_aops;
break; return;
default: default:
BUG(); BUG();
} }
if (test_opt(inode->i_sb, DELALLOC))
inode->i_mapping->a_ops = &ext4_da_aops;
else
inode->i_mapping->a_ops = &ext4_aops;
} }
......
...@@ -257,15 +257,7 @@ DECLARE_EVENT_CLASS(ext4__write_end, ...@@ -257,15 +257,7 @@ DECLARE_EVENT_CLASS(ext4__write_end,
__entry->pos, __entry->len, __entry->copied) __entry->pos, __entry->len, __entry->copied)
); );
DEFINE_EVENT(ext4__write_end, ext4_ordered_write_end, DEFINE_EVENT(ext4__write_end, ext4_write_end,
TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
unsigned int copied),
TP_ARGS(inode, pos, len, copied)
);
DEFINE_EVENT(ext4__write_end, ext4_writeback_write_end,
TP_PROTO(struct inode *inode, loff_t pos, unsigned int len, TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
unsigned int copied), unsigned int copied),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment