Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1374,6 +1374,7 @@ enum {
	EXT4_STATE_DIOREAD_LOCK,	/* Disable support for dio read
					   nolocking */
	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)				\
+29 −96
Original line number Diff line number Diff line
@@ -1145,7 +1145,7 @@ static int ext4_generic_write_end(struct file *file,
 * ext4 never places buffers on inode->i_mapping->private_list.  metadata
 * 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,
			  loff_t pos, unsigned len, unsigned copied,
			  struct page *page, void *fsdata)
@@ -1154,68 +1154,27 @@ static int ext4_ordered_write_end(struct file *file,
	struct inode *inode = mapping->host;
	int ret = 0, ret2;

	trace_ext4_ordered_write_end(inode, pos, len, copied);
	trace_ext4_write_end(inode, pos, len, copied);
	if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) {
		ret = ext4_jbd2_file_inode(handle, inode);

	if (ret == 0) {
		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 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 {
		if (ret) {
			unlock_page(page);
			page_cache_release(page);
			goto errout;
		}

	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);
	}


	return ret ? 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,
	copied = ext4_generic_write_end(file, mapping, pos, len, copied,
					page, fsdata);
	copied = ret2;
	if (copied < 0)
		ret = copied;
	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;

errout:
	ret2 = ext4_journal_stop(handle);
	if (!ret)
		ret = ret2;
@@ -2818,18 +2777,9 @@ static int ext4_da_write_end(struct file *file,
	unsigned long start, end;
	int write_mode = (int)(unsigned long)fsdata;

	if (write_mode == FALL_BACK_TO_NONDELALLOC) {
		switch (ext4_inode_journal_mode(inode)) {
		case EXT4_INODE_ORDERED_DATA_MODE:
			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,
	if (write_mode == FALL_BACK_TO_NONDELALLOC)
		return ext4_write_end(file, mapping, pos,
				      len, copied, page, fsdata);
		default:
			BUG();
		}
	}

	trace_ext4_da_write_end(inode, pos, len, copied);
	start = pos & (PAGE_CACHE_SIZE - 1);
@@ -3334,27 +3284,12 @@ static int ext4_journalled_set_page_dirty(struct page *page)
	return __set_page_dirty_nobuffers(page);
}

static const struct address_space_operations ext4_ordered_aops = {
	.readpage		= ext4_readpage,
	.readpages		= ext4_readpages,
	.writepage		= ext4_writepage,
	.write_begin		= ext4_write_begin,
	.write_end		= ext4_ordered_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 = {
static const struct address_space_operations ext4_aops = {
	.readpage		= ext4_readpage,
	.readpages		= ext4_readpages,
	.writepage		= ext4_writepage,
	.write_begin		= ext4_write_begin,
	.write_end		= ext4_writeback_write_end,
	.write_end		= ext4_write_end,
	.bmap			= ext4_bmap,
	.invalidatepage		= ext4_invalidatepage,
	.releasepage		= ext4_releasepage,
@@ -3399,23 +3334,21 @@ void ext4_set_aops(struct inode *inode)
{
	switch (ext4_inode_journal_mode(inode)) {
	case EXT4_INODE_ORDERED_DATA_MODE:
		if (test_opt(inode->i_sb, DELALLOC))
			inode->i_mapping->a_ops = &ext4_da_aops;
		else
			inode->i_mapping->a_ops = &ext4_ordered_aops;
		ext4_set_inode_state(inode, EXT4_STATE_ORDERED_MODE);
		break;
	case EXT4_INODE_WRITEBACK_DATA_MODE:
		if (test_opt(inode->i_sb, DELALLOC))
			inode->i_mapping->a_ops = &ext4_da_aops;
		else
			inode->i_mapping->a_ops = &ext4_writeback_aops;
		ext4_clear_inode_state(inode, EXT4_STATE_ORDERED_MODE);
		break;
	case EXT4_INODE_JOURNAL_DATA_MODE:
		inode->i_mapping->a_ops = &ext4_journalled_aops;
		break;
		return;
	default:
		BUG();
	}
	if (test_opt(inode->i_sb, DELALLOC))
		inode->i_mapping->a_ops = &ext4_da_aops;
	else
		inode->i_mapping->a_ops = &ext4_aops;
}


+1 −9
Original line number Diff line number Diff line
@@ -257,15 +257,7 @@ DECLARE_EVENT_CLASS(ext4__write_end,
		  __entry->pos, __entry->len, __entry->copied)
);

DEFINE_EVENT(ext4__write_end, ext4_ordered_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,
DEFINE_EVENT(ext4__write_end, ext4_write_end,

	TP_PROTO(struct inode *inode, loff_t pos, unsigned int len,
		 unsigned int copied),