]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
start up the 2.6.27 queue
authorGreg Kroah-Hartman <gregkh@suse.de>
Thu, 23 Oct 2008 20:51:33 +0000 (13:51 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 23 Oct 2008 20:51:33 +0000 (13:51 -0700)
22 files changed:
queue-2.6.27/amd_iommu-fix-nasty-bug-that-caused-illegal_device_table_entry-errors.patch [new file with mode: 0644]
queue-2.6.27/anon_vma_prepare-properly-lock-even-newly-allocated-entries.patch [new file with mode: 0644]
queue-2.6.27/cifs-fix-saving-of-resume-key-before-cifsfindnext.patch [new file with mode: 0644]
queue-2.6.27/dm-exception-store-fix-misordered-writes.patch [new file with mode: 0644]
queue-2.6.27/dm-exception-store-refactor-zero_area.patch [new file with mode: 0644]
queue-2.6.27/dm-kcopyd-avoid-queue-shuffle.patch [new file with mode: 0644]
queue-2.6.27/dm-snapshot-fix-primary_pe-race.patch [new file with mode: 0644]
queue-2.6.27/edac-cell-fix-incorrect-edac_mode.patch [new file with mode: 0644]
queue-2.6.27/ext-avoid-printk-floods-in-the-face-of-directory-corruption.patch [new file with mode: 0644]
queue-2.6.27/gpiolib-fix-oops-in-gpio_get_value_cansleep.patch [new file with mode: 0644]
queue-2.6.27/hvc_console-fix-free_irq-in-spinlocked-section.patch [new file with mode: 0644]
queue-2.6.27/netfilter-restore-lost-ifdef-guarding-defrag-exception.patch [new file with mode: 0644]
queue-2.6.27/netfilter-snmp-nat-leaks-memory-in-case-of-failure.patch [new file with mode: 0644]
queue-2.6.27/netfilter-xt_iprange-fix-range-inversion-match.patch [new file with mode: 0644]
queue-2.6.27/regression-inclusion-of-linux-module.h-triggers-a-compiler-warning.patch [new file with mode: 0644]
queue-2.6.27/sched-fix-the-wrong-mask_len.patch [new file with mode: 0644]
queue-2.6.27/series [new file with mode: 0644]
queue-2.6.27/usb-cdc-wdm-make-module-autoload-work.patch [new file with mode: 0644]
queue-2.6.27/usb-don-t-rebind-drivers-after-failed-resume-or-reset.patch [new file with mode: 0644]
queue-2.6.27/usb-fix-memory-leak-in-cdc-acm.patch [new file with mode: 0644]
queue-2.6.27/usb-speedtouch-add-pre_reset-and-post_reset-routines.patch [new file with mode: 0644]
queue-2.6.27/x86-acpi-fix-breakage-of-resume-on-64-bit-up-systems-with-smp-kernel.patch [new file with mode: 0644]

diff --git a/queue-2.6.27/amd_iommu-fix-nasty-bug-that-caused-illegal_device_table_entry-errors.patch b/queue-2.6.27/amd_iommu-fix-nasty-bug-that-caused-illegal_device_table_entry-errors.patch
new file mode 100644 (file)
index 0000000..8ad1fe6
--- /dev/null
@@ -0,0 +1,45 @@
+From jejb@kernel.org  Thu Oct 23 13:11:21 2008
+From: Andreas Herrmann <andreas.herrmann3@amd.com>
+Date: Thu, 23 Oct 2008 17:35:28 GMT
+Subject: amd_iommu: fix nasty bug that caused ILLEGAL_DEVICE_TABLE_ENTRY errors
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200810231735.m9NHZSI0008803@hera.kernel.org>
+
+From: Andreas Herrmann <andreas.herrmann3@amd.com>
+
+commit f609891f428e1c20e270e7c350daf8c93cc459d7 upstream
+
+We are on 64-bit so better use u64 instead of u32 to deal with
+addresses:
+
+static void __init iommu_set_device_table(struct amd_iommu *iommu)
+{
+        u64 entry;
+  ...
+        entry = virt_to_phys(amd_iommu_dev_table);
+  ...
+
+(I am wondering why gcc 4.2.x did not warn about the assignment
+between u32 and unsigned long.)
+
+Cc: iommu@lists.linux-foundation.org
+Signed-off-by: Andreas Herrmann <andreas.herrmann3@amd.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/kernel/amd_iommu_init.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/x86/kernel/amd_iommu_init.c
++++ b/arch/x86/kernel/amd_iommu_init.c
+@@ -210,7 +210,7 @@ static void __init iommu_set_exclusion_r
+ /* Programs the physical address of the device table into the IOMMU hardware */
+ static void __init iommu_set_device_table(struct amd_iommu *iommu)
+ {
+-      u32 entry;
++      u64 entry;
+       BUG_ON(iommu->mmio_base == NULL);
diff --git a/queue-2.6.27/anon_vma_prepare-properly-lock-even-newly-allocated-entries.patch b/queue-2.6.27/anon_vma_prepare-properly-lock-even-newly-allocated-entries.patch
new file mode 100644 (file)
index 0000000..6803884
--- /dev/null
@@ -0,0 +1,104 @@
+From d9d332e0874f46b91d8ac4604b68ee42b8a7a2c6 Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Sun, 19 Oct 2008 10:32:20 -0700
+Subject: anon_vma_prepare: properly lock even newly allocated entries
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit d9d332e0874f46b91d8ac4604b68ee42b8a7a2c6 upstream
+
+The anon_vma code is very subtle, and we end up doing optimistic lookups
+of anon_vmas under RCU in page_lock_anon_vma() with no locking.  Other
+CPU's can also see the newly allocated entry immediately after we've
+exposed it by setting "vma->anon_vma" to the new value.
+
+We protect against the anon_vma being destroyed by having the SLAB
+marked as SLAB_DESTROY_BY_RCU, so the RCU lookup can depend on the
+allocation not being destroyed - but it might still be free'd and
+re-allocated here to a new vma.
+
+As a result, we should not do the anon_vma list ops on a newly allocated
+vma without proper locking.
+
+Acked-by: Nick Piggin <npiggin@suse.de>
+Acked-by: Hugh Dickins <hugh@veritas.com>
+Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ mm/rmap.c |   42 ++++++++++++++++++++++++++++++++----------
+ 1 file changed, 32 insertions(+), 10 deletions(-)
+
+--- a/mm/rmap.c
++++ b/mm/rmap.c
+@@ -55,7 +55,33 @@
+ struct kmem_cache *anon_vma_cachep;
+-/* This must be called under the mmap_sem. */
++/**
++ * anon_vma_prepare - attach an anon_vma to a memory region
++ * @vma: the memory region in question
++ *
++ * This makes sure the memory mapping described by 'vma' has
++ * an 'anon_vma' attached to it, so that we can associate the
++ * anonymous pages mapped into it with that anon_vma.
++ *
++ * The common case will be that we already have one, but if
++ * if not we either need to find an adjacent mapping that we
++ * can re-use the anon_vma from (very common when the only
++ * reason for splitting a vma has been mprotect()), or we
++ * allocate a new one.
++ *
++ * Anon-vma allocations are very subtle, because we may have
++ * optimistically looked up an anon_vma in page_lock_anon_vma()
++ * and that may actually touch the spinlock even in the newly
++ * allocated vma (it depends on RCU to make sure that the
++ * anon_vma isn't actually destroyed).
++ *
++ * As a result, we need to do proper anon_vma locking even
++ * for the new allocation. At the same time, we do not want
++ * to do any locking for the common case of already having
++ * an anon_vma.
++ *
++ * This must be called with the mmap_sem held for reading.
++ */
+ int anon_vma_prepare(struct vm_area_struct *vma)
+ {
+       struct anon_vma *anon_vma = vma->anon_vma;
+@@ -63,20 +89,17 @@ int anon_vma_prepare(struct vm_area_stru
+       might_sleep();
+       if (unlikely(!anon_vma)) {
+               struct mm_struct *mm = vma->vm_mm;
+-              struct anon_vma *allocated, *locked;
++              struct anon_vma *allocated;
+               anon_vma = find_mergeable_anon_vma(vma);
+-              if (anon_vma) {
+-                      allocated = NULL;
+-                      locked = anon_vma;
+-                      spin_lock(&locked->lock);
+-              } else {
++              allocated = NULL;
++              if (!anon_vma) {
+                       anon_vma = anon_vma_alloc();
+                       if (unlikely(!anon_vma))
+                               return -ENOMEM;
+                       allocated = anon_vma;
+-                      locked = NULL;
+               }
++              spin_lock(&anon_vma->lock);
+               /* page_table_lock to protect against threads */
+               spin_lock(&mm->page_table_lock);
+@@ -87,8 +110,7 @@ int anon_vma_prepare(struct vm_area_stru
+               }
+               spin_unlock(&mm->page_table_lock);
+-              if (locked)
+-                      spin_unlock(&locked->lock);
++              spin_unlock(&anon_vma->lock);
+               if (unlikely(allocated))
+                       anon_vma_free(allocated);
+       }
diff --git a/queue-2.6.27/cifs-fix-saving-of-resume-key-before-cifsfindnext.patch b/queue-2.6.27/cifs-fix-saving-of-resume-key-before-cifsfindnext.patch
new file mode 100644 (file)
index 0000000..0827061
--- /dev/null
@@ -0,0 +1,46 @@
+From jejb@kernel.org  Thu Oct 23 13:12:20 2008
+From: Jeff Layton <sfrench@us.ibm.com>
+Date: Thu, 23 Oct 2008 18:05:02 GMT
+Subject: CIFS: fix saving of resume key before CIFSFindNext
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200810231805.m9NI526B029178@hera.kernel.org>
+
+From: Jeff Layton <sfrench@us.ibm.com>
+
+commit a364bc0b37f14ffd66c1f982af42990a9d77fa43 upstream
+
+We recently fixed the cifs readdir code so that it saves the resume key
+before calling CIFSFindNext. Unfortunately, this assumes that we have
+just done a CIFSFindFirst (or FindNext) and have resume info to save.
+This isn't necessarily the case. Fix the code to save resume info if we
+had to reinitiate the search, and after a FindNext.
+
+This fixes connectathon basic test6 against NetApp filers.
+
+Signed-off-by: Jeff Layton <jlayton@redhat.com>
+Signed-off-by: Steve French <sfrench@us.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/cifs/readdir.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/cifs/readdir.c
++++ b/fs/cifs/readdir.c
+@@ -762,14 +762,15 @@ static int find_cifs_entry(const int xid
+                                rc));
+                       return rc;
+               }
++              cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile);
+       }
+       while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
+             (rc == 0) && !cifsFile->srch_inf.endOfSearch) {
+               cFYI(1, ("calling findnext2"));
+-              cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile);
+               rc = CIFSFindNext(xid, pTcon, cifsFile->netfid,
+                                 &cifsFile->srch_inf);
++              cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile);
+               if (rc)
+                       return -ENOENT;
+       }
diff --git a/queue-2.6.27/dm-exception-store-fix-misordered-writes.patch b/queue-2.6.27/dm-exception-store-fix-misordered-writes.patch
new file mode 100644 (file)
index 0000000..1665482
--- /dev/null
@@ -0,0 +1,51 @@
+From jejb@kernel.org  Thu Oct 23 13:10:46 2008
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Thu, 23 Oct 2008 17:35:17 GMT
+Subject: dm exception store: fix misordered writes
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200810231735.m9NHZHnu008554@hera.kernel.org>
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 7acedc5b98a2fcff64f00c21110aae7d3ac2f7df upstream
+
+We must zero the next chunk on disk *before* writing out the current chunk, not
+after.  Otherwise if the machine crashes at the wrong time, the "end of metadata"
+marker may be missing.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Alasdair G Kergon <agk@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/md/dm-exception-store.c |   11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/drivers/md/dm-exception-store.c
++++ b/drivers/md/dm-exception-store.c
+@@ -603,17 +603,22 @@ static void persistent_commit(struct exc
+               return;
+       /*
++       * If we completely filled the current area, then wipe the next one.
++       */
++      if ((ps->current_committed == ps->exceptions_per_area) &&
++           zero_disk_area(ps, ps->current_area + 1))
++              ps->valid = 0;
++
++      /*
+        * Commit exceptions to disk.
+        */
+-      if (area_io(ps, WRITE))
++      if (ps->valid && area_io(ps, WRITE))
+               ps->valid = 0;
+       /*
+        * Advance to the next area if this one is full.
+        */
+       if (ps->current_committed == ps->exceptions_per_area) {
+-              if (zero_disk_area(ps, ps->current_area + 1))
+-                      ps->valid = 0;
+               ps->current_committed = 0;
+               ps->current_area++;
+               zero_memory_area(ps);
diff --git a/queue-2.6.27/dm-exception-store-refactor-zero_area.patch b/queue-2.6.27/dm-exception-store-refactor-zero_area.patch
new file mode 100644 (file)
index 0000000..3763c8f
--- /dev/null
@@ -0,0 +1,220 @@
+From jejb@kernel.org  Thu Oct 23 13:05:28 2008
+From: Alasdair G Kergon <agk@redhat.com>
+Date: Thu, 23 Oct 2008 17:35:19 GMT
+Subject: dm exception store: refactor zero_area
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200810231735.m9NHZJcS008600@hera.kernel.org>
+
+From: Alasdair G Kergon <agk@redhat.com>
+
+commit 7c9e6c17325fab380fbe9c9787680ff7d4a51abd upstream
+
+Use a separate buffer for writing zeroes to the on-disk snapshot
+exception store, make the updating of ps->current_area explicit and
+refactor the code in preparation for the fix in the next patch.
+
+No functional change.
+
+Signed-off-by: Alasdair G Kergon <agk@redhat.com>
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/md/dm-exception-store.c |  103 ++++++++++++++++++++++++++--------------
+ 1 file changed, 69 insertions(+), 34 deletions(-)
+
+--- a/drivers/md/dm-exception-store.c
++++ b/drivers/md/dm-exception-store.c
+@@ -105,6 +105,11 @@ struct pstore {
+       void *area;
+       /*
++       * An area of zeros used to clear the next area.
++       */
++      void *zero_area;
++
++      /*
+        * Used to keep track of which metadata area the data in
+        * 'chunk' refers to.
+        */
+@@ -149,6 +154,13 @@ static int alloc_area(struct pstore *ps)
+       if (!ps->area)
+               return r;
++      ps->zero_area = vmalloc(len);
++      if (!ps->zero_area) {
++              vfree(ps->area);
++              return r;
++      }
++      memset(ps->zero_area, 0, len);
++
+       return 0;
+ }
+@@ -156,6 +168,8 @@ static void free_area(struct pstore *ps)
+ {
+       vfree(ps->area);
+       ps->area = NULL;
++      vfree(ps->zero_area);
++      ps->zero_area = NULL;
+ }
+ struct mdata_req {
+@@ -212,13 +226,13 @@ static int chunk_io(struct pstore *ps, u
+  * Read or write a metadata area.  Remembering to skip the first
+  * chunk which holds the header.
+  */
+-static int area_io(struct pstore *ps, uint32_t area, int rw)
++static int area_io(struct pstore *ps, int rw)
+ {
+       int r;
+       uint32_t chunk;
+       /* convert a metadata area index to a chunk index */
+-      chunk = 1 + ((ps->exceptions_per_area + 1) * area);
++      chunk = area_location(ps, ps->current_area);
+       r = chunk_io(ps, chunk, rw, 0);
+       if (r)
+@@ -228,10 +242,27 @@ static int area_io(struct pstore *ps, ui
+       return 0;
+ }
+-static int zero_area(struct pstore *ps, uint32_t area)
++static void zero_memory_area(struct pstore *ps)
+ {
+       memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
+-      return area_io(ps, area, WRITE);
++}
++
++static int zero_disk_area(struct pstore *ps, chunk_t area)
++{
++      struct dm_io_region where = {
++              .bdev = ps->snap->cow->bdev,
++              .sector = ps->snap->chunk_size * area_location(ps, area),
++              .count = ps->snap->chunk_size,
++      };
++      struct dm_io_request io_req = {
++              .bi_rw = WRITE,
++              .mem.type = DM_IO_VMA,
++              .mem.ptr.vma = ps->zero_area,
++              .client = ps->io_client,
++              .notify.fn = NULL,
++      };
++
++      return dm_io(&io_req, 1, &where, NULL);
+ }
+ static int read_header(struct pstore *ps, int *new_snapshot)
+@@ -404,15 +435,14 @@ static int insert_exceptions(struct psto
+ static int read_exceptions(struct pstore *ps)
+ {
+-      uint32_t area;
+       int r, full = 1;
+       /*
+        * Keeping reading chunks and inserting exceptions until
+        * we find a partially full area.
+        */
+-      for (area = 0; full; area++) {
+-              r = area_io(ps, area, READ);
++      for (ps->current_area = 0; full; ps->current_area++) {
++              r = area_io(ps, READ);
+               if (r)
+                       return r;
+@@ -421,6 +451,8 @@ static int read_exceptions(struct pstore
+                       return r;
+       }
++      ps->current_area--;
++
+       return 0;
+ }
+@@ -479,12 +511,13 @@ static int persistent_read_metadata(stru
+                       return r;
+               }
+-              r = zero_area(ps, 0);
++              ps->current_area = 0;
++              zero_memory_area(ps);
++              r = zero_disk_area(ps, 0);
+               if (r) {
+-                      DMWARN("zero_area(0) failed");
++                      DMWARN("zero_disk_area(0) failed");
+                       return r;
+               }
+-
+       } else {
+               /*
+                * Sanity checks.
+@@ -542,7 +575,6 @@ static void persistent_commit(struct exc
+                             void (*callback) (void *, int success),
+                             void *callback_context)
+ {
+-      int r;
+       unsigned int i;
+       struct pstore *ps = get_info(store);
+       struct disk_exception de;
+@@ -563,33 +595,36 @@ static void persistent_commit(struct exc
+       cb->context = callback_context;
+       /*
+-       * If there are no more exceptions in flight, or we have
+-       * filled this metadata area we commit the exceptions to
+-       * disk.
+-       */
+-      if (atomic_dec_and_test(&ps->pending_count) ||
+-          (ps->current_committed == ps->exceptions_per_area)) {
+-              r = area_io(ps, ps->current_area, WRITE);
+-              if (r)
+-                      ps->valid = 0;
++       * If there are exceptions in flight and we have not yet
++       * filled this metadata area there's nothing more to do.
++       */
++      if (!atomic_dec_and_test(&ps->pending_count) &&
++          (ps->current_committed != ps->exceptions_per_area))
++              return;
+-              /*
+-               * Have we completely filled the current area ?
+-               */
+-              if (ps->current_committed == ps->exceptions_per_area) {
+-                      ps->current_committed = 0;
+-                      r = zero_area(ps, ps->current_area + 1);
+-                      if (r)
+-                              ps->valid = 0;
+-              }
++      /*
++       * Commit exceptions to disk.
++       */
++      if (area_io(ps, WRITE))
++              ps->valid = 0;
+-              for (i = 0; i < ps->callback_count; i++) {
+-                      cb = ps->callbacks + i;
+-                      cb->callback(cb->context, r == 0 ? 1 : 0);
+-              }
++      /*
++       * Advance to the next area if this one is full.
++       */
++      if (ps->current_committed == ps->exceptions_per_area) {
++              if (zero_disk_area(ps, ps->current_area + 1))
++                      ps->valid = 0;
++              ps->current_committed = 0;
++              ps->current_area++;
++              zero_memory_area(ps);
++      }
+-              ps->callback_count = 0;
++      for (i = 0; i < ps->callback_count; i++) {
++              cb = ps->callbacks + i;
++              cb->callback(cb->context, ps->valid);
+       }
++
++      ps->callback_count = 0;
+ }
+ static void persistent_drop(struct exception_store *store)
diff --git a/queue-2.6.27/dm-kcopyd-avoid-queue-shuffle.patch b/queue-2.6.27/dm-kcopyd-avoid-queue-shuffle.patch
new file mode 100644 (file)
index 0000000..6c3b97d
--- /dev/null
@@ -0,0 +1,102 @@
+From jejb@kernel.org  Thu Oct 23 13:06:15 2008
+From: Kazuo Ito <ito.kazuo@oss.ntt.co.jp>
+Date: Thu, 23 Oct 2008 17:35:24 GMT
+Subject: dm kcopyd: avoid queue shuffle
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200810231735.m9NHZOgW008656@hera.kernel.org>
+
+From: Kazuo Ito <ito.kazuo@oss.ntt.co.jp>
+
+commit b673c3a8192e28f13e2050a4b82c1986be92cc15 upstream
+
+Write throughput to LVM snapshot origin volume is an order
+of magnitude slower than those to LV without snapshots or
+snapshot target volumes, especially in the case of sequential
+writes with O_SYNC on.
+
+The following patch originally written by Kevin Jamieson and
+Jan Blunck and slightly modified for the current RCs by myself
+tries to improve the performance by modifying the behaviour
+of kcopyd, so that it pushes back an I/O job to the head of
+the job queue instead of the tail as process_jobs() currently
+does when it has to wait for free pages. This way, write
+requests aren't shuffled to cause extra seeks.
+
+I tested the patch against 2.6.27-rc5 and got the following results.
+The test is a dd command writing to snapshot origin followed by fsync
+to the file just created/updated.  A couple of filesystem benchmarks
+gave me similar results in case of sequential writes, while random
+writes didn't suffer much.
+
+dd if=/dev/zero of=<somewhere on snapshot origin> bs=4096 count=...
+   [conv=notrunc when updating]
+
+1) linux 2.6.27-rc5 without the patch, write to snapshot origin,
+average throughput (MB/s)
+                     10M     100M    1000M
+create,dd         511.46   610.72    11.81
+create,dd+fsync     7.10     6.77     8.13
+update,dd         431.63   917.41    12.75
+update,dd+fsync     7.79     7.43     8.12
+
+compared with write throughput to LV without any snapshots,
+all dd+fsync and 1000 MiB writes perform very poorly.
+
+                     10M     100M    1000M
+create,dd         555.03   608.98   123.29
+create,dd+fsync   114.27    72.78    76.65
+update,dd         152.34  1267.27   124.04
+update,dd+fsync   130.56    77.81    77.84
+
+2) linux 2.6.27-rc5 with the patch, write to snapshot origin,
+average throughput (MB/s)
+
+                     10M     100M    1000M
+create,dd         537.06   589.44    46.21
+create,dd+fsync    31.63    29.19    29.23
+update,dd         487.59   897.65    37.76
+update,dd+fsync    34.12    30.07    26.85
+
+Although still not on par with plain LV performance -
+cannot be avoided because it's copy on write anyway -
+this simple patch successfully improves throughtput
+of dd+fsync while not affecting the rest.
+
+Signed-off-by: Jan Blunck <jblunck@suse.de>
+Signed-off-by: Kazuo Ito <ito.kazuo@oss.ntt.co.jp>
+Signed-off-by: Alasdair G Kergon <agk@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/md/dm-kcopyd.c |   13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+--- a/drivers/md/dm-kcopyd.c
++++ b/drivers/md/dm-kcopyd.c
+@@ -268,6 +268,17 @@ static void push(struct list_head *jobs,
+       spin_unlock_irqrestore(&kc->job_lock, flags);
+ }
++
++static void push_head(struct list_head *jobs, struct kcopyd_job *job)
++{
++      unsigned long flags;
++      struct dm_kcopyd_client *kc = job->kc;
++
++      spin_lock_irqsave(&kc->job_lock, flags);
++      list_add(&job->list, jobs);
++      spin_unlock_irqrestore(&kc->job_lock, flags);
++}
++
+ /*
+  * These three functions process 1 item from the corresponding
+  * job list.
+@@ -398,7 +409,7 @@ static int process_jobs(struct list_head
+                        * We couldn't service this job ATM, so
+                        * push this job back onto the list.
+                        */
+-                      push(jobs, job);
++                      push_head(jobs, job);
+                       break;
+               }
diff --git a/queue-2.6.27/dm-snapshot-fix-primary_pe-race.patch b/queue-2.6.27/dm-snapshot-fix-primary_pe-race.patch
new file mode 100644 (file)
index 0000000..37f160e
--- /dev/null
@@ -0,0 +1,109 @@
+From jejb@kernel.org  Thu Oct 23 13:07:01 2008
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Thu, 23 Oct 2008 17:35:22 GMT
+Subject: dm snapshot: fix primary_pe race
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200810231735.m9NHZMDk008629@hera.kernel.org>
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit 7c5f78b9d7f21937e46c26db82976df4b459c95c upstream
+
+Fix a race condition with primary_pe ref_count handling.
+
+put_pending_exception runs under dm_snapshot->lock, it does atomic_dec_and_test
+on primary_pe->ref_count, and later does atomic_read primary_pe->ref_count.
+
+__origin_write does atomic_dec_and_test on primary_pe->ref_count without holding
+dm_snapshot->lock.
+
+This opens the following race condition:
+Assume two CPUs, CPU1 is executing put_pending_exception (and holding
+dm_snapshot->lock). CPU2 is executing __origin_write in parallel.
+primary_pe->ref_count == 2.
+
+CPU1:
+if (primary_pe && atomic_dec_and_test(&primary_pe->ref_count))
+       origin_bios = bio_list_get(&primary_pe->origin_bios);
+.. decrements primary_pe->ref_count to 1. Doesn't load origin_bios
+
+CPU2:
+if (first && atomic_dec_and_test(&primary_pe->ref_count)) {
+       flush_bios(bio_list_get(&primary_pe->origin_bios));
+       free_pending_exception(primary_pe);
+       /* If we got here, pe_queue is necessarily empty. */
+       return r;
+}
+.. decrements primary_pe->ref_count to 0, submits pending bios, frees
+primary_pe.
+
+CPU1:
+if (!primary_pe || primary_pe != pe)
+       free_pending_exception(pe);
+.. this has no effect.
+if (primary_pe && !atomic_read(&primary_pe->ref_count))
+       free_pending_exception(primary_pe);
+.. sees ref_count == 0 (written by CPU 2), does double free !!
+
+This bug can happen only if someone is simultaneously writing to both the
+origin and the snapshot.
+
+If someone is writing only to the origin, __origin_write will submit kcopyd
+request after it decrements primary_pe->ref_count (so it can't happen that the
+finished copy races with primary_pe->ref_count decrementation).
+
+If someone is writing only to the snapshot, __origin_write isn't invoked at all
+and the race can't happen.
+
+The race happens when someone writes to the snapshot --- this creates
+pending_exception with primary_pe == NULL and starts copying. Then, someone
+writes to the same chunk in the snapshot, and __origin_write races with
+termination of already submitted request in pending_complete (that calls
+put_pending_exception).
+
+This race may be reason for bugs:
+  http://bugzilla.kernel.org/show_bug.cgi?id=11636
+  https://bugzilla.redhat.com/show_bug.cgi?id=465825
+
+The patch fixes the code to make sure that:
+1. If atomic_dec_and_test(&primary_pe->ref_count) returns false, the process
+must no longer dereference primary_pe (because someone else may free it under
+us).
+2. If atomic_dec_and_test(&primary_pe->ref_count) returns true, the process
+is responsible for freeing primary_pe.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Alasdair G Kergon <agk@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/md/dm-snap.c |   10 +++-------
+ 1 file changed, 3 insertions(+), 7 deletions(-)
+
+--- a/drivers/md/dm-snap.c
++++ b/drivers/md/dm-snap.c
+@@ -824,8 +824,10 @@ static struct bio *put_pending_exception
+        * the bios for the original write to the origin.
+        */
+       if (primary_pe &&
+-          atomic_dec_and_test(&primary_pe->ref_count))
++          atomic_dec_and_test(&primary_pe->ref_count)) {
+               origin_bios = bio_list_get(&primary_pe->origin_bios);
++              free_pending_exception(primary_pe);
++      }
+       /*
+        * Free the pe if it's not linked to an origin write or if
+@@ -834,12 +836,6 @@ static struct bio *put_pending_exception
+       if (!primary_pe || primary_pe != pe)
+               free_pending_exception(pe);
+-      /*
+-       * Free the primary pe if nothing references it.
+-       */
+-      if (primary_pe && !atomic_read(&primary_pe->ref_count))
+-              free_pending_exception(primary_pe);
+-
+       return origin_bios;
+ }
diff --git a/queue-2.6.27/edac-cell-fix-incorrect-edac_mode.patch b/queue-2.6.27/edac-cell-fix-incorrect-edac_mode.patch
new file mode 100644 (file)
index 0000000..2437030
--- /dev/null
@@ -0,0 +1,36 @@
+From jejb@kernel.org  Thu Oct 23 12:58:23 2008
+From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Date: Mon, 20 Oct 2008 16:50:07 GMT
+Subject: edac cell: fix incorrect edac_mode
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200810201650.m9KGo7ld012751@hera.kernel.org>
+
+From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+
+commit 3b274f44d2ca05f719fe39947b6a5293a2dbd8fd upstream
+
+The cell_edac driver is setting the edac_mode field of the csrow's to an
+incorrect value, causing the sysfs show routine for that field to go out
+of an array bound and Oopsing the kernel when used.
+
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Signed-off-by: Doug Thompson <dougthompson@xmission.com>
+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@suse.de>
+
+---
+ drivers/edac/cell_edac.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/edac/cell_edac.c
++++ b/drivers/edac/cell_edac.c
+@@ -142,7 +142,7 @@ static void __devinit cell_edac_init_csr
+               csrow->nr_pages = (r.end - r.start + 1) >> PAGE_SHIFT;
+               csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
+               csrow->mtype = MEM_XDR;
+-              csrow->edac_mode = EDAC_FLAG_EC | EDAC_FLAG_SECDED;
++              csrow->edac_mode = EDAC_SECDED;
+               dev_dbg(mci->dev,
+                       "Initialized on node %d, chanmask=0x%x,"
+                       " first_page=0x%lx, nr_pages=0x%x\n",
diff --git a/queue-2.6.27/ext-avoid-printk-floods-in-the-face-of-directory-corruption.patch b/queue-2.6.27/ext-avoid-printk-floods-in-the-face-of-directory-corruption.patch
new file mode 100644 (file)
index 0000000..f9cf4b5
--- /dev/null
@@ -0,0 +1,247 @@
+From sandeen@redhat.com  Thu Oct 23 13:13:44 2008
+From: Eric Sandeen <sandeen@redhat.com>
+Date: Wed, 22 Oct 2008 10:11:52 -0500
+Subject: ext[234]: Avoid printk floods in the face of directory corruption (CVE-2008-3528)
+To: stable@kernel.org
+Cc: ext4 development <linux-ext4@vger.kernel.org>
+Message-ID: <48FF42B8.3030606@redhat.com>
+
+From: Eric Sandeen <sandeen@redhat.com>
+
+This is a trivial backport of the following upstream commits:
+
+- bd39597cbd42a784105a04010100e27267481c67 (ext2)
+- cdbf6dba28e8e6268c8420857696309470009fd9 (ext3)
+- 9d9f177572d9e4eba0f2e18523b44f90dd51fe74 (ext4)
+
+This addresses CVE-2008-3528
+
+ext[234]: Avoid printk floods in the face of directory corruption
+
+Note: some people thinks this represents a security bug, since it
+might make the system go away while it is printing a large number of
+console messages, especially if a serial console is involved.  Hence,
+it has been assigned CVE-2008-3528, but it requires that the attacker
+either has physical access to your machine to insert a USB disk with a
+corrupted filesystem image (at which point why not just hit the power
+button), or is otherwise able to convince the system administrator to
+mount an arbitrary filesystem image (at which point why not just
+include a setuid shell or world-writable hard disk device file or some
+such).  Me, I think they're just being silly. --tytso
+
+Signed-off-by: Eric Sandeen <sandeen@redhat.com>
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+Cc: linux-ext4@vger.kernel.org
+Cc: Eugene Teo <eugeneteo@kernel.sg>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/ext2/dir.c |   60 +++++++++++++++++++++++++++++++++-------------------------
+ fs/ext3/dir.c |   10 ++++++---
+ fs/ext4/dir.c |   11 +++++++---
+ 3 files changed, 50 insertions(+), 31 deletions(-)
+
+--- a/fs/ext2/dir.c
++++ b/fs/ext2/dir.c
+@@ -103,7 +103,7 @@ static int ext2_commit_chunk(struct page
+       return err;
+ }
+-static void ext2_check_page(struct page *page)
++static void ext2_check_page(struct page *page, int quiet)
+ {
+       struct inode *dir = page->mapping->host;
+       struct super_block *sb = dir->i_sb;
+@@ -146,10 +146,10 @@ out:
+       /* Too bad, we had an error */
+ Ebadsize:
+-      ext2_error(sb, "ext2_check_page",
+-              "size of directory #%lu is not a multiple of chunk size",
+-              dir->i_ino
+-      );
++      if (!quiet)
++              ext2_error(sb, __func__,
++                      "size of directory #%lu is not a multiple "
++                      "of chunk size", dir->i_ino);
+       goto fail;
+ Eshort:
+       error = "rec_len is smaller than minimal";
+@@ -166,32 +166,36 @@ Espan:
+ Einumber:
+       error = "inode out of bounds";
+ bad_entry:
+-      ext2_error (sb, "ext2_check_page", "bad entry in directory #%lu: %s - "
+-              "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
+-              dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs,
+-              (unsigned long) le32_to_cpu(p->inode),
+-              rec_len, p->name_len);
++      if (!quiet)
++              ext2_error(sb, __func__, "bad entry in directory #%lu: : %s - "
++                      "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
++                      dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs,
++                      (unsigned long) le32_to_cpu(p->inode),
++                      rec_len, p->name_len);
+       goto fail;
+ Eend:
+-      p = (ext2_dirent *)(kaddr + offs);
+-      ext2_error (sb, "ext2_check_page",
+-              "entry in directory #%lu spans the page boundary"
+-              "offset=%lu, inode=%lu",
+-              dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs,
+-              (unsigned long) le32_to_cpu(p->inode));
++      if (!quiet) {
++              p = (ext2_dirent *)(kaddr + offs);
++              ext2_error(sb, "ext2_check_page",
++                      "entry in directory #%lu spans the page boundary"
++                      "offset=%lu, inode=%lu",
++                      dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs,
++                      (unsigned long) le32_to_cpu(p->inode));
++      }
+ fail:
+       SetPageChecked(page);
+       SetPageError(page);
+ }
+-static struct page * ext2_get_page(struct inode *dir, unsigned long n)
++static struct page * ext2_get_page(struct inode *dir, unsigned long n,
++                                 int quiet)
+ {
+       struct address_space *mapping = dir->i_mapping;
+       struct page *page = read_mapping_page(mapping, n, NULL);
+       if (!IS_ERR(page)) {
+               kmap(page);
+               if (!PageChecked(page))
+-                      ext2_check_page(page);
++                      ext2_check_page(page, quiet);
+               if (PageError(page))
+                       goto fail;
+       }
+@@ -292,7 +296,7 @@ ext2_readdir (struct file * filp, void *
+       for ( ; n < npages; n++, offset = 0) {
+               char *kaddr, *limit;
+               ext2_dirent *de;
+-              struct page *page = ext2_get_page(inode, n);
++              struct page *page = ext2_get_page(inode, n, 0);
+               if (IS_ERR(page)) {
+                       ext2_error(sb, __func__,
+@@ -361,6 +365,7 @@ struct ext2_dir_entry_2 * ext2_find_entr
+       struct page *page = NULL;
+       struct ext2_inode_info *ei = EXT2_I(dir);
+       ext2_dirent * de;
++      int dir_has_error = 0;
+       if (npages == 0)
+               goto out;
+@@ -374,7 +379,7 @@ struct ext2_dir_entry_2 * ext2_find_entr
+       n = start;
+       do {
+               char *kaddr;
+-              page = ext2_get_page(dir, n);
++              page = ext2_get_page(dir, n, dir_has_error);
+               if (!IS_ERR(page)) {
+                       kaddr = page_address(page);
+                       de = (ext2_dirent *) kaddr;
+@@ -391,7 +396,9 @@ struct ext2_dir_entry_2 * ext2_find_entr
+                               de = ext2_next_entry(de);
+                       }
+                       ext2_put_page(page);
+-              }
++              } else
++                      dir_has_error = 1;
++
+               if (++n >= npages)
+                       n = 0;
+               /* next page is past the blocks we've got */
+@@ -414,7 +421,7 @@ found:
+ struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p)
+ {
+-      struct page *page = ext2_get_page(dir, 0);
++      struct page *page = ext2_get_page(dir, 0, 0);
+       ext2_dirent *de = NULL;
+       if (!IS_ERR(page)) {
+@@ -487,7 +494,7 @@ int ext2_add_link (struct dentry *dentry
+       for (n = 0; n <= npages; n++) {
+               char *dir_end;
+-              page = ext2_get_page(dir, n);
++              page = ext2_get_page(dir, n, 0);
+               err = PTR_ERR(page);
+               if (IS_ERR(page))
+                       goto out;
+@@ -655,14 +662,17 @@ int ext2_empty_dir (struct inode * inode
+ {
+       struct page *page = NULL;
+       unsigned long i, npages = dir_pages(inode);
++      int dir_has_error = 0;
+       for (i = 0; i < npages; i++) {
+               char *kaddr;
+               ext2_dirent * de;
+-              page = ext2_get_page(inode, i);
++              page = ext2_get_page(inode, i, dir_has_error);
+-              if (IS_ERR(page))
++              if (IS_ERR(page)) {
++                      dir_has_error = 1;
+                       continue;
++              }
+               kaddr = page_address(page);
+               de = (ext2_dirent *)kaddr;
+--- a/fs/ext3/dir.c
++++ b/fs/ext3/dir.c
+@@ -102,6 +102,7 @@ static int ext3_readdir(struct file * fi
+       int err;
+       struct inode *inode = filp->f_path.dentry->d_inode;
+       int ret = 0;
++      int dir_has_error = 0;
+       sb = inode->i_sb;
+@@ -148,9 +149,12 @@ static int ext3_readdir(struct file * fi
+                * of recovering data when there's a bad sector
+                */
+               if (!bh) {
+-                      ext3_error (sb, "ext3_readdir",
+-                              "directory #%lu contains a hole at offset %lu",
+-                              inode->i_ino, (unsigned long)filp->f_pos);
++                      if (!dir_has_error) {
++                              ext3_error(sb, __func__, "directory #%lu "
++                                      "contains a hole at offset %lld",
++                                      inode->i_ino, filp->f_pos);
++                              dir_has_error = 1;
++                      }
+                       /* corrupt size?  Maybe no more blocks to read */
+                       if (filp->f_pos > inode->i_blocks << 9)
+                               break;
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -102,6 +102,7 @@ static int ext4_readdir(struct file * fi
+       int err;
+       struct inode *inode = filp->f_path.dentry->d_inode;
+       int ret = 0;
++      int dir_has_error = 0;
+       sb = inode->i_sb;
+@@ -148,9 +149,13 @@ static int ext4_readdir(struct file * fi
+                * of recovering data when there's a bad sector
+                */
+               if (!bh) {
+-                      ext4_error (sb, "ext4_readdir",
+-                              "directory #%lu contains a hole at offset %lu",
+-                              inode->i_ino, (unsigned long)filp->f_pos);
++                      if (!dir_has_error) {
++                              ext4_error(sb, __func__, "directory #%lu "
++                                         "contains a hole at offset %Lu",
++                                         inode->i_ino,
++                                         (unsigned long long) filp->f_pos);
++                              dir_has_error = 1;
++                      }
+                       /* corrupt size?  Maybe no more blocks to read */
+                       if (filp->f_pos > inode->i_blocks << 9)
+                               break;
diff --git a/queue-2.6.27/gpiolib-fix-oops-in-gpio_get_value_cansleep.patch b/queue-2.6.27/gpiolib-fix-oops-in-gpio_get_value_cansleep.patch
new file mode 100644 (file)
index 0000000..05d34df
--- /dev/null
@@ -0,0 +1,58 @@
+From jejb@kernel.org  Thu Oct 23 12:54:37 2008
+From: David Brownell <dbrownell@users.sourceforge.net>
+Date: Mon, 20 Oct 2008 16:50:10 GMT
+Subject: gpiolib: fix oops in gpio_get_value_cansleep()
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200810201650.m9KGoAvI012814@hera.kernel.org>
+
+From: David Brownell <dbrownell@users.sourceforge.net>
+
+commit 978ccaa8ea5d8c7bf6b676209f2fc126eae6355b upstream
+
+We can get the following oops from gpio_get_value_cansleep() when a GPIO
+controller doesn't provide a get() callback:
+
+ Unable to handle kernel paging request for instruction fetch
+ Faulting instruction address: 0x00000000
+ Oops: Kernel access of bad area, sig: 11 [#1]
+ [...]
+ NIP [00000000] 0x0
+ LR [c0182fb0] gpio_get_value_cansleep+0x40/0x50
+ Call Trace:
+ [c7b79e80] [c0183f28] gpio_value_show+0x5c/0x94
+ [c7b79ea0] [c01a584c] dev_attr_show+0x30/0x7c
+ [c7b79eb0] [c00d6b48] fill_read_buffer+0x68/0xe0
+ [c7b79ed0] [c00d6c54] sysfs_read_file+0x94/0xbc
+ [c7b79ef0] [c008f24c] vfs_read+0xb4/0x16c
+ [c7b79f10] [c008f580] sys_read+0x4c/0x90
+ [c7b79f40] [c0013a14] ret_from_syscall+0x0/0x38
+
+It's OK to request the value of *any* GPIO; most GPIOs are bidirectional,
+so configuring them as outputs just enables an output driver and doesn't
+disable the input logic.
+
+So the problem is that gpio_get_value_cansleep() isn't making the same
+sanity check that gpio_get_value() does: making sure this GPIO isn't one
+of the atypical "no input logic" cases.
+
+Reported-by: Anton Vorontsov <avorontsov@ru.mvista.com>
+Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
+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@suse.de>
+
+---
+ drivers/gpio/gpiolib.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -1020,7 +1020,7 @@ int gpio_get_value_cansleep(unsigned gpi
+       might_sleep_if(extra_checks);
+       chip = gpio_to_chip(gpio);
+-      return chip->get(chip, gpio - chip->base);
++      return chip->get ? chip->get(chip, gpio - chip->base) : 0;
+ }
+ EXPORT_SYMBOL_GPL(gpio_get_value_cansleep);
diff --git a/queue-2.6.27/hvc_console-fix-free_irq-in-spinlocked-section.patch b/queue-2.6.27/hvc_console-fix-free_irq-in-spinlocked-section.patch
new file mode 100644 (file)
index 0000000..916d60b
--- /dev/null
@@ -0,0 +1,62 @@
+From benh@kernel.crashing.org  Thu Oct 23 13:18:50 2008
+From: Christian Borntraeger <borntraeger@de.ibm.com>
+Date: Thu, 23 Oct 2008 12:18:31 +1100
+Subject: hvc_console: Fix free_irq in spinlocked section
+To: stable <stable@kernel.org>
+Message-ID: <1224724711.7654.357.camel@pasglop>
+
+From: Christian Borntraeger <borntraeger@de.ibm.com>
+
+commit eef2622a9fcfa964073333ea72c7c9cd20ad45e6 upstream
+
+hvc_console: Fix free_irq in spinlocked section
+
+    commit 611e097d7707741a336a0677d9d69bec40f29f3d
+    Author: Christian Borntraeger <borntraeger@de.ibm.com>
+    hvc_console: rework setup to replace irq functions with callbacks
+    introduced a spinlock recursion problem. The notifier_del is
+    called with a lock held, and in turns calls free_irq which then
+    complains when manipulating procfs. This fixes it by moving the
+    call to the notifier to outside of the locked section.
+
+Signed-off-by: Christian Borntraeger<borntraeger@de.ibm.com>
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/hvc_console.c |   10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/char/hvc_console.c
++++ b/drivers/char/hvc_console.c
+@@ -367,13 +367,13 @@ static void hvc_close(struct tty_struct 
+       spin_lock_irqsave(&hp->lock, flags);
+       if (--hp->count == 0) {
+-              if (hp->ops->notifier_del)
+-                      hp->ops->notifier_del(hp, hp->data);
+-
+               /* We are done with the tty pointer now. */
+               hp->tty = NULL;
+               spin_unlock_irqrestore(&hp->lock, flags);
++              if (hp->ops->notifier_del)
++                      hp->ops->notifier_del(hp, hp->data);
++
+               /*
+                * Chain calls chars_in_buffer() and returns immediately if
+                * there is no buffered data otherwise sleeps on a wait queue
+@@ -416,11 +416,11 @@ static void hvc_hangup(struct tty_struct
+       hp->n_outbuf = 0;
+       hp->tty = NULL;
++      spin_unlock_irqrestore(&hp->lock, flags);
++
+       if (hp->ops->notifier_del)
+                       hp->ops->notifier_del(hp, hp->data);
+-      spin_unlock_irqrestore(&hp->lock, flags);
+-
+       while(temp_open_count) {
+               --temp_open_count;
+               kref_put(&hp->kref, destroy_hvc_struct);
diff --git a/queue-2.6.27/netfilter-restore-lost-ifdef-guarding-defrag-exception.patch b/queue-2.6.27/netfilter-restore-lost-ifdef-guarding-defrag-exception.patch
new file mode 100644 (file)
index 0000000..91839dd
--- /dev/null
@@ -0,0 +1,48 @@
+From kaber@trash.net  Thu Oct 23 13:16:48 2008
+From: Patrick McHardy <kaber@trash.net>
+Date: Wed, 22 Oct 2008 19:41:31 +0200 (MEST)
+Subject: netfilter: restore lost ifdef guarding defrag exception
+To: stable@kernel.org
+Cc: netfilter-devel@vger.kernel.org, Patrick McHardy <kaber@trash.net>, davem@davemloft.net
+Message-ID: <20081022174130.21341.48347.sendpatchset@x2.localnet>
+
+From: Patrick McHardy <kaber@trash.net>
+
+netfilter: restore lost #ifdef guarding defrag exception
+
+Upstream commit 38f7ac3eb:
+
+Nir Tzachar <nir.tzachar@gmail.com> reported a warning when sending
+fragments over loopback with NAT:
+
+[ 6658.338121] WARNING: at net/ipv4/netfilter/nf_nat_standalone.c:89 nf_nat_fn+0x33/0x155()
+
+The reason is that defragmentation is skipped for already tracked connections.
+This is wrong in combination with NAT and ip_conntrack actually had some ifdefs
+to avoid this behaviour when NAT is compiled in.
+
+The entire "optimization" may seem a bit silly, for now simply restoring the
+lost #ifdef is the easiest solution until we can come up with something better.
+
+Signed-off-by: Patrick McHardy <kaber@trash.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
++++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+@@ -150,10 +150,12 @@ static unsigned int ipv4_conntrack_defra
+                                         const struct net_device *out,
+                                         int (*okfn)(struct sk_buff *))
+ {
++#if !defined(CONFIG_NF_NAT) && !defined(CONFIG_NF_NAT_MODULE)
+       /* Previously seen (loopback)?  Ignore.  Do this before
+          fragment check. */
+       if (skb->nfct)
+               return NF_ACCEPT;
++#endif
+       /* Gather fragments. */
+       if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
diff --git a/queue-2.6.27/netfilter-snmp-nat-leaks-memory-in-case-of-failure.patch b/queue-2.6.27/netfilter-snmp-nat-leaks-memory-in-case-of-failure.patch
new file mode 100644 (file)
index 0000000..24e7fe0
--- /dev/null
@@ -0,0 +1,31 @@
+From kaber@trash.net  Thu Oct 23 13:16:08 2008
+From: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
+Date: Wed, 22 Oct 2008 19:41:29 +0200 (MEST)
+Subject: netfilter: snmp nat leaks memory in case of failure
+To: stable@kernel.org
+Cc: netfilter-devel@vger.kernel.org, Patrick McHardy <kaber@trash.net>, davem@davemloft.net
+Message-ID: <20081022174129.21341.93881.sendpatchset@x2.localnet>
+
+From: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
+
+netfilter: snmp nat leaks memory in case of failure
+
+Upstream commit 311670f3e:
+
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
+Signed-off-by: Patrick McHardy <kaber@trash.net>
+
+---
+ net/ipv4/netfilter/nf_nat_snmp_basic.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
++++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
+@@ -742,6 +742,7 @@ static unsigned char snmp_object_decode(
+                       *obj = kmalloc(sizeof(struct snmp_object) + len,
+                                      GFP_ATOMIC);
+                       if (*obj == NULL) {
++                              kfree(p);
+                               kfree(id);
+                               if (net_ratelimit())
+                                       printk("OOM in bsalg (%d)\n", __LINE__);
diff --git a/queue-2.6.27/netfilter-xt_iprange-fix-range-inversion-match.patch b/queue-2.6.27/netfilter-xt_iprange-fix-range-inversion-match.patch
new file mode 100644 (file)
index 0000000..e8999a5
--- /dev/null
@@ -0,0 +1,63 @@
+From kaber@trash.net  Thu Oct 23 13:14:58 2008
+From: Alexey Dobriyan <adobriyan@gmail.com>
+Date: Wed, 22 Oct 2008 19:41:28 +0200 (MEST)
+Subject: netfilter: xt_iprange: fix range inversion match
+To: stable@kernel.org
+Cc: netfilter-devel@vger.kernel.org, Patrick McHardy <kaber@trash.net>, davem@davemloft.net
+Message-ID: <20081022174128.21341.79877.sendpatchset@x2.localnet>
+
+
+From: Alexey Dobriyan <adobriyan@gmail.com>
+
+netfilter: xt_iprange: fix range inversion match
+
+Upstream commit 6def1eb48:
+
+Inverted IPv4 v1 and IPv6 v0 matches don't match anything since 2.6.25-rc1!
+
+Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
+Acked-by: Jan Engelhardt <jengelh@medozas.de>
+Signed-off-by: Patrick McHardy <kaber@trash.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/netfilter/xt_iprange.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/net/netfilter/xt_iprange.c
++++ b/net/netfilter/xt_iprange.c
+@@ -67,7 +67,7 @@ iprange_mt4(const struct sk_buff *skb, c
+       if (info->flags & IPRANGE_SRC) {
+               m  = ntohl(iph->saddr) < ntohl(info->src_min.ip);
+               m |= ntohl(iph->saddr) > ntohl(info->src_max.ip);
+-              m ^= info->flags & IPRANGE_SRC_INV;
++              m ^= !!(info->flags & IPRANGE_SRC_INV);
+               if (m) {
+                       pr_debug("src IP " NIPQUAD_FMT " NOT in range %s"
+                                NIPQUAD_FMT "-" NIPQUAD_FMT "\n",
+@@ -81,7 +81,7 @@ iprange_mt4(const struct sk_buff *skb, c
+       if (info->flags & IPRANGE_DST) {
+               m  = ntohl(iph->daddr) < ntohl(info->dst_min.ip);
+               m |= ntohl(iph->daddr) > ntohl(info->dst_max.ip);
+-              m ^= info->flags & IPRANGE_DST_INV;
++              m ^= !!(info->flags & IPRANGE_DST_INV);
+               if (m) {
+                       pr_debug("dst IP " NIPQUAD_FMT " NOT in range %s"
+                                NIPQUAD_FMT "-" NIPQUAD_FMT "\n",
+@@ -123,14 +123,14 @@ iprange_mt6(const struct sk_buff *skb, c
+       if (info->flags & IPRANGE_SRC) {
+               m  = iprange_ipv6_sub(&iph->saddr, &info->src_min.in6) < 0;
+               m |= iprange_ipv6_sub(&iph->saddr, &info->src_max.in6) > 0;
+-              m ^= info->flags & IPRANGE_SRC_INV;
++              m ^= !!(info->flags & IPRANGE_SRC_INV);
+               if (m)
+                       return false;
+       }
+       if (info->flags & IPRANGE_DST) {
+               m  = iprange_ipv6_sub(&iph->daddr, &info->dst_min.in6) < 0;
+               m |= iprange_ipv6_sub(&iph->daddr, &info->dst_max.in6) > 0;
+-              m ^= info->flags & IPRANGE_DST_INV;
++              m ^= !!(info->flags & IPRANGE_DST_INV);
+               if (m)
+                       return false;
+       }
diff --git a/queue-2.6.27/regression-inclusion-of-linux-module.h-triggers-a-compiler-warning.patch b/queue-2.6.27/regression-inclusion-of-linux-module.h-triggers-a-compiler-warning.patch
new file mode 100644 (file)
index 0000000..8dd3cf5
--- /dev/null
@@ -0,0 +1,57 @@
+From bart.vanassche@gmail.com  Thu Oct 23 13:40:27 2008
+From: Bart Van Assche <bart.vanassche@gmail.com>
+Date: Tue, 21 Oct 2008 19:05:50 +0200
+Subject: Regression: inclusion of <linux/module.h> triggers a compiler warning
+To: stable@kernel.org
+Cc: Vladislav Bolkhovitin <vst@vlnb.net>, Andrew Morton <akpm@linux-foundation.org>, Linus Torvalds <torvalds@linux-foundation.org>, Dave Young <hidave.darkstar@gmail.com>
+Message-ID: <200810211905.50915.bart.vanassche@gmail.com>
+Content-Disposition: inline
+
+From: Bart Van Assche <bart.vanassche@gmail.com>
+
+Not upstream, only a 2.6.27-stable issue.
+
+When compiling kernel modules against the 2.6.27, 2.6.27.1 or 2.6.27.2 kernel
+headers, a compiler warning similar to the following is reported:
+
+CC [M]  trunk/scst/src/scst_targ.o
+In file included from include/linux/kernel.h:19,
+                from include/asm/system.h:11,
+                from include/asm/processor.h:18,
+                from include/linux/prefetch.h:15,
+                from include/linux/list.h:7,
+                from include/linux/module.h:10,
+                from trunk/scst/src/scst_main.c:20:
+include/linux/ratelimit.h: In function 'ratelimit':
+include/linux/ratelimit.h:23: warning: missing initializer
+include/linux/ratelimit.h:23: warning: (near initialization for 'rs.printed')
+
+This issue was introduced through commit
+717115e1a5856b57af0f71e1df7149108294fc10
+(http://git.kernel.org/?p=linux/kernel/git/stable/linux-2.6.27.y.git;a=commit;h=717115e1a5856b57af0f71e1df7149108294fc10).
+I have added the people who signed this patch in CC.
+
+The patch below fixes this warning, without changing the semantics of the code.
+
+Signed-off-by: Bart Van Assche <bart.vanassche@gmail.com>
+Acked-by: Dave Young <hidave.darkstar@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/ratelimit.h |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/include/linux/ratelimit.h
++++ b/include/linux/ratelimit.h
+@@ -13,8 +13,9 @@ struct ratelimit_state {
+       unsigned long begin;
+ };
+-#define DEFINE_RATELIMIT_STATE(name, interval, burst)         \
+-              struct ratelimit_state name = {interval, burst,}
++#define DEFINE_RATELIMIT_STATE(name, interval_value, burst_value)       \
++      struct ratelimit_state name                                       \
++              = { .interval = (interval_value), .burst = (burst_value) }
+ extern int __ratelimit(struct ratelimit_state *rs);
diff --git a/queue-2.6.27/sched-fix-the-wrong-mask_len.patch b/queue-2.6.27/sched-fix-the-wrong-mask_len.patch
new file mode 100644 (file)
index 0000000..0d6c357
--- /dev/null
@@ -0,0 +1,35 @@
+From jejb@kernel.org  Thu Oct 23 13:00:30 2008
+From: Miao Xie <miaox@cn.fujitsu.com>
+Date: Thu, 23 Oct 2008 16:50:03 GMT
+Subject: sched: fix the wrong mask_len
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200810231650.m9NGo3aY001438@hera.kernel.org>
+
+From: Miao Xie <miaox@cn.fujitsu.com>
+
+commit c851c8676bd7ae456e9b3af8e6bb2c434eddcc75 upstream
+
+If NR_CPUS isn't a multiple of 32, we get a truncated string of sched
+domains by catting /proc/schedstat. This is caused by the wrong mask_len.
+
+This patch fixes it.
+
+Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/sched_stats.h |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/sched_stats.h
++++ b/kernel/sched_stats.h
+@@ -9,7 +9,7 @@
+ static int show_schedstat(struct seq_file *seq, void *v)
+ {
+       int cpu;
+-      int mask_len = NR_CPUS/32 * 9;
++      int mask_len = (NR_CPUS/32 + 1) * 9;
+       char *mask_str = kmalloc(mask_len, GFP_KERNEL);
+       if (mask_str == NULL)
diff --git a/queue-2.6.27/series b/queue-2.6.27/series
new file mode 100644 (file)
index 0000000..e414f06
--- /dev/null
@@ -0,0 +1,21 @@
+gpiolib-fix-oops-in-gpio_get_value_cansleep.patch
+edac-cell-fix-incorrect-edac_mode.patch
+x86-acpi-fix-breakage-of-resume-on-64-bit-up-systems-with-smp-kernel.patch
+sched-fix-the-wrong-mask_len.patch
+usb-cdc-wdm-make-module-autoload-work.patch
+usb-don-t-rebind-drivers-after-failed-resume-or-reset.patch
+usb-fix-memory-leak-in-cdc-acm.patch
+usb-speedtouch-add-pre_reset-and-post_reset-routines.patch
+dm-kcopyd-avoid-queue-shuffle.patch
+dm-snapshot-fix-primary_pe-race.patch
+dm-exception-store-refactor-zero_area.patch
+dm-exception-store-fix-misordered-writes.patch
+amd_iommu-fix-nasty-bug-that-caused-illegal_device_table_entry-errors.patch
+cifs-fix-saving-of-resume-key-before-cifsfindnext.patch
+ext-avoid-printk-floods-in-the-face-of-directory-corruption.patch
+netfilter-xt_iprange-fix-range-inversion-match.patch
+netfilter-snmp-nat-leaks-memory-in-case-of-failure.patch
+netfilter-restore-lost-ifdef-guarding-defrag-exception.patch
+anon_vma_prepare-properly-lock-even-newly-allocated-entries.patch
+hvc_console-fix-free_irq-in-spinlocked-section.patch
+regression-inclusion-of-linux-module.h-triggers-a-compiler-warning.patch
diff --git a/queue-2.6.27/usb-cdc-wdm-make-module-autoload-work.patch b/queue-2.6.27/usb-cdc-wdm-make-module-autoload-work.patch
new file mode 100644 (file)
index 0000000..6b92ed9
--- /dev/null
@@ -0,0 +1,32 @@
+From jejb@kernel.org  Thu Oct 23 13:02:01 2008
+From: Oliver Neukum <oliver@neukum.org>
+Date: Thu, 23 Oct 2008 17:35:11 GMT
+Subject: USB: cdc-wdm: make module autoload work
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200810231735.m9NHZBH3008400@hera.kernel.org>
+
+From: Oliver Neukum <oliver@neukum.org>
+
+commit aa5380b904e7f896db0931320160bdea93e41f6a upstream
+
+this fixes an omission that led to no alias being computed for the
+cdc-wdm module.
+
+Signed-off-by: Oliver Neukum <oneukum@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/class/cdc-wdm.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/class/cdc-wdm.c
++++ b/drivers/usb/class/cdc-wdm.c
+@@ -42,6 +42,8 @@ static struct usb_device_id wdm_ids[] = 
+       { }
+ };
++MODULE_DEVICE_TABLE (usb, wdm_ids);
++
+ #define WDM_MINOR_BASE        176
diff --git a/queue-2.6.27/usb-don-t-rebind-drivers-after-failed-resume-or-reset.patch b/queue-2.6.27/usb-don-t-rebind-drivers-after-failed-resume-or-reset.patch
new file mode 100644 (file)
index 0000000..c8aae33
--- /dev/null
@@ -0,0 +1,53 @@
+From jejb@kernel.org  Thu Oct 23 13:02:28 2008
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Thu, 23 Oct 2008 17:35:07 GMT
+Subject: USB: don't rebind drivers after failed resume or reset
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200810231735.m9NHZ7jJ008353@hera.kernel.org>
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit 6c6409459a18a825ce12ecb003d5686af61f7a2f upstream
+
+This patch (as1152) may help prevent some problems associated with the
+new policy of unbinding drivers that don't support suspend/resume or
+pre_reset/post_reset.  If for any reason the resume or reset fails, and
+the device is logically disconnected, there's no point in trying to
+rebind the driver.  So the patch checks for success before carrying
+out the unbind/rebind.
+
+There was a report from one user that this fixed a problem he was
+experiencing, but the details never became fully clear.  In any case,
+adding these tests can't hurt.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/driver.c |    3 ++-
+ drivers/usb/core/hub.c    |    2 +-
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -1609,7 +1609,8 @@ int usb_external_resume_device(struct us
+       status = usb_resume_both(udev);
+       udev->last_busy = jiffies;
+       usb_pm_unlock(udev);
+-      do_unbind_rebind(udev, DO_REBIND);
++      if (status == 0)
++              do_unbind_rebind(udev, DO_REBIND);
+       /* Now that the device is awake, we can start trying to autosuspend
+        * it again. */
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -3424,7 +3424,7 @@ int usb_reset_device(struct usb_device *
+                                               USB_INTERFACE_BOUND)
+                                       rebind = 1;
+                       }
+-                      if (rebind)
++                      if (ret == 0 && rebind)
+                               usb_rebind_intf(cintf);
+               }
+       }
diff --git a/queue-2.6.27/usb-fix-memory-leak-in-cdc-acm.patch b/queue-2.6.27/usb-fix-memory-leak-in-cdc-acm.patch
new file mode 100644 (file)
index 0000000..176a2c0
--- /dev/null
@@ -0,0 +1,36 @@
+From jejb@kernel.org  Thu Oct 23 13:04:06 2008
+From: Oliver Neukum <oliver@neukum.org>
+Date: Thu, 23 Oct 2008 17:35:09 GMT
+Subject: USB: fix memory leak in cdc-acm
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200810231735.m9NHZ9bR008373@hera.kernel.org>
+
+From: Oliver Neukum <oliver@neukum.org>
+
+commit a496c64f1363ec4d67ebdc1e1f619ad6372a574c upstream
+
+This fixes a memory leak on disconnect in cdc-acm
+
+Thanks to 施金前 for finding it.
+
+Signed-off-by: Oliver Neukum <oneukum@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/class/cdc-acm.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -849,9 +849,10 @@ static void acm_write_buffers_free(struc
+ {
+       int i;
+       struct acm_wb *wb;
++      struct usb_device *usb_dev = interface_to_usbdev(acm->control);
+       for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) {
+-              usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah);
++              usb_buffer_free(usb_dev, acm->writesize, wb->buf, wb->dmah);
+       }
+ }
diff --git a/queue-2.6.27/usb-speedtouch-add-pre_reset-and-post_reset-routines.patch b/queue-2.6.27/usb-speedtouch-add-pre_reset-and-post_reset-routines.patch
new file mode 100644 (file)
index 0000000..8aae1c2
--- /dev/null
@@ -0,0 +1,53 @@
+From jejb@kernel.org  Thu Oct 23 13:04:42 2008
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Thu, 23 Oct 2008 17:35:13 GMT
+Subject: USB: Speedtouch: add pre_reset and post_reset routines
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200810231735.m9NHZDhu008428@hera.kernel.org>
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit 8fc7aeab3851ed8c3ecf28901ca2c6f0400955c7 upstream
+
+This patch (as1150) fixes a problem in the speedtch driver.  When it
+resets the modem during probe it will be unbound from the other
+interfaces it has claimed, because it doesn't define a pre_reset and a
+post_reset method.
+
+The patch defines "do-nothing" methods.  This fixes Bugzilla #11767.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/atm/speedtch.c |   12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/drivers/usb/atm/speedtch.c
++++ b/drivers/usb/atm/speedtch.c
+@@ -722,6 +722,16 @@ static void speedtch_atm_stop(struct usb
+       flush_scheduled_work();
+ }
++static int speedtch_pre_reset(struct usb_interface *intf)
++{
++      return 0;
++}
++
++static int speedtch_post_reset(struct usb_interface *intf)
++{
++      return 0;
++}
++
+ /**********
+ **  USB  **
+@@ -740,6 +750,8 @@ static struct usb_driver speedtch_usb_dr
+       .name           = speedtch_driver_name,
+       .probe          = speedtch_usb_probe,
+       .disconnect     = usbatm_usb_disconnect,
++      .pre_reset      = speedtch_pre_reset,
++      .post_reset     = speedtch_post_reset,
+       .id_table       = speedtch_usb_ids
+ };
diff --git a/queue-2.6.27/x86-acpi-fix-breakage-of-resume-on-64-bit-up-systems-with-smp-kernel.patch b/queue-2.6.27/x86-acpi-fix-breakage-of-resume-on-64-bit-up-systems-with-smp-kernel.patch
new file mode 100644 (file)
index 0000000..4817a64
--- /dev/null
@@ -0,0 +1,58 @@
+From jejb@kernel.org  Thu Oct 23 12:59:15 2008
+From: Rafael J. Wysocki <rjw@sisk.pl>
+Date: Mon, 20 Oct 2008 21:30:19 GMT
+Subject: x86 ACPI: fix breakage of resume on 64-bit UP systems with SMP kernel
+To: jejb@kernel.org, stable@kernel.org
+Message-ID: <200810202130.m9KLUJU5017800@hera.kernel.org>
+
+From: Rafael J. Wysocki <rjw@sisk.pl>
+
+commit 3038edabf48f01421c621cb77a712b446d3a5d67 upstream
+
+x86 ACPI: Fix breakage of resume on 64-bit UP systems with SMP kernel
+
+We are now using per CPU GDT tables in head_64.S and the original
+early_gdt_descr.address is invalidated after boot by
+setup_per_cpu_areas().  This breaks resume from suspend to RAM on
+x86_64 UP systems using SMP kernels, because this part of head_64.S
+is also executed during the resume and the invalid GDT address
+causes the system to crash.  It doesn't break on 'true' SMP systems,
+because early_gdt_descr.address is modified every time
+native_cpu_up() runs.  However, during resume it should point to the
+GDT of the boot CPU rather than to another CPU's GDT.
+
+For this reason, during suspend to RAM always make
+early_gdt_descr.address point to the boot CPU's GDT.
+
+This fixes http://bugzilla.kernel.org/show_bug.cgi?id=11568, which
+is a regression from 2.6.26.
+
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+Acked-by: Pavel Machek <pavel@suse.cz>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Reported-and-tested-by: Andy Wettstein <ajw1980@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/kernel/acpi/sleep.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/arch/x86/kernel/acpi/sleep.c
++++ b/arch/x86/kernel/acpi/sleep.c
+@@ -10,6 +10,7 @@
+ #include <linux/dmi.h>
+ #include <linux/cpumask.h>
+ #include <asm/segment.h>
++#include <asm/desc.h>
+ #include "realmode/wakeup.h"
+ #include "sleep.h"
+@@ -98,6 +99,8 @@ int acpi_save_state_mem(void)
+       header->trampoline_segment = setup_trampoline() >> 4;
+ #ifdef CONFIG_SMP
+       stack_start.sp = temp_stack + 4096;
++      early_gdt_descr.address =
++                      (unsigned long)get_cpu_gdt_table(smp_processor_id());
+ #endif
+       initial_code = (unsigned long)wakeup_long64;
+       saved_magic = 0x123456789abcdef0;