]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 31 Jul 2021 06:48:50 +0000 (08:48 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 31 Jul 2021 06:48:50 +0000 (08:48 +0200)
added patches:
can-ems_usb-fix-memory-leak.patch
can-esd_usb2-fix-memory-leak.patch
can-usb_8dev-fix-memory-leak.patch
niu-fix-incorrect-error-return-missed-in-previous-revert.patch
ocfs2-fix-zero-out-valid-data.patch
ocfs2-issue-zeroout-to-eof-blocks.patch

queue-4.4/can-ems_usb-fix-memory-leak.patch [new file with mode: 0644]
queue-4.4/can-esd_usb2-fix-memory-leak.patch [new file with mode: 0644]
queue-4.4/can-usb_8dev-fix-memory-leak.patch [new file with mode: 0644]
queue-4.4/niu-fix-incorrect-error-return-missed-in-previous-revert.patch [new file with mode: 0644]
queue-4.4/ocfs2-fix-zero-out-valid-data.patch [new file with mode: 0644]
queue-4.4/ocfs2-issue-zeroout-to-eof-blocks.patch [new file with mode: 0644]
queue-4.4/series

diff --git a/queue-4.4/can-ems_usb-fix-memory-leak.patch b/queue-4.4/can-ems_usb-fix-memory-leak.patch
new file mode 100644 (file)
index 0000000..8bec1ac
--- /dev/null
@@ -0,0 +1,93 @@
+From 9969e3c5f40c166e3396acc36c34f9de502929f6 Mon Sep 17 00:00:00 2001
+From: Pavel Skripkin <paskripkin@gmail.com>
+Date: Tue, 27 Jul 2021 20:00:33 +0300
+Subject: can: ems_usb: fix memory leak
+
+From: Pavel Skripkin <paskripkin@gmail.com>
+
+commit 9969e3c5f40c166e3396acc36c34f9de502929f6 upstream.
+
+In ems_usb_start() MAX_RX_URBS coherent buffers are allocated and
+there is nothing, that frees them:
+
+1) In callback function the urb is resubmitted and that's all
+2) In disconnect function urbs are simply killed, but URB_FREE_BUFFER
+   is not set (see ems_usb_start) and this flag cannot be used with
+   coherent buffers.
+
+So, all allocated buffers should be freed with usb_free_coherent()
+explicitly.
+
+Side note: This code looks like a copy-paste of other can drivers. The
+same patch was applied to mcba_usb driver and it works nice with real
+hardware. There is no change in functionality, only clean-up code for
+coherent buffers.
+
+Fixes: 702171adeed3 ("ems_usb: Added support for EMS CPC-USB/ARM7 CAN/USB interface")
+Link: https://lore.kernel.org/r/59aa9fbc9a8cbf9af2bbd2f61a659c480b415800.1627404470.git.paskripkin@gmail.com
+Cc: linux-stable <stable@vger.kernel.org>
+Signed-off-by: Pavel Skripkin <paskripkin@gmail.com>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/can/usb/ems_usb.c |   14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/can/usb/ems_usb.c
++++ b/drivers/net/can/usb/ems_usb.c
+@@ -267,6 +267,8 @@ struct ems_usb {
+       unsigned int free_slots; /* remember number of available slots */
+       struct ems_cpc_msg active_params; /* active controller parameters */
++      void *rxbuf[MAX_RX_URBS];
++      dma_addr_t rxbuf_dma[MAX_RX_URBS];
+ };
+ static void ems_usb_read_interrupt_callback(struct urb *urb)
+@@ -600,6 +602,7 @@ static int ems_usb_start(struct ems_usb
+       for (i = 0; i < MAX_RX_URBS; i++) {
+               struct urb *urb = NULL;
+               u8 *buf = NULL;
++              dma_addr_t buf_dma;
+               /* create a URB, and a buffer for it */
+               urb = usb_alloc_urb(0, GFP_KERNEL);
+@@ -610,7 +613,7 @@ static int ems_usb_start(struct ems_usb
+               }
+               buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL,
+-                                       &urb->transfer_dma);
++                                       &buf_dma);
+               if (!buf) {
+                       netdev_err(netdev, "No memory left for USB buffer\n");
+                       usb_free_urb(urb);
+@@ -618,6 +621,8 @@ static int ems_usb_start(struct ems_usb
+                       break;
+               }
++              urb->transfer_dma = buf_dma;
++
+               usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 2),
+                                 buf, RX_BUFFER_SIZE,
+                                 ems_usb_read_bulk_callback, dev);
+@@ -633,6 +638,9 @@ static int ems_usb_start(struct ems_usb
+                       break;
+               }
++              dev->rxbuf[i] = buf;
++              dev->rxbuf_dma[i] = buf_dma;
++
+               /* Drop reference, USB core will take care of freeing it */
+               usb_free_urb(urb);
+       }
+@@ -698,6 +706,10 @@ static void unlink_all_urbs(struct ems_u
+       usb_kill_anchored_urbs(&dev->rx_submitted);
++      for (i = 0; i < MAX_RX_URBS; ++i)
++              usb_free_coherent(dev->udev, RX_BUFFER_SIZE,
++                                dev->rxbuf[i], dev->rxbuf_dma[i]);
++
+       usb_kill_anchored_urbs(&dev->tx_submitted);
+       atomic_set(&dev->active_tx_urbs, 0);
diff --git a/queue-4.4/can-esd_usb2-fix-memory-leak.patch b/queue-4.4/can-esd_usb2-fix-memory-leak.patch
new file mode 100644 (file)
index 0000000..faccdff
--- /dev/null
@@ -0,0 +1,97 @@
+From 928150fad41ba16df7fcc9f7f945747d0f56cbb6 Mon Sep 17 00:00:00 2001
+From: Pavel Skripkin <paskripkin@gmail.com>
+Date: Tue, 27 Jul 2021 20:00:46 +0300
+Subject: can: esd_usb2: fix memory leak
+
+From: Pavel Skripkin <paskripkin@gmail.com>
+
+commit 928150fad41ba16df7fcc9f7f945747d0f56cbb6 upstream.
+
+In esd_usb2_setup_rx_urbs() MAX_RX_URBS coherent buffers are allocated
+and there is nothing, that frees them:
+
+1) In callback function the urb is resubmitted and that's all
+2) In disconnect function urbs are simply killed, but URB_FREE_BUFFER
+   is not set (see esd_usb2_setup_rx_urbs) and this flag cannot be used
+   with coherent buffers.
+
+So, all allocated buffers should be freed with usb_free_coherent()
+explicitly.
+
+Side note: This code looks like a copy-paste of other can drivers. The
+same patch was applied to mcba_usb driver and it works nice with real
+hardware. There is no change in functionality, only clean-up code for
+coherent buffers.
+
+Fixes: 96d8e90382dc ("can: Add driver for esd CAN-USB/2 device")
+Link: https://lore.kernel.org/r/b31b096926dcb35998ad0271aac4b51770ca7cc8.1627404470.git.paskripkin@gmail.com
+Cc: linux-stable <stable@vger.kernel.org>
+Signed-off-by: Pavel Skripkin <paskripkin@gmail.com>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/can/usb/esd_usb2.c |   16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/can/usb/esd_usb2.c
++++ b/drivers/net/can/usb/esd_usb2.c
+@@ -207,6 +207,8 @@ struct esd_usb2 {
+       int net_count;
+       u32 version;
+       int rxinitdone;
++      void *rxbuf[MAX_RX_URBS];
++      dma_addr_t rxbuf_dma[MAX_RX_URBS];
+ };
+ struct esd_usb2_net_priv {
+@@ -556,6 +558,7 @@ static int esd_usb2_setup_rx_urbs(struct
+       for (i = 0; i < MAX_RX_URBS; i++) {
+               struct urb *urb = NULL;
+               u8 *buf = NULL;
++              dma_addr_t buf_dma;
+               /* create a URB, and a buffer for it */
+               urb = usb_alloc_urb(0, GFP_KERNEL);
+@@ -567,7 +570,7 @@ static int esd_usb2_setup_rx_urbs(struct
+               }
+               buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL,
+-                                       &urb->transfer_dma);
++                                       &buf_dma);
+               if (!buf) {
+                       dev_warn(dev->udev->dev.parent,
+                                "No memory left for USB buffer\n");
+@@ -575,6 +578,8 @@ static int esd_usb2_setup_rx_urbs(struct
+                       goto freeurb;
+               }
++              urb->transfer_dma = buf_dma;
++
+               usb_fill_bulk_urb(urb, dev->udev,
+                                 usb_rcvbulkpipe(dev->udev, 1),
+                                 buf, RX_BUFFER_SIZE,
+@@ -587,8 +592,12 @@ static int esd_usb2_setup_rx_urbs(struct
+                       usb_unanchor_urb(urb);
+                       usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
+                                         urb->transfer_dma);
++                      goto freeurb;
+               }
++              dev->rxbuf[i] = buf;
++              dev->rxbuf_dma[i] = buf_dma;
++
+ freeurb:
+               /* Drop reference, USB core will take care of freeing it */
+               usb_free_urb(urb);
+@@ -676,6 +685,11 @@ static void unlink_all_urbs(struct esd_u
+       int i, j;
+       usb_kill_anchored_urbs(&dev->rx_submitted);
++
++      for (i = 0; i < MAX_RX_URBS; ++i)
++              usb_free_coherent(dev->udev, RX_BUFFER_SIZE,
++                                dev->rxbuf[i], dev->rxbuf_dma[i]);
++
+       for (i = 0; i < dev->net_count; i++) {
+               priv = dev->nets[i];
+               if (priv) {
diff --git a/queue-4.4/can-usb_8dev-fix-memory-leak.patch b/queue-4.4/can-usb_8dev-fix-memory-leak.patch
new file mode 100644 (file)
index 0000000..1875c32
--- /dev/null
@@ -0,0 +1,94 @@
+From 0e865f0c31928d6a313269ef624907eec55287c4 Mon Sep 17 00:00:00 2001
+From: Pavel Skripkin <paskripkin@gmail.com>
+Date: Tue, 27 Jul 2021 19:59:57 +0300
+Subject: can: usb_8dev: fix memory leak
+
+From: Pavel Skripkin <paskripkin@gmail.com>
+
+commit 0e865f0c31928d6a313269ef624907eec55287c4 upstream.
+
+In usb_8dev_start() MAX_RX_URBS coherent buffers are allocated and
+there is nothing, that frees them:
+
+1) In callback function the urb is resubmitted and that's all
+2) In disconnect function urbs are simply killed, but URB_FREE_BUFFER
+   is not set (see usb_8dev_start) and this flag cannot be used with
+   coherent buffers.
+
+So, all allocated buffers should be freed with usb_free_coherent()
+explicitly.
+
+Side note: This code looks like a copy-paste of other can drivers. The
+same patch was applied to mcba_usb driver and it works nice with real
+hardware. There is no change in functionality, only clean-up code for
+coherent buffers.
+
+Fixes: 0024d8ad1639 ("can: usb_8dev: Add support for USB2CAN interface from 8 devices")
+Link: https://lore.kernel.org/r/d39b458cd425a1cf7f512f340224e6e9563b07bd.1627404470.git.paskripkin@gmail.com
+Cc: linux-stable <stable@vger.kernel.org>
+Signed-off-by: Pavel Skripkin <paskripkin@gmail.com>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/can/usb/usb_8dev.c |   15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/can/usb/usb_8dev.c
++++ b/drivers/net/can/usb/usb_8dev.c
+@@ -148,7 +148,8 @@ struct usb_8dev_priv {
+       u8 *cmd_msg_buffer;
+       struct mutex usb_8dev_cmd_lock;
+-
++      void *rxbuf[MAX_RX_URBS];
++      dma_addr_t rxbuf_dma[MAX_RX_URBS];
+ };
+ /* tx frame */
+@@ -746,6 +747,7 @@ static int usb_8dev_start(struct usb_8de
+       for (i = 0; i < MAX_RX_URBS; i++) {
+               struct urb *urb = NULL;
+               u8 *buf;
++              dma_addr_t buf_dma;
+               /* create a URB, and a buffer for it */
+               urb = usb_alloc_urb(0, GFP_KERNEL);
+@@ -756,7 +758,7 @@ static int usb_8dev_start(struct usb_8de
+               }
+               buf = usb_alloc_coherent(priv->udev, RX_BUFFER_SIZE, GFP_KERNEL,
+-                                       &urb->transfer_dma);
++                                       &buf_dma);
+               if (!buf) {
+                       netdev_err(netdev, "No memory left for USB buffer\n");
+                       usb_free_urb(urb);
+@@ -764,6 +766,8 @@ static int usb_8dev_start(struct usb_8de
+                       break;
+               }
++              urb->transfer_dma = buf_dma;
++
+               usb_fill_bulk_urb(urb, priv->udev,
+                                 usb_rcvbulkpipe(priv->udev,
+                                                 USB_8DEV_ENDP_DATA_RX),
+@@ -781,6 +785,9 @@ static int usb_8dev_start(struct usb_8de
+                       break;
+               }
++              priv->rxbuf[i] = buf;
++              priv->rxbuf_dma[i] = buf_dma;
++
+               /* Drop reference, USB core will take care of freeing it */
+               usb_free_urb(urb);
+       }
+@@ -850,6 +857,10 @@ static void unlink_all_urbs(struct usb_8
+       usb_kill_anchored_urbs(&priv->rx_submitted);
++      for (i = 0; i < MAX_RX_URBS; ++i)
++              usb_free_coherent(priv->udev, RX_BUFFER_SIZE,
++                                priv->rxbuf[i], priv->rxbuf_dma[i]);
++
+       usb_kill_anchored_urbs(&priv->tx_submitted);
+       atomic_set(&priv->active_tx_urbs, 0);
diff --git a/queue-4.4/niu-fix-incorrect-error-return-missed-in-previous-revert.patch b/queue-4.4/niu-fix-incorrect-error-return-missed-in-previous-revert.patch
new file mode 100644 (file)
index 0000000..6497017
--- /dev/null
@@ -0,0 +1,42 @@
+From 15bbf8bb4d4ab87108ecf5f4155ec8ffa3c141d6 Mon Sep 17 00:00:00 2001
+From: Paul Jakma <paul@jakma.org>
+Date: Fri, 23 Jul 2021 16:13:04 +0100
+Subject: NIU: fix incorrect error return, missed in previous revert
+
+From: Paul Jakma <paul@jakma.org>
+
+commit 15bbf8bb4d4ab87108ecf5f4155ec8ffa3c141d6 upstream.
+
+Commit 7930742d6, reverting 26fd962, missed out on reverting an incorrect
+change to a return value.  The niu_pci_vpd_scan_props(..) == 1 case appears
+to be a normal path - treating it as an error and return -EINVAL was
+breaking VPD_SCAN and causing the driver to fail to load.
+
+Fix, so my Neptune card works again.
+
+Cc: Kangjie Lu <kjlu@umn.edu>
+Cc: Shannon Nelson <shannon.lee.nelson@gmail.com>
+Cc: David S. Miller <davem@davemloft.net>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: stable <stable@vger.kernel.org>
+Fixes: 7930742d ('Revert "niu: fix missing checks of niu_pci_eeprom_read"')
+Signed-off-by: Paul Jakma <paul@jakma.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/sun/niu.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/sun/niu.c
++++ b/drivers/net/ethernet/sun/niu.c
+@@ -8213,8 +8213,9 @@ static int niu_pci_vpd_fetch(struct niu
+               err = niu_pci_vpd_scan_props(np, here, end);
+               if (err < 0)
+                       return err;
++              /* ret == 1 is not an error */
+               if (err == 1)
+-                      return -EINVAL;
++                      return 0;
+       }
+       return 0;
+ }
diff --git a/queue-4.4/ocfs2-fix-zero-out-valid-data.patch b/queue-4.4/ocfs2-fix-zero-out-valid-data.patch
new file mode 100644 (file)
index 0000000..73649fb
--- /dev/null
@@ -0,0 +1,60 @@
+From f267aeb6dea5e468793e5b8eb6a9c72c0020d418 Mon Sep 17 00:00:00 2001
+From: Junxiao Bi <junxiao.bi@oracle.com>
+Date: Thu, 29 Jul 2021 14:53:38 -0700
+Subject: ocfs2: fix zero out valid data
+
+From: Junxiao Bi <junxiao.bi@oracle.com>
+
+commit f267aeb6dea5e468793e5b8eb6a9c72c0020d418 upstream.
+
+If append-dio feature is enabled, direct-io write and fallocate could
+run in parallel to extend file size, fallocate used "orig_isize" to
+record i_size before taking "ip_alloc_sem", when
+ocfs2_zeroout_partial_cluster() zeroout EOF blocks, i_size maybe already
+extended by ocfs2_dio_end_io_write(), that will cause valid data zeroed
+out.
+
+Link: https://lkml.kernel.org/r/20210722054923.24389-1-junxiao.bi@oracle.com
+Fixes: 6bba4471f0cc ("ocfs2: fix data corruption by fallocate")
+Signed-off-by: Junxiao Bi <junxiao.bi@oracle.com>
+Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
+Cc: Changwei Ge <gechangwei@live.cn>
+Cc: Gang He <ghe@suse.com>
+Cc: Joel Becker <jlbec@evilplan.org>
+Cc: Jun Piao <piaojun@huawei.com>
+Cc: Mark Fasheh <mark@fasheh.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ocfs2/file.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/ocfs2/file.c
++++ b/fs/ocfs2/file.c
+@@ -1939,7 +1939,6 @@ static int __ocfs2_change_file_space(str
+               goto out_inode_unlock;
+       }
+-      orig_isize = i_size_read(inode);
+       switch (sr->l_whence) {
+       case 0: /*SEEK_SET*/
+               break;
+@@ -1947,7 +1946,7 @@ static int __ocfs2_change_file_space(str
+               sr->l_start += f_pos;
+               break;
+       case 2: /*SEEK_END*/
+-              sr->l_start += orig_isize;
++              sr->l_start += i_size_read(inode);
+               break;
+       default:
+               ret = -EINVAL;
+@@ -2002,6 +2001,7 @@ static int __ocfs2_change_file_space(str
+               ret = -EINVAL;
+       }
++      orig_isize = i_size_read(inode);
+       /* zeroout eof blocks in the cluster. */
+       if (!ret && change_size && orig_isize < size) {
+               ret = ocfs2_zeroout_partial_cluster(inode, orig_isize,
diff --git a/queue-4.4/ocfs2-issue-zeroout-to-eof-blocks.patch b/queue-4.4/ocfs2-issue-zeroout-to-eof-blocks.patch
new file mode 100644 (file)
index 0000000..1bdaff2
--- /dev/null
@@ -0,0 +1,186 @@
+From 9449ad33be8480f538b11a593e2dda2fb33ca06d Mon Sep 17 00:00:00 2001
+From: Junxiao Bi <junxiao.bi@oracle.com>
+Date: Thu, 29 Jul 2021 14:53:41 -0700
+Subject: ocfs2: issue zeroout to EOF blocks
+
+From: Junxiao Bi <junxiao.bi@oracle.com>
+
+commit 9449ad33be8480f538b11a593e2dda2fb33ca06d upstream.
+
+For punch holes in EOF blocks, fallocate used buffer write to zero the
+EOF blocks in last cluster.  But since ->writepage will ignore EOF
+pages, those zeros will not be flushed.
+
+This "looks" ok as commit 6bba4471f0cc ("ocfs2: fix data corruption by
+fallocate") will zero the EOF blocks when extend the file size, but it
+isn't.  The problem happened on those EOF pages, before writeback, those
+pages had DIRTY flag set and all buffer_head in them also had DIRTY flag
+set, when writeback run by write_cache_pages(), DIRTY flag on the page
+was cleared, but DIRTY flag on the buffer_head not.
+
+When next write happened to those EOF pages, since buffer_head already
+had DIRTY flag set, it would not mark page DIRTY again.  That made
+writeback ignore them forever.  That will cause data corruption.  Even
+directio write can't work because it will fail when trying to drop pages
+caches before direct io, as it found the buffer_head for those pages
+still had DIRTY flag set, then it will fall back to buffer io mode.
+
+To make a summary of the issue, as writeback ingores EOF pages, once any
+EOF page is generated, any write to it will only go to the page cache,
+it will never be flushed to disk even file size extends and that page is
+not EOF page any more.  The fix is to avoid zero EOF blocks with buffer
+write.
+
+The following code snippet from qemu-img could trigger the corruption.
+
+  656   open("6b3711ae-3306-4bdd-823c-cf1c0060a095.conv.2", O_RDWR|O_DIRECT|O_CLOEXEC) = 11
+  ...
+  660   fallocate(11, FALLOC_FL_KEEP_SIZE|FALLOC_FL_PUNCH_HOLE, 2275868672, 327680 <unfinished ...>
+  660   fallocate(11, 0, 2275868672, 327680) = 0
+  658   pwrite64(11, "
+
+Link: https://lkml.kernel.org/r/20210722054923.24389-2-junxiao.bi@oracle.com
+Signed-off-by: Junxiao Bi <junxiao.bi@oracle.com>
+Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
+Cc: Mark Fasheh <mark@fasheh.com>
+Cc: Joel Becker <jlbec@evilplan.org>
+Cc: Changwei Ge <gechangwei@live.cn>
+Cc: Gang He <ghe@suse.com>
+Cc: Jun Piao <piaojun@huawei.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ocfs2/file.c |   99 +++++++++++++++++++++++++++++++++-----------------------
+ 1 file changed, 60 insertions(+), 39 deletions(-)
+
+--- a/fs/ocfs2/file.c
++++ b/fs/ocfs2/file.c
+@@ -1532,6 +1532,45 @@ static void ocfs2_truncate_cluster_pages
+       }
+ }
++/*
++ * zero out partial blocks of one cluster.
++ *
++ * start: file offset where zero starts, will be made upper block aligned.
++ * len: it will be trimmed to the end of current cluster if "start + len"
++ *      is bigger than it.
++ */
++static int ocfs2_zeroout_partial_cluster(struct inode *inode,
++                                      u64 start, u64 len)
++{
++      int ret;
++      u64 start_block, end_block, nr_blocks;
++      u64 p_block, offset;
++      u32 cluster, p_cluster, nr_clusters;
++      struct super_block *sb = inode->i_sb;
++      u64 end = ocfs2_align_bytes_to_clusters(sb, start);
++
++      if (start + len < end)
++              end = start + len;
++
++      start_block = ocfs2_blocks_for_bytes(sb, start);
++      end_block = ocfs2_blocks_for_bytes(sb, end);
++      nr_blocks = end_block - start_block;
++      if (!nr_blocks)
++              return 0;
++
++      cluster = ocfs2_bytes_to_clusters(sb, start);
++      ret = ocfs2_get_clusters(inode, cluster, &p_cluster,
++                              &nr_clusters, NULL);
++      if (ret)
++              return ret;
++      if (!p_cluster)
++              return 0;
++
++      offset = start_block - ocfs2_clusters_to_blocks(sb, cluster);
++      p_block = ocfs2_clusters_to_blocks(sb, p_cluster) + offset;
++      return sb_issue_zeroout(sb, p_block, nr_blocks, GFP_NOFS);
++}
++
+ static int ocfs2_zero_partial_clusters(struct inode *inode,
+                                      u64 start, u64 len)
+ {
+@@ -1541,6 +1580,7 @@ static int ocfs2_zero_partial_clusters(s
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       unsigned int csize = osb->s_clustersize;
+       handle_t *handle;
++      loff_t isize = i_size_read(inode);
+       /*
+        * The "start" and "end" values are NOT necessarily part of
+@@ -1561,6 +1601,26 @@ static int ocfs2_zero_partial_clusters(s
+       if ((start & (csize - 1)) == 0 && (end & (csize - 1)) == 0)
+               goto out;
++      /* No page cache for EOF blocks, issue zero out to disk. */
++      if (end > isize) {
++              /*
++               * zeroout eof blocks in last cluster starting from
++               * "isize" even "start" > "isize" because it is
++               * complicated to zeroout just at "start" as "start"
++               * may be not aligned with block size, buffer write
++               * would be required to do that, but out of eof buffer
++               * write is not supported.
++               */
++              ret = ocfs2_zeroout_partial_cluster(inode, isize,
++                                      end - isize);
++              if (ret) {
++                      mlog_errno(ret);
++                      goto out;
++              }
++              if (start >= isize)
++                      goto out;
++              end = isize;
++      }
+       handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+@@ -1860,45 +1920,6 @@ out:
+ }
+ /*
+- * zero out partial blocks of one cluster.
+- *
+- * start: file offset where zero starts, will be made upper block aligned.
+- * len: it will be trimmed to the end of current cluster if "start + len"
+- *      is bigger than it.
+- */
+-static int ocfs2_zeroout_partial_cluster(struct inode *inode,
+-                                      u64 start, u64 len)
+-{
+-      int ret;
+-      u64 start_block, end_block, nr_blocks;
+-      u64 p_block, offset;
+-      u32 cluster, p_cluster, nr_clusters;
+-      struct super_block *sb = inode->i_sb;
+-      u64 end = ocfs2_align_bytes_to_clusters(sb, start);
+-
+-      if (start + len < end)
+-              end = start + len;
+-
+-      start_block = ocfs2_blocks_for_bytes(sb, start);
+-      end_block = ocfs2_blocks_for_bytes(sb, end);
+-      nr_blocks = end_block - start_block;
+-      if (!nr_blocks)
+-              return 0;
+-
+-      cluster = ocfs2_bytes_to_clusters(sb, start);
+-      ret = ocfs2_get_clusters(inode, cluster, &p_cluster,
+-                              &nr_clusters, NULL);
+-      if (ret)
+-              return ret;
+-      if (!p_cluster)
+-              return 0;
+-
+-      offset = start_block - ocfs2_clusters_to_blocks(sb, cluster);
+-      p_block = ocfs2_clusters_to_blocks(sb, p_cluster) + offset;
+-      return sb_issue_zeroout(sb, p_block, nr_blocks, GFP_NOFS);
+-}
+-
+-/*
+  * Parts of this function taken from xfs_change_file_space()
+  */
+ static int __ocfs2_change_file_space(struct file *file, struct inode *inode,
index f45042549e5530421e27b5d8e6ede03c9575445e..c833cf32dbb0ec6631142d32072319d0c664f874 100644 (file)
@@ -10,4 +10,10 @@ hfs-add-lock-nesting-notation-to-hfs_find_init.patch
 arm-dts-versatile-fix-up-interrupt-controller-node-n.patch
 lib-string.c-add-multibyte-memset-functions.patch
 arm-ensure-the-signal-page-contains-defined-contents.patch
+ocfs2-fix-zero-out-valid-data.patch
+ocfs2-issue-zeroout-to-eof-blocks.patch
+can-usb_8dev-fix-memory-leak.patch
+can-ems_usb-fix-memory-leak.patch
+can-esd_usb2-fix-memory-leak.patch
+niu-fix-incorrect-error-return-missed-in-previous-revert.patch
 x86-asm-ensure-asm-proto.h-can-be-included-stand-alo.patch