summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@nuts.ninka.net>2003-07-20 08:52:43 -0700
committerDavid S. Miller <davem@nuts.ninka.net>2003-07-20 08:52:43 -0700
commit764cf56e6ddb2a5ed92b73cf6e0b71f611302273 (patch)
treee2a7855e76914435e3f91a16304b0b48590e919b
parentd7cd83673b6a522b47586cf8d09144caadcef396 (diff)
parent50692f8c6b6a27ffed9b5b7206ca6682a60ff354 (diff)
Merge nuts.ninka.net:/home/davem/src/BK/network-2.5
into nuts.ninka.net:/home/davem/src/BK/net-2.5
-rw-r--r--arch/i386/kernel/setup.c23
-rw-r--r--arch/i386/mm/init.c2
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c2
-rw-r--r--arch/sparc64/kernel/time.c4
-rw-r--r--arch/sparc64/lib/atomic.S23
-rw-r--r--arch/sparc64/mm/fault.c4
-rw-r--r--arch/sparc64/mm/init.c23
-rw-r--r--drivers/block/paride/pf.c3
-rw-r--r--drivers/char/istallion.c2
-rw-r--r--drivers/char/moxa.c5
-rw-r--r--drivers/char/nwbutton.h4
-rw-r--r--drivers/char/pcxx.c16
-rw-r--r--drivers/char/stallion.c2
-rw-r--r--drivers/char/watchdog/wdt977.c10
-rw-r--r--drivers/ieee1394/amdtp.c9
-rw-r--r--drivers/media/video/pms.c7
-rw-r--r--drivers/net/irda/vlsi_ir.c6
-rw-r--r--drivers/net/wan/comx-hw-comx.c9
-rw-r--r--drivers/net/wan/sdladrv.c13
-rw-r--r--drivers/net/wan/sdlamain.c12
-rw-r--r--drivers/net/wireless/ray_cs.c5
-rw-r--r--drivers/parisc/led.c8
-rw-r--r--drivers/sbus/char/envctrl.c33
-rw-r--r--drivers/telephony/ixj.c41
-rw-r--r--fs/devfs/base.c24
-rw-r--r--fs/lockd/clntlock.c9
-rw-r--r--fs/lockd/svc.c8
-rw-r--r--fs/nfsd/nfssvc.c8
-rw-r--r--fs/umsdos/ioctl.c15
-rw-r--r--fs/vfat/namei.c2
-rw-r--r--include/asm-generic/local.h118
-rw-r--r--include/asm-generic/percpu.h33
-rw-r--r--include/asm-generic/sections.h9
-rw-r--r--include/asm-i386/hw_irq.h5
-rw-r--r--include/asm-i386/local.h70
-rw-r--r--include/asm-sparc64/atomic.h23
-rw-r--r--include/asm-sparc64/local.h40
-rw-r--r--include/asm-sparc64/sections.h7
-rw-r--r--include/linux/module.h17
-rw-r--r--kernel/extable.c2
-rw-r--r--kernel/module.c22
-rw-r--r--kernel/profile.c5
42 files changed, 506 insertions, 177 deletions
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index d6dce76e594e..01a3990182c5 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -42,6 +42,7 @@
#include <asm/edd.h>
#include <asm/setup.h>
#include <asm/arch_hooks.h>
+#include <asm/sections.h>
#include "setup_arch_pre.h"
#include "mach_resources.h"
@@ -100,7 +101,7 @@ extern void early_cpu_init(void);
extern void dmi_scan_machine(void);
extern void generic_apic_probe(char *);
extern int root_mountflags;
-extern char _text, _etext, _edata, _end;
+extern char _end[];
unsigned long saved_videomode;
@@ -676,7 +677,7 @@ static unsigned long __init setup_memory(void)
* partially used pages are not usable - thus
* we are rounding upwards:
*/
- start_pfn = PFN_UP(__pa(&_end));
+ start_pfn = PFN_UP(__pa(_end));
find_max_pfn();
@@ -947,15 +948,15 @@ void __init setup_arch(char **cmdline_p)
if (!MOUNT_ROOT_RDONLY)
root_mountflags &= ~MS_RDONLY;
- init_mm.start_code = (unsigned long) &_text;
- init_mm.end_code = (unsigned long) &_etext;
- init_mm.end_data = (unsigned long) &_edata;
- init_mm.brk = (unsigned long) &_end;
-
- code_resource.start = virt_to_phys(&_text);
- code_resource.end = virt_to_phys(&_etext)-1;
- data_resource.start = virt_to_phys(&_etext);
- data_resource.end = virt_to_phys(&_edata)-1;
+ init_mm.start_code = (unsigned long) _text;
+ init_mm.end_code = (unsigned long) _etext;
+ init_mm.end_data = (unsigned long) _edata;
+ init_mm.brk = (unsigned long) _end;
+
+ code_resource.start = virt_to_phys(_text);
+ code_resource.end = virt_to_phys(_etext)-1;
+ data_resource.start = virt_to_phys(_etext);
+ data_resource.end = virt_to_phys(_edata)-1;
parse_cmdline_early(cmdline_p);
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index daba5d620477..d991c2e3debc 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -562,7 +562,7 @@ void free_initmem(void)
free_page(addr);
totalram_pages++;
}
- printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
+ printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (__init_end - __init_begin) >> 10);
}
#ifdef CONFIG_BLK_DEV_INITRD
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 2af4669e3396..2f01619bf8ad 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -176,6 +176,8 @@ EXPORT_SYMBOL(up);
/* Atomic counter implementation. */
EXPORT_SYMBOL(__atomic_add);
EXPORT_SYMBOL(__atomic_sub);
+EXPORT_SYMBOL(__atomic64_add);
+EXPORT_SYMBOL(__atomic64_sub);
#ifdef CONFIG_SMP
EXPORT_SYMBOL(atomic_dec_and_lock);
#endif
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 6aee8b7801ca..f4e9da69e146 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -41,6 +41,7 @@
#include <asm/isa.h>
#include <asm/starfire.h>
#include <asm/smp.h>
+#include <asm/sections.h>
spinlock_t mostek_lock = SPIN_LOCK_UNLOCKED;
spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
@@ -449,7 +450,6 @@ void sparc64_do_profile(struct pt_regs *regs)
return;
{
- extern int _stext;
extern int rwlock_impl_begin, rwlock_impl_end;
extern int atomic_impl_begin, atomic_impl_end;
extern int __memcpy_begin, __memcpy_end;
@@ -468,7 +468,7 @@ void sparc64_do_profile(struct pt_regs *regs)
pc < (unsigned long) &__bitops_end))
pc = o7;
- pc -= (unsigned long) &_stext;
+ pc -= (unsigned long) _stext;
pc >>= prof_shift;
if(pc >= prof_len)
diff --git a/arch/sparc64/lib/atomic.S b/arch/sparc64/lib/atomic.S
index 77be8b1f3e0c..13d68fd64d95 100644
--- a/arch/sparc64/lib/atomic.S
+++ b/arch/sparc64/lib/atomic.S
@@ -33,4 +33,27 @@ __atomic_sub: /* %o0 = increment, %o1 = atomic_ptr */
membar #StoreLoad | #StoreStore
retl
sub %g7, %o0, %o0
+
+ .globl __atomic64_add
+__atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
+ ldx [%o1], %g5
+ add %g5, %o0, %g7
+ casx [%o1], %g5, %g7
+ cmp %g5, %g7
+ bne,pn %xcc, __atomic64_add
+ membar #StoreLoad | #StoreStore
+ retl
+ add %g7, %o0, %o0
+
+ .globl __atomic64_sub
+__atomic64_sub: /* %o0 = increment, %o1 = atomic_ptr */
+ ldx [%o1], %g5
+ sub %g5, %o0, %g7
+ casx [%o1], %g5, %g7
+ cmp %g5, %g7
+ bne,pn %xcc, __atomic64_sub
+ membar #StoreLoad | #StoreStore
+ retl
+ sub %g7, %o0, %o0
+
atomic_impl_end:
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index e0a9cc52b831..348f206f0663 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -26,6 +26,7 @@
#include <asm/uaccess.h>
#include <asm/asi.h>
#include <asm/lsu.h>
+#include <asm/sections.h>
#define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0]))
@@ -320,10 +321,9 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs)
if (regs->tstate & TSTATE_PRIV) {
unsigned long tpc = regs->tpc;
- extern unsigned int _etext;
/* Sanity check the PC. */
- if ((tpc >= KERNBASE && tpc < (unsigned long) &_etext) ||
+ if ((tpc >= KERNBASE && tpc < (unsigned long) _etext) ||
(tpc >= MODULES_VADDR && tpc < MODULES_END)) {
/* Valid, no problems... */
} else {
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 3f25da91293f..6127d73d1e8e 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -35,6 +35,7 @@
#include <asm/starfire.h>
#include <asm/tlb.h>
#include <asm/spitfire.h>
+#include <asm/sections.h>
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
@@ -54,8 +55,8 @@ unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1;
#define CTX_BMAP_SLOTS (1UL << (CTX_VERSION_SHIFT - 6))
unsigned long mmu_context_bmap[CTX_BMAP_SLOTS];
-/* References to section boundaries */
-extern char __init_begin, __init_end, _start, _end, etext, edata;
+/* References to special section boundaries */
+extern char _start[], _end[];
/* Initial ramdisk setup */
extern unsigned int sparc_ramdisk_image;
@@ -1331,7 +1332,7 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
* image. The kernel is hard mapped below PAGE_OFFSET in a
* 4MB locked TLB translation.
*/
- start_pfn = PAGE_ALIGN((unsigned long) &_end) -
+ start_pfn = PAGE_ALIGN((unsigned long) _end) -
((unsigned long) KERNBASE);
/* Adjust up to the physical address where the kernel begins. */
@@ -1347,7 +1348,7 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
#ifdef CONFIG_BLK_DEV_INITRD
/* Now have to check initial ramdisk, so that bootmap does not overwrite it */
if (sparc_ramdisk_image) {
- if (sparc_ramdisk_image >= (unsigned long)&_end - 2 * PAGE_SIZE)
+ if (sparc_ramdisk_image >= (unsigned long)_end - 2 * PAGE_SIZE)
sparc_ramdisk_image -= KERNBASE;
initrd_start = sparc_ramdisk_image + phys_base;
initrd_end = initrd_start + sparc_ramdisk_size;
@@ -1424,7 +1425,7 @@ void __init paging_init(void)
set_bit(0, mmu_context_bmap);
- real_end = (unsigned long)&_end;
+ real_end = (unsigned long)_end;
if ((real_end > ((unsigned long)KERNBASE + 0x400000)))
bigkernel = 1;
#ifdef CONFIG_BLK_DEV_INITRD
@@ -1716,7 +1717,7 @@ void __init mem_init(void)
memset(sparc64_valid_addr_bitmap, 0, i << 3);
addr = PAGE_OFFSET + phys_base;
- last = PAGE_ALIGN((unsigned long)&_end) -
+ last = PAGE_ALIGN((unsigned long)_end) -
((unsigned long) KERNBASE);
last += PAGE_OFFSET + phys_base;
while (addr < last) {
@@ -1743,11 +1744,11 @@ void __init mem_init(void)
SetPageReserved(mem_map_zero);
clear_page(page_address(mem_map_zero));
- codepages = (((unsigned long) &etext) - ((unsigned long)&_start));
+ codepages = (((unsigned long) _etext) - ((unsigned long) _start));
codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT;
- datapages = (((unsigned long) &edata) - ((unsigned long)&etext));
+ datapages = (((unsigned long) _edata) - ((unsigned long) _etext));
datapages = PAGE_ALIGN(datapages) >> PAGE_SHIFT;
- initpages = (((unsigned long) &__init_end) - ((unsigned long) &__init_begin));
+ initpages = (((unsigned long) __init_end) - ((unsigned long) __init_begin));
initpages = PAGE_ALIGN(initpages) >> PAGE_SHIFT;
#ifndef CONFIG_SMP
@@ -1810,8 +1811,8 @@ void free_initmem (void)
/*
* The init section is aligned to 8k in vmlinux.lds. Page align for >8k pagesizes.
*/
- addr = PAGE_ALIGN((unsigned long)(&__init_begin));
- initend = (unsigned long)(&__init_end) & PAGE_MASK;
+ addr = PAGE_ALIGN((unsigned long)(__init_begin));
+ initend = (unsigned long)(__init_end) & PAGE_MASK;
for (; addr < initend; addr += PAGE_SIZE) {
unsigned long page;
struct page *p;
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 421750488515..fb0d28ee9ea6 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -222,9 +222,6 @@ MODULE_PARM(drive3, "1-7i");
#define ATAPI_READ_10 0x28
#define ATAPI_WRITE_10 0x2a
-#ifdef MODULE
-void cleanup_module(void);
-#endif
static int pf_open(struct inode *inode, struct file *file);
static void do_pf_request(request_queue_t * q);
static int pf_ioctl(struct inode *inode, struct file *file,
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 58534683cd03..429fb2955573 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -650,8 +650,6 @@ static unsigned int stli_baudrates[] = {
*/
#ifdef MODULE
-int init_module(void);
-void cleanup_module(void);
static void stli_argbrds(void);
static int stli_parsebrd(stlconf_t *confp, char **argp);
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index f0b8aa4d1fc7..bf63034c0703 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -216,10 +216,7 @@ static struct timer_list moxaEmptyTimer[MAX_PORTS];
static struct semaphore moxaBuffSem;
int moxa_init(void);
-#ifdef MODULE
-int init_module(void);
-void cleanup_module(void);
-#endif
+
/*
* static functions:
*/
diff --git a/drivers/char/nwbutton.h b/drivers/char/nwbutton.h
index a59a045af441..91176b5097ab 100644
--- a/drivers/char/nwbutton.h
+++ b/drivers/char/nwbutton.h
@@ -32,10 +32,6 @@ int button_init (void);
int button_add_callback (void (*callback) (void), int count);
int button_del_callback (void (*callback) (void));
static void button_consume_callbacks (int bpcount);
-#ifdef MODULE
-int init_module (void);
-void cleanup_module (void);
-#endif /* MODULE */
#else /* Not compiling the driver itself */
diff --git a/drivers/char/pcxx.c b/drivers/char/pcxx.c
index 6789262c625e..430c3dd743e4 100644
--- a/drivers/char/pcxx.c
+++ b/drivers/char/pcxx.c
@@ -209,17 +209,9 @@ static void cleanup_board_resources(void)
#ifdef MODULE
-/*
- * pcxe_init() is our init_module():
- */
-#define pcxe_init init_module
-
-void cleanup_module(void);
-
-
/*****************************************************************************/
-void cleanup_module()
+static void pcxe_cleanup()
{
unsigned long flags;
@@ -240,6 +232,12 @@ void cleanup_module()
kfree(digi_channels);
restore_flags(flags);
}
+
+/*
+ * pcxe_init() is our init_module():
+ */
+module_init(pcxe_init);
+module_cleanup(pcxe_cleanup);
#endif
static inline struct channel *chan(register struct tty_struct *tty)
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index cc443e25168e..4f066afb3ba7 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -472,8 +472,6 @@ static unsigned int stl_baudrates[] = {
*/
#ifdef MODULE
-int init_module(void);
-void cleanup_module(void);
static void stl_argbrds(void);
static int stl_parsebrd(stlconf_t *confp, char **argp);
diff --git a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c
index fe58b5ff1d8e..4b81d1698e6a 100644
--- a/drivers/char/watchdog/wdt977.c
+++ b/drivers/char/watchdog/wdt977.c
@@ -16,6 +16,8 @@
* 19-Dec-2001 Woody Suwalski: Netwinder fixes, ioctl interface
* 06-Jan-2002 Woody Suwalski: For compatibility, convert all timeouts
* from minutes to seconds.
+ * 07-Jul-2003 Daniele Bellucci: Audit return code of misc_register in
+ * nwwatchdog_init.
*/
#include <linux/module.h>
@@ -343,12 +345,14 @@ static struct miscdevice wdt977_miscdev=
static int __init nwwatchdog_init(void)
{
+ int retval;
if (!machine_is_netwinder())
return -ENODEV;
- misc_register(&wdt977_miscdev);
- printk(KERN_INFO "Wdt977 Watchdog sleeping.\n");
- return 0;
+ retval = misc_register(&wdt977_miscdev);
+ if (!retval)
+ printk(KERN_INFO "Wdt977 Watchdog sleeping.\n");
+ return retval;
}
static void __exit nwwatchdog_exit(void)
diff --git a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c
index 524c66f2597c..a947de74a926 100644
--- a/drivers/ieee1394/amdtp.c
+++ b/drivers/ieee1394/amdtp.c
@@ -62,6 +62,12 @@
* - Maybe make an ALSA interface, that is, create a file_ops
* implementation that recognizes ALSA ioctls and uses defaults for
* things that can't be controlled through ALSA (iso channel).
+ *
+ * Changes:
+ *
+ * - Audit copy_from_user in amdtp_write.
+ * Daniele Bellucci <bellucda@tiscali.it>
+ *
*/
#include <linux/module.h>
@@ -1112,7 +1118,8 @@ static ssize_t amdtp_write(struct file *file, const char *buffer, size_t count,
for (i = 0; i < count; i += length) {
p = buffer_put_bytes(s->input, count - i, &length);
- copy_from_user(p, buffer + i, length);
+ if (copy_from_user(p, buffer + i, length))
+ return -EFAULT;
if (s->input->length < s->input->size)
continue;
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c
index 952b0b9865e1..f8df5e1d669f 100644
--- a/drivers/media/video/pms.c
+++ b/drivers/media/video/pms.c
@@ -12,6 +12,10 @@
* Most of this code is directly derived from his userspace driver.
* His driver works so send any reports to alan@redhat.com unless the
* userspace driver also doesn't work for you...
+ *
+ * Changes:
+ * 08/07/2003 Daniele Bellucci <bellucda@tiscali.it>
+ * - pms_capture: report back -EFAULT
*/
#include <linux/module.h>
@@ -659,7 +663,8 @@ static int pms_capture(struct pms_device *dev, char *buf, int rgb555, int count)
if(dt+len>count)
dt=count-len;
cnt += dev->height;
- copy_to_user(buf, tmp+32, dt);
+ if (copy_to_user(buf, tmp+32, dt))
+ return -EFAULT;
buf += dt;
len += dt;
}
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index a1074f660875..984afdd8dd0d 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -474,10 +474,8 @@ static ssize_t vlsi_proc_read(struct file *file, char *buf, size_t nbytes,
if (pos + nbytes > size)
nbytes = size - pos;
- if (!access_ok(VERIFY_WRITE, buf, nbytes))
- return -EINVAL;
-
- copy_to_user(buf, procdata->data + pos, nbytes);
+ if (copy_to_user(buf, procdata->data + pos, nbytes))
+ return -EFAULT;
*ppos += nbytes;
diff --git a/drivers/net/wan/comx-hw-comx.c b/drivers/net/wan/comx-hw-comx.c
index e57c8cf9dfca..17d797e727b1 100644
--- a/drivers/net/wan/comx-hw-comx.c
+++ b/drivers/net/wan/comx-hw-comx.c
@@ -11,6 +11,7 @@
*
* Contributors:
* Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 0.86
+ * Daniele Bellucci <bellucda@tiscali.it> - 0.87
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -42,9 +43,12 @@
* - printk cleanups
* Version 0.86 (00/08/15):
* - resource release on failure at COMX_init
+ *
+ * Version 0.87 (03/07/09)
+ * - audit copy_from_user in comxhw_write_proc
*/
-#define VERSION "0.86"
+#define VERSION "0.87"
#include <linux/module.h>
#include <linux/version.h>
@@ -1084,7 +1088,8 @@ static int comxhw_write_proc(struct file *file, const char *buffer,
if (hw->firmware->data) {
kfree(hw->firmware->data);
}
- copy_from_user(tmp + file->f_pos, buffer, count);
+ if (copy_from_user(tmp + file->f_pos, buffer, count))
+ return -EFAULT;
hw->firmware->len = entry->size = file->f_pos + count;
hw->firmware->data = tmp;
file->f_pos += count;
diff --git a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c
index b0e15cc9e3f9..5a4ceee9716f 100644
--- a/drivers/net/wan/sdladrv.c
+++ b/drivers/net/wan/sdladrv.c
@@ -160,10 +160,6 @@
/****** Function Prototypes *************************************************/
-/* Module entry points. These are called by the OS and must be public. */
-int init_module (void);
-void cleanup_module (void);
-
/* Hardware-specific functions */
static int sdla_detect (sdlahw_t* hw);
static int sdla_autodpm (sdlahw_t* hw);
@@ -325,11 +321,7 @@ static int pci_slot_ar[MAX_S514_CARDS];
* Context: process
*/
-#ifdef MODULE
-int init_module (void)
-#else
int sdladrv_init(void)
-#endif
{
int i=0;
@@ -354,9 +346,12 @@ int sdladrv_init(void)
* Module 'remove' entry point.
* o release all remaining system resources
*/
-void cleanup_module (void)
+static void sdladrv_cleanup(void)
{
}
+
+module_init(sdladrv_init);
+module_cleanup(sdladrv_cleanup);
#endif
/******* Kernel APIs ********************************************************/
diff --git a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c
index 173810a600e7..de695ac6ff6e 100644
--- a/drivers/net/wan/sdlamain.c
+++ b/drivers/net/wan/sdlamain.c
@@ -177,10 +177,6 @@ static void dbg_kfree(void * v, int line) {
extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int);
-/* Module entry points */
-int init_module (void);
-void cleanup_module (void);
-
/* WAN link driver entry points */
static int setup(struct wan_device* wandev, wandev_conf_t* conf);
static int shutdown(struct wan_device* wandev);
@@ -246,11 +242,7 @@ static int wanpipe_bh_critical=0;
* Context: process
*/
-#ifdef MODULE
-int init_module (void)
-#else
int wanpipe_init(void)
-#endif
{
int cnt, err = 0;
@@ -313,7 +305,7 @@ int wanpipe_init(void)
* o unregister all adapters from the WAN router
* o release all remaining system resources
*/
-void cleanup_module (void)
+static void wanpipe_cleanup(void)
{
int i;
@@ -329,6 +321,8 @@ void cleanup_module (void)
printk(KERN_INFO "\nwanpipe: WANPIPE Modules Unloaded.\n");
}
+module_init(wanpipe_init);
+module_exit(wanpipe_cleanup);
#endif
/******* WAN Device Driver Entry Points *************************************/
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 83630b0e59b5..a73dcffa4957 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -25,6 +25,8 @@
* - reorganize kmallocs in ray_attach, checking all for failure
* and releasing the previous allocations if one fails
*
+ * Daniele Bellucci <bellucda@tiscali.it> - 07/10/2003
+ * - Audit copy_to_user in ioctl(SIOCGIWESSID)
*
=============================================================================*/
@@ -1315,7 +1317,8 @@ static int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
/* Push it out ! */
wrq->u.data.length = strlen(essid) + 1;
wrq->u.data.flags = 1; /* active */
- copy_to_user(wrq->u.data.pointer, essid, sizeof(essid));
+ if (copy_to_user(wrq->u.data.pointer, essid, sizeof(essid)))
+ err = -EFAULT;
}
break;
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 69a53774882d..d164351b4925 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -14,6 +14,10 @@
* TODO:
* - speed-up calculations with inlined assembler
* - interface to write to second row of LCD from /proc (if technically possible)
+ *
+ * Changes:
+ * - Audit copy_from_user in led_proc_write.
+ * Daniele Bellucci <bellucda@tiscali.it>
*/
#include <linux/config.h>
@@ -160,7 +164,9 @@ static int led_proc_write(struct file *file, const char *buf,
memset(lbuf, 0, count);
- copy_from_user(lbuf, buf, count);
+ if (copy_from_user(lbuf, buf, count))
+ return -EFAULT;
+
cur = lbuf;
/* skip initial spaces */
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index ab8641e98b23..da05d2635f5e 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -14,6 +14,9 @@
*
* EB - Added support for CP1500 Global Address and PS/Voltage monitoring.
* Eric Brower <ebrower@usa.net>
+ *
+ * DB - Audit every copy_to_user in envctrl_read.
+ * Daniele Bellucci <bellucda@tiscali.it>
*/
#include <linux/config.h>
@@ -571,7 +574,8 @@ envctrl_read(struct file *file, char *buf, size_t count, loff_t *ppos)
data[0] = (unsigned char)(warning_temperature);
ret = 1;
- copy_to_user((unsigned char *)buf, data, ret);
+ if (copy_to_user((unsigned char *)buf, data, ret))
+ ret = -EFAULT;
break;
case ENVCTRL_RD_SHUTDOWN_TEMPERATURE:
@@ -580,14 +584,16 @@ envctrl_read(struct file *file, char *buf, size_t count, loff_t *ppos)
data[0] = (unsigned char)(shutdown_temperature);
ret = 1;
- copy_to_user((unsigned char *)buf, data, ret);
+ if (copy_to_user((unsigned char *)buf, data, ret))
+ ret = -EFAULT;
break;
case ENVCTRL_RD_MTHRBD_TEMPERATURE:
if (!(pchild = envctrl_get_i2c_child(ENVCTRL_MTHRBDTEMP_MON)))
return 0;
ret = envctrl_read_noncpu_info(pchild, ENVCTRL_MTHRBDTEMP_MON, data);
- copy_to_user((unsigned char *)buf, data, ret);
+ if (copy_to_user((unsigned char *)buf, data, ret))
+ ret = -EFAULT;
break;
case ENVCTRL_RD_CPU_TEMPERATURE:
@@ -596,7 +602,8 @@ envctrl_read(struct file *file, char *buf, size_t count, loff_t *ppos)
ret = envctrl_read_cpu_info(read_cpu, pchild, ENVCTRL_CPUTEMP_MON, data);
/* Reset cpu to the default cpu0. */
- copy_to_user((unsigned char *)buf, data, ret);
+ if (copy_to_user((unsigned char *)buf, data, ret))
+ ret = -EFAULT;
break;
case ENVCTRL_RD_CPU_VOLTAGE:
@@ -605,21 +612,24 @@ envctrl_read(struct file *file, char *buf, size_t count, loff_t *ppos)
ret = envctrl_read_cpu_info(read_cpu, pchild, ENVCTRL_CPUVOLTAGE_MON, data);
/* Reset cpu to the default cpu0. */
- copy_to_user((unsigned char *)buf, data, ret);
+ if (copy_to_user((unsigned char *)buf, data, ret))
+ ret = -EFAULT;
break;
case ENVCTRL_RD_SCSI_TEMPERATURE:
if (!(pchild = envctrl_get_i2c_child(ENVCTRL_SCSITEMP_MON)))
return 0;
ret = envctrl_read_noncpu_info(pchild, ENVCTRL_SCSITEMP_MON, data);
- copy_to_user((unsigned char *)buf, data, ret);
+ if (copy_to_user((unsigned char *)buf, data, ret))
+ ret = -EFAULT;
break;
case ENVCTRL_RD_ETHERNET_TEMPERATURE:
if (!(pchild = envctrl_get_i2c_child(ENVCTRL_ETHERTEMP_MON)))
return 0;
ret = envctrl_read_noncpu_info(pchild, ENVCTRL_ETHERTEMP_MON, data);
- copy_to_user((unsigned char *)buf, data, ret);
+ if (copy_to_user((unsigned char *)buf, data, ret))
+ ret = -EFAULT;
break;
case ENVCTRL_RD_FAN_STATUS:
@@ -627,7 +637,8 @@ envctrl_read(struct file *file, char *buf, size_t count, loff_t *ppos)
return 0;
data[0] = envctrl_i2c_read_8574(pchild->addr);
ret = envctrl_i2c_fan_status(pchild,data[0], data);
- copy_to_user((unsigned char *)buf, data, ret);
+ if (copy_to_user((unsigned char *)buf, data, ret))
+ ret = -EFAULT;
break;
case ENVCTRL_RD_GLOBALADDRESS:
@@ -635,7 +646,8 @@ envctrl_read(struct file *file, char *buf, size_t count, loff_t *ppos)
return 0;
data[0] = envctrl_i2c_read_8574(pchild->addr);
ret = envctrl_i2c_globaladdr(pchild, data[0], data);
- copy_to_user((unsigned char *)buf, data, ret);
+ if (copy_to_user((unsigned char *)buf, data, ret))
+ ret = -EFAULT;
break;
case ENVCTRL_RD_VOLTAGE_STATUS:
@@ -645,7 +657,8 @@ envctrl_read(struct file *file, char *buf, size_t count, loff_t *ppos)
return 0;
data[0] = envctrl_i2c_read_8574(pchild->addr);
ret = envctrl_i2c_voltage_status(pchild, data[0], data);
- copy_to_user((unsigned char *)buf, data, ret);
+ if (copy_to_user((unsigned char *)buf, data, ret))
+ ret = -EFAULT;
break;
default:
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index 74d68c51b957..f51308d086db 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -23,6 +23,7 @@
* Fixes: David Huggins-Daines, <dhd@cepstral.com>
* Fabio Ferrari, <fabio.ferrari@digitro.com.br>
* Artis Kugevics, <artis@mt.lv>
+ * Daniele Bellucci, <bellucda@tiscali.it>
*
* More information about the hardware related to this driver can be found
* at our website: http://www.quicknet.net
@@ -45,6 +46,10 @@ static char ixj_c_revision[] = "$Revision: 4.7 $";
/*
* $Log: ixj.c,v $
+ *
+ * Revision 4.8 2003/07/09 19:39:00 Daniele Bellucci
+ * Audit some copy_*_user and minor cleanup.
+ *
* Revision 4.7 2001/08/13 06:19:33 craigs
* Added additional changes from Alan Cox and John Anderson for
* 2.2 to 2.4 cleanup and bounds checking
@@ -363,12 +368,9 @@ static IXJ ixj[IXJMAX];
static IXJ *ixj_alloc(void)
{
int cnt;
- for(cnt=0; cnt<IXJMAX; cnt++)
- {
+ for(cnt=0; cnt<IXJMAX; cnt++) {
if(!ixj[cnt].DSPbase)
- {
return &ixj[cnt];
- }
}
return NULL;
}
@@ -6260,9 +6262,11 @@ static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd,
break;
case IXJCTL_CIDCW:
if(arg) {
- copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID));
- }
- else {
+ if (copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID))) {
+ retval = -EFAULT;
+ break;
+ }
+ } else {
memset(&j->cid_send, 0, sizeof(PHONE_CID));
}
ixj_write_cidcw(j);
@@ -6273,14 +6277,12 @@ static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd,
/* Fall through */
case PHONE_RING_START:
if(arg) {
- if(copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID)))
- {
+ if (copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID))) {
retval = -EFAULT;
break;
}
ixj_write_cid(j);
- }
- else {
+ } else {
memset(&j->cid_send, 0, sizeof(PHONE_CID));
}
ixj_ring_start(j);
@@ -6696,7 +6698,8 @@ static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd,
case IXJCTL_SET_FILTER_RAW:
if (copy_from_user(&jfr, (char *) arg, sizeof(jfr)))
retval = -EFAULT;
- retval = ixj_init_filter_raw(j, &jfr);
+ else
+ retval = ixj_init_filter_raw(j, &jfr);
break;
case IXJCTL_GET_FILTER_HIST:
if(arg<0||arg>3)
@@ -6705,8 +6708,10 @@ static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd,
retval = j->filter_hist[arg];
break;
case IXJCTL_INIT_TONE:
- copy_from_user(&ti, (char *) arg, sizeof(ti));
- retval = ixj_init_tone(j, &ti);
+ if (copy_from_user(&ti, (char *) arg, sizeof(ti)))
+ retval = -EFAULT;
+ else
+ retval = ixj_init_tone(j, &ti);
break;
case IXJCTL_TONE_CADENCE:
retval = ixj_build_cadence(j, (IXJ_CADENCE *) arg);
@@ -6715,8 +6720,10 @@ static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd,
retval = ixj_build_filter_cadence(j, (IXJ_FILTER_CADENCE *) arg);
break;
case IXJCTL_SIGCTL:
- if (copy_from_user(&j->sigdef, (char *)arg, sizeof(IXJ_SIGDEF)))
+ if (copy_from_user(&j->sigdef, (char *)arg, sizeof(IXJ_SIGDEF))) {
retval = -EFAULT;
+ break;
+ }
j->ixj_signals[j->sigdef.event] = j->sigdef.signal;
if(j->sigdef.event < 33) {
raise = 1;
@@ -7693,7 +7700,7 @@ MODULE_DESCRIPTION("Quicknet VoIP Telephony card module - www.quicknet.net");
MODULE_AUTHOR("Ed Okerson <eokerson@quicknet.net>");
MODULE_LICENSE("GPL");
-void ixj_exit(void)
+static void __exit ixj_exit(void)
{
cleanup();
}
@@ -7852,7 +7859,7 @@ int __init ixj_probe_pci(int *cnt)
return probe;
}
-int __init ixj_init(void)
+static int __init ixj_init(void)
{
int cnt = 0;
int probe = 0;
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
index 54a3e5a9dc49..060f20ef11f1 100644
--- a/fs/devfs/base.c
+++ b/fs/devfs/base.c
@@ -1445,12 +1445,6 @@ int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...)
va_list args;
int error, n;
- if (!S_ISBLK(mode)) {
- printk(KERN_WARNING "%s: invalide mode (%u) for %s\n",
- __FUNCTION__, mode, buf);
- return -EINVAL;
- }
-
va_start(args, fmt);
n = vsnprintf(buf, 64, fmt, args);
if (n >= 64 || !buf[0]) {
@@ -1458,6 +1452,12 @@ int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...)
__FUNCTION__);
return -EINVAL;
}
+
+ if (!S_ISBLK(mode)) {
+ printk(KERN_WARNING "%s: invalide mode (%u) for %s\n",
+ __FUNCTION__, mode, buf);
+ return -EINVAL;
+ }
de = _devfs_prepare_leaf(&dir, buf, mode);
if (!de) {
@@ -1491,12 +1491,6 @@ int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...)
va_list args;
int error, n;
- if (!S_ISCHR(mode)) {
- printk(KERN_WARNING "%s: invalide mode (%u) for %s\n",
- __FUNCTION__, mode, buf);
- return -EINVAL;
- }
-
va_start(args, fmt);
n = vsnprintf(buf, 64, fmt, args);
if (n >= 64 || !buf[0]) {
@@ -1505,6 +1499,12 @@ int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...)
return -EINVAL;
}
+ if (!S_ISCHR(mode)) {
+ printk(KERN_WARNING "%s: invalide mode (%u) for %s\n",
+ __FUNCTION__, mode, buf);
+ return -EINVAL;
+ }
+
de = _devfs_prepare_leaf(&dir, buf, mode);
if (!de) {
printk(KERN_WARNING "%s: could not prepare leaf for %s\n",
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index 6f3f77110ead..14f12cc1ad8f 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -187,8 +187,9 @@ nlmclnt_recovery(struct nlm_host *host, u32 newstate)
} else {
nlmclnt_prepare_reclaim(host, newstate);
nlm_get_host(host);
- MOD_INC_USE_COUNT;
- kernel_thread(reclaimer, host, CLONE_KERNEL);
+ __module_get(THIS_MODULE);
+ if (kernel_thread(reclaimer, host, CLONE_KERNEL))
+ module_put(THIS_MODULE);
}
}
@@ -244,7 +245,5 @@ restart:
nlm_release_host(host);
lockd_down();
unlock_kernel();
- MOD_DEC_USE_COUNT;
-
- return 0;
+ module_put_and_exit(0);
}
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 0bf32fd74efc..63b8f1062092 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -88,7 +88,11 @@ lockd(struct svc_rqst *rqstp)
unsigned long grace_period_expire;
/* Lock module and set up kernel thread */
- MOD_INC_USE_COUNT;
+ /* lockd_up is waiting for us to startup, so will
+ * be holding a reference to this module, so it
+ * is safe to just claim another reference
+ */
+ __module_get(THIS_MODULE);
lock_kernel();
/*
@@ -183,7 +187,7 @@ lockd(struct svc_rqst *rqstp)
/* Release module */
unlock_kernel();
- MOD_DEC_USE_COUNT;
+ module_put_and_exit(0);
}
/*
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 1ba9f02f63e6..b783620ff9dd 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -116,9 +116,12 @@ nfsd_svc(unsigned short port, int nrservs)
nrservs -= (nfsd_serv->sv_nrthreads-1);
while (nrservs > 0) {
nrservs--;
+ __module_get(THIS_MODULE);
error = svc_create_thread(nfsd, nfsd_serv);
- if (error < 0)
+ if (error < 0) {
+ module_put(THIS_MODULE);
break;
+ }
}
victim = nfsd_list.next;
while (nrservs < 0 && victim != &nfsd_list) {
@@ -175,7 +178,6 @@ nfsd(struct svc_rqst *rqstp)
sigset_t shutdown_mask, allowed_mask;
/* Lock module and set up kernel thread */
- MOD_INC_USE_COUNT;
lock_kernel();
daemonize("nfsd");
current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
@@ -281,7 +283,7 @@ out:
svc_exit_thread(rqstp);
/* Release module */
- MOD_DEC_USE_COUNT;
+ module_put_and_exit(0);
}
int
diff --git a/fs/umsdos/ioctl.c b/fs/umsdos/ioctl.c
index 323c2dbcccd0..fc300030afd1 100644
--- a/fs/umsdos/ioctl.c
+++ b/fs/umsdos/ioctl.c
@@ -4,6 +4,10 @@
* Written 1993 by Jacques Gelinas
*
* Extended MS-DOS ioctl directory handling functions
+ *
+ * Changes:
+ * 11/07/2003 Daniele Bellucci <bellucda@tiscali.it>
+ * - audit copy_to_user/put_user in umsdos_ioctl_fill.
*/
#include <asm/uaccess.h>
@@ -36,11 +40,12 @@ static int umsdos_ioctl_fill (
struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *) buf;
if (d->count == 0) {
- copy_to_user (d->ent->d_name, name, name_len);
- put_user ('\0', d->ent->d_name + name_len);
- put_user (name_len, &d->ent->d_reclen);
- put_user (ino, &d->ent->d_ino);
- put_user (offset, &d->ent->d_off);
+ if (copy_to_user (d->ent->d_name, name, name_len) ||
+ put_user ('\0', d->ent->d_name + name_len) ||
+ put_user (name_len, &d->ent->d_reclen) ||
+ put_user (ino, &d->ent->d_ino) ||
+ put_user (offset, &d->ent->d_off))
+ return -EFAULT;
d->count = 1;
ret = 0;
}
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 12c067c8355d..0a366b54e2c5 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -375,7 +375,7 @@ shortname_info_to_lcase(struct shortname_info *base,
}
static inline int to_shortname_char(struct nls_table *nls,
- char *buf, int buf_size, wchar_t *src,
+ unsigned char *buf, int buf_size, wchar_t *src,
struct shortname_info *info)
{
int len;
diff --git a/include/asm-generic/local.h b/include/asm-generic/local.h
new file mode 100644
index 000000000000..45c07dbc0a59
--- /dev/null
+++ b/include/asm-generic/local.h
@@ -0,0 +1,118 @@
+#ifndef _ASM_GENERIC_LOCAL_H
+#define _ASM_GENERIC_LOCAL_H
+
+#include <linux/config.h>
+#include <linux/percpu.h>
+#include <asm/types.h>
+#include <asm/hardirq.h>
+
+/* An unsigned long type for operations which are atomic for a single
+ * CPU. Usually used in combination with per-cpu variables. */
+
+#if BITS_PER_LONG == 32 && !defined(CONFIG_SPARC32)
+/* Implement in terms of atomics. */
+
+/* Don't use typedef: don't want them to be mixed with atomic_t's. */
+typedef struct
+{
+ atomic_t a;
+} local_t;
+
+#define LOCAL_INIT(i) { ATOMIC_INIT(i) }
+
+#define local_read(l) ((unsigned long)atomic_read(&(l)->a))
+#define local_set(l,i) atomic_set((&(l)->a),(i))
+#define local_inc(l) atomic_inc(&(l)->a)
+#define local_dec(l) atomic_dec(&(l)->a)
+#define local_add(i,l) atomic_add((i),(&(l)->a))
+#define local_sub(i,l) atomic_sub((i),(&(l)->a))
+
+/* Non-atomic variants, ie. preemption disabled and won't be touched
+ * in interrupt, etc. Some archs can optimize this case well. */
+#define __local_inc(l) local_set((l), local_read(l) + 1)
+#define __local_dec(l) local_set((l), local_read(l) - 1)
+#define __local_add(i,l) local_set((l), local_read(l) + (i))
+#define __local_sub(i,l) local_set((l), local_read(l) - (i))
+
+#else /* ... can't use atomics. */
+/* Implement in terms of three variables.
+ Another option would be to use local_irq_save/restore. */
+
+typedef struct
+{
+ /* 0 = in hardirq, 1 = in softirq, 2 = usermode. */
+ unsigned long v[3];
+} local_t;
+
+#define _LOCAL_VAR(l) ((l)->v[!in_interrupt() + !in_irq()])
+
+#define LOCAL_INIT(i) { { (i), 0, 0 } }
+
+static inline unsigned long local_read(local_t *l)
+{
+ return l->v[0] + l->v[1] + l->v[2];
+}
+
+static inline void local_set(local_t *l, unsigned long v)
+{
+ l->v[0] = v;
+ l->v[1] = l->v[2] = 0;
+}
+
+static inline void local_inc(local_t *l)
+{
+ preempt_disable();
+ _LOCAL_VAR(l)++;
+ preempt_enable();
+}
+
+static inline void local_dec(local_t *l)
+{
+ preempt_disable();
+ _LOCAL_VAR(l)--;
+ preempt_enable();
+}
+
+static inline void local_add(unsigned long v, local_t *l)
+{
+ preempt_disable();
+ _LOCAL_VAR(l) += v;
+ preempt_enable();
+}
+
+static inline void local_sub(unsigned long v, local_t *l)
+{
+ preempt_disable();
+ _LOCAL_VAR(l) -= v;
+ preempt_enable();
+}
+
+/* Non-atomic variants, ie. preemption disabled and won't be touched
+ * in interrupt, etc. Some archs can optimize this case well. */
+#define __local_inc(l) ((l)->v[0]++)
+#define __local_dec(l) ((l)->v[0]--)
+#define __local_add(i,l) ((l)->v[0] += (i))
+#define __local_sub(i,l) ((l)->v[0] -= (i))
+
+#endif /* Non-atomic implementation */
+
+/* Use these for per-cpu local_t variables: on some archs they are
+ * much more efficient than these naive implementations. Note they take
+ * a variable (eg. mystruct.foo), not an address.
+ */
+#define cpu_local_read(v) local_read(&__get_cpu_var(v))
+#define cpu_local_set(v, i) local_set(&__get_cpu_var(v), (i))
+#define cpu_local_inc(v) local_inc(&__get_cpu_var(v))
+#define cpu_local_dec(v) local_dec(&__get_cpu_var(v))
+#define cpu_local_add(i, v) local_add((i), &__get_cpu_var(v))
+#define cpu_local_sub(i, v) local_sub((i), &__get_cpu_var(v))
+
+/* Non-atomic increments, ie. preemption disabled and won't be touched
+ * in interrupt, etc. Some archs can optimize this case well.
+ */
+#define __cpu_local_inc(v) __local_inc(&__get_cpu_var(v))
+#define __cpu_local_dec(v) __local_dec(&__get_cpu_var(v))
+#define __cpu_local_add(i, v) __local_add((i), &__get_cpu_var(v))
+#define __cpu_local_sub(i, v) __local_sub((i), &__get_cpu_var(v))
+
+#endif /* _ASM_GENERIC_LOCAL_H */
diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
index f13b44926e6a..96d909da9ae7 100644
--- a/include/asm-generic/percpu.h
+++ b/include/asm-generic/percpu.h
@@ -9,33 +9,34 @@ extern unsigned long __per_cpu_offset[NR_CPUS];
/* Separate out the type, so (int[3], foo) works. */
#define DEFINE_PER_CPU(type, name) \
- __attribute__((__section__(".data.percpu"))) __typeof__(type) name##__per_cpu
+ __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name
/* var is in discarded region: offset to particular copy we want */
-#define per_cpu(var, cpu) (*RELOC_HIDE(&var##__per_cpu, __per_cpu_offset[cpu]))
+#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
#define __get_cpu_var(var) per_cpu(var, smp_processor_id())
-static inline void percpu_modcopy(void *pcpudst, const void *src,
- unsigned long size)
-{
- unsigned int i;
- for (i = 0; i < NR_CPUS; i++)
- if (cpu_possible(i))
- memcpy(pcpudst + __per_cpu_offset[i], src, size);
-}
+/* A macro to avoid #include hell... */
+#define percpu_modcopy(pcpudst, src, size) \
+do { \
+ unsigned int __i; \
+ for (__i = 0; __i < NR_CPUS; __i++) \
+ if (cpu_possible(__i)) \
+ memcpy((pcpudst)+__per_cpu_offset[__i], \
+ (src), (size)); \
+} while (0)
#else /* ! SMP */
#define DEFINE_PER_CPU(type, name) \
- __typeof__(type) name##__per_cpu
+ __typeof__(type) per_cpu__##name
-#define per_cpu(var, cpu) ((void)cpu, var##__per_cpu)
-#define __get_cpu_var(var) var##__per_cpu
+#define per_cpu(var, cpu) ((void)cpu, per_cpu__##var)
+#define __get_cpu_var(var) per_cpu__##var
#endif /* SMP */
-#define DECLARE_PER_CPU(type, name) extern __typeof__(type) name##__per_cpu
+#define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu__##name
-#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(var##__per_cpu)
-#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(var##__per_cpu)
+#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var)
+#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var)
#endif /* _ASM_GENERIC_PERCPU_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index fe290e3349be..ce400f39ba25 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -3,9 +3,10 @@
/* References to section boundaries */
-extern char _text, _etext;
-extern char _data, _edata;
-extern char __bss_start;
-extern char __init_begin, __init_end;
+extern char _text[], _stext[], _etext[];
+extern char _data[], _sdata[], _edata[];
+extern char __bss_start[];
+extern char __init_begin[], __init_end[];
+extern char _sinittext[], _einittext[];
#endif /* _ASM_GENERIC_SECTIONS_H_ */
diff --git a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h
index 30e4cfa8395b..eaee6b7cd24f 100644
--- a/include/asm-i386/hw_irq.h
+++ b/include/asm-i386/hw_irq.h
@@ -16,6 +16,7 @@
#include <linux/profile.h>
#include <asm/atomic.h>
#include <asm/irq.h>
+#include <asm/sections.h>
/*
* Various low-level irq details needed by irq.c, process.c,
@@ -63,8 +64,6 @@ extern unsigned long io_apic_irqs;
extern atomic_t irq_err_count;
extern atomic_t irq_mis_count;
-extern char _stext, _etext;
-
#define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
/*
@@ -95,7 +94,7 @@ static inline void x86_do_profile(struct pt_regs * regs)
if (!((1<<smp_processor_id()) & prof_cpu_mask))
return;
- eip -= (unsigned long) &_stext;
+ eip -= (unsigned long)_stext;
eip >>= prof_shift;
/*
* Don't ignore out-of-bounds EIP values silently,
diff --git a/include/asm-i386/local.h b/include/asm-i386/local.h
new file mode 100644
index 000000000000..0177da80dde3
--- /dev/null
+++ b/include/asm-i386/local.h
@@ -0,0 +1,70 @@
+#ifndef _ARCH_I386_LOCAL_H
+#define _ARCH_I386_LOCAL_H
+
+#include <linux/percpu.h>
+
+typedef struct
+{
+ volatile unsigned long counter;
+} local_t;
+
+#define LOCAL_INIT(i) { (i) }
+
+#define local_read(v) ((v)->counter)
+#define local_set(v,i) (((v)->counter) = (i))
+
+static __inline__ void local_inc(local_t *v)
+{
+ __asm__ __volatile__(
+ "incl %0"
+ :"=m" (v->counter)
+ :"m" (v->counter));
+}
+
+static __inline__ void local_dec(local_t *v)
+{
+ __asm__ __volatile__(
+ "decl %0"
+ :"=m" (v->counter)
+ :"m" (v->counter));
+}
+
+static __inline__ void local_add(unsigned long i, local_t *v)
+{
+ __asm__ __volatile__(
+ "addl %1,%0"
+ :"=m" (v->counter)
+ :"ir" (i), "m" (v->counter));
+}
+
+static __inline__ void local_sub(unsigned long i, local_t *v)
+{
+ __asm__ __volatile__(
+ "subl %1,%0"
+ :"=m" (v->counter)
+ :"ir" (i), "m" (v->counter));
+}
+
+/* On x86, these are no better than the atomic variants. */
+#define __local_inc(l) local_inc(l)
+#define __local_dec(l) local_dec(l)
+#define __local_add(i,l) local_add((i),(l))
+#define __local_sub(i,l) local_sub((i),(l))
+
+/* Use these for per-cpu local_t variables: on some archs they are
+ * much more efficient than these naive implementations. Note they take
+ * a variable, not an address.
+ */
+#define cpu_local_read(v) local_read(&__get_cpu_var(v))
+#define cpu_local_set(v, i) local_set(&__get_cpu_var(v), (i))
+#define cpu_local_inc(v) local_inc(&__get_cpu_var(v))
+#define cpu_local_dec(v) local_dec(&__get_cpu_var(v))
+#define cpu_local_add(i, v) local_add((i), &__get_cpu_var(v))
+#define cpu_local_sub(i, v) local_sub((i), &__get_cpu_var(v))
+
+#define __cpu_local_inc(v) cpu_local_inc(v)
+#define __cpu_local_dec(v) cpu_local_dec(v)
+#define __cpu_local_add(i, v) cpu_local_add((i), (v))
+#define __cpu_local_sub(i, v) cpu_local_sub((i), (v))
+
+#endif /* _ARCH_I386_LOCAL_H */
diff --git a/include/asm-sparc64/atomic.h b/include/asm-sparc64/atomic.h
index fc10b924f42e..ea155897855c 100644
--- a/include/asm-sparc64/atomic.h
+++ b/include/asm-sparc64/atomic.h
@@ -9,25 +9,46 @@
#define __ARCH_SPARC64_ATOMIC__
typedef struct { volatile int counter; } atomic_t;
-#define ATOMIC_INIT(i) { (i) }
+typedef struct { volatile long counter; } atomic64_t;
+
+#define ATOMIC_INIT(i) { (i) }
+#define ATOMIC64_INIT(i) { (i) }
#define atomic_read(v) ((v)->counter)
+#define atomic64_read(v) ((v)->counter)
+
#define atomic_set(v, i) (((v)->counter) = i)
+#define atomic64_set(v, i) (((v)->counter) = i)
extern int __atomic_add(int, atomic_t *);
+extern int __atomic64_add(int, atomic64_t *);
+
extern int __atomic_sub(int, atomic_t *);
+extern int __atomic64_sub(int, atomic64_t *);
#define atomic_add(i, v) ((void)__atomic_add(i, v))
+#define atomic64_add(i, v) ((void)__atomic64_add(i, v))
+
#define atomic_sub(i, v) ((void)__atomic_sub(i, v))
+#define atomic64_sub(i, v) ((void)__atomic64_sub(i, v))
#define atomic_dec_return(v) __atomic_sub(1, v)
+#define atomic64_dec_return(v) __atomic64_sub(1, v)
+
#define atomic_inc_return(v) __atomic_add(1, v)
+#define atomic64_inc_return(v) __atomic64_add(1, v)
#define atomic_sub_and_test(i, v) (__atomic_sub(i, v) == 0)
+#define atomic64_sub_and_test(i, v) (__atomic64_sub(i, v) == 0)
+
#define atomic_dec_and_test(v) (__atomic_sub(1, v) == 0)
+#define atomic64_dec_and_test(v) (__atomic64_sub(1, v) == 0)
#define atomic_inc(v) ((void)__atomic_add(1, v))
+#define atomic64_inc(v) ((void)__atomic64_add(1, v))
+
#define atomic_dec(v) ((void)__atomic_sub(1, v))
+#define atomic64_dec(v) ((void)__atomic64_sub(1, v))
/* Atomic operations are already serializing */
#define smp_mb__before_atomic_dec() barrier()
diff --git a/include/asm-sparc64/local.h b/include/asm-sparc64/local.h
new file mode 100644
index 000000000000..49f543a8f11e
--- /dev/null
+++ b/include/asm-sparc64/local.h
@@ -0,0 +1,40 @@
+#ifndef _ARCH_SPARC64_LOCAL_H
+#define _ARCH_SPARC64_LOCAL_H
+
+#include <linux/percpu.h>
+#include <asm/atomic.h>
+
+typedef atomic64_t local_t;
+
+#define LOCAL_INIT(i) ATOMIC64_INIT(i)
+#define local_read(v) atomic64_read(v)
+#define local_set(v,i) atomic64_set(v,i)
+
+#define local_inc(v) atomic64_inc(v)
+#define local_dec(v) atomic64_inc(v)
+#define local_add(i, v) atomic64_add(i, v)
+#define local_sub(i, v) atomic64_sub(i, v)
+
+#define __local_inc(v) ((v)->counter++)
+#define __local_dec(v) ((v)->counter++)
+#define __local_add(i,v) ((v)->counter+=(i))
+#define __local_sub(i,v) ((v)->counter-=(i))
+
+/* Use these for per-cpu local_t variables: on some archs they are
+ * much more efficient than these naive implementations. Note they take
+ * a variable, not an address.
+ */
+#define cpu_local_read(v) local_read(&__get_cpu_var(v))
+#define cpu_local_set(v, i) local_set(&__get_cpu_var(v), (i))
+
+#define cpu_local_inc(v) local_inc(&__get_cpu_var(v))
+#define cpu_local_dec(v) local_dec(&__get_cpu_var(v))
+#define cpu_local_add(i, v) local_add((i), &__get_cpu_var(v))
+#define cpu_local_sub(i, v) local_sub((i), &__get_cpu_var(v))
+
+#define __cpu_local_inc(v) __local_inc(&__get_cpu_var(v))
+#define __cpu_local_dec(v) __local_dec(&__get_cpu_var(v))
+#define __cpu_local_add(i, v) __local_add((i), &__get_cpu_var(v))
+#define __cpu_local_sub(i, v) __local_sub((i), &__get_cpu_var(v))
+
+#endif /* _ARCH_SPARC64_LOCAL_H */
diff --git a/include/asm-sparc64/sections.h b/include/asm-sparc64/sections.h
new file mode 100644
index 000000000000..e6dcceabffb2
--- /dev/null
+++ b/include/asm-sparc64/sections.h
@@ -0,0 +1,7 @@
+#ifndef _SPARC64_SECTIONS_H
+#define _SPARC64_SECTIONS_H
+
+/* nothing to see, move along */
+#include <asm-generic/sections.h>
+
+#endif
diff --git a/include/linux/module.h b/include/linux/module.h
index 1d48f23a8a6a..13ff244afdbf 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -16,6 +16,7 @@
#include <linux/kmod.h>
#include <linux/elf.h>
#include <linux/stringify.h>
+#include <asm/local.h>
#include <asm/module.h>
@@ -171,7 +172,7 @@ void *__symbol_get_gpl(const char *symbol);
struct module_ref
{
- atomic_t count;
+ local_t count;
} ____cacheline_aligned;
enum module_state
@@ -276,19 +277,17 @@ struct module *module_get_kallsym(unsigned int symnum,
char *type,
char namebuf[128]);
int is_exported(const char *name, const struct module *mod);
-#ifdef CONFIG_MODULE_UNLOAD
+extern void __module_put_and_exit(struct module *mod, long code)
+ __attribute__((noreturn));
+#define module_put_and_exit(code) __module_put_and_exit(THIS_MODULE, code);
+
+#ifdef CONFIG_MODULE_UNLOAD
unsigned int module_refcount(struct module *mod);
void __symbol_put(const char *symbol);
#define symbol_put(x) __symbol_put(MODULE_SYMBOL_PREFIX #x)
void symbol_put_addr(void *addr);
-/* We only need protection against local interrupts. */
-#ifndef __HAVE_ARCH_LOCAL_INC
-#define local_inc(x) atomic_inc(x)
-#define local_dec(x) atomic_dec(x)
-#endif
-
/* Sometimes we know we already have a refcount, and it's easier not
to handle the error case (which only happens with rmmod --wait). */
static inline void __module_get(struct module *module)
@@ -445,6 +444,8 @@ static inline int unregister_module_notifier(struct notifier_block * nb)
return 0;
}
+#define module_put_and_exit(code) do_exit(code)
+
#endif /* CONFIG_MODULES */
#ifdef MODULE
diff --git a/kernel/extable.c b/kernel/extable.c
index d49099854024..6f1fb8c6b75b 100644
--- a/kernel/extable.c
+++ b/kernel/extable.c
@@ -17,10 +17,10 @@
*/
#include <linux/module.h>
#include <asm/uaccess.h>
+#include <asm/sections.h>
extern const struct exception_table_entry __start___ex_table[];
extern const struct exception_table_entry __stop___ex_table[];
-extern char _stext[], _etext[], _sinittext[], _einittext[];
/* Given an address, look for it in the exception tables. */
const struct exception_table_entry *search_exception_tables(unsigned long addr)
diff --git a/kernel/module.c b/kernel/module.c
index ea1cf83ee2b3..58d73701bbde 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -98,6 +98,17 @@ int init_module(void)
}
EXPORT_SYMBOL(init_module);
+/* A thread that wants to hold a reference to a module only while it
+ * is running can call ths to safely exit.
+ * nfsd and lockd use this.
+ */
+void __module_put_and_exit(struct module *mod, long code)
+{
+ module_put(mod);
+ do_exit(code);
+}
+EXPORT_SYMBOL(__module_put_and_exit);
+
/* Find a module section: 0 means not found. */
static unsigned int find_sec(Elf_Ehdr *hdr,
Elf_Shdr *sechdrs,
@@ -374,9 +385,9 @@ static void module_unload_init(struct module *mod)
INIT_LIST_HEAD(&mod->modules_which_use_me);
for (i = 0; i < NR_CPUS; i++)
- atomic_set(&mod->ref[i].count, 0);
+ local_set(&mod->ref[i].count, 0);
/* Hold reference count during initialization. */
- atomic_set(&mod->ref[smp_processor_id()].count, 1);
+ local_set(&mod->ref[smp_processor_id()].count, 1);
/* Backwards compatibility macros put refcount during init. */
mod->waiter = current;
}
@@ -599,7 +610,7 @@ unsigned int module_refcount(struct module *mod)
unsigned int i, total = 0;
for (i = 0; i < NR_CPUS; i++)
- total += atomic_read(&mod->ref[i].count);
+ total += local_read(&mod->ref[i].count);
return total;
}
EXPORT_SYMBOL(module_refcount);
@@ -610,7 +621,10 @@ static void free_module(struct module *mod);
#ifdef CONFIG_MODULE_FORCE_UNLOAD
static inline int try_force(unsigned int flags)
{
- return (flags & O_TRUNC);
+ int ret = (flags & O_TRUNC);
+ if (ret)
+ tainted |= TAINT_FORCED_MODULE;
+ return ret;
}
#else
static inline int try_force(unsigned int flags)
diff --git a/kernel/profile.c b/kernel/profile.c
index 4f6d22ce33f2..5c02ac0fbbda 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -8,8 +8,7 @@
#include <linux/bootmem.h>
#include <linux/notifier.h>
#include <linux/mm.h>
-
-extern char _stext, _etext;
+#include <asm/sections.h>
unsigned int * prof_buffer;
unsigned long prof_len;
@@ -36,7 +35,7 @@ void __init profile_init(void)
return;
/* only text is profiled */
- prof_len = (unsigned long) &_etext - (unsigned long) &_stext;
+ prof_len = _etext - _stext;
prof_len >>= prof_shift;
size = prof_len * sizeof(unsigned int) + PAGE_SIZE - 1;