]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
more patches added to 2.6.16 queue
authorGreg Kroah-Hartman <gregkh@suse.de>
Wed, 12 Apr 2006 20:58:40 +0000 (13:58 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 12 Apr 2006 20:58:40 +0000 (13:58 -0700)
queue-2.6.16/RLIMIT_CPU-fix-handling-of-a-zero-limit.patch [new file with mode: 0644]
queue-2.6.16/XFS-Fix-utime-2-in-the-case-that-no-times-parameter-was-passed-in.patch [new file with mode: 0644]
queue-2.6.16/alpha-smp-boot-fixes.patch [new file with mode: 0644]
queue-2.6.16/cciss-bug-fix-for-crash-when-running-hpacucli.patch [new file with mode: 0644]
queue-2.6.16/edac_752x-needs-config_hotplug.patch [new file with mode: 0644]
queue-2.6.16/ext3-fix-missed-mutex-unlock.patch [new file with mode: 0644]
queue-2.6.16/fix-block-device-symlink-name.patch [new file with mode: 0644]
queue-2.6.16/fix-buddy-list-race-that-could-lead-to-page-lru-list-corruptions.patch [new file with mode: 0644]
queue-2.6.16/fuse-fix-oops-in-fuse_send_readpages.patch [new file with mode: 0644]
queue-2.6.16/m32r-fix-cpu_possible_map-and-cpu_present_map-initialization-for-smp-kernel.patch [new file with mode: 0644]
queue-2.6.16/m32r-security-fix-of-get-put-_user-macros.patch [new file with mode: 0644]

diff --git a/queue-2.6.16/RLIMIT_CPU-fix-handling-of-a-zero-limit.patch b/queue-2.6.16/RLIMIT_CPU-fix-handling-of-a-zero-limit.patch
new file mode 100644 (file)
index 0000000..2c8dc83
--- /dev/null
@@ -0,0 +1,52 @@
+From nobody Mon Sep 17 00:00:00 2001
+From: Andrew Morton <akpm@osdl.org>
+Date: Fri Mar 24 03:18:35 2006 -0800
+Subject: [PATCH] RLIMIT_CPU: fix handling of a zero limit
+
+At present the kernel doesn't honour an attempt to set RLIMIT_CPU to zero
+seconds.  But the spec says it should, and that's what 2.4.x does.
+
+Fixing this for real would involve some complexity (such as adding a new
+it-has-been-set flag to the task_struct, and testing that everwhere, instead
+of overloading the value of it_prof_expires).
+
+Given that a 2.4 kernel won't actually send the signal until one second has
+expired anyway, let's just handle this case by treating the caller's
+zero-seconds as one second.
+
+Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Cc: Ulrich Weigand <uweigand@de.ibm.com>
+Cc: Cliff Wickman <cpw@sgi.com>
+Acked-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+
+---
+
+ kernel/sys.c |   14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+e0661111e5441995f7a69dc4336c9f131cb9bc58
+--- linux-2.6.16.4.orig/kernel/sys.c
++++ linux-2.6.16.4/kernel/sys.c
+@@ -1657,7 +1657,19 @@ asmlinkage long sys_setrlimit(unsigned i
+           (cputime_eq(current->signal->it_prof_expires, cputime_zero) ||
+            new_rlim.rlim_cur <= cputime_to_secs(
+                    current->signal->it_prof_expires))) {
+-              cputime_t cputime = secs_to_cputime(new_rlim.rlim_cur);
++              unsigned long rlim_cur = new_rlim.rlim_cur;
++              cputime_t cputime;
++
++              if (rlim_cur == 0) {
++                      /*
++                       * The caller is asking for an immediate RLIMIT_CPU
++                       * expiry.  But we use the zero value to mean "it was
++                       * never set".  So let's cheat and make it one second
++                       * instead
++                       */
++                      rlim_cur = 1;
++              }
++              cputime = secs_to_cputime(rlim_cur);
+               read_lock(&tasklist_lock);
+               spin_lock_irq(&current->sighand->siglock);
+               set_process_cpu_timer(current, CPUCLOCK_PROF,
diff --git a/queue-2.6.16/XFS-Fix-utime-2-in-the-case-that-no-times-parameter-was-passed-in.patch b/queue-2.6.16/XFS-Fix-utime-2-in-the-case-that-no-times-parameter-was-passed-in.patch
new file mode 100644 (file)
index 0000000..d373f03
--- /dev/null
@@ -0,0 +1,29 @@
+From nobody Mon Sep 17 00:00:00 2001
+From: Nathan Scott <nathans@sgi.com>
+Date: Tue Apr 11 15:12:45 2006 +1000
+Subject: [PATCH] [XFS] Fix utime(2) in the case that no times parameter was passed in.
+
+SGI-PV: 949858
+SGI-Modid: xfs-linux-melb:xfs-kern:25717a
+
+Signed-off-by: Jes Sorensen <jes@sgi.com>
+Signed-off-by: Nathan Scott <nathans@sgi.com>
+
+---
+
+ fs/xfs/linux-2.6/xfs_iops.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+8c0b5113a55c698f3190ec85925815640f1c2049
+--- linux-2.6.16.4.orig/fs/xfs/linux-2.6/xfs_iops.c
++++ linux-2.6.16.4/fs/xfs/linux-2.6/xfs_iops.c
+@@ -673,8 +673,7 @@ linvfs_setattr(
+       if (ia_valid & ATTR_ATIME) {
+               vattr.va_mask |= XFS_AT_ATIME;
+               vattr.va_atime = attr->ia_atime;
+-              if (ia_valid & ATTR_ATIME_SET)
+-                      inode->i_atime = attr->ia_atime;
++              inode->i_atime = attr->ia_atime;
+       }
+       if (ia_valid & ATTR_MTIME) {
+               vattr.va_mask |= XFS_AT_MTIME;
diff --git a/queue-2.6.16/alpha-smp-boot-fixes.patch b/queue-2.6.16/alpha-smp-boot-fixes.patch
new file mode 100644 (file)
index 0000000..1dcb5e8
--- /dev/null
@@ -0,0 +1,115 @@
+From stable-bounces@linux.kernel.org Mon Apr 10 23:54:14 2006
+Message-Id: <200604110653.k3B6rwKk013629@shell0.pdx.osdl.net>
+To: torvalds@osdl.org
+From: akpm@osdl.org
+Date: Mon, 10 Apr 2006 22:53:16 -0700
+Cc: buhrain@rosettastone.com, ink@jurassic.park.msu.ru, stable@kernel.org,
+        rth@twiddle.net
+Subject: alpha: SMP boot fixes
+
+
+From: Brian Uhrain <buhrain@rosettastone.com> says:
+
+I've encountered two problems with 2.6.16 and newer kernels on my API CS20
+(dual 833MHz Alpha 21264b processors).  The first is the kernel OOPSing
+because of a NULL pointer dereference while trying to populate SysFS with the
+CPU information.  The other is that only one processor was being brought up. 
+I've included a small Alpha-specific patch that fixes both problems.
+
+The first problem was caused by the CPUs never being properly registered using
+register_cpu(), the way it's done on other architectures.
+
+The second problem has to do with the removal of hwrpb_cpu_present_mask in
+arch/alpha/kernel/smp.c.  In setup_smp() in the 2.6.15 kernel sources,
+hwrpb_cpu_present_mask has a bit set for each processor that is probed, and
+afterwards cpu_present_mask is set to the cpumask for the boot CPU.  In the
+same function of the same file in the 2.6.16 sources, instead of
+hwrpb_cpu_present_mask being set, cpu_possible_map is updated for each probed
+CPU.  cpu_present_mask is still set to the cpumask of the boot CPU afterwards.
+ The problem lies in include/asm-alpha/smp.h, where cpu_possible_map is
+#define'd to be cpu_present_mask.
+
+Cleanups from: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
+
+ - cpu_present_mask and cpu_possible_map are essentially the same thing
+   on alpha, as it doesn't support CPU hotplug;
+ - allocate "struct cpu" only for present CPUs, like sparc64 does.
+   Static array of "struct cpu" is just a waste of memory.
+
+Signed-off-by: Brian Uhrain <buhrain@rosettastone.com>
+Cc: Richard Henderson <rth@twiddle.net>
+Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/alpha/kernel/setup.c |   17 +++++++++++++++++
+ arch/alpha/kernel/smp.c   |    8 +++-----
+ 2 files changed, 20 insertions(+), 5 deletions(-)
+
+--- linux-2.6.16.4.orig/arch/alpha/kernel/setup.c
++++ linux-2.6.16.4/arch/alpha/kernel/setup.c
+@@ -24,6 +24,7 @@
+ #include <linux/config.h>     /* CONFIG_ALPHA_LCA etc */
+ #include <linux/mc146818rtc.h>
+ #include <linux/console.h>
++#include <linux/cpu.h>
+ #include <linux/errno.h>
+ #include <linux/init.h>
+ #include <linux/string.h>
+@@ -477,6 +478,22 @@ page_is_ram(unsigned long pfn)
+ #undef PFN_PHYS
+ #undef PFN_MAX
++static int __init
++register_cpus(void)
++{
++      int i;
++
++      for_each_possible_cpu(i) {
++              struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
++              if (!p)
++                      return -ENOMEM;
++              register_cpu(p, i, NULL);
++      }
++      return 0;
++}
++
++arch_initcall(register_cpus);
++
+ void __init
+ setup_arch(char **cmdline_p)
+ {
+--- linux-2.6.16.4.orig/arch/alpha/kernel/smp.c
++++ linux-2.6.16.4/arch/alpha/kernel/smp.c
+@@ -439,7 +439,7 @@ setup_smp(void)
+                       if ((cpu->flags & 0x1cc) == 0x1cc) {
+                               smp_num_probed++;
+                               /* Assume here that "whami" == index */
+-                              cpu_set(i, cpu_possible_map);
++                              cpu_set(i, cpu_present_mask);
+                               cpu->pal_revision = boot_cpu_palrev;
+                       }
+@@ -450,9 +450,8 @@ setup_smp(void)
+               }
+       } else {
+               smp_num_probed = 1;
+-              cpu_set(boot_cpuid, cpu_possible_map);
++              cpu_set(boot_cpuid, cpu_present_mask);
+       }
+-      cpu_present_mask = cpumask_of_cpu(boot_cpuid);
+       printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n",
+              smp_num_probed, cpu_possible_map.bits[0]);
+@@ -488,9 +487,8 @@ void __devinit
+ smp_prepare_boot_cpu(void)
+ {
+       /*
+-       * Mark the boot cpu (current cpu) as both present and online
++       * Mark the boot cpu (current cpu) as online
+        */ 
+-      cpu_set(smp_processor_id(), cpu_present_mask);
+       cpu_set(smp_processor_id(), cpu_online_map);
+ }
diff --git a/queue-2.6.16/cciss-bug-fix-for-crash-when-running-hpacucli.patch b/queue-2.6.16/cciss-bug-fix-for-crash-when-running-hpacucli.patch
new file mode 100644 (file)
index 0000000..6b1b73d
--- /dev/null
@@ -0,0 +1,155 @@
+From stable-bounces@linux.kernel.org Mon Apr 10 16:42:08 2006
+Message-Id: <200604102338.k3ANckgo000802@shell0.pdx.osdl.net>
+To: mikem@beardog.cca.cpqcorp.net, mike.miller@hp.com, stable@kernel.org,
+        steve.cameron@hp.com, mm-commits@vger.kernel.org
+From: akpm@osdl.org
+Date: Mon, 10 Apr 2006 15:38:07 -0700
+Cc: 
+Subject: cciss: bug fix for crash when running hpacucli
+
+
+From: "Mike Miller" <mikem@beardog.cca.cpqcorp.net>
+
+Fix a crash when running hpacucli with multiple logical volumes on a cciss
+controller.  We were not properly initializing the disk->queue and causing
+a fault.
+
+Thanks to Hasso Tepper for reporting the problem.  Thanks to Steve Cameron
+for root causing the problem.  Most of the patch just moves things around. 
+The fix is a one-liner.
+
+Signed-off-by: Mike Miller <mike.miller@hp.com>
+Signed-off-by: Stephen Cameron <steve.cameron@hp.com>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/block/cciss.c |   96 +++++++++++++++++++++++++-------------------------
+ 1 file changed, 49 insertions(+), 47 deletions(-)
+
+--- linux-2.6.16.4.orig/drivers/block/cciss.c
++++ linux-2.6.16.4/drivers/block/cciss.c
+@@ -1181,6 +1181,53 @@ static int revalidate_allvol(ctlr_info_t
+         return 0;
+ }
++static inline void complete_buffers(struct bio *bio, int status)
++{
++      while (bio) {
++              struct bio *xbh = bio->bi_next;
++              int nr_sectors = bio_sectors(bio);
++
++              bio->bi_next = NULL;
++              blk_finished_io(len);
++              bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
++              bio = xbh;
++      }
++
++}
++
++static void cciss_softirq_done(struct request *rq)
++{
++      CommandList_struct *cmd = rq->completion_data;
++      ctlr_info_t *h = hba[cmd->ctlr];
++      unsigned long flags;
++      u64bit temp64;
++      int i, ddir;
++
++      if (cmd->Request.Type.Direction == XFER_READ)
++              ddir = PCI_DMA_FROMDEVICE;
++      else
++              ddir = PCI_DMA_TODEVICE;
++
++      /* command did not need to be retried */
++      /* unmap the DMA mapping for all the scatter gather elements */
++      for(i=0; i<cmd->Header.SGList; i++) {
++              temp64.val32.lower = cmd->SG[i].Addr.lower;
++              temp64.val32.upper = cmd->SG[i].Addr.upper;
++              pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
++      }
++
++      complete_buffers(rq->bio, rq->errors);
++
++#ifdef CCISS_DEBUG
++      printk("Done with %p\n", rq);
++#endif /* CCISS_DEBUG */
++
++      spin_lock_irqsave(&h->lock, flags);
++      end_that_request_last(rq, rq->errors);
++      cmd_free(h, cmd,1);
++      spin_unlock_irqrestore(&h->lock, flags);
++}
++
+ /* This function will check the usage_count of the drive to be updated/added.
+  * If the usage_count is zero then the drive information will be updated and
+  * the disk will be re-registered with the kernel.  If not then it will be
+@@ -1249,6 +1296,8 @@ static void cciss_update_drive_info(int 
+               blk_queue_max_sectors(disk->queue, 512);
++              blk_queue_softirq_done(disk->queue, cciss_softirq_done);
++
+               disk->queue->queuedata = hba[ctlr];
+               blk_queue_hardsect_size(disk->queue,
+@@ -2148,20 +2197,6 @@ static void start_io( ctlr_info_t *h)
+               addQ (&(h->cmpQ), c); 
+       }
+ }
+-
+-static inline void complete_buffers(struct bio *bio, int status)
+-{
+-      while (bio) {
+-              struct bio *xbh = bio->bi_next; 
+-              int nr_sectors = bio_sectors(bio);
+-
+-              bio->bi_next = NULL; 
+-              blk_finished_io(len);
+-              bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
+-              bio = xbh;
+-      }
+-
+-} 
+ /* Assumes that CCISS_LOCK(h->ctlr) is held. */
+ /* Zeros out the error record and then resends the command back */
+ /* to the controller */
+@@ -2179,39 +2214,6 @@ static inline void resend_cciss_cmd( ctl
+       start_io(h);
+ }
+-static void cciss_softirq_done(struct request *rq)
+-{
+-      CommandList_struct *cmd = rq->completion_data;
+-      ctlr_info_t *h = hba[cmd->ctlr];
+-      unsigned long flags;
+-      u64bit temp64;
+-      int i, ddir;
+-
+-      if (cmd->Request.Type.Direction == XFER_READ)
+-              ddir = PCI_DMA_FROMDEVICE;
+-      else
+-              ddir = PCI_DMA_TODEVICE;
+-
+-      /* command did not need to be retried */
+-      /* unmap the DMA mapping for all the scatter gather elements */
+-      for(i=0; i<cmd->Header.SGList; i++) {
+-              temp64.val32.lower = cmd->SG[i].Addr.lower;
+-              temp64.val32.upper = cmd->SG[i].Addr.upper;
+-              pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
+-      }
+-
+-      complete_buffers(rq->bio, rq->errors);
+-
+-#ifdef CCISS_DEBUG
+-      printk("Done with %p\n", rq);
+-#endif /* CCISS_DEBUG */ 
+-
+-      spin_lock_irqsave(&h->lock, flags);
+-      end_that_request_last(rq, rq->errors);
+-      cmd_free(h, cmd,1);
+-      spin_unlock_irqrestore(&h->lock, flags);
+-}
+-
+ /* checks the status of the job and calls complete buffers to mark all 
+  * buffers for the completed job. Note that this function does not need
+  * to hold the hba/queue lock.
diff --git a/queue-2.6.16/edac_752x-needs-config_hotplug.patch b/queue-2.6.16/edac_752x-needs-config_hotplug.patch
new file mode 100644 (file)
index 0000000..7f6adf3
--- /dev/null
@@ -0,0 +1,38 @@
+From stable-bounces@linux.kernel.org Mon Apr 10 13:55:06 2006
+Date: Mon, 10 Apr 2006 20:54:24 +0200
+From: Adrian Bunk <bunk@stusta.de>
+To: stable@kernel.org
+Message-ID: <20060410185424.GF2408@stusta.de>
+Content-Disposition: inline
+Cc: Randy Dunlap <rdunlap@xenotime.net>
+Subject: edac_752x needs CONFIG_HOTPLUG
+
+From: Randy Dunlap <rdunlap@xenotime.net>
+
+EDAC_752X uses pci_scan_single_device(), which is only available
+if CONFIG_HOTPLUG is enabled, so limit this driver with HOTPLUG.
+
+This patch was already included in Linus' tree.
+
+Adrian Bunk:
+Rediffed for 2.6.16.x due to unrelated context changes.
+
+Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>
+Signed-off-by: Adrian Bunk <bunk@stusta.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/edac/Kconfig |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- linux-2.6.16.4.orig/drivers/edac/Kconfig
++++ linux-2.6.16.4/drivers/edac/Kconfig
+@@ -71,7 +71,7 @@ config EDAC_E7XXX
+ config EDAC_E752X
+       tristate "Intel e752x (e7520, e7525, e7320)"
+-      depends on EDAC_MM_EDAC && PCI
++      depends on EDAC_MM_EDAC && PCI && HOTPLUG
+       help
+         Support for error detection and correction on the Intel
+         E7520, E7525, E7320 server chipsets.
diff --git a/queue-2.6.16/ext3-fix-missed-mutex-unlock.patch b/queue-2.6.16/ext3-fix-missed-mutex-unlock.patch
new file mode 100644 (file)
index 0000000..1fe2677
--- /dev/null
@@ -0,0 +1,31 @@
+From stable-bounces@linux.kernel.org Mon Apr 10 23:55:30 2006
+Message-Id: <200604110655.k3B6tJlG014021@shell0.pdx.osdl.net>
+To: torvalds@osdl.org
+From: akpm@osdl.org
+Date: Mon, 10 Apr 2006 22:54:38 -0700
+Cc: stable@kernel.org, leonid.i.ananiev@intel.com
+Subject: ext3: Fix missed mutex unlock
+
+
+From: "Ananiev, Leonid I" <leonid.i.ananiev@intel.com>
+
+Missed unlock_super()call is added in error condition code path.
+
+Signed-off-by: Leonid Ananiev <leonid.i.ananiev@intel.com>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/ext3/resize.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- linux-2.6.16.4.orig/fs/ext3/resize.c
++++ linux-2.6.16.4/fs/ext3/resize.c
+@@ -974,6 +974,7 @@ int ext3_group_extend(struct super_block
+       if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) {
+               ext3_warning(sb, __FUNCTION__,
+                            "multiple resizers run on filesystem!");
++              unlock_super(sb);
+               err = -EBUSY;
+               goto exit_put;
+       }
diff --git a/queue-2.6.16/fix-block-device-symlink-name.patch b/queue-2.6.16/fix-block-device-symlink-name.patch
new file mode 100644 (file)
index 0000000..40d41a5
--- /dev/null
@@ -0,0 +1,47 @@
+From stable-bounces@linux.kernel.org Mon Apr 10 01:18:42 2006
+Message-Id: <200604100817.k3A8Hvcu001424@shell0.pdx.osdl.net>
+To: sfr@canb.auug.org.au, hch@lst.de, stable@kernel.org,
+        viro@zeniv.linux.org.uk, mm-commits@vger.kernel.org
+From: akpm@osdl.org
+Date: Mon, 10 Apr 2006 00:17:20 -0700
+Cc: 
+Subject: Fix block device symlink name
+
+
+From: Stephen Rothwell <sfr@canb.auug.org.au>
+
+As noted further on the this file, some block devices have a / in their
+name, so fix the "block:..." symlink name the same as the /sys/block name.
+
+Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Cc: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ fs/partitions/check.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- linux-2.6.16.4.orig/fs/partitions/check.c
++++ linux-2.6.16.4/fs/partitions/check.c
+@@ -345,6 +345,7 @@ static char *make_block_name(struct gend
+       char *name;
+       static char *block_str = "block:";
+       int size;
++      char *s;
+       size = strlen(block_str) + strlen(disk->disk_name) + 1;
+       name = kmalloc(size, GFP_KERNEL);
+@@ -352,6 +353,10 @@ static char *make_block_name(struct gend
+               return NULL;
+       strcpy(name, block_str);
+       strcat(name, disk->disk_name);
++      /* ewww... some of these buggers have / in name... */
++      s = strchr(name, '/');
++      if (s)
++              *s = '!';
+       return name;
+ }
diff --git a/queue-2.6.16/fix-buddy-list-race-that-could-lead-to-page-lru-list-corruptions.patch b/queue-2.6.16/fix-buddy-list-race-that-could-lead-to-page-lru-list-corruptions.patch
new file mode 100644 (file)
index 0000000..2501862
--- /dev/null
@@ -0,0 +1,163 @@
+From stable-bounces@linux.kernel.org Mon Apr 10 17:55:02 2006
+Date: Mon, 10 Apr 2006 16:54:00 -0700
+From: Andrew Morton <akpm@osdl.org>
+To: stable@kernel.org
+Message-Id: <20060410165400.47d0d311.akpm@osdl.org>
+Cc: 
+Subject: Fix buddy list race that could lead to page lru list corruptions
+
+From: Nick Piggin <piggin@cyberone.com.au>
+
+[PATCH] Fix buddy list race that could lead to page lru list corruptions
+
+Rohit found an obscure bug causing buddy list corruption.
+
+page_is_buddy is using a non-atomic test (PagePrivate && page_count == 0)
+to determine whether or not a free page's buddy is itself free and in the
+buddy lists.
+
+Each of the conjuncts may be true at different times due to unrelated
+conditions, so the non-atomic page_is_buddy test may find each conjunct to
+be true even if they were not both true at the same time (ie. the page was
+not on the buddy lists).
+
+Signed-off-by: Martin Bligh <mbligh@google.com>
+Signed-off-by: Rohit Seth <rohitseth@google.com>
+Signed-off-by: Nick Piggin <npiggin@suse.de>
+Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
+Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/mm.h         |    5 ++---
+ include/linux/page-flags.h |    8 +++++++-
+ mm/page_alloc.c            |   31 ++++++++++++++++++-------------
+ 3 files changed, 27 insertions(+), 17 deletions(-)
+
+--- linux-2.6.16.4.orig/include/linux/mm.h
++++ linux-2.6.16.4/include/linux/mm.h
+@@ -229,10 +229,9 @@ struct page {
+               unsigned long private;          /* Mapping-private opaque data:
+                                                * usually used for buffer_heads
+                                                * if PagePrivate set; used for
+-                                               * swp_entry_t if PageSwapCache.
+-                                               * When page is free, this
++                                               * swp_entry_t if PageSwapCache;
+                                                * indicates order in the buddy
+-                                               * system.
++                                               * system if PG_buddy is set.
+                                                */
+               struct address_space *mapping;  /* If low bit clear, points to
+                                                * inode address_space, or NULL.
+--- linux-2.6.16.4.orig/include/linux/page-flags.h
++++ linux-2.6.16.4/include/linux/page-flags.h
+@@ -74,7 +74,9 @@
+ #define PG_mappedtodisk               16      /* Has blocks allocated on-disk */
+ #define PG_reclaim            17      /* To be reclaimed asap */
+ #define PG_nosave_free                18      /* Free, should not be written */
+-#define PG_uncached           19      /* Page has been mapped as uncached */
++#define PG_buddy              19      /* Page is free, on buddy lists */
++
++#define PG_uncached           20      /* Page has been mapped as uncached */
+ /*
+  * Global page accounting.  One instance per CPU.  Only unsigned longs are
+@@ -319,6 +321,10 @@ extern void __mod_page_state_offset(unsi
+ #define SetPageNosaveFree(page)       set_bit(PG_nosave_free, &(page)->flags)
+ #define ClearPageNosaveFree(page)             clear_bit(PG_nosave_free, &(page)->flags)
++#define PageBuddy(page)               test_bit(PG_buddy, &(page)->flags)
++#define __SetPageBuddy(page)  __set_bit(PG_buddy, &(page)->flags)
++#define __ClearPageBuddy(page)        __clear_bit(PG_buddy, &(page)->flags)
++
+ #define PageMappedToDisk(page)        test_bit(PG_mappedtodisk, &(page)->flags)
+ #define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags)
+ #define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags)
+--- linux-2.6.16.4.orig/mm/page_alloc.c
++++ linux-2.6.16.4/mm/page_alloc.c
+@@ -153,7 +153,8 @@ static void bad_page(struct page *page)
+                       1 << PG_reclaim |
+                       1 << PG_slab    |
+                       1 << PG_swapcache |
+-                      1 << PG_writeback );
++                      1 << PG_writeback |
++                      1 << PG_buddy );
+       set_page_count(page, 0);
+       reset_page_mapcount(page);
+       page->mapping = NULL;
+@@ -224,12 +225,12 @@ static inline unsigned long page_order(s
+ static inline void set_page_order(struct page *page, int order) {
+       set_page_private(page, order);
+-      __SetPagePrivate(page);
++      __SetPageBuddy(page);
+ }
+ static inline void rmv_page_order(struct page *page)
+ {
+-      __ClearPagePrivate(page);
++      __ClearPageBuddy(page);
+       set_page_private(page, 0);
+ }
+@@ -268,11 +269,13 @@ __find_combined_index(unsigned long page
+  * This function checks whether a page is free && is the buddy
+  * we can do coalesce a page and its buddy if
+  * (a) the buddy is not in a hole &&
+- * (b) the buddy is free &&
+- * (c) the buddy is on the buddy system &&
+- * (d) a page and its buddy have the same order.
+- * for recording page's order, we use page_private(page) and PG_private.
++ * (b) the buddy is in the buddy system &&
++ * (c) a page and its buddy have the same order.
++ *
++ * For recording whether a page is in the buddy system, we use PG_buddy.
++ * Setting, clearing, and testing PG_buddy is serialized by zone->lock.
+  *
++ * For recording page's order, we use page_private(page).
+  */
+ static inline int page_is_buddy(struct page *page, int order)
+ {
+@@ -281,10 +284,10 @@ static inline int page_is_buddy(struct p
+               return 0;
+ #endif
+-       if (PagePrivate(page)           &&
+-           (page_order(page) == order) &&
+-            page_count(page) == 0)
++      if (PageBuddy(page) && page_order(page) == order) {
++              BUG_ON(page_count(page) != 0);
+                return 1;
++      }
+        return 0;
+ }
+@@ -301,7 +304,7 @@ static inline int page_is_buddy(struct p
+  * as necessary, plus some accounting needed to play nicely with other
+  * parts of the VM system.
+  * At each level, we keep a list of pages, which are heads of continuous
+- * free pages of length of (1 << order) and marked with PG_Private.Page's
++ * free pages of length of (1 << order) and marked with PG_buddy. Page's
+  * order is recorded in page_private(page) field.
+  * So when we are allocating or freeing one, we can derive the state of the
+  * other.  That is, if we allocate a small block, and both were   
+@@ -364,7 +367,8 @@ static inline int free_pages_check(struc
+                       1 << PG_slab    |
+                       1 << PG_swapcache |
+                       1 << PG_writeback |
+-                      1 << PG_reserved ))))
++                      1 << PG_reserved |
++                      1 << PG_buddy ))))
+               bad_page(page);
+       if (PageDirty(page))
+               __ClearPageDirty(page);
+@@ -522,7 +526,8 @@ static int prep_new_page(struct page *pa
+                       1 << PG_slab    |
+                       1 << PG_swapcache |
+                       1 << PG_writeback |
+-                      1 << PG_reserved ))))
++                      1 << PG_reserved |
++                      1 << PG_buddy ))))
+               bad_page(page);
+       /*
diff --git a/queue-2.6.16/fuse-fix-oops-in-fuse_send_readpages.patch b/queue-2.6.16/fuse-fix-oops-in-fuse_send_readpages.patch
new file mode 100644 (file)
index 0000000..8314d8a
--- /dev/null
@@ -0,0 +1,44 @@
+From stable-bounces@linux.kernel.org Tue Apr 11 09:38:51 2006
+To: stable@kernel.org
+Message-Id: <E1FTLsL-0003AF-00@dorka.pomaz.szeredi.hu>
+From: Miklos Szeredi <miklos@szeredi.hu>
+Date: Tue, 11 Apr 2006 18:37:57 +0200
+Cc: 
+Subject: fuse: fix oops in fuse_send_readpages()
+
+During heavy parallel filesystem activity it was possible to Oops the
+kernel.  The reason is that read_cache_pages() could skip pages which
+have already been inserted into the cache by another task.
+Occasionally this may result in zero pages actually being sent, while
+fuse_send_readpages() relies on at least one page being in the
+request.
+
+So check this corner case and just free the request instead of trying
+to send it.
+
+Reported and tested by Konstantin Isakov.
+
+Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/fuse/file.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- linux-2.6.16.4.orig/fs/fuse/file.c
++++ linux-2.6.16.4/fs/fuse/file.c
+@@ -397,8 +397,12 @@ static int fuse_readpages(struct file *f
+               return -EINTR;
+       err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
+-      if (!err)
+-              fuse_send_readpages(data.req, file, inode);
++      if (!err) {
++              if (data.req->num_pages)
++                      fuse_send_readpages(data.req, file, inode);
++              else
++                      fuse_put_request(fc, data.req);
++      }
+       return err;
+ }
diff --git a/queue-2.6.16/m32r-fix-cpu_possible_map-and-cpu_present_map-initialization-for-smp-kernel.patch b/queue-2.6.16/m32r-fix-cpu_possible_map-and-cpu_present_map-initialization-for-smp-kernel.patch
new file mode 100644 (file)
index 0000000..59266a0
--- /dev/null
@@ -0,0 +1,153 @@
+From stable-bounces@linux.kernel.org Mon Apr 10 23:54:17 2006
+Message-Id: <200604110654.k3B6rxI6013633@shell0.pdx.osdl.net>
+To: torvalds@osdl.org
+From: akpm@osdl.org
+Date: Mon, 10 Apr 2006 22:53:18 -0700
+Cc: takata@linux-m32r.org, stable@kernel.org, fujiwara.hayato@renesas.com
+Subject: m32r: Fix cpu_possible_map and cpu_present_map initialization for SMP kernel
+
+
+From: Hirokazu Takata <takata@linux-m32r.org>
+
+This patch fixes a boot problem of the m32r SMP kernel 2.6.16-rc1-mm3 or
+later.
+
+In this patch, cpu_possible_map is statically initialized, and cpu_present_map
+is also copied from cpu_possible_map in smp_prepare_cpus(), because the m32r
+architecture has not supported CPU hotplug yet.
+
+Signed-off-by: Hayato Fujiwara <fujiwara.hayato@renesas.com>
+Signed-off-by: Hirokazu Takata <takata@linux-m32r.org>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/m32r/kernel/setup.c   |   12 +++++-------
+ arch/m32r/kernel/smpboot.c |   19 ++++++++++---------
+ include/asm-m32r/smp.h     |    3 ++-
+ 3 files changed, 17 insertions(+), 17 deletions(-)
+
+--- linux-2.6.16.4.orig/arch/m32r/kernel/setup.c
++++ linux-2.6.16.4/arch/m32r/kernel/setup.c
+@@ -9,6 +9,7 @@
+ #include <linux/config.h>
+ #include <linux/init.h>
++#include <linux/kernel.h>
+ #include <linux/stddef.h>
+ #include <linux/fs.h>
+ #include <linux/sched.h>
+@@ -218,8 +219,6 @@ static unsigned long __init setup_memory
+ extern unsigned long setup_memory(void);
+ #endif        /* CONFIG_DISCONTIGMEM */
+-#define M32R_PCC_PCATCR       0x00ef7014      /* will move to m32r.h */
+-
+ void __init setup_arch(char **cmdline_p)
+ {
+       ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
+@@ -268,15 +267,14 @@ void __init setup_arch(char **cmdline_p)
+       paging_init();
+ }
+-static struct cpu cpu[NR_CPUS];
++static struct cpu cpu_devices[NR_CPUS];
+ static int __init topology_init(void)
+ {
+-      int cpu_id;
++      int i;
+-      for (cpu_id = 0; cpu_id < NR_CPUS; cpu_id++)
+-              if (cpu_possible(cpu_id))
+-                      register_cpu(&cpu[cpu_id], cpu_id, NULL);
++      for_each_present_cpu(i)
++              register_cpu(&cpu_devices[i], i, NULL);
+       return 0;
+ }
+--- linux-2.6.16.4.orig/arch/m32r/kernel/smpboot.c
++++ linux-2.6.16.4/arch/m32r/kernel/smpboot.c
+@@ -39,8 +39,10 @@
+  *            Martin J. Bligh :       Added support for multi-quad systems
+  */
++#include <linux/module.h>
+ #include <linux/config.h>
+ #include <linux/init.h>
++#include <linux/kernel.h>
+ #include <linux/mm.h>
+ #include <linux/smp_lock.h>
+ #include <linux/irq.h>
+@@ -72,11 +74,15 @@ physid_mask_t phys_cpu_present_map;
+ /* Bitmask of currently online CPUs */
+ cpumask_t cpu_online_map;
++EXPORT_SYMBOL(cpu_online_map);
+ cpumask_t cpu_bootout_map;
+ cpumask_t cpu_bootin_map;
+-cpumask_t cpu_callout_map;
+ static cpumask_t cpu_callin_map;
++cpumask_t cpu_callout_map;
++EXPORT_SYMBOL(cpu_callout_map);
++cpumask_t cpu_possible_map = CPU_MASK_ALL;
++EXPORT_SYMBOL(cpu_possible_map);
+ /* Per CPU bogomips and other parameters */
+ struct cpuinfo_m32r cpu_data[NR_CPUS] __cacheline_aligned;
+@@ -110,7 +116,6 @@ static unsigned int calibration_result;
+ void smp_prepare_boot_cpu(void);
+ void smp_prepare_cpus(unsigned int);
+-static void smp_tune_scheduling(void);
+ static void init_ipi_lock(void);
+ static void do_boot_cpu(int);
+ int __cpu_up(unsigned int);
+@@ -177,6 +182,9 @@ void __init smp_prepare_cpus(unsigned in
+       }
+       for (phys_id = 0 ; phys_id < nr_cpu ; phys_id++)
+               physid_set(phys_id, phys_cpu_present_map);
++#ifndef CONFIG_HOTPLUG_CPU
++      cpu_present_map = cpu_possible_map;
++#endif
+       show_mp_info(nr_cpu);
+@@ -186,7 +194,6 @@ void __init smp_prepare_cpus(unsigned in
+        * Setup boot CPU information
+        */
+       smp_store_cpu_info(0); /* Final full version of the data */
+-      smp_tune_scheduling();
+       /*
+        * If SMP should be disabled, then really disable it!
+@@ -230,11 +237,6 @@ smp_done:
+       Dprintk("Boot done.\n");
+ }
+-static void __init smp_tune_scheduling(void)
+-{
+-      /* Nothing to do. */
+-}
+-
+ /*
+  * init_ipi_lock : Initialize IPI locks.
+  */
+@@ -629,4 +631,3 @@ static void __init unmap_cpu_to_physid(i
+       physid_2_cpu[phys_id] = -1;
+       cpu_2_physid[cpu_id] = -1;
+ }
+-
+--- linux-2.6.16.4.orig/include/asm-m32r/smp.h
++++ linux-2.6.16.4/include/asm-m32r/smp.h
+@@ -67,7 +67,8 @@ extern volatile int cpu_2_physid[NR_CPUS
+ #define raw_smp_processor_id()        (current_thread_info()->cpu)
+ extern cpumask_t cpu_callout_map;
+-#define cpu_possible_map cpu_callout_map
++extern cpumask_t cpu_possible_map;
++extern cpumask_t cpu_present_map;
+ static __inline__ int hard_smp_processor_id(void)
+ {
diff --git a/queue-2.6.16/m32r-security-fix-of-get-put-_user-macros.patch b/queue-2.6.16/m32r-security-fix-of-get-put-_user-macros.patch
new file mode 100644 (file)
index 0000000..9054cdd
--- /dev/null
@@ -0,0 +1,642 @@
+From stable-bounces@linux.kernel.org Mon Apr 10 23:54:24 2006
+Message-Id: <200604110654.k3B6s1lW013637@shell0.pdx.osdl.net>
+To: torvalds@osdl.org
+From: akpm@osdl.org
+Date: Mon, 10 Apr 2006 22:53:20 -0700
+Cc: takata@linux-m32r.org, gniibe@fsij.org, stable@kernel.org
+Subject: m32r: security fix of {get, put}_user macros
+
+
+From: Hirokazu Takata <takata@linux-m32r.org>
+
+Update {get,put}_user macros for m32r kernel.
+- Modify get_user to use __get_user_asm macro, instead of __get_user_x macro.
+- Remove arch/m32r/lib/{get,put}user.S.
+- Some cosmetic updates.
+
+I would like to thank NIIBE Yutaka for his reporting about the m32r kernel's
+security problem in {get,put}_user macros.
+
+There were no address checking for user space access in {get,put}_user macros.
+ ;-)
+
+Signed-off-by: Hirokazu Takata <takata@linux-m32r.org>
+Cc: NIIBE Yutaka <gniibe@fsij.org>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+
+ arch/m32r/kernel/m32r_ksyms.c |    4 
+ arch/m32r/lib/Makefile        |    4 
+ arch/m32r/lib/getuser.S       |   88 -------------
+ arch/m32r/lib/putuser.S       |   84 -------------
+ include/asm-m32r/uaccess.h    |  266 ++++++++++++++++++------------------------
+ 5 files changed, 117 insertions(+), 329 deletions(-)
+
+--- linux-2.6.16.4.orig/arch/m32r/kernel/m32r_ksyms.c
++++ linux-2.6.16.4/arch/m32r/kernel/m32r_ksyms.c
+@@ -38,10 +38,6 @@ EXPORT_SYMBOL(__udelay);
+ EXPORT_SYMBOL(__delay);
+ EXPORT_SYMBOL(__const_udelay);
+-EXPORT_SYMBOL(__get_user_1);
+-EXPORT_SYMBOL(__get_user_2);
+-EXPORT_SYMBOL(__get_user_4);
+-
+ EXPORT_SYMBOL(strpbrk);
+ EXPORT_SYMBOL(strstr);
+--- linux-2.6.16.4.orig/arch/m32r/lib/Makefile
++++ linux-2.6.16.4/arch/m32r/lib/Makefile
+@@ -2,6 +2,6 @@
+ # Makefile for M32R-specific library files..
+ #
+-lib-y  := checksum.o ashxdi3.o memset.o memcpy.o getuser.o \
+-        putuser.o delay.o strlen.o usercopy.o csum_partial_copy.o
++lib-y  := checksum.o ashxdi3.o memset.o memcpy.o \
++        delay.o strlen.o usercopy.o csum_partial_copy.o
+--- linux-2.6.16.4.orig/arch/m32r/lib/getuser.S
++++ /dev/null
+@@ -1,88 +0,0 @@
+-/*
+- * __get_user functions.
+- *
+- * (C) Copyright 2001 Hirokazu Takata
+- *
+- * These functions have a non-standard call interface
+- * to make them more efficient, especially as they
+- * return an error value in addition to the "real"
+- * return value.
+- */
+-
+-#include <linux/config.h>
+-
+-/*
+- * __get_user_X
+- *
+- * Inputs:    r0 contains the address
+- *
+- * Outputs:   r0 is error code (0 or -EFAULT)
+- *            r1 contains zero-extended value
+- *
+- * These functions should not modify any other registers,
+- * as they get called from within inline assembly.
+- */
+-
+-#ifdef CONFIG_ISA_DUAL_ISSUE
+-
+-      .text
+-      .balign 4
+-      .globl __get_user_1
+-__get_user_1:
+-1:    ldub    r1, @r0             ||  ldi     r0, #0
+-      jmp     r14
+-
+-      .balign 4
+-      .globl __get_user_2
+-__get_user_2:
+-2:    lduh    r1, @r0             ||  ldi     r0, #0
+-      jmp     r14
+-
+-      .balign 4
+-      .globl __get_user_4
+-__get_user_4:
+-3:    ld      r1, @r0             ||  ldi     r0, #0
+-      jmp     r14
+-
+-bad_get_user:
+-      ldi     r1, #0              ||  ldi     r0, #-14
+-      jmp     r14
+-
+-#else /* not CONFIG_ISA_DUAL_ISSUE */
+-
+-      .text
+-      .balign 4
+-      .globl __get_user_1
+-__get_user_1:
+-1:    ldub    r1, @r0
+-      ldi     r0, #0
+-      jmp     r14
+-
+-      .balign 4
+-      .globl __get_user_2
+-__get_user_2:
+-2:    lduh    r1, @r0
+-      ldi     r0, #0
+-      jmp     r14
+-
+-      .balign 4
+-      .globl __get_user_4
+-__get_user_4:
+-3:    ld      r1, @r0
+-      ldi     r0, #0
+-      jmp     r14
+-
+-bad_get_user:
+-      ldi     r1, #0
+-      ldi     r0, #-14
+-      jmp     r14
+-
+-#endif /* not CONFIG_ISA_DUAL_ISSUE */
+-
+-.section __ex_table,"a"
+-      .long 1b,bad_get_user
+-      .long 2b,bad_get_user
+-      .long 3b,bad_get_user
+-.previous
+-
+-      .end
+--- linux-2.6.16.4.orig/arch/m32r/lib/putuser.S
++++ /dev/null
+@@ -1,84 +0,0 @@
+-/*
+- * __put_user functions.
+- *
+- * (C) Copyright 1998 Linus Torvalds
+- * (C) Copyright 2001 Hirokazu Takata
+- *
+- * These functions have a non-standard call interface
+- * to make them more efficient.
+- */
+-
+-#include <linux/config.h>
+-
+-/*
+- * __put_user_X
+- *
+- * Inputs:    r0 contains the address
+- *            r1 contains the value
+- *
+- * Outputs:   r0 is error code (0 or -EFAULT)
+- *            r1 is corrupted (will contain "current_task").
+- *
+- * These functions should not modify any other registers,
+- * as they get called from within inline assembly.
+- */
+-
+-#ifdef CONFIG_ISA_DUAL_ISSUE
+-
+-      .text
+-      .balign 4
+-      .globl __put_user_1
+-__put_user_1:
+-1:    stb     r1, @r0             ||  ldi     r0, #0
+-      jmp     r14
+-
+-      .balign 4
+-      .globl __put_user_2
+-__put_user_2:
+-2:    sth     r1, @r0             ||  ldi     r0, #0
+-      jmp     r14
+-
+-      .balign 4
+-      .globl __put_user_4
+-__put_user_4:
+-3:    st      r1, @r0             ||  ldi     r0, #0
+-      jmp     r14
+-
+-bad_put_user:
+-      ldi     r0, #-14            ||  jmp     r14
+-
+-#else /* not CONFIG_ISA_DUAL_ISSUE */
+-
+-      .text
+-      .balign 4
+-      .globl __put_user_1
+-__put_user_1:
+-1:    stb     r1, @r0
+-      ldi     r0, #0
+-      jmp     r14
+-
+-      .balign 4
+-      .globl __put_user_2
+-__put_user_2:
+-2:    sth     r1, @r0
+-      ldi     r0, #0
+-      jmp     r14
+-
+-      .balign 4
+-      .globl __put_user_4
+-__put_user_4:
+-3:    st      r1, @r0
+-      ldi     r0, #0
+-      jmp     r14
+-
+-bad_put_user:
+-      ldi     r0, #-14
+-      jmp     r14
+-
+-#endif /* not CONFIG_ISA_DUAL_ISSUE */
+-
+-.section __ex_table,"a"
+-      .long 1b,bad_put_user
+-      .long 2b,bad_put_user
+-      .long 3b,bad_put_user
+-.previous
+--- linux-2.6.16.4.orig/include/asm-m32r/uaccess.h
++++ linux-2.6.16.4/include/asm-m32r/uaccess.h
+@@ -5,17 +5,9 @@
+  *  linux/include/asm-m32r/uaccess.h
+  *
+  *  M32R version.
+- *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
++ *    Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
+  */
+-#undef UACCESS_DEBUG
+-
+-#ifdef UACCESS_DEBUG
+-#define UAPRINTK(args...) printk(args)
+-#else
+-#define UAPRINTK(args...)
+-#endif /* UACCESS_DEBUG */
+-
+ /*
+  * User space memory access functions
+  */
+@@ -38,27 +30,29 @@
+ #define MAKE_MM_SEG(s)        ((mm_segment_t) { (s) })
+ #ifdef CONFIG_MMU
++
+ #define KERNEL_DS     MAKE_MM_SEG(0xFFFFFFFF)
+ #define USER_DS               MAKE_MM_SEG(PAGE_OFFSET)
+-#else
+-#define KERNEL_DS     MAKE_MM_SEG(0xFFFFFFFF)
+-#define USER_DS               MAKE_MM_SEG(0xFFFFFFFF)
+-#endif /* CONFIG_MMU */
+-
+ #define get_ds()      (KERNEL_DS)
+-#ifdef CONFIG_MMU
+ #define get_fs()      (current_thread_info()->addr_limit)
+ #define set_fs(x)     (current_thread_info()->addr_limit = (x))
+-#else
++
++#else /* not CONFIG_MMU */
++
++#define KERNEL_DS     MAKE_MM_SEG(0xFFFFFFFF)
++#define USER_DS               MAKE_MM_SEG(0xFFFFFFFF)
++#define get_ds()      (KERNEL_DS)
++
+ static inline mm_segment_t get_fs(void)
+ {
+-  return USER_DS;
++      return USER_DS;
+ }
+ static inline void set_fs(mm_segment_t s)
+ {
+ }
+-#endif /* CONFIG_MMU */
++
++#endif /* not CONFIG_MMU */
+ #define segment_eq(a,b)       ((a).seg == (b).seg)
+@@ -83,9 +77,9 @@ static inline void set_fs(mm_segment_t s
+               "       subx    %0, %0\n"                               \
+               "       cmpu    %4, %1\n"                               \
+               "       subx    %0, %5\n"                               \
+-              : "=&r"(flag), "=r"(sum)                                \
+-              : "1"(addr), "r"((int)(size)),                          \
+-                "r"(current_thread_info()->addr_limit.seg), "r"(0)    \
++              : "=&r" (flag), "=r" (sum)                              \
++              : "1" (addr), "r" ((int)(size)),                        \
++                "r" (current_thread_info()->addr_limit.seg), "r" (0)  \
+               : "cbit" );                                             \
+       flag; })
+@@ -113,10 +107,10 @@ static inline void set_fs(mm_segment_t s
+ #else
+ static inline int access_ok(int type, const void *addr, unsigned long size)
+ {
+-  extern unsigned long memory_start, memory_end;
+-  unsigned long val = (unsigned long)addr;
++      extern unsigned long memory_start, memory_end;
++      unsigned long val = (unsigned long)addr;
+-  return ((val >= memory_start) && ((val + size) < memory_end));
++      return ((val >= memory_start) && ((val + size) < memory_end));
+ }
+ #endif /* CONFIG_MMU */
+@@ -155,39 +149,6 @@ extern int fixup_exception(struct pt_reg
+  * accesses to the same area of user memory).
+  */
+-extern void __get_user_1(void);
+-extern void __get_user_2(void);
+-extern void __get_user_4(void);
+-
+-#ifndef MODULE
+-#define __get_user_x(size,ret,x,ptr)                                  \
+-      __asm__ __volatile__(                                           \
+-              "       mv      r0, %0\n"                               \
+-              "       mv      r1, %1\n"                               \
+-              "       bl __get_user_" #size "\n"                      \
+-              "       mv      %0, r0\n"                               \
+-              "       mv      %1, r1\n"                               \
+-              : "=r"(ret), "=r"(x)                                    \
+-              : "0"(ptr)                                              \
+-              : "r0", "r1", "r14" )
+-#else /* MODULE */
+-/*
+- * Use "jl" instead of "bl" for MODULE
+- */
+-#define __get_user_x(size,ret,x,ptr)                                  \
+-      __asm__ __volatile__(                                           \
+-              "       mv      r0, %0\n"                               \
+-              "       mv      r1, %1\n"                               \
+-              "       seth    lr, #high(__get_user_" #size ")\n"      \
+-              "       or3     lr, lr, #low(__get_user_" #size ")\n"   \
+-              "       jl      lr\n"                                   \
+-              "       mv      %0, r0\n"                               \
+-              "       mv      %1, r1\n"                               \
+-              : "=r"(ret), "=r"(x)                                    \
+-              : "0"(ptr)                                              \
+-              : "r0", "r1", "r14" )
+-#endif
+-
+ /* Careful: we have to cast the result to the type of the pointer for sign
+    reasons */
+ /**
+@@ -208,20 +169,7 @@ extern void __get_user_4(void);
+  * On error, the variable @x is set to zero.
+  */
+ #define get_user(x,ptr)                                                       \
+-({    int __ret_gu;                                                   \
+-      unsigned long __val_gu;                                         \
+-      __chk_user_ptr(ptr);                                            \
+-      switch(sizeof (*(ptr))) {                                       \
+-      case 1:  __get_user_x(1,__ret_gu,__val_gu,ptr); break;          \
+-      case 2:  __get_user_x(2,__ret_gu,__val_gu,ptr); break;          \
+-      case 4:  __get_user_x(4,__ret_gu,__val_gu,ptr); break;          \
+-      default: __get_user_x(X,__ret_gu,__val_gu,ptr); break;          \
+-      }                                                               \
+-      (x) = (__typeof__(*(ptr)))__val_gu;                             \
+-      __ret_gu;                                                       \
+-})
+-
+-extern void __put_user_bad(void);
++      __get_user_check((x),(ptr),sizeof(*(ptr)))
+ /**
+  * put_user: - Write a simple value into user space.
+@@ -240,8 +188,7 @@ extern void __put_user_bad(void);
+  * Returns zero on success, or -EFAULT on error.
+  */
+ #define put_user(x,ptr)                                                       \
+-  __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+-
++      __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+ /**
+  * __get_user: - Get a simple variable from user space, with less checking.
+@@ -264,8 +211,64 @@ extern void __put_user_bad(void);
+  * On error, the variable @x is set to zero.
+  */
+ #define __get_user(x,ptr) \
+-  __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
++      __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
++#define __get_user_nocheck(x,ptr,size)                                        \
++({                                                                    \
++      long __gu_err = 0;                                              \
++      unsigned long __gu_val;                                         \
++      might_sleep();                                                  \
++      __get_user_size(__gu_val,(ptr),(size),__gu_err);                \
++      (x) = (__typeof__(*(ptr)))__gu_val;                             \
++      __gu_err;                                                       \
++})
++
++#define __get_user_check(x,ptr,size)                                  \
++({                                                                    \
++      long __gu_err = -EFAULT;                                        \
++      unsigned long __gu_val = 0;                                     \
++      const __typeof__(*(ptr)) __user *__gu_addr = (ptr);             \
++      might_sleep();                                                  \
++      if (access_ok(VERIFY_READ,__gu_addr,size))                      \
++              __get_user_size(__gu_val,__gu_addr,(size),__gu_err);    \
++      (x) = (__typeof__(*(ptr)))__gu_val;                             \
++      __gu_err;                                                       \
++})
++
++extern long __get_user_bad(void);
++
++#define __get_user_size(x,ptr,size,retval)                            \
++do {                                                                  \
++      retval = 0;                                                     \
++      __chk_user_ptr(ptr);                                            \
++      switch (size) {                                                 \
++        case 1: __get_user_asm(x,ptr,retval,"ub"); break;             \
++        case 2: __get_user_asm(x,ptr,retval,"uh"); break;             \
++        case 4: __get_user_asm(x,ptr,retval,""); break;               \
++        default: (x) = __get_user_bad();                              \
++      }                                                               \
++} while (0)
++
++#define __get_user_asm(x, addr, err, itype)                           \
++      __asm__ __volatile__(                                           \
++              "       .fillinsn\n"                                    \
++              "1:     ld"itype" %1,@%2\n"                             \
++              "       .fillinsn\n"                                    \
++              "2:\n"                                                  \
++              ".section .fixup,\"ax\"\n"                              \
++              "       .balign 4\n"                                    \
++              "3:     ldi %0,%3\n"                                    \
++              "       seth r14,#high(2b)\n"                           \
++              "       or3 r14,r14,#low(2b)\n"                         \
++              "       jmp r14\n"                                      \
++              ".previous\n"                                           \
++              ".section __ex_table,\"a\"\n"                           \
++              "       .balign 4\n"                                    \
++              "       .long 1b,3b\n"                                  \
++              ".previous"                                             \
++              : "=&r" (err), "=&r" (x)                                \
++              : "r" (addr), "i" (-EFAULT), "0" (err)                  \
++              : "r14", "memory")
+ /**
+  * __put_user: - Write a simple value into user space, with less checking.
+@@ -287,11 +290,13 @@ extern void __put_user_bad(void);
+  * Returns zero on success, or -EFAULT on error.
+  */
+ #define __put_user(x,ptr) \
+-  __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
++      __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
++
+ #define __put_user_nocheck(x,ptr,size)                                        \
+ ({                                                                    \
+       long __pu_err;                                                  \
++      might_sleep();                                                  \
+       __put_user_size((x),(ptr),(size),__pu_err);                     \
+       __pu_err;                                                       \
+ })
+@@ -308,28 +313,28 @@ extern void __put_user_bad(void);
+ })
+ #if defined(__LITTLE_ENDIAN__)
+-#define __put_user_u64(x, addr, err)                                    \
+-        __asm__ __volatile__(                                           \
+-                "       .fillinsn\n"                                    \
+-                "1:     st %L1,@%2\n"                                    \
+-                "       .fillinsn\n"                                    \
+-                "2:     st %H1,@(4,%2)\n"                                \
+-                "       .fillinsn\n"                                    \
+-                "3:\n"                                                  \
+-                ".section .fixup,\"ax\"\n"                              \
+-                "       .balign 4\n"                                    \
+-                "4:     ldi %0,%3\n"                                    \
+-                "       seth r14,#high(3b)\n"                           \
+-                "       or3 r14,r14,#low(3b)\n"                         \
+-                "       jmp r14\n"                                      \
+-                ".previous\n"                                           \
+-                ".section __ex_table,\"a\"\n"                           \
+-                "       .balign 4\n"                                    \
+-                "       .long 1b,4b\n"                                  \
+-                "       .long 2b,4b\n"                                  \
+-                ".previous"                                             \
+-                : "=&r"(err)                                             \
+-                : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err)           \
++#define __put_user_u64(x, addr, err)                                  \
++        __asm__ __volatile__(                                         \
++                "       .fillinsn\n"                                  \
++                "1:     st %L1,@%2\n"                                 \
++                "       .fillinsn\n"                                  \
++                "2:     st %H1,@(4,%2)\n"                             \
++                "       .fillinsn\n"                                  \
++                "3:\n"                                                        \
++                ".section .fixup,\"ax\"\n"                            \
++                "       .balign 4\n"                                  \
++                "4:     ldi %0,%3\n"                                  \
++                "       seth r14,#high(3b)\n"                         \
++                "       or3 r14,r14,#low(3b)\n"                               \
++                "       jmp r14\n"                                    \
++                ".previous\n"                                         \
++                ".section __ex_table,\"a\"\n"                         \
++                "       .balign 4\n"                                  \
++                "       .long 1b,4b\n"                                        \
++                "       .long 2b,4b\n"                                        \
++                ".previous"                                           \
++                : "=&r" (err)                                         \
++                : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err)               \
+                 : "r14", "memory")
+ #elif defined(__BIG_ENDIAN__)
+@@ -353,13 +358,15 @@ extern void __put_user_bad(void);
+               "       .long 1b,4b\n"                                  \
+               "       .long 2b,4b\n"                                  \
+               ".previous"                                             \
+-              : "=&r"(err)                                            \
+-              : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err)             \
++              : "=&r" (err)                                           \
++              : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err)         \
+               : "r14", "memory")
+ #else
+ #error no endian defined
+ #endif
++extern void __put_user_bad(void);
++
+ #define __put_user_size(x,ptr,size,retval)                            \
+ do {                                                                  \
+       retval = 0;                                                     \
+@@ -398,52 +405,8 @@ struct __large_struct { unsigned long bu
+               "       .balign 4\n"                                    \
+               "       .long 1b,3b\n"                                  \
+               ".previous"                                             \
+-              : "=&r"(err)                                            \
+-              : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err)             \
+-              : "r14", "memory")
+-
+-#define __get_user_nocheck(x,ptr,size)                                        \
+-({                                                                    \
+-      long __gu_err;                                                  \
+-      unsigned long __gu_val;                                         \
+-      __get_user_size(__gu_val,(ptr),(size),__gu_err);                \
+-      (x) = (__typeof__(*(ptr)))__gu_val;                             \
+-      __gu_err;                                                       \
+-})
+-
+-extern long __get_user_bad(void);
+-
+-#define __get_user_size(x,ptr,size,retval)                            \
+-do {                                                                  \
+-      retval = 0;                                                     \
+-      __chk_user_ptr(ptr);                                            \
+-      switch (size) {                                                 \
+-        case 1: __get_user_asm(x,ptr,retval,"ub"); break;             \
+-        case 2: __get_user_asm(x,ptr,retval,"uh"); break;             \
+-        case 4: __get_user_asm(x,ptr,retval,""); break;               \
+-        default: (x) = __get_user_bad();                              \
+-      }                                                               \
+-} while (0)
+-
+-#define __get_user_asm(x, addr, err, itype)                           \
+-      __asm__ __volatile__(                                           \
+-              "       .fillinsn\n"                                    \
+-              "1:     ld"itype" %1,@%2\n"                             \
+-              "       .fillinsn\n"                                    \
+-              "2:\n"                                                  \
+-              ".section .fixup,\"ax\"\n"                              \
+-              "       .balign 4\n"                                    \
+-              "3:     ldi %0,%3\n"                                    \
+-              "       seth r14,#high(2b)\n"                           \
+-              "       or3 r14,r14,#low(2b)\n"                         \
+-              "       jmp r14\n"                                      \
+-              ".previous\n"                                           \
+-              ".section __ex_table,\"a\"\n"                           \
+-              "       .balign 4\n"                                    \
+-              "       .long 1b,3b\n"                                  \
+-              ".previous"                                             \
+-              : "=&r"(err), "=&r"(x)                                  \
+-              : "r"(addr), "i"(-EFAULT), "0"(err)                     \
++              : "=&r" (err)                                           \
++              : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err)         \
+               : "r14", "memory")
+ /*
+@@ -453,7 +416,6 @@ do {                                                                       \
+  * anything, so this is accurate.
+  */
+-
+ /*
+  * Copy To/From Userspace
+  */
+@@ -511,8 +473,9 @@ do {                                                                       \
+               "       .long 2b,9b\n"                                  \
+               "       .long 3b,9b\n"                                  \
+               ".previous\n"                                           \
+-              : "=&r"(__dst), "=&r"(__src), "=&r"(size), "=&r"(__c)   \
+-              : "0"(to), "1"(from), "2"(size), "3"(size / 4)          \
++              : "=&r" (__dst), "=&r" (__src), "=&r" (size),           \
++                "=&r" (__c)                                           \
++              : "0" (to), "1" (from), "2" (size), "3" (size / 4)      \
+               : "r14", "memory");                                     \
+ } while (0)
+@@ -573,8 +536,9 @@ do {                                                                       \
+               "       .long 2b,7b\n"                                  \
+               "       .long 3b,7b\n"                                  \
+               ".previous\n"                                           \
+-              : "=&r"(__dst), "=&r"(__src), "=&r"(size), "=&r"(__c)   \
+-              : "0"(to), "1"(from), "2"(size), "3"(size / 4)          \
++              : "=&r" (__dst), "=&r" (__src), "=&r" (size),           \
++                "=&r" (__c)                                           \
++              : "0" (to), "1" (from), "2" (size), "3" (size / 4)      \
+               : "r14", "memory");                                     \
+ } while (0)
+@@ -676,7 +640,7 @@ unsigned long __generic_copy_from_user(v
+ #define copy_from_user(to,from,n)                     \
+ ({                                                    \
+       might_sleep();                                  \
+-__generic_copy_from_user((to),(from),(n));    \
++      __generic_copy_from_user((to),(from),(n));      \
+ })
+ long __must_check strncpy_from_user(char *dst, const char __user *src,