summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2019-06-28 19:31:37 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2019-06-30 09:05:17 -0700
commit7dbae9fbde8a2d3accf4b89502d5557bf3905e73 (patch)
tree91d3ab999a5cfb59657155b9e5d785f351f41c7b /fs
parent0290d9c1e56fc9964c6a0fa42cce251aecee606a (diff)
downloadlinux-7dbae9fbde8a2d3accf4b89502d5557bf3905e73.tar.gz
linux-7dbae9fbde8a2d3accf4b89502d5557bf3905e73.tar.bz2
linux-7dbae9fbde8a2d3accf4b89502d5557bf3905e73.zip
xfs: allow merging ioends over append boundaries
There is no real problem merging ioends that go beyond i_size into an ioend that doesn't. We just need to move the append transaction to the base ioend. Also use the opportunity to use a real error code instead of the magic 1 to cancel the transactions, and write a comment explaining the scheme. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_aops.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 1d147ef047f7..84fca91dacf1 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -300,11 +300,28 @@ xfs_ioend_can_merge(
return false;
if (ioend->io_offset + ioend->io_size != next->io_offset)
return false;
- if (xfs_ioend_is_append(ioend) != xfs_ioend_is_append(next))
- return false;
return true;
}
+/*
+ * If the to be merged ioend has a preallocated transaction for file
+ * size updates we need to ensure the ioend it is merged into also
+ * has one. If it already has one we can simply cancel the transaction
+ * as it is guaranteed to be clean.
+ */
+static void
+xfs_ioend_merge_append_transactions(
+ struct xfs_ioend *ioend,
+ struct xfs_ioend *next)
+{
+ if (!ioend->io_append_trans) {
+ ioend->io_append_trans = next->io_append_trans;
+ next->io_append_trans = NULL;
+ } else {
+ xfs_setfilesize_ioend(next, -ECANCELED);
+ }
+}
+
/* Try to merge adjacent completions. */
STATIC void
xfs_ioend_try_merge(
@@ -313,7 +330,6 @@ xfs_ioend_try_merge(
{
struct xfs_ioend *next_ioend;
int ioend_error;
- int error;
if (list_empty(more_ioends))
return;
@@ -327,10 +343,8 @@ xfs_ioend_try_merge(
break;
list_move_tail(&next_ioend->io_list, &ioend->io_list);
ioend->io_size += next_ioend->io_size;
- if (ioend->io_append_trans) {
- error = xfs_setfilesize_ioend(next_ioend, 1);
- ASSERT(error == 1);
- }
+ if (next_ioend->io_append_trans)
+ xfs_ioend_merge_append_transactions(ioend, next_ioend);
}
}