From: Dave Chinner <david@fromorbit.com>
To: xfs@oss.sgi.com
Subject: [PATCH 4/8] xfs: add ioend and iohead to xfs_writepage_ctx
Date: Wed, 12 Aug 2015 08:49:44 +1000 [thread overview]
Message-ID: <1439333388-16452-5-git-send-email-david@fromorbit.com> (raw)
In-Reply-To: <1439333388-16452-1-git-send-email-david@fromorbit.com>
From: Dave Chinner <dchinner@redhat.com>
Now we have a cross-writepage context, we don't need to submit IO at
the end of the writepage call - we can continue to aggregate ioends
across the entire writepages call if the iohead and ioend are held
in the writepage context.
This requires us to move the ioend submission up to the level where
the writepage context is declared. This does mean we do not submit
IO until we packaged the entire writeback range, but with the block
plugging in the writepages call this is the way IO is submitted,
anyway.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
fs/xfs/xfs_aops.c | 122 +++++++++++++++++++++++++++---------------------------
1 file changed, 60 insertions(+), 62 deletions(-)
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index b718156..e4184f5 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -43,6 +43,8 @@ struct xfs_writepage_ctx {
struct xfs_bmbt_irec imap;
bool imap_valid;
unsigned int io_type;
+ struct xfs_ioend *iohead;
+ struct xfs_ioend *ioend;
};
void
@@ -525,38 +527,6 @@ xfs_submit_ioend(
}
/*
- * Cancel submission of all buffer_heads so far in this endio.
- * Toss the endio too. Only ever called for the initial page
- * in a writepage request, so only ever one page.
- */
-STATIC void
-xfs_cancel_ioend(
- xfs_ioend_t *ioend)
-{
- xfs_ioend_t *next;
- struct buffer_head *bh, *next_bh;
-
- do {
- next = ioend->io_list;
- bh = ioend->io_buffer_head;
- do {
- next_bh = bh->b_private;
- clear_buffer_async_write(bh);
- /*
- * The unwritten flag is cleared when added to the
- * ioend. We're not submitting for I/O so mark the
- * buffer unwritten again for next time around.
- */
- if (ioend->io_type == XFS_IO_UNWRITTEN)
- set_buffer_unwritten(bh);
- unlock_buffer(bh);
- } while ((bh = next_bh) != NULL);
-
- mempool_free(ioend, xfs_ioend_pool);
- } while ((ioend = next) != NULL);
-}
-
-/*
* Test to see if we've been building up a completion structure for
* earlier buffers -- if so, we try to append to this ioend if we
* can, otherwise we finish off any current ioend and start another.
@@ -928,6 +898,27 @@ out_invalidate:
return;
}
+static int
+xfs_writepage_submit(
+ struct xfs_writepage_ctx *wpc,
+ struct writeback_control *wbc,
+ int status)
+{
+ struct blk_plug plug;
+
+ /* Reserve log space if we might write beyond the on-disk inode size. */
+ if (!status && wpc->ioend && wpc->ioend->io_type != XFS_IO_UNWRITTEN &&
+ xfs_ioend_is_append(wpc->ioend))
+ status = xfs_setfilesize_trans_alloc(wpc->ioend);
+
+ if (wpc->iohead) {
+ blk_start_plug(&plug);
+ xfs_submit_ioend(wbc, wpc->iohead, status);
+ blk_finish_plug(&plug);
+ }
+ return status;
+}
+
/*
* Write out a dirty page.
*
@@ -945,7 +936,6 @@ xfs_do_writepage(
struct xfs_writepage_ctx *wpc = data;
struct inode *inode = page->mapping->host;
struct buffer_head *bh, *head;
- xfs_ioend_t *ioend = NULL, *iohead = NULL;
loff_t offset;
__uint64_t end_offset;
pgoff_t end_index, last_index;
@@ -1122,12 +1112,12 @@ xfs_do_writepage(
if (wpc->io_type != XFS_IO_OVERWRITE)
xfs_map_at_offset(inode, bh, &wpc->imap, offset);
xfs_add_to_ioend(inode, bh, offset, wpc->io_type,
- &ioend, new_ioend);
+ &wpc->ioend, new_ioend);
count++;
}
- if (!iohead)
- iohead = ioend;
+ if (!wpc->iohead)
+ wpc->iohead = wpc->ioend;
} while (offset += len, ((bh = bh->b_this_page) != head));
@@ -1137,10 +1127,10 @@ xfs_do_writepage(
xfs_start_page_writeback(page, 1, count);
/* if there is no IO to be submitted for this page, we are done */
- if (!ioend)
+ if (!count)
return 0;
- ASSERT(iohead);
+ ASSERT(wpc->iohead);
/*
* Any errors from this point onwards need tobe reported through the IO
@@ -1162,31 +1152,37 @@ xfs_do_writepage(
if (end_index > last_index)
end_index = last_index;
- xfs_cluster_write(inode, page->index + 1, &wpc->imap, &ioend,
- wbc, end_index);
+ xfs_cluster_write(inode, page->index + 1, &wpc->imap,
+ &wpc->ioend, wbc, end_index);
}
-
- /*
- * Reserve log space if we might write beyond the on-disk inode size.
- */
- err = 0;
- if (ioend->io_type != XFS_IO_UNWRITTEN && xfs_ioend_is_append(ioend))
- err = xfs_setfilesize_trans_alloc(ioend);
-
- xfs_submit_ioend(wbc, iohead, err);
-
return 0;
error:
- if (iohead)
- xfs_cancel_ioend(iohead);
+ /*
+ * We have to fail the iohead here because we buffers locked in the
+ * ioend chain. If we don't do this, we'll deadlock invalidating the
+ * page as that tries to lock the buffers on the page. Also, because we
+ * have set pages under writeback, we have to run IO completion to mark
+ * the error state of the IO appropriately, so we can't cancel the ioend
+ * directly here. That means we have to mark this page as under
+ * writeback if we included any buffers from it in the ioend chain.
+ */
+ if (count)
+ xfs_start_page_writeback(page, 0, count);
+ xfs_writepage_submit(wpc, wbc, err);
- xfs_aops_discard_page(page);
- ClearPageUptodate(page);
- unlock_page(page);
+ /*
+ * We can only discard the page we had the IO error on if we haven't
+ * included it in the ioend above. If it has already been errored out,
+ * the it is unlocked and we can't touch it here.
+ */
+ if (!count) {
+ xfs_aops_discard_page(page);
+ ClearPageUptodate(page);
+ unlock_page(page);
+ }
mapping_set_error(page->mapping, err);
- wpc->imap_valid = false;
return err;
redirty:
@@ -1203,8 +1199,12 @@ xfs_vm_writepage(
struct xfs_writepage_ctx wpc = {
.io_type = XFS_IO_OVERWRITE,
};
+ int ret;
- return xfs_do_writepage(page, wbc, &wpc);
+ ret = xfs_do_writepage(page, wbc, &wpc);
+ if (ret)
+ return ret;
+ return xfs_writepage_submit(&wpc, wbc, ret);
}
STATIC int
@@ -1215,15 +1215,13 @@ xfs_vm_writepages(
struct xfs_writepage_ctx wpc = {
.io_type = XFS_IO_OVERWRITE,
};
- struct blk_plug plug;
int ret;
xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED);
- blk_start_plug(&plug);
ret = write_cache_pages(mapping, wbc, xfs_do_writepage, &wpc);
- blk_finish_plug(&plug);
-
- return ret;
+ if (ret)
+ return ret;
+ return xfs_writepage_submit(&wpc, wbc, ret);
}
/*
--
2.5.0
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next prev parent reply other threads:[~2015-08-11 22:50 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-11 22:49 [RFC, PATCH 0/8] xfs: get rid of xfs_cluster_write() Dave Chinner
2015-08-11 22:49 ` [PATCH 1/8] xfs: Introduce writeback context for writepages Dave Chinner
2015-08-12 7:26 ` Christoph Hellwig
2015-08-13 1:32 ` Dave Chinner
2015-08-13 6:52 ` Christoph Hellwig
2015-08-14 1:53 ` Dave Chinner
2015-08-15 13:23 ` Christoph Hellwig
2015-08-15 22:57 ` Dave Chinner
2015-08-11 22:49 ` [PATCH 2/8] xfs: io type needs to be part of the writepage context Dave Chinner
2015-08-11 22:49 ` [PATCH 3/8] xfs: remove nonblocking mode from xfs_vm_writepage Dave Chinner
2015-08-12 7:27 ` Christoph Hellwig
2015-08-11 22:49 ` Dave Chinner [this message]
2015-08-11 22:49 ` [PATCH 5/8] xfs: writepage context needs to handle discontiguous page ranges Dave Chinner
2015-08-11 22:49 ` [PATCH 6/8] xfs: xfs_cluster_write is redundant Dave Chinner
2015-08-11 22:49 ` [PATCH 7/8] xfs: factor mapping out of xfs_do_writepage Dave Chinner
2015-08-11 22:49 ` [PATCH 8/8] xfs: bufferheads are not needed in ->writepage Dave Chinner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1439333388-16452-5-git-send-email-david@fromorbit.com \
--to=david@fromorbit.com \
--cc=xfs@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox