[PATCH 1/8] xfs: Introduce writeback context for writepages
Dave Chinner
david at fromorbit.com
Tue Aug 11 17:49:41 CDT 2015
From: Dave Chinner <dchinner at redhat.com>
xfs_vm_writepages() calls generic_writepages to writeback a range of
a file, but then xfs_vm_writepage() clusters pages itself as it does
not have any context it can pass between->writepage calls from
__write_cache_pages().
Introduce a writeback context for xfs_vm_writepages() and call
__write_cache_pages directly with our own writepage callback so that
we can pass that context to each writepage invocation.
Signed-off-by: Dave Chinner <dchinner at redhat.com>
---
fs/xfs/xfs_aops.c | 73 +++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 52 insertions(+), 21 deletions(-)
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 3859f5e..6dc1154 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -36,6 +36,14 @@
#include <linux/pagevec.h>
#include <linux/writeback.h>
+/*
+ * structure owned by writepages passed to individual writepage calls
+ */
+struct xfs_writepage_ctx {
+ struct xfs_bmbt_irec imap;
+ bool imap_valid;
+};
+
void
xfs_count_page_state(
struct page *page,
@@ -334,7 +342,7 @@ xfs_map_blocks(
return 0;
}
-STATIC int
+STATIC bool
xfs_imap_valid(
struct inode *inode,
struct xfs_bmbt_irec *imap,
@@ -934,20 +942,21 @@ out_invalidate:
* For any other dirty buffer heads on the page we should flush them.
*/
STATIC int
-xfs_vm_writepage(
+xfs_do_writepage(
struct page *page,
- struct writeback_control *wbc)
+ struct writeback_control *wbc,
+ void *data)
{
+ struct xfs_writepage_ctx *wpc = data;
struct inode *inode = page->mapping->host;
struct buffer_head *bh, *head;
- struct xfs_bmbt_irec imap;
xfs_ioend_t *ioend = NULL, *iohead = NULL;
loff_t offset;
unsigned int type;
__uint64_t end_offset;
pgoff_t end_index, last_index;
ssize_t len;
- int err, imap_valid = 0, uptodate = 1;
+ int err, uptodate = 1;
int count = 0;
int nonblocking = 0;
@@ -1067,24 +1076,24 @@ xfs_vm_writepage(
* buffers covering holes here.
*/
if (!buffer_mapped(bh) && buffer_uptodate(bh)) {
- imap_valid = 0;
+ wpc->imap_valid = false;
continue;
}
if (buffer_unwritten(bh)) {
if (type != XFS_IO_UNWRITTEN) {
type = XFS_IO_UNWRITTEN;
- imap_valid = 0;
+ wpc->imap_valid = false;
}
} else if (buffer_delay(bh)) {
if (type != XFS_IO_DELALLOC) {
type = XFS_IO_DELALLOC;
- imap_valid = 0;
+ wpc->imap_valid = false;
}
} else if (buffer_uptodate(bh)) {
if (type != XFS_IO_OVERWRITE) {
type = XFS_IO_OVERWRITE;
- imap_valid = 0;
+ wpc->imap_valid = false;
}
} else {
if (PageUptodate(page))
@@ -1095,13 +1104,14 @@ xfs_vm_writepage(
* subsequent writeable buffers into a new
* ioend.
*/
- imap_valid = 0;
+ wpc->imap_valid = false;
continue;
}
- if (imap_valid)
- imap_valid = xfs_imap_valid(inode, &imap, offset);
- if (!imap_valid) {
+ if (wpc->imap_valid)
+ wpc->imap_valid = xfs_imap_valid(inode, &wpc->imap,
+ offset);
+ if (!wpc->imap_valid) {
/*
* If we didn't have a valid mapping then we need to
* put the new mapping into a separate ioend structure.
@@ -1111,16 +1121,17 @@ xfs_vm_writepage(
* time.
*/
new_ioend = 1;
- err = xfs_map_blocks(inode, offset, &imap, type,
+ err = xfs_map_blocks(inode, offset, &wpc->imap, type,
nonblocking);
if (err)
goto error;
- imap_valid = xfs_imap_valid(inode, &imap, offset);
+ wpc->imap_valid = xfs_imap_valid(inode, &wpc->imap,
+ offset);
}
- if (imap_valid) {
+ if (wpc->imap_valid) {
lock_buffer(bh);
if (type != XFS_IO_OVERWRITE)
- xfs_map_at_offset(inode, bh, &imap, offset);
+ xfs_map_at_offset(inode, bh, &wpc->imap, offset);
xfs_add_to_ioend(inode, bh, offset, type, &ioend,
new_ioend);
count++;
@@ -1147,10 +1158,10 @@ xfs_vm_writepage(
* completion path as we have marked the initial page as under writeback
* and unlocked it.
*/
- if (imap_valid) {
+ if (wpc->imap_valid) {
xfs_off_t end_index;
- end_index = imap.br_startoff + imap.br_blockcount;
+ end_index = wpc->imap.br_startoff + wpc->imap.br_blockcount;
/* to bytes */
end_index <<= inode->i_blkbits;
@@ -1162,7 +1173,7 @@ xfs_vm_writepage(
if (end_index > last_index)
end_index = last_index;
- xfs_cluster_write(inode, page->index + 1, &imap, &ioend,
+ xfs_cluster_write(inode, page->index + 1, &wpc->imap, &ioend,
wbc, end_index);
}
@@ -1188,6 +1199,8 @@ error:
xfs_aops_discard_page(page);
ClearPageUptodate(page);
unlock_page(page);
+ mapping_set_error(page->mapping, err);
+ wpc->imap_valid = false;
return err;
redirty:
@@ -1197,12 +1210,30 @@ redirty:
}
STATIC int
+xfs_vm_writepage(
+ struct page *page,
+ struct writeback_control *wbc)
+{
+ struct xfs_writepage_ctx wpc = {};
+
+ return xfs_do_writepage(page, wbc, &wpc);
+}
+
+STATIC int
xfs_vm_writepages(
struct address_space *mapping,
struct writeback_control *wbc)
{
+ struct xfs_writepage_ctx wpc = {};
+ struct blk_plug plug;
+ int ret;
+
xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED);
- return generic_writepages(mapping, wbc);
+ blk_start_plug(&plug);
+ ret = write_cache_pages(mapping, wbc, xfs_do_writepage, &wpc);
+ blk_finish_plug(&plug);
+
+ return ret;
}
/*
--
2.5.0
More information about the xfs
mailing list