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

Commit 9ff8ec32 authored by Steven Whitehouse's avatar Steven Whitehouse
Browse files

[GFS2] Split gfs2_writepage into three cases



This patch splits gfs2_writepage into separate functions for each of
the three cases: writeback, ordered and journalled. As a result
it becomes a lot easier to see what each one is doing. The common
code is moved into gfs2_writepage_common.

This fixes a performance bug where we were doing more work than
strictly required in the ordered write case.

Signed-off-by: default avatarSteven Whitehouse <swhiteho@redhat.com>
parent 5561093e
Loading
Loading
Loading
Loading
+10 −7
Original line number Diff line number Diff line
@@ -556,6 +556,7 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)

	lock_buffer(bd->bd_bh);
	gfs2_log_lock(sdp);
	if (tr) {
		if (!list_empty(&bd->bd_list_tr))
			goto out;
		tr->tr_touched = 1;
@@ -563,9 +564,11 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
			tr->tr_num_buf++;
			list_add(&bd->bd_list_tr, &tr->tr_list_buf);
		}
	}
	if (!list_empty(&le->le_list))
		goto out;

	if (tr)
		__glock_lo_add(sdp, &bd->bd_gl->gl_le);
	if (gfs2_is_jdata(ip)) {
		gfs2_pin(sdp, bd->bd_bh);
+91 −21
Original line number Diff line number Diff line
@@ -103,16 +103,15 @@ static int gfs2_get_block_direct(struct inode *inode, sector_t lblock,
}

/**
 * gfs2_writepage - Write complete page
 * @page: Page to write
 *
 * Returns: errno
 * gfs2_writepage_common - Common bits of writepage
 * @page: The page to be written
 * @wbc: The writeback control
 *
 * Some of this is copied from block_write_full_page() although we still
 * call it to do most of the work.
 * Returns: 1 if writepage is ok, otherwise an error code or zero if no error.
 */

static int gfs2_writepage(struct page *page, struct writeback_control *wbc)
static int gfs2_writepage_common(struct page *page,
				 struct writeback_control *wbc)
{
	struct inode *inode = page->mapping->host;
	struct gfs2_inode *ip = GFS2_I(inode);
@@ -120,24 +119,95 @@ static int gfs2_writepage(struct page *page, struct writeback_control *wbc)
	loff_t i_size = i_size_read(inode);
	pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
	unsigned offset;
	int error;
	int done_trans = 0;
	int ret = -EIO;

	if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl))) {
		unlock_page(page);
		return -EIO;
	}
	if (gfs2_assert_withdraw(sdp, gfs2_glock_is_held_excl(ip->i_gl)))
		goto out;
	ret = 0;
	if (current->journal_info)
		goto out_ignore;

		goto redirty;
	/* Is the page fully outside i_size? (truncate in progress) */
	offset = i_size & (PAGE_CACHE_SIZE-1);
	if (page->index > end_index || (page->index == end_index && !offset)) {
		page->mapping->a_ops->invalidatepage(page, 0);
		goto out;
	}
	return 1;
redirty:
	redirty_page_for_writepage(wbc, page);
out:
	unlock_page(page);
		return 0; /* don't care */
	return 0;
}

/**
 * gfs2_writeback_writepage - Write page for writeback mappings
 * @page: The page
 * @wbc: The writeback control
 *
 */

static int gfs2_writeback_writepage(struct page *page,
				    struct writeback_control *wbc)
{
	int ret;

	ret = gfs2_writepage_common(page, wbc);
	if (ret <= 0)
		return ret;

	ret = mpage_writepage(page, gfs2_get_block_noalloc, wbc);
	if (ret == -EAGAIN)
		ret = block_write_full_page(page, gfs2_get_block_noalloc, wbc);
	return ret;
}

/**
 * gfs2_ordered_writepage - Write page for ordered data files
 * @page: The page to write
 * @wbc: The writeback control
 *
 */

static int gfs2_ordered_writepage(struct page *page,
				  struct writeback_control *wbc)
{
	struct inode *inode = page->mapping->host;
	struct gfs2_inode *ip = GFS2_I(inode);
	int ret;

	ret = gfs2_writepage_common(page, wbc);
	if (ret <= 0)
		return ret;

	if (!page_has_buffers(page)) {
		create_empty_buffers(page, inode->i_sb->s_blocksize,
				     (1 << BH_Dirty)|(1 << BH_Uptodate));
	}
	gfs2_page_add_databufs(ip, page, 0, inode->i_sb->s_blocksize-1);
	return block_write_full_page(page, gfs2_get_block_noalloc, wbc);
}

/**
 * gfs2_jdata_writepage - Write complete page
 * @page: Page to write
 *
 * Returns: errno
 *
 */

static int gfs2_jdata_writepage(struct page *page, struct writeback_control *wbc)
{
	struct inode *inode = page->mapping->host;
	struct gfs2_inode *ip = GFS2_I(inode);
	struct gfs2_sbd *sdp = GFS2_SB(inode);
	int error;
	int done_trans = 0;

	error = gfs2_writepage_common(page, wbc);
	if (error <= 0)
		return error;

	if (PageChecked(page)) {
		error = gfs2_trans_begin(sdp, RES_DINODE + 1, 0);
		if (error)
@@ -838,7 +908,7 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
}

static const struct address_space_operations gfs2_writeback_aops = {
	.writepage = gfs2_writepage,
	.writepage = gfs2_writeback_writepage,
	.writepages = gfs2_writeback_writepages,
	.readpage = gfs2_readpage,
	.readpages = gfs2_readpages,
@@ -852,7 +922,7 @@ static const struct address_space_operations gfs2_writeback_aops = {
};

static const struct address_space_operations gfs2_ordered_aops = {
	.writepage = gfs2_writepage,
	.writepage = gfs2_ordered_writepage,
	.readpage = gfs2_readpage,
	.readpages = gfs2_readpages,
	.sync_page = block_sync_page,
@@ -866,7 +936,7 @@ static const struct address_space_operations gfs2_ordered_aops = {
};

static const struct address_space_operations gfs2_jdata_aops = {
	.writepage = gfs2_writepage,
	.writepage = gfs2_jdata_writepage,
	.readpage = gfs2_readpage,
	.readpages = gfs2_readpages,
	.sync_page = block_sync_page,