]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 2 Aug 2013 09:21:22 +0000 (17:21 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 2 Aug 2013 09:21:22 +0000 (17:21 +0800)
added patches:
mm-memory-hotplug-fix-lowmem-count-overflow-when-offline-pages.patch
virtio-race-1of2-3.4.diff
virtio-race-2of2.diff

queue-3.4/mm-memory-hotplug-fix-lowmem-count-overflow-when-offline-pages.patch [new file with mode: 0644]
queue-3.4/series
queue-3.4/virtio-race-1of2-3.4.diff [new file with mode: 0644]
queue-3.4/virtio-race-2of2.diff [new file with mode: 0644]

diff --git a/queue-3.4/mm-memory-hotplug-fix-lowmem-count-overflow-when-offline-pages.patch b/queue-3.4/mm-memory-hotplug-fix-lowmem-count-overflow-when-offline-pages.patch
new file mode 100644 (file)
index 0000000..22611fe
--- /dev/null
@@ -0,0 +1,81 @@
+From cea27eb2a202959783f81254c48c250ddd80e129 Mon Sep 17 00:00:00 2001
+From: Wanpeng Li <liwanp@linux.vnet.ibm.com>
+Date: Wed, 3 Jul 2013 15:02:40 -0700
+Subject: mm/memory-hotplug: fix lowmem count overflow when offline pages
+
+From: Wanpeng Li <liwanp@linux.vnet.ibm.com>
+
+commit cea27eb2a202959783f81254c48c250ddd80e129 upstream.
+
+The logic for the memory-remove code fails to correctly account the
+Total High Memory when a memory block which contains High Memory is
+offlined as shown in the example below.  The following patch fixes it.
+
+Before logic memory remove:
+
+MemTotal:        7603740 kB
+MemFree:         6329612 kB
+Buffers:           94352 kB
+Cached:           872008 kB
+SwapCached:            0 kB
+Active:           626932 kB
+Inactive:         519216 kB
+Active(anon):     180776 kB
+Inactive(anon):   222944 kB
+Active(file):     446156 kB
+Inactive(file):   296272 kB
+Unevictable:           0 kB
+Mlocked:               0 kB
+HighTotal:       7294672 kB
+HighFree:        5704696 kB
+LowTotal:         309068 kB
+LowFree:          624916 kB
+
+After logic memory remove:
+
+MemTotal:        7079452 kB
+MemFree:         5805976 kB
+Buffers:           94372 kB
+Cached:           872000 kB
+SwapCached:            0 kB
+Active:           626936 kB
+Inactive:         519236 kB
+Active(anon):     180780 kB
+Inactive(anon):   222944 kB
+Active(file):     446156 kB
+Inactive(file):   296292 kB
+Unevictable:           0 kB
+Mlocked:               0 kB
+HighTotal:       7294672 kB
+HighFree:        5181024 kB
+LowTotal:       4294752076 kB
+LowFree:          624952 kB
+
+[mhocko@suse.cz: fix CONFIG_HIGHMEM=n build]
+Signed-off-by: Wanpeng Li <liwanp@linux.vnet.ibm.com>
+Reviewed-by: Michal Hocko <mhocko@suse.cz>
+Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
+Cc: David Rientjes <rientjes@google.com>
+Cc: <stable@vger.kernel.org>   [2.6.24+]
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Zhouping Liu <zliu@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ mm/page_alloc.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -5592,6 +5592,10 @@ __offline_isolated_pages(unsigned long s
+               zone->free_area[order].nr_free--;
+               __mod_zone_page_state(zone, NR_FREE_PAGES,
+                                     - (1UL << order));
++#ifdef CONFIG_HIGHMEM
++              if (PageHighMem(page))
++                      totalhigh_pages -= 1 << order;
++#endif
+               for (i = 0; i < (1 << order); i++)
+                       SetPageReserved((page+i));
+               pfn += (1 << order);
index 13d1e4ff9e856e8a68713fd9ca1ef89257d606bd..78f2230e6e2a0777cde707067f213b8a3c50296f 100644 (file)
@@ -34,3 +34,6 @@ xen-evtchn-avoid-a-deadlock-when-unbinding-an-event-channel.patch
 firewire-fix-libdc1394-flycap2-iso-event-regression.patch
 zfcp-status-read-buffers-on-first-adapter-open-with-link-down.patch
 s390-move-dummy-io_remap_pfn_range-to-asm-pgtable.h.patch
+virtio-race-1of2-3.4.diff
+virtio-race-2of2.diff
+mm-memory-hotplug-fix-lowmem-count-overflow-when-offline-pages.patch
diff --git a/queue-3.4/virtio-race-1of2-3.4.diff b/queue-3.4/virtio-race-1of2-3.4.diff
new file mode 100644 (file)
index 0000000..f67d546
--- /dev/null
@@ -0,0 +1,120 @@
+From: Michael S. Tsirkin <mst@redhat.com>
+Date: Tue, 9 Jul 2013 13:19:18 +0300
+Subject: virtio: support unlocked queue poll
+
+From: Michael S. Tsirkin <mst@redhat.com>
+
+commit cc229884d3f77ec3b1240e467e0236c3e0647c0c upstream.
+
+This adds a way to check ring empty state after enable_cb outside any
+locks. Will be used by virtio_net.
+
+Note: there's room for more optimization: caller is likely to have a
+memory barrier already, which means we might be able to get rid of a
+barrier here.  Deferring this optimization until we do some
+benchmarking.
+
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[wg: Backported to 3.2]
+Signed-off-by: Wolfram Gloger <wmglo@dent.med.uni-muenchen.de>
+[bwh: Backported to 3.4: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+---
+ drivers/virtio/virtio_ring.c |   54 ++++++++++++++++++++++++++++++++++---------
+ include/linux/virtio.h       |    4 +++
+ 2 files changed, 47 insertions(+), 11 deletions(-)
+
+--- a/drivers/virtio/virtio_ring.c
++++ b/drivers/virtio/virtio_ring.c
+@@ -498,16 +498,18 @@ EXPORT_SYMBOL_GPL(virtqueue_disable_cb);
+  * virtqueue_enable_cb - restart callbacks after disable_cb.
+  * @vq: the struct virtqueue we're talking about.
+  *
+- * This re-enables callbacks; it returns "false" if there are pending
+- * buffers in the queue, to detect a possible race between the driver
+- * checking for more work, and enabling callbacks.
++ * This re-enables callbacks; it returns current queue state
++ * in an opaque unsigned value. This value should be later tested by
++ * virtqueue_poll, to detect a possible race between the driver checking for
++ * more work, and enabling callbacks.
+  *
+  * Caller must ensure we don't call this with other virtqueue
+  * operations at the same time (except where noted).
+  */
+-bool virtqueue_enable_cb(struct virtqueue *_vq)
++unsigned virtqueue_enable_cb_prepare(struct virtqueue *_vq)
+ {
+       struct vring_virtqueue *vq = to_vvq(_vq);
++      u16 last_used_idx;
+       START_USE(vq);
+@@ -517,15 +519,45 @@ bool virtqueue_enable_cb(struct virtqueu
+        * either clear the flags bit or point the event index at the next
+        * entry. Always do both to keep code simple. */
+       vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT;
+-      vring_used_event(&vq->vring) = vq->last_used_idx;
++      vring_used_event(&vq->vring) = last_used_idx = vq->last_used_idx;
++      END_USE(vq);
++      return last_used_idx;
++}
++EXPORT_SYMBOL_GPL(virtqueue_enable_cb_prepare);
++
++/**
++ * virtqueue_poll - query pending used buffers
++ * @vq: the struct virtqueue we're talking about.
++ * @last_used_idx: virtqueue state (from call to virtqueue_enable_cb_prepare).
++ *
++ * Returns "true" if there are pending used buffers in the queue.
++ *
++ * This does not need to be serialized.
++ */
++bool virtqueue_poll(struct virtqueue *_vq, unsigned last_used_idx)
++{
++      struct vring_virtqueue *vq = to_vvq(_vq);
++
+       virtio_mb(vq);
+-      if (unlikely(more_used(vq))) {
+-              END_USE(vq);
+-              return false;
+-      }
++      return (u16)last_used_idx != vq->vring.used->idx;
++}
++EXPORT_SYMBOL_GPL(virtqueue_poll);
+-      END_USE(vq);
+-      return true;
++/**
++ * virtqueue_enable_cb - restart callbacks after disable_cb.
++ * @vq: the struct virtqueue we're talking about.
++ *
++ * This re-enables callbacks; it returns "false" if there are pending
++ * buffers in the queue, to detect a possible race between the driver
++ * checking for more work, and enabling callbacks.
++ *
++ * Caller must ensure we don't call this with other virtqueue
++ * operations at the same time (except where noted).
++ */
++bool virtqueue_enable_cb(struct virtqueue *_vq)
++{
++      unsigned last_used_idx = virtqueue_enable_cb_prepare(_vq);
++      return !virtqueue_poll(_vq, last_used_idx);
+ }
+ EXPORT_SYMBOL_GPL(virtqueue_enable_cb);
+--- a/include/linux/virtio.h
++++ b/include/linux/virtio.h
+@@ -44,6 +44,10 @@ void virtqueue_disable_cb(struct virtque
+ bool virtqueue_enable_cb(struct virtqueue *vq);
++unsigned virtqueue_enable_cb_prepare(struct virtqueue *vq);
++
++bool virtqueue_poll(struct virtqueue *vq, unsigned);
++
+ bool virtqueue_enable_cb_delayed(struct virtqueue *vq);
+ void *virtqueue_detach_unused_buf(struct virtqueue *vq);
diff --git a/queue-3.4/virtio-race-2of2.diff b/queue-3.4/virtio-race-2of2.diff
new file mode 100644 (file)
index 0000000..d48e580
--- /dev/null
@@ -0,0 +1,60 @@
+From: Michael S. Tsirkin <mst@redhat.com>
+Subject: virtio_net: fix race in RX VQ processing
+
+From: Michael S. Tsirkin <mst@redhat.com>
+
+commit cbdadbbf0c790f79350a8f36029208944c5487d0 upstream
+
+virtio net called virtqueue_enable_cq on RX path after napi_complete, so
+with NAPI_STATE_SCHED clear - outside the implicit napi lock.
+This violates the requirement to synchronize virtqueue_enable_cq wrt
+virtqueue_add_buf.  In particular, used event can move backwards,
+causing us to lose interrupts.
+In a debug build, this can trigger panic within START_USE.
+
+Jason Wang reports that he can trigger the races artificially,
+by adding udelay() in virtqueue_enable_cb() after virtio_mb().
+
+However, we must call napi_complete to clear NAPI_STATE_SCHED before
+polling the virtqueue for used buffers, otherwise napi_schedule_prep in
+a callback will fail, causing us to lose RX events.
+
+To fix, call virtqueue_enable_cb_prepare with NAPI_STATE_SCHED
+set (under napi lock), later call virtqueue_poll with
+NAPI_STATE_SCHED clear (outside the lock).
+
+Reported-by: Jason Wang <jasowang@redhat.com>
+Tested-by: Jason Wang <jasowang@redhat.com>
+Acked-by: Jason Wang <jasowang@redhat.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[wg: Backported to 3.2]
+Signed-off-by: Wolfram Gloger <wmglo@dent.med.uni-muenchen.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+---
+ drivers/net/virtio_net.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -518,7 +518,7 @@ static int virtnet_poll(struct napi_stru
+ {
+       struct virtnet_info *vi = container_of(napi, struct virtnet_info, napi);
+       void *buf;
+-      unsigned int len, received = 0;
++      unsigned int r, len, received = 0;
+ again:
+       while (received < budget &&
+@@ -535,8 +535,9 @@ again:
+       /* Out of packets? */
+       if (received < budget) {
++              r = virtqueue_enable_cb_prepare(vi->rvq);
+               napi_complete(napi);
+-              if (unlikely(!virtqueue_enable_cb(vi->rvq)) &&
++              if (unlikely(virtqueue_poll(vi->rvq, r)) &&
+                   napi_schedule_prep(napi)) {
+                       virtqueue_disable_cb(vi->rvq);
+                       __napi_schedule(napi);