From: Greg Kroah-Hartman Date: Wed, 12 Apr 2006 20:58:40 +0000 (-0700) Subject: more patches added to 2.6.16 queue X-Git-Tag: v2.6.16.6~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5e5242fde078f27478f3db41b565756c3696e7e8;p=thirdparty%2Fkernel%2Fstable-queue.git more patches added to 2.6.16 queue --- 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 index 00000000000..2c8dc83b82d --- /dev/null +++ b/queue-2.6.16/RLIMIT_CPU-fix-handling-of-a-zero-limit.patch @@ -0,0 +1,52 @@ +From nobody Mon Sep 17 00:00:00 2001 +From: Andrew Morton +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 +Cc: Ulrich Weigand +Cc: Cliff Wickman +Acked-by: Ingo Molnar +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds + +--- + + 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(¤t->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 index 00000000000..d373f03369b --- /dev/null +++ b/queue-2.6.16/XFS-Fix-utime-2-in-the-case-that-no-times-parameter-was-passed-in.patch @@ -0,0 +1,29 @@ +From nobody Mon Sep 17 00:00:00 2001 +From: Nathan Scott +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 +Signed-off-by: Nathan Scott + +--- + + 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 index 00000000000..1dcb5e8df7f --- /dev/null +++ b/queue-2.6.16/alpha-smp-boot-fixes.patch @@ -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 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 + + - 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 +Cc: Richard Henderson +Cc: Ivan Kokshaysky +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman + +--- + 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 /* CONFIG_ALPHA_LCA etc */ + #include + #include ++#include + #include + #include + #include +@@ -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 index 00000000000..6b1b73d011e --- /dev/null +++ b/queue-2.6.16/cciss-bug-fix-for-crash-when-running-hpacucli.patch @@ -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" + +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 +Signed-off-by: Stephen Cameron +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman + +--- + 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; iHeader.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; iHeader.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 index 00000000000..7f6adf33cf9 --- /dev/null +++ b/queue-2.6.16/edac_752x-needs-config_hotplug.patch @@ -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 +To: stable@kernel.org +Message-ID: <20060410185424.GF2408@stusta.de> +Content-Disposition: inline +Cc: Randy Dunlap +Subject: edac_752x needs CONFIG_HOTPLUG + +From: Randy Dunlap + +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 +Signed-off-by: Adrian Bunk +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..1fe26770ca2 --- /dev/null +++ b/queue-2.6.16/ext3-fix-missed-mutex-unlock.patch @@ -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" + +Missed unlock_super()call is added in error condition code path. + +Signed-off-by: Leonid Ananiev +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..40d41a52205 --- /dev/null +++ b/queue-2.6.16/fix-block-device-symlink-name.patch @@ -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 + +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 +Cc: Al Viro +Cc: Christoph Hellwig +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman + + +--- + 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 index 00000000000..2501862b972 --- /dev/null +++ b/queue-2.6.16/fix-buddy-list-race-that-could-lead-to-page-lru-list-corruptions.patch @@ -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 +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 + +[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 +Signed-off-by: Rohit Seth +Signed-off-by: Nick Piggin +Signed-off-by: KAMEZAWA Hiroyuki +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..8314d8aa693 --- /dev/null +++ b/queue-2.6.16/fuse-fix-oops-in-fuse_send_readpages.patch @@ -0,0 +1,44 @@ +From stable-bounces@linux.kernel.org Tue Apr 11 09:38:51 2006 +To: stable@kernel.org +Message-Id: +From: Miklos Szeredi +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..59266a0b141 --- /dev/null +++ b/queue-2.6.16/m32r-fix-cpu_possible_map-and-cpu_present_map-initialization-for-smp-kernel.patch @@ -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 + +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 +Signed-off-by: Hirokazu Takata +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman + +--- + 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 + #include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + #include + #include + #include +@@ -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 index 00000000000..9054cdd23ca --- /dev/null +++ b/queue-2.6.16/m32r-security-fix-of-get-put-_user-macros.patch @@ -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 + +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 +Cc: NIIBE Yutaka +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + + 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 +- +-/* +- * __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 +- +-/* +- * __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 ++ * Copyright (C) 2004, 2006 Hirokazu Takata + */ + +-#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,