]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 24 Feb 2017 08:27:47 +0000 (09:27 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 24 Feb 2017 08:27:47 +0000 (09:27 +0100)
added patches:
xfs-clear-delalloc-and-cache-on-buffered-write-failure.patch

queue-4.9/series
queue-4.9/xfs-clear-delalloc-and-cache-on-buffered-write-failure.patch [new file with mode: 0644]

index 0691bc174e6374ccbedce6ecf50197bf8a45bbf2..0e2df40a17c8530103b6641235285b75183a5222 100644 (file)
@@ -29,3 +29,4 @@ netfilter-nf_ct_helper-warn-when-not-applying-default-helper-assignment.patch
 acpica-linuxize-restore-and-fix-intel-compiler-build.patch
 block-fix-double-free-in-the-failure-path-of-cgwb_bdi_init.patch
 rtlwifi-rtl_usb-fix-for-urb-leaking-when-doing-ifconfig-up-down.patch
+xfs-clear-delalloc-and-cache-on-buffered-write-failure.patch
diff --git a/queue-4.9/xfs-clear-delalloc-and-cache-on-buffered-write-failure.patch b/queue-4.9/xfs-clear-delalloc-and-cache-on-buffered-write-failure.patch
new file mode 100644 (file)
index 0000000..9f982cc
--- /dev/null
@@ -0,0 +1,66 @@
+From fa7f138ac4c70dc00519c124cf7cd4862a0a5b0e Mon Sep 17 00:00:00 2001
+From: Brian Foster <bfoster@redhat.com>
+Date: Thu, 16 Feb 2017 17:19:12 -0800
+Subject: xfs: clear delalloc and cache on buffered write failure
+
+From: Brian Foster <bfoster@redhat.com>
+
+commit fa7f138ac4c70dc00519c124cf7cd4862a0a5b0e upstream.
+
+The buffered write failure handling code in
+xfs_file_iomap_end_delalloc() has a couple minor problems. First, if
+written == 0, start_fsb is not rounded down and it fails to kill off a
+delalloc block if the start offset is block unaligned. This results in a
+lingering delalloc block and broken delalloc block accounting detected
+at unmount time. Fix this by rounding down start_fsb in the unlikely
+event that written == 0.
+
+Second, it is possible for a failed overwrite of a delalloc extent to
+leave dirty pagecache around over a hole in the file. This is because is
+possible to hit ->iomap_end() on write failure before the iomap code has
+attempted to allocate pagecache, and thus has no need to clean it up. If
+the targeted delalloc extent was successfully written by a previous
+write, however, then it does still have dirty pages when ->iomap_end()
+punches out the underlying blocks. This ultimately results in writeback
+over a hole. To fix this problem, unconditionally punch out the
+pagecache from XFS before the associated delalloc range.
+
+Signed-off-by: Brian Foster <bfoster@redhat.com>
+Reviewed-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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/xfs/xfs_iomap.c |   13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+--- a/fs/xfs/xfs_iomap.c
++++ b/fs/xfs/xfs_iomap.c
+@@ -1068,7 +1068,15 @@ xfs_file_iomap_end_delalloc(
+       xfs_fileoff_t           end_fsb;
+       int                     error = 0;
+-      start_fsb = XFS_B_TO_FSB(mp, offset + written);
++      /*
++       * start_fsb refers to the first unused block after a short write. If
++       * nothing was written, round offset down to point at the first block in
++       * the range.
++       */
++      if (unlikely(!written))
++              start_fsb = XFS_B_TO_FSBT(mp, offset);
++      else
++              start_fsb = XFS_B_TO_FSB(mp, offset + written);
+       end_fsb = XFS_B_TO_FSB(mp, offset + length);
+       /*
+@@ -1080,6 +1088,9 @@ xfs_file_iomap_end_delalloc(
+        * blocks in the range, they are ours.
+        */
+       if (start_fsb < end_fsb) {
++              truncate_pagecache_range(VFS_I(ip), XFS_FSB_TO_B(mp, start_fsb),
++                                       XFS_FSB_TO_B(mp, end_fsb) - 1);
++
+               xfs_ilock(ip, XFS_ILOCK_EXCL);
+               error = xfs_bmap_punch_delalloc_range(ip, start_fsb,
+                                              end_fsb - start_fsb);