summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Mochel <mochel@osdl.org>2003-01-06 23:38:43 -0600
committerPatrick Mochel <mochel@osdl.org>2003-01-06 23:38:43 -0600
commiteeacc9367455a3bbbed00ced63a06c65fe347784 (patch)
tree55b12e320e6065468186214509cc08076e0fb32f
parent351b11abdb0c25cb383b8e881939a6e2f3d64c28 (diff)
parenta34aca8a2ee295cc711418518f1d8c9fe099833d (diff)
Merge osdl.org:/home/mochel/src/kernel/devel/linux-2.5-virgin
into osdl.org:/home/mochel/src/kernel/devel/linux-2.5-core
-rw-r--r--Documentation/DocBook/Makefile2
-rw-r--r--Documentation/DocBook/journal-api.tmpl2
-rw-r--r--Documentation/DocBook/kernel-api.tmpl29
-rw-r--r--Documentation/DocBook/scsidrivers.tmpl4
-rw-r--r--Documentation/DocBook/videobook.tmpl14
-rw-r--r--MAINTAINERS6
-rw-r--r--arch/alpha/Makefile6
-rw-r--r--arch/alpha/kernel/Makefile1
-rw-r--r--arch/alpha/kernel/module.c306
-rw-r--r--arch/alpha/kernel/traps.c5
-rw-r--r--arch/alpha/mm/extable.c43
-rw-r--r--arch/alpha/mm/fault.c5
-rw-r--r--arch/arm/kernel/module.c6
-rw-r--r--arch/i386/kernel/apm.c2
-rw-r--r--arch/i386/kernel/cpu/cpufreq/elanfreq.c59
-rw-r--r--arch/i386/kernel/cpu/cpufreq/p4-clockmod.c90
-rw-r--r--arch/i386/kernel/entry.S12
-rw-r--r--arch/i386/kernel/ioport.c2
-rw-r--r--arch/i386/kernel/module.c6
-rw-r--r--arch/i386/kernel/process.c2
-rw-r--r--arch/i386/kernel/signal.c2
-rw-r--r--arch/i386/kernel/timers/timer_tsc.c54
-rw-r--r--arch/i386/kernel/traps.c56
-rw-r--r--arch/i386/mm/extable.c48
-rw-r--r--arch/i386/mm/fault.c7
-rw-r--r--arch/i386/mm/hugetlbpage.c6
-rw-r--r--arch/i386/mm/init.c10
-rw-r--r--arch/m68k/kernel/traps.c36
-rw-r--r--arch/mips/kernel/pci.c2
-rw-r--r--arch/mips64/sgi-ip27/ip27-rtc.c10
-rw-r--r--arch/parisc/kernel/perf.c10
-rw-r--r--arch/parisc/kernel/traps.c25
-rw-r--r--arch/ppc/kernel/module.c2
-rw-r--r--arch/ppc/kernel/traps.c5
-rw-r--r--arch/ppc/mm/extable.c46
-rw-r--r--arch/ppc/mm/fault.c8
-rw-r--r--arch/ppc64/kernel/rtc.c13
-rw-r--r--arch/ppc64/kernel/signal32.c2
-rw-r--r--arch/s390/kernel/module.c6
-rw-r--r--arch/s390/kernel/traps.c44
-rw-r--r--arch/s390x/kernel/module.c6
-rw-r--r--arch/s390x/kernel/traps.c44
-rw-r--r--arch/sparc/kernel/module.c6
-rw-r--r--arch/sparc64/kernel/ioctl32.c62
-rw-r--r--arch/sparc64/kernel/module.c6
-rw-r--r--arch/sparc64/kernel/sunos_ioctl32.c5
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c85
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c24
-rw-r--r--arch/sparc64/kernel/traps.c10
-rw-r--r--arch/sparc64/kernel/unaligned.c3
-rw-r--r--arch/sparc64/mm/extable.c65
-rw-r--r--arch/sparc64/mm/fault.c3
-rw-r--r--arch/sparc64/mm/hugetlbpage.c9
-rw-r--r--arch/um/kernel/sysrq.c43
-rw-r--r--arch/x86_64/kernel/module.c6
-rw-r--r--arch/x86_64/kernel/traps.c38
-rw-r--r--arch/x86_64/mm/hugetlbpage.c6
-rw-r--r--drivers/char/agp/agp.h2
-rw-r--r--drivers/char/agp/ali-agp.c1
-rw-r--r--drivers/char/agp/amd-k7-agp.c4
-rw-r--r--drivers/char/agp/amd-k8-agp.c4
-rw-r--r--drivers/char/agp/backend.c13
-rw-r--r--drivers/char/agp/generic.c15
-rw-r--r--drivers/char/agp/hp-agp.c1
-rw-r--r--drivers/char/agp/i460-agp.c1
-rw-r--r--drivers/char/agp/i7x05-agp.c1
-rw-r--r--drivers/char/agp/intel-agp.c24
-rw-r--r--drivers/char/agp/sis-agp.c1
-rw-r--r--drivers/char/agp/sworks-agp.c4
-rw-r--r--drivers/char/agp/via-agp.c7
-rw-r--r--drivers/char/agp/via-kt400.c1
-rw-r--r--drivers/char/drm/radeon_mem.c10
-rw-r--r--drivers/char/ftape/lowlevel/fdc-io.c17
-rw-r--r--drivers/char/ftape/zftape/zftape-ctl.c7
-rw-r--r--drivers/char/ftape/zftape/zftape-ctl.h1
-rw-r--r--drivers/char/genrtc.c15
-rw-r--r--drivers/char/nwflash.c7
-rw-r--r--drivers/char/sx.c12
-rw-r--r--drivers/char/toshiba.c15
-rw-r--r--drivers/isdn/hisax/asuscom.c5
-rw-r--r--drivers/isdn/hisax/avm_pci.c6
-rw-r--r--drivers/isdn/hisax/bkm_a8.c4
-rw-r--r--drivers/isdn/hisax/enternow_pci.c4
-rw-r--r--drivers/isdn/hisax/mic.c4
-rw-r--r--drivers/isdn/hisax/nj_u.c4
-rw-r--r--drivers/isdn/hisax/s0box.c5
-rw-r--r--drivers/isdn/hisax/saphir.c5
-rw-r--r--drivers/isdn/hisax/sedlbauer.c4
-rw-r--r--drivers/isdn/hisax/sportster.c5
-rw-r--r--drivers/isdn/hisax/teles0.c4
-rw-r--r--drivers/isdn/hisax/w6692.c6
-rw-r--r--drivers/macintosh/ans-lcd.c8
-rw-r--r--drivers/macintosh/via-pmu.c6
-rw-r--r--drivers/macintosh/via-pmu68k.c6
-rw-r--r--drivers/md/md.c102
-rw-r--r--drivers/md/raid1.c4
-rw-r--r--drivers/md/raid5.c2
-rw-r--r--drivers/net/3c59x.c4
-rw-r--r--drivers/net/aironet4500_proc.c15
-rw-r--r--drivers/net/irda/sa1100_ir.c5
-rw-r--r--drivers/net/starfire.c8
-rw-r--r--drivers/pci/probe.c8
-rw-r--r--drivers/sbus/char/bpp.c7
-rw-r--r--drivers/sbus/char/envctrl.c4
-rw-r--r--drivers/serial/68360serial.c1
-rw-r--r--drivers/sgi/char/streamable.c27
-rw-r--r--drivers/sgi/char/usema.c7
-rw-r--r--drivers/telephony/ixj.c12
-rw-r--r--drivers/usb/input/Kconfig2
-rw-r--r--drivers/video/fbmem.c5
-rw-r--r--fs/exec.c8
-rw-r--r--fs/mpage.c3
-rw-r--r--fs/ncpfs/sock.c2
-rw-r--r--fs/nfsctl.c17
-rw-r--r--fs/nfsd/export.c27
-rw-r--r--fs/nfsd/nfs3xdr.c2
-rw-r--r--fs/nfsd/nfs4proc.c2
-rw-r--r--fs/nfsd/nfs4xdr.c53
-rw-r--r--fs/nfsd/nfsctl.c355
-rw-r--r--fs/nfsd/nfsfh.c4
-rw-r--r--fs/nfsd/nfssvc.c8
-rw-r--r--fs/readdir.c12
-rw-r--r--include/asm-alpha/module.h25
-rw-r--r--include/asm-alpha/uaccess.h17
-rw-r--r--include/asm-i386/highmem.h2
-rw-r--r--include/asm-i386/thread_info.h2
-rw-r--r--include/asm-i386/uaccess.h4
-rw-r--r--include/asm-ppc/uaccess.h2
-rw-r--r--include/asm-sparc64/compat.h67
-rw-r--r--include/asm-sparc64/posix_types.h17
-rw-r--r--include/asm-sparc64/siginfo.h8
-rw-r--r--include/asm-sparc64/statfs.h3
-rw-r--r--include/asm-sparc64/uaccess.h4
-rw-r--r--include/linux/agp_backend.h2
-rw-r--r--include/linux/dirent.h13
-rw-r--r--include/linux/elf.h35
-rw-r--r--include/linux/highmem.h9
-rw-r--r--include/linux/init.h3
-rw-r--r--include/linux/kernel.h3
-rw-r--r--include/linux/module.h99
-rw-r--r--include/linux/moduleloader.h6
-rw-r--r--include/linux/nfsd/xdr4.h1
-rw-r--r--include/linux/pagemap.h8
-rw-r--r--include/linux/pci_ids.h2
-rw-r--r--include/linux/radix-tree.h8
-rw-r--r--include/linux/raid/md_k.h5
-rw-r--r--include/linux/raid/md_p.h7
-rw-r--r--include/linux/rmap-locking.h14
-rw-r--r--include/linux/smp.h1
-rw-r--r--include/linux/sunrpc/cache.h7
-rw-r--r--include/linux/sunrpc/svcauth.h8
-rw-r--r--include/linux/swap.h12
-rw-r--r--init/Kconfig45
-rw-r--r--init/do_mounts.c29
-rw-r--r--init/main.c7
-rw-r--r--kernel/cpufreq.c20
-rw-r--r--kernel/extable.c41
-rw-r--r--kernel/module.c206
-rw-r--r--kernel/panic.c4
-rw-r--r--kernel/pid.c49
-rw-r--r--kernel/printk.c11
-rw-r--r--kernel/sched.c2
-rw-r--r--lib/crc32.c4
-rw-r--r--lib/radix-tree.c89
-rw-r--r--mm/filemap.c53
-rw-r--r--mm/fremap.c8
-rw-r--r--mm/memory.c137
-rw-r--r--mm/mempool.c28
-rw-r--r--mm/mremap.c21
-rw-r--r--mm/readahead.c5
-rw-r--r--mm/rmap.c125
-rw-r--r--mm/shmem.c2
-rw-r--r--mm/slab.c67
-rw-r--r--mm/swap_state.c5
-rw-r--r--mm/swapfile.c18
-rw-r--r--net/core/dv.c6
-rw-r--r--net/ipv4/route.c23
-rw-r--r--net/ipv6/exthdrs.c8
-rw-r--r--net/sunrpc/cache.c248
-rw-r--r--net/sunrpc/svcauth.c21
-rw-r--r--net/sunrpc/svcauth_unix.c46
-rw-r--r--sound/sound_firmware.c1
182 files changed, 2535 insertions, 1548 deletions
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 11c194d9615d..4e689b702761 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -90,7 +90,7 @@ IMG-parportbook2 := $(addprefix $(obj)/,$(IMG-parportbook))
EPS-parportbook := $(patsubst %.fig,%.eps, $(IMG-parportbook2))
PNG-parportbook := $(patsubst %.fig,%.png, $(IMG-parportbook2))
$(obj)/parportbook.html: $(PNG-parportbook)
-$(obj)/parportbook.ps $(obj)/parportbook.pdf: $(EPS-parportbook)
+$(obj)/parportbook.ps $(obj)/parportbook.pdf: $(EPS-parportbook) $(PNG-parportbook)
###
# Rules to generate postscript, PDF and HTML
diff --git a/Documentation/DocBook/journal-api.tmpl b/Documentation/DocBook/journal-api.tmpl
index 3df30534a4bd..e57c8593eabd 100644
--- a/Documentation/DocBook/journal-api.tmpl
+++ b/Documentation/DocBook/journal-api.tmpl
@@ -206,6 +206,7 @@ eg.
journal_unlock_updates() // carry on with filesystem use.
</programlisting>
+<para>
The opportunities for abuse and DOS attacks with this should be obvious,
if you allow unprivileged userspace to trigger codepaths containing these
calls.
@@ -250,7 +251,6 @@ an example.
}
journal_destroy(my_jrnl);
</programlisting>
-</para>
</sect1>
</chapter>
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index f7b088432595..74dd7dd4a51f 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -150,7 +150,12 @@ KAO -->
!Ekernel/kmod.c
</sect1>
<sect1><title>Inter Module support</title>
-!Ekernel/module.c
+ <para>
+ Refer to the file kernel/module.c for more information.
+ </para>
+<!-- FIXME: Removed for now since no structured comments in source
+X!Ekernel/module.c
+-->
</sect1>
</chapter>
@@ -172,7 +177,12 @@ KAO -->
</sect1>
<sect1><title>MCA Architecture</title>
<sect2><title>MCA Device Functions</title>
-!Earch/i386/kernel/mca.c
+ <para>
+ Refer to the file arch/i386/kernel/mca.c for more information.
+ </para>
+<!-- FIXME: Removed for now since no structured comments in source
+X!Earch/i386/kernel/mca.c
+-->
</sect2>
<sect2><title>MCA Bus DMA</title>
!Iinclude/asm-i386/mca_dma.h
@@ -213,7 +223,9 @@ KAO -->
<chapter id="snddev">
<title>Sound Devices</title>
!Esound/sound_core.c
-!Isound/sound_firmware.c
+<!-- FIXME: Removed for now since no structured comments in source
+X!Isound/sound_firmware.c
+-->
</chapter>
<chapter id="usb">
@@ -292,7 +304,9 @@ KAO -->
<sect1><title>USB Core APIs</title>
!Edrivers/usb/core/urb.c
-!Edrivers/usb/core/config.c
+<!-- FIXME: Removed for now since no structured comments in source
+X!Edrivers/usb/core/config.c
+-->
!Edrivers/usb/core/message.c
!Edrivers/usb/core/file.c
!Edrivers/usb/core/usb.c
@@ -385,7 +399,12 @@ KAO -->
!Idrivers/video/macmodes.c
</sect1>
<sect1><title>Frame Buffer Fonts</title>
-!Idrivers/video/console/fonts.c
+ <para>
+ Refer to the file drivers/video/console/fonts.c for more information.
+ </para>
+<!-- FIXME: Removed for now since no structured comments in source
+X!Idrivers/video/console/fonts.c
+-->
</sect1>
</chapter>
<!-- Needs ksyms to list additional exported symbols, but no specific doc.
diff --git a/Documentation/DocBook/scsidrivers.tmpl b/Documentation/DocBook/scsidrivers.tmpl
index 1911dc943cec..1dbafa7c2bd9 100644
--- a/Documentation/DocBook/scsidrivers.tmpl
+++ b/Documentation/DocBook/scsidrivers.tmpl
@@ -52,7 +52,7 @@ level drivers can control one or more scsi hosts (a.k.a. scsi initiators).
</para>
<para>
This document can been found in an ASCII text file in the linux kernel
-source: <filename>drivers/scsi/scsi_mid_low_api.txt</filename> .
+source: <filename>Documentation/scsi/scsi_mid_low_api.txt</filename> .
It currently hold a little more information than this document. The
<filename>drivers/scsi/hosts.h</filename> and <filename>
drivers/scsi/scsi.h</filename> headers contain descriptions of members
@@ -107,7 +107,7 @@ an existing lower level driver does in this regard.
<chapter id="intfunctions">
<title>Interface Functions</title>
-!Edrivers/scsi/scsi_mid_low_api.txt
+!EDocumentation/scsi/scsi_mid_low_api.txt
</chapter>
<chapter id="locks">
diff --git a/Documentation/DocBook/videobook.tmpl b/Documentation/DocBook/videobook.tmpl
index 11eb55fd5f07..de05ab79c79e 100644
--- a/Documentation/DocBook/videobook.tmpl
+++ b/Documentation/DocBook/videobook.tmpl
@@ -146,16 +146,17 @@ static int io = 0x320;
int __init myradio_init(struct video_init *v)
{
- if(check_region(io, MY_IO_SIZE))
+ if(!request_region(io, MY_IO_SIZE, "myradio"))
{
printk(KERN_ERR
"myradio: port 0x%03X is in use.\n", io);
return -EBUSY;
}
- if(video_device_register(&amp;my_radio, VFL_TYPE_RADIO)==-1)
+ if(video_device_register(&amp;my_radio, VFL_TYPE_RADIO)==-1) {
+ release_region(io, MY_IO_SIZE);
return -EINVAL;
- request_region(io, MY_IO_SIZE, "myradio");
+ }
return 0;
}
@@ -920,7 +921,7 @@ static int irq = 11;
int __init mycamera_init(struct video_init *v)
{
- if(check_region(io, MY_IO_SIZE))
+ if(!request_region(io, MY_IO_SIZE, "mycamera"))
{
printk(KERN_ERR
"mycamera: port 0x%03X is in use.\n", io);
@@ -928,9 +929,10 @@ int __init mycamera_init(struct video_init *v)
}
if(video_device_register(&amp;my_camera,
- VFL_TYPE_GRABBER)==-1)
+ VFL_TYPE_GRABBER)==-1) {
+ release_region(io, MY_IO_SIZE);
return -EINVAL;
- request_region(io, MY_IO_SIZE, "mycamera");
+ }
return 0;
}
diff --git a/MAINTAINERS b/MAINTAINERS
index 9c9e21aebc61..0ff1129888a4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1133,6 +1133,12 @@ W: http://www.acc.umu.se/~mcalinux/
L: linux-kernel@vger.kernel.org
S: Maintained
+MODULE SUPPORT
+P: Rusty Russell
+M: rusty@rustcorp.com.au
+L: linux-kernel@vger.kernel.org
+S: Maintained
+
MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER
P: Stelian Pop
M: stelian@popies.net
diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile
index 79f400d4888f..d2fadd634e45 100644
--- a/arch/alpha/Makefile
+++ b/arch/alpha/Makefile
@@ -121,8 +121,10 @@ include/asm-$(ARCH)/asm_offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
archclean:
$(Q)$(MAKE) -f scripts/Makefile.clean obj=$(boot)
-CLEAN_FILES += include/asm-$(ARCH)/offset.h.tmp \
- include/asm-$(ARCH)/offset.h
+archmrproper:
+
+CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h.tmp \
+ include/asm-$(ARCH)/asm_offsets.h
define archhelp
echo '* boot - Compressed kernel image (arch/alpha/boot/vmlinux.gz)'
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index b22cbaeae0b8..d9523688bf66 100644
--- a/arch/alpha/kernel/Makefile
+++ b/arch/alpha/kernel/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_VGA_HOSE) += console.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PCI) += pci.o pci_iommu.o
obj-$(CONFIG_SRM_ENV) += srm_env.o
+obj-$(CONFIG_MODULES) += module.o
ifdef CONFIG_ALPHA_GENERIC
diff --git a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c
new file mode 100644
index 000000000000..0d3f1f35a937
--- /dev/null
+++ b/arch/alpha/kernel/module.c
@@ -0,0 +1,306 @@
+/* Kernel module help for Alpha.
+ Copyright (C) 2002 Richard Henderson.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt...)
+#endif
+
+void *
+module_alloc(unsigned long size)
+{
+ if (size == 0)
+ return NULL;
+ return vmalloc(size);
+}
+
+void
+module_free(struct module *mod, void *module_region)
+{
+ vfree(module_region);
+}
+
+/* Allocate the GOT at the end of the core sections. */
+
+struct got_entry {
+ struct got_entry *next;
+ Elf64_Addr r_offset;
+ int got_offset;
+};
+
+static inline void
+process_reloc_for_got(Elf64_Rela *rela,
+ struct got_entry *chains, Elf64_Xword *poffset)
+{
+ unsigned long r_sym = ELF64_R_SYM (rela->r_info);
+ unsigned long r_type = ELF64_R_TYPE (rela->r_info);
+ Elf64_Addr r_offset = rela->r_offset;
+ struct got_entry *g;
+
+ if (r_type != R_ALPHA_LITERAL)
+ return;
+
+ for (g = chains + r_sym; g ; g = g->next)
+ if (g->r_offset == r_offset) {
+ if (g->got_offset == 0) {
+ g->got_offset = *poffset;
+ *poffset += 8;
+ }
+ goto found_entry;
+ }
+
+ g = kmalloc (sizeof (*g), GFP_KERNEL);
+ g->next = chains[r_sym].next;
+ g->r_offset = r_offset;
+ g->got_offset = *poffset;
+ *poffset += 8;
+ chains[r_sym].next = g;
+
+ found_entry:
+ /* Trick: most of the ELF64_R_TYPE field is unused. There are
+ 42 valid relocation types, and a 32-bit field. Co-opt the
+ bits above 256 to store the got offset for this reloc. */
+ rela->r_info |= g->got_offset << 8;
+}
+
+int
+module_frob_arch_sections(const Elf64_Ehdr *hdr, const Elf64_Shdr *sechdrs,
+ const char *secstrings, struct module *me)
+{
+ struct got_entry *chains;
+ Elf64_Rela *rela;
+ const Elf64_Shdr *esechdrs, *symtab, *s;
+ Elf64_Shdr *got;
+ unsigned long nsyms, nrela, i;
+
+ esechdrs = sechdrs + hdr->e_shnum;
+ symtab = got = NULL;
+
+ /* Find out how large the symbol table is. Allocate one got_entry
+ head per symbol. Normally this will be enough, but not always.
+ We'll chain different offsets for the symbol down each head. */
+ for (s = sechdrs; s < esechdrs; ++s)
+ if (s->sh_type == SHT_SYMTAB)
+ symtab = s;
+ else if (!strcmp(".got", secstrings + s->sh_name)) {
+ got = (Elf64_Shdr *) s;
+ me->arch.gotsecindex = s - sechdrs;
+ }
+
+ if (!symtab) {
+ printk(KERN_ERR "module %s: no symbol table\n", me->name);
+ return -ENOEXEC;
+ }
+ if (!got) {
+ printk(KERN_ERR "module %s: no got section\n", me->name);
+ return -ENOEXEC;
+ }
+
+ nsyms = symtab->sh_size / sizeof(Elf64_Sym);
+ chains = kmalloc(nsyms * sizeof(struct got_entry), GFP_KERNEL);
+ memset(chains, 0, nsyms * sizeof(struct got_entry));
+
+ got->sh_size = 0;
+ got->sh_addralign = 8;
+ got->sh_type = SHT_NOBITS;
+
+ /* Examine all LITERAL relocations to find out what GOT entries
+ are required. This sizes the GOT section as well. */
+ for (s = sechdrs; s < esechdrs; ++s)
+ if (s->sh_type == SHT_RELA) {
+ nrela = s->sh_size / sizeof(Elf64_Rela);
+ rela = (void *)hdr + s->sh_offset;
+ for (i = 0; i < nrela; ++i)
+ process_reloc_for_got(rela+i, chains,
+ &got->sh_size);
+ }
+
+ /* Free the memory we allocated. */
+ for (i = 0; i < nsyms; ++i) {
+ struct got_entry *g, *n;
+ for (g = chains[i].next; g ; g = n) {
+ n = g->next;
+ kfree(g);
+ }
+ }
+ kfree(chains);
+
+ return 0;
+}
+
+int
+apply_relocate(Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex,
+ unsigned int relsec, struct module *me)
+{
+ printk(KERN_ERR "module %s: REL relocation unsupported\n", me->name);
+ return -ENOEXEC;
+}
+
+int
+apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab,
+ unsigned int symindex, unsigned int relsec,
+ struct module *me)
+{
+ Elf64_Rela *rela = (void *)sechdrs[relsec].sh_addr;
+ unsigned long i, n = sechdrs[relsec].sh_size / sizeof(*rela);
+ Elf64_Sym *symtab, *sym;
+ void *base, *location;
+ unsigned long got, gp;
+
+ DEBUGP("Applying relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+
+ base = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr;
+ symtab = (Elf64_Sym *)sechdrs[symindex].sh_addr;
+
+ /* The small sections were sorted to the end of the segment.
+ The following should definitely cover them. */
+ gp = (u64)me->module_core + me->core_size - 0x8000;
+ got = sechdrs[me->arch.gotsecindex].sh_addr;
+
+ for (i = 0; i < n; i++) {
+ unsigned long r_sym = ELF64_R_SYM (rela[i].r_info);
+ unsigned long r_type = ELF64_R_TYPE (rela[i].r_info);
+ unsigned long r_got_offset = r_type >> 8;
+ unsigned long value, hi, lo;
+ r_type &= 0xff;
+
+ /* This is where to make the change. */
+ location = base + rela[i].r_offset;
+
+ /* This is the symbol it is referring to. */
+ sym = symtab + r_sym;
+ value = sym->st_value;
+ if (!value) {
+ printk(KERN_ERR "module %s: Unknown symbol %s\n",
+ me->name, strtab + sym->st_name);
+ return -ENOENT;
+ }
+ value += rela[i].r_addend;
+
+ switch (r_type) {
+ case R_ALPHA_NONE:
+ break;
+ case R_ALPHA_REFQUAD:
+ *(u64 *)location = value;
+ break;
+ case R_ALPHA_GPREL32:
+ value -= gp;
+ if ((int)value != value)
+ goto reloc_overflow;
+ *(u32 *)location = value;
+ break;
+ case R_ALPHA_LITERAL:
+ hi = got + r_got_offset;
+ lo = hi - gp;
+ if ((short)lo != lo)
+ goto reloc_overflow;
+ *(u16 *)location = lo;
+ *(u64 *)hi = value;
+ break;
+ case R_ALPHA_LITUSE:
+ break;
+ case R_ALPHA_GPDISP:
+ value = gp - (u64)location;
+ lo = (short)value;
+ hi = (int)(value - lo);
+ if (hi + lo != value)
+ goto reloc_overflow;
+ *(u16 *)location = hi >> 16;
+ *(u16 *)(location + rela[i].r_addend) = lo;
+ break;
+ case R_ALPHA_BRSGP:
+ /* BRSGP is only allowed to bind to local symbols.
+ If the section is undef, this means that the
+ value was resolved from somewhere else. */
+ if (sym->st_shndx == SHN_UNDEF)
+ goto reloc_overflow;
+ /* FALLTHRU */
+ case R_ALPHA_BRADDR:
+ value -= (u64)location + 4;
+ if (value & 3)
+ goto reloc_overflow;
+ value = (long)value >> 2;
+ if (value + (1<<21) >= 1<<22)
+ goto reloc_overflow;
+ value &= 0x1fffff;
+ value |= *(u32 *)location & ~0x1fffff;
+ *(u32 *)location = value;
+ break;
+ case R_ALPHA_HINT:
+ break;
+ case R_ALPHA_SREL32:
+ value -= (u64)location;
+ if ((int)value != value)
+ goto reloc_overflow;
+ *(u32 *)location = value;
+ break;
+ case R_ALPHA_SREL64:
+ value -= (u64)location;
+ *(u64 *)location = value;
+ break;
+ case R_ALPHA_GPRELHIGH:
+ value = (value - gp + 0x8000) >> 16;
+ if ((short) value != value)
+ goto reloc_overflow;
+ *(u16 *)location = value;
+ break;
+ case R_ALPHA_GPRELLOW:
+ value -= gp;
+ *(u16 *)location = value;
+ break;
+ case R_ALPHA_GPREL16:
+ value -= gp;
+ if ((short) value != value)
+ goto reloc_overflow;
+ *(u16 *)location = value;
+ break;
+ default:
+ printk(KERN_ERR "module %s: Unknown relocation: %lu\n",
+ me->name, r_type);
+ return -ENOEXEC;
+ reloc_overflow:
+ if (ELF64_ST_TYPE (sym->st_info) == STT_SECTION)
+ printk(KERN_ERR
+ "module %s: Relocation overflow vs section %d\n",
+ me->name, sym->st_shndx);
+ else
+ printk(KERN_ERR
+ "module %s: Relocation overflow vs %s\n",
+ me->name, strtab + sym->st_name);
+ return -ENOEXEC;
+ }
+ }
+
+ return 0;
+}
+
+int
+module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
+ struct module *me)
+{
+ return 0;
+}
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index 7f30895ca719..4963bab746af 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -14,6 +14,7 @@
#include <linux/tty.h>
#include <linux/delay.h>
#include <linux/smp_lock.h>
+#include <linux/module.h>
#include <asm/gentrap.h>
#include <asm/uaccess.h>
@@ -465,7 +466,7 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg,
{
long error, tmp1, tmp2, tmp3, tmp4;
unsigned long pc = regs.pc - 4;
- unsigned fixup;
+ const struct exception_table_entry *fixup;
unaligned[0].count++;
unaligned[0].va = (unsigned long) va;
@@ -638,7 +639,7 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg,
got_exception:
/* Ok, we caught the exception, but we don't want it. Is there
someone to pass it along to? */
- if ((fixup = search_exception_table(pc)) != 0) {
+ if ((fixup = search_exception_tables(pc)) != 0) {
unsigned long newpc;
newpc = fixup_exception(una_reg, fixup, pc);
diff --git a/arch/alpha/mm/extable.c b/arch/alpha/mm/extable.c
index c856eea015f3..310c9fd5604f 100644
--- a/arch/alpha/mm/extable.c
+++ b/arch/alpha/mm/extable.c
@@ -6,13 +6,10 @@
#include <linux/module.h>
#include <asm/uaccess.h>
-extern const struct exception_table_entry __start___ex_table[];
-extern const struct exception_table_entry __stop___ex_table[];
-
-static inline unsigned
-search_one_table(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value)
+const struct exception_table_entry *
+search_extable(const struct exception_table_entry *first,
+ const struct exception_table_entry *last,
+ unsigned long value)
{
while (first <= last) {
const struct exception_table_entry *mid;
@@ -21,40 +18,12 @@ search_one_table(const struct exception_table_entry *first,
mid = (last - first) / 2 + first;
mid_value = (unsigned long)&mid->insn + mid->insn;
if (mid_value == value)
- return mid->fixup.unit;
+ return mid;
else if (mid_value < value)
first = mid+1;
else
last = mid-1;
}
- return 0;
-}
-
-unsigned
-search_exception_table(unsigned long addr)
-{
- unsigned ret;
-
-#ifndef CONFIG_MODULES
- ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
-#else
- extern spinlock_t modlist_lock;
- unsigned long flags;
- /* The kernel is the last "module" -- no need to treat it special. */
- struct module *mp;
-
- ret = 0;
- spin_lock_irqsave(&modlist_lock, flags);
- for (mp = module_list; mp ; mp = mp->next) {
- if (!mp->ex_table_start || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING)))
- continue;
- ret = search_one_table(mp->ex_table_start,
- mp->ex_table_end - 1, addr);
- if (ret)
- break;
- }
- spin_unlock_irqrestore(&modlist_lock, flags);
-#endif
- return ret;
+ return NULL;
}
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
index 8285db87a801..d0c12c8de82e 100644
--- a/arch/alpha/mm/fault.c
+++ b/arch/alpha/mm/fault.c
@@ -24,6 +24,7 @@
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -88,7 +89,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
{
struct vm_area_struct * vma;
struct mm_struct *mm = current->mm;
- unsigned int fixup;
+ const struct exception_table_entry *fixup;
int fault, si_code = SEGV_MAPERR;
siginfo_t info;
@@ -176,7 +177,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
no_context:
/* Are we prepared to handle this fault as an exception? */
- if ((fixup = search_exception_table(regs->pc)) != 0) {
+ if ((fixup = search_exception_tables(regs->pc)) != 0) {
unsigned long newpc;
newpc = fixup_exception(dpf_reg, fixup, regs->pc);
regs->pc = newpc;
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 3a2b5aaaa3b6..8e22b9bb6726 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -67,9 +67,9 @@ void module_free(struct module *module, void *region)
vfree(region);
}
-int module_frob_arch_sections(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- const char *secstrings,
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ char *secstrings,
struct module *mod)
{
return 0;
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index a81108dfb113..2fc083a98278 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -718,7 +718,7 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax)
* same format.
*/
-static int __init apm_driver_version(u_short *val)
+static int apm_driver_version(u_short *val)
{
u32 eax;
diff --git a/arch/i386/kernel/cpu/cpufreq/elanfreq.c b/arch/i386/kernel/cpu/cpufreq/elanfreq.c
index 2623e01b2d87..08fac292dff8 100644
--- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c
@@ -31,8 +31,6 @@
#define REG_CSCIR 0x22 /* Chip Setup and Control Index Register */
#define REG_CSCDR 0x23 /* Chip Setup and Control Data Register */
-#define SAFE_FREQ 33000 /* every Elan CPU can run at 33 MHz */
-
static struct cpufreq_driver *elanfreq_driver;
/* Module parameter */
@@ -184,7 +182,7 @@ static int elanfreq_verify (struct cpufreq_policy *policy)
cpufreq_verify_within_limits(policy, 1000, max_freq);
- for (i=(sizeof(elan_multiplier)/sizeof(struct s_elan_multiplier) - 1); i>=0; i--)
+ for (i=7; i>=0; i--)
if ((elan_multiplier[i].clock >= policy->min) &&
(elan_multiplier[i].clock <= policy->max))
number_states++;
@@ -192,57 +190,46 @@ static int elanfreq_verify (struct cpufreq_policy *policy)
if (number_states)
return 0;
- for (i=(sizeof(elan_multiplier)/sizeof(struct s_elan_multiplier) - 1); i>=0; i--)
+ for (i=7; i>=0; i--)
if (elan_multiplier[i].clock < policy->max)
break;
policy->max = elan_multiplier[i+1].clock;
+ cpufreq_verify_within_limits(policy, 1000, max_freq);
+
return 0;
}
static int elanfreq_setpolicy (struct cpufreq_policy *policy)
{
- unsigned int number_states = 0;
- unsigned int i, j=4;
+ unsigned int i;
+ unsigned int optimal = 8;
if (!elanfreq_driver)
return -EINVAL;
- for (i=(sizeof(elan_multiplier)/sizeof(struct s_elan_multiplier) - 1); i>=0; i--)
- if ((elan_multiplier[i].clock >= policy->min) &&
- (elan_multiplier[i].clock <= policy->max))
- {
- number_states++;
- j = i;
+ for (i=0; i<8; i++) {
+ if ((elan_multiplier[i].clock > policy->max) ||
+ (elan_multiplier[i].clock < policy->min))
+ continue;
+ switch(policy->policy) {
+ case CPUFREQ_POLICY_POWERSAVE:
+ if (optimal == 8)
+ optimal = i;
+ break;
+ case CPUFREQ_POLICY_PERFORMANCE:
+ optimal = i;
+ break;
+ default:
+ return -EINVAL;
}
-
- if (number_states == 1) {
- elanfreq_set_cpu_state(j);
- return 0;
}
-
- switch (policy->policy) {
- case CPUFREQ_POLICY_POWERSAVE:
- for (i=(sizeof(elan_multiplier)/sizeof(struct s_elan_multiplier) - 1); i>=0; i--)
- if ((elan_multiplier[i].clock >= policy->min) &&
- (elan_multiplier[i].clock <= policy->max))
- j = i;
- break;
- case CPUFREQ_POLICY_PERFORMANCE:
- for (i=0; i<(sizeof(elan_multiplier)/sizeof(struct s_elan_multiplier) - 1); i++)
- if ((elan_multiplier[i].clock >= policy->min) &&
- (elan_multiplier[i].clock <= policy->max))
- j = i;
- break;
- default:
+ if ((optimal == 8) || (elan_multiplier[optimal].clock > max_freq))
return -EINVAL;
- }
- if (elan_multiplier[j].clock > max_freq)
- return -EINVAL;
+ elanfreq_set_cpu_state(optimal);
- elanfreq_set_cpu_state(j);
return 0;
}
@@ -307,7 +294,7 @@ static int __init elanfreq_init(void)
driver->policy[0].max = max_freq;
driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE;
driver->policy[0].cpuinfo.max_freq = max_freq;
- driver->policy[0].cpuinfo.min_freq = min_freq;
+ driver->policy[0].cpuinfo.min_freq = 1000;
driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
elanfreq_driver = driver;
diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
index 52cb1a4ab188..88b88508c4e1 100644
--- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
+++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
@@ -82,12 +82,17 @@ static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
/* get current state */
rdmsr(MSR_IA32_THERM_CONTROL, l, h);
- l = l >> 1;
- l &= 0x7;
-
+ if (l & 0x10) {
+ l = l >> 1;
+ l &= 0x7;
+ } else
+ l = DC_DISABLE;
+
if (l == newstate) {
set_cpus_allowed(current, cpus_allowed);
return 0;
+ } else if (l == DC_RESV) {
+ printk(KERN_ERR PFX "BIG FAT WARNING: currently in invalid setting\n");
}
/* notifiers */
@@ -141,13 +146,18 @@ static int cpufreq_p4_setpolicy(struct cpufreq_policy *policy)
unsigned int i;
unsigned int newstate = 0;
unsigned int number_states = 0;
+ unsigned int minstate = 1;
- if (!cpufreq_p4_driver || !stock_freq || !policy)
+ if (!cpufreq_p4_driver || !stock_freq ||
+ !policy || !cpu_online(policy->cpu))
return -EINVAL;
+ if (has_N44_O17_errata)
+ minstate = 3;
+
if (policy->policy == CPUFREQ_POLICY_POWERSAVE)
{
- for (i=8; i>0; i--)
+ for (i=8; i>=minstate; i--)
if ((policy->min <= ((stock_freq / 8) * i)) &&
(policy->max >= ((stock_freq / 8) * i)))
{
@@ -155,7 +165,7 @@ static int cpufreq_p4_setpolicy(struct cpufreq_policy *policy)
number_states++;
}
} else {
- for (i=1; i<=8; i++)
+ for (i=minstate; i<=8; i++)
if ((policy->min <= ((stock_freq / 8) * i)) &&
(policy->max >= ((stock_freq / 8) * i)))
{
@@ -164,25 +174,8 @@ static int cpufreq_p4_setpolicy(struct cpufreq_policy *policy)
}
}
- /* if (number_states == 1) */
- {
- if (policy->cpu == CPUFREQ_ALL_CPUS) {
- for (i=0; i<NR_CPUS; i++)
- if (cpu_online(i))
- cpufreq_p4_setdc(i, newstate);
- } else {
- cpufreq_p4_setdc(policy->cpu, newstate);
- }
- }
- /* else {
- if (policy->policy == CPUFREQ_POLICY_POWERSAVE) {
- min_state = newstate;
- max_state = newstate + (number_states - 1);
- } else {
- max_state = newstate;
- min_state = newstate - (number_states - 1);
- }
- } */
+ cpufreq_p4_setdc(policy->cpu, newstate);
+
return 0;
}
@@ -190,17 +183,21 @@ static int cpufreq_p4_setpolicy(struct cpufreq_policy *policy)
static int cpufreq_p4_verify(struct cpufreq_policy *policy)
{
unsigned int number_states = 0;
- unsigned int i;
+ unsigned int i = 1;
- if (!cpufreq_p4_driver || !stock_freq || !policy)
+ if (!cpufreq_p4_driver || !stock_freq ||
+ !policy || !cpu_online(policy->cpu))
return -EINVAL;
- if (!cpu_online(policy->cpu))
- policy->cpu = CPUFREQ_ALL_CPUS;
- cpufreq_verify_within_limits(policy, (stock_freq / 8), stock_freq);
+ cpufreq_verify_within_limits(policy,
+ policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
+
+ if (has_N44_O17_errata)
+ i = 3;
- /* is there at least one state within limit? */
- for (i=1; i<=8; i++)
+ /* is there at least one state within the limit? */
+ for (; i<=8; i++)
if ((policy->min <= ((stock_freq / 8) * i)) &&
(policy->max >= ((stock_freq / 8) * i)))
number_states++;
@@ -209,11 +206,14 @@ static int cpufreq_p4_verify(struct cpufreq_policy *policy)
return 0;
policy->max = (stock_freq / 8) * (((unsigned int) ((policy->max * 8) / stock_freq)) + 1);
+ cpufreq_verify_within_limits(policy,
+ policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
return 0;
}
-int __init cpufreq_p4_init(void)
+static int __init cpufreq_p4_init(void)
{
struct cpuinfo_x86 *c = cpu_data;
int cpuid;
@@ -245,6 +245,16 @@ int __init cpufreq_p4_init(void)
}
printk(KERN_INFO PFX "P4/Xeon(TM) CPU On-Demand Clock Modulation available\n");
+
+ if (!stock_freq) {
+ if (cpu_khz)
+ stock_freq = cpu_khz;
+ else {
+ printk(KERN_INFO PFX "unknown core frequency - please use module parameter 'stock_freq'\n");
+ return -EINVAL;
+ }
+ }
+
driver = kmalloc(sizeof(struct cpufreq_driver) +
NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
if (!driver)
@@ -252,9 +262,6 @@ int __init cpufreq_p4_init(void)
driver->policy = (struct cpufreq_policy *) (driver + 1);
- if (!stock_freq)
- stock_freq = cpu_khz;
-
#ifdef CONFIG_CPU_FREQ_24_API
for (i=0;i<NR_CPUS;i++) {
driver->cpu_cur_freq[i] = stock_freq;
@@ -290,15 +297,16 @@ int __init cpufreq_p4_init(void)
}
-void __exit cpufreq_p4_exit(void)
+static void __exit cpufreq_p4_exit(void)
{
- u32 l, h;
+ unsigned int i;
if (cpufreq_p4_driver) {
+ for (i=0; i<NR_CPUS; i++) {
+ if (cpu_online(i))
+ cpufreq_p4_setdc(i, DC_DISABLE);
+ }
cpufreq_unregister();
- /* return back to a non modulated state */
- rdmsr(MSR_IA32_THERM_CONTROL, l, h);
- wrmsr(MSR_IA32_THERM_CONTROL, l & ~(1<<4), h);
kfree(cpufreq_p4_driver);
}
}
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index 5da9aae308d6..198def807850 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -253,11 +253,11 @@ ENTRY(sysenter_entry)
* Careful about security.
*/
cmpl $__PAGE_OFFSET-3,%ebp
- jae syscall_badsys
+ jae syscall_fault
1: movl (%ebp),%ebp
.section __ex_table,"a"
.align 4
- .long 1b,syscall_badsys
+ .long 1b,syscall_fault
.previous
pushl %eax
@@ -367,6 +367,14 @@ syscall_exit_work:
jmp resume_userspace
ALIGN
+syscall_fault:
+ pushl %eax # save orig_eax
+ SAVE_ALL
+ GET_THREAD_INFO(%ebx)
+ movl $-EFAULT,EAX(%esp)
+ jmp resume_userspace
+
+ ALIGN
syscall_badsys:
movl $-ENOSYS,EAX(%esp)
jmp resume_userspace
diff --git a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c
index a795bafc6f17..fcaa3693e115 100644
--- a/arch/i386/kernel/ioport.c
+++ b/arch/i386/kernel/ioport.c
@@ -124,6 +124,6 @@ asmlinkage int sys_iopl(unsigned long unused)
}
regs->eflags = (regs->eflags & 0xffffcfff) | (level << 12);
/* Make sure we return the long way (not sysenter) */
- set_thread_flag(TIF_SIGPENDING);
+ set_thread_flag(TIF_IRET);
return 0;
}
diff --git a/arch/i386/kernel/module.c b/arch/i386/kernel/module.c
index d71b0e367eb6..d92e448a2c8c 100644
--- a/arch/i386/kernel/module.c
+++ b/arch/i386/kernel/module.c
@@ -45,9 +45,9 @@ void module_free(struct module *mod, void *module_region)
}
/* We don't need anything special. */
-int module_frob_arch_sections(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- const char *secstrings,
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ char *secstrings,
struct module *mod)
{
return 0;
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index c6108fa910e1..fbcfc1f2c2bd 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -555,7 +555,7 @@ asmlinkage int sys_execve(struct pt_regs regs)
if (error == 0) {
current->ptrace &= ~PT_DTRACE;
/* Make sure we don't return using sysenter.. */
- set_thread_flag(TIF_SIGPENDING);
+ set_thread_flag(TIF_IRET);
}
putname(filename);
out:
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index 444e1c24a808..1c17237fe978 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -617,4 +617,6 @@ void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
/* deal with pending signal delivery */
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs,oldset);
+
+ clear_thread_flag(TIF_IRET);
}
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
index 2f84d4172cd8..4e56b5f99a60 100644
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ b/arch/i386/kernel/timers/timer_tsc.c
@@ -189,39 +189,38 @@ bad_ctc:
#ifdef CONFIG_CPU_FREQ
+static unsigned int ref_freq = 0;
+static unsigned long loops_per_jiffy_ref = 0;
+
+#ifndef CONFIG_SMP
+static unsigned long fast_gettimeoffset_ref = 0;
+static unsigned long cpu_khz_ref = 0;
+#endif
static int
time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{
struct cpufreq_freqs *freq = data;
- unsigned int i;
- if (!cpu_has_tsc)
- return 0;
+ if (!ref_freq) {
+ ref_freq = freq->old;
+ loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy;
+#ifndef CONFIG_SMP
+ fast_gettimeoffset_ref = fast_gettimeoffset_quotient;
+ cpu_khz_ref = cpu_khz;
+#endif
+ }
- switch (val) {
- case CPUFREQ_PRECHANGE:
- if ((freq->old < freq->new) &&
- ((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == 0))) {
- cpu_khz = cpufreq_scale(cpu_khz, freq->old, freq->new);
- fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_quotient, freq->new, freq->old);
- }
- for (i=0; i<NR_CPUS; i++)
- if ((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == i))
- cpu_data[i].loops_per_jiffy = cpufreq_scale(cpu_data[i].loops_per_jiffy, freq->old, freq->new);
- break;
-
- case CPUFREQ_POSTCHANGE:
- if ((freq->new < freq->old) &&
- ((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == 0))) {
- cpu_khz = cpufreq_scale(cpu_khz, freq->old, freq->new);
- fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_quotient, freq->new, freq->old);
+ if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
+ (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
+ cpu_data[freq->cpu].loops_per_jiffy = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
+#ifndef CONFIG_SMP
+ if (use_tsc) {
+ fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_ref, freq->new, ref_freq);
+ cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
}
- for (i=0; i<NR_CPUS; i++)
- if ((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == i))
- cpu_data[i].loops_per_jiffy = cpufreq_scale(cpu_data[i].loops_per_jiffy, freq->old, freq->new);
- break;
+#endif
}
return 0;
@@ -260,6 +259,10 @@ static int init_tsc(void)
* moaned if you have the only one in the world - you fix it!
*/
+#ifdef CONFIG_CPU_FREQ
+ cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
+#endif
+
if (cpu_has_tsc) {
unsigned long tsc_quotient = calibrate_tsc();
if (tsc_quotient) {
@@ -282,9 +285,6 @@ static int init_tsc(void)
"0" (eax), "1" (edx));
printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000);
}
-#ifdef CONFIG_CPU_FREQ
- cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
-#endif
return 0;
}
}
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index c028ac4ab667..332ccea33b8b 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -87,50 +87,6 @@ asmlinkage void machine_check(void);
static int kstack_depth_to_print = 24;
-
-/*
- * If the address is either in the .text section of the
- * kernel, or in the vmalloc'ed module regions, it *may*
- * be the address of a calling routine
- */
-
-#ifdef CONFIG_MODULES
-
-/* FIXME: Accessed without a lock --RR */
-extern struct list_head modules;
-
-static inline int kernel_text_address(unsigned long addr)
-{
- int retval = 0;
- struct module *mod;
-
- if (addr >= (unsigned long) &_stext &&
- addr <= (unsigned long) &_etext)
- return 1;
-
- list_for_each_entry(mod, &modules, list) {
- /* mod_bound tests for addr being inside the vmalloc'ed
- * module area. Of course it'd be better to test only
- * for the .text subset... */
- if (mod_bound((void *)addr, 0, mod)) {
- retval = 1;
- break;
- }
- }
-
- return retval;
-}
-
-#else
-
-static inline int kernel_text_address(unsigned long addr)
-{
- return (addr >= (unsigned long) &_stext &&
- addr <= (unsigned long) &_etext);
-}
-
-#endif
-
void show_trace(unsigned long * stack)
{
int i;
@@ -338,7 +294,7 @@ static inline void do_trap(int trapnr, int signr, char *str, int vm86,
}
kernel_trap: {
- unsigned long fixup;
+ const struct exception_table_entry *fixup;
#ifdef CONFIG_PNPBIOS
if (unlikely((regs->xcs | 8) == 0x88)) /* 0x80 or 0x88 */
{
@@ -354,9 +310,9 @@ static inline void do_trap(int trapnr, int signr, char *str, int vm86,
}
#endif
- fixup = search_exception_table(regs->eip);
+ fixup = search_exception_tables(regs->eip);
if (fixup)
- regs->eip = fixup;
+ regs->eip = fixup->fixup;
else
die(str, regs, error_code);
return;
@@ -435,10 +391,10 @@ gp_in_vm86:
gp_in_kernel:
{
- unsigned long fixup;
- fixup = search_exception_table(regs->eip);
+ const struct exception_table_entry *fixup;
+ fixup = search_exception_tables(regs->eip);
if (fixup) {
- regs->eip = fixup;
+ regs->eip = fixup->fixup;
return;
}
die("general protection fault", regs, error_code);
diff --git a/arch/i386/mm/extable.c b/arch/i386/mm/extable.c
index b94fb8d234da..946e7ad6fbcb 100644
--- a/arch/i386/mm/extable.c
+++ b/arch/i386/mm/extable.c
@@ -7,13 +7,11 @@
#include <linux/spinlock.h>
#include <asm/uaccess.h>
-extern const struct exception_table_entry __start___ex_table[];
-extern const struct exception_table_entry __stop___ex_table[];
-
-static inline unsigned long
-search_one_table(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value)
+/* Simple binary search */
+const struct exception_table_entry *
+search_extable(const struct exception_table_entry *first,
+ const struct exception_table_entry *last,
+ unsigned long value)
{
while (first <= last) {
const struct exception_table_entry *mid;
@@ -22,43 +20,11 @@ search_one_table(const struct exception_table_entry *first,
mid = (last - first) / 2 + first;
diff = mid->insn - value;
if (diff == 0)
- return mid->fixup;
+ return mid;
else if (diff < 0)
first = mid+1;
else
last = mid-1;
}
- return 0;
-}
-
-extern spinlock_t modlist_lock;
-
-unsigned long
-search_exception_table(unsigned long addr)
-{
- unsigned long ret = 0;
-
-#ifndef CONFIG_MODULES
- /* There is only the kernel to search. */
- ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
- return ret;
-#else
- unsigned long flags;
- struct list_head *i;
-
- /* The kernel is the last "module" -- no need to treat it special. */
- spin_lock_irqsave(&modlist_lock, flags);
- list_for_each(i, &extables) {
- struct exception_table *ex
- = list_entry(i, struct exception_table, list);
- if (ex->num_entries == 0)
- continue;
- ret = search_one_table(ex->entry,
- ex->entry + ex->num_entries - 1, addr);
- if (ret)
- break;
- }
- spin_unlock_irqrestore(&modlist_lock, flags);
- return ret;
-#endif
+ return NULL;
}
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index 56827d817963..e1ebd7239849 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/tty.h>
#include <linux/vt_kern.h> /* For unblank_screen() */
+#include <linux/module.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -154,7 +155,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
struct vm_area_struct * vma;
unsigned long address;
unsigned long page;
- unsigned long fixup;
+ const struct exception_table_entry *fixup;
int write;
siginfo_t info;
@@ -310,8 +311,8 @@ bad_area:
no_context:
/* Are we prepared to handle this kernel fault? */
- if ((fixup = search_exception_table(regs->eip)) != 0) {
- regs->eip = fixup;
+ if ((fixup = search_exception_tables(regs->eip)) != NULL) {
+ regs->eip = fixup->fixup;
return;
}
diff --git a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c
index 14a61a9bf5c4..1663e7730a18 100644
--- a/arch/i386/mm/hugetlbpage.c
+++ b/arch/i386/mm/hugetlbpage.c
@@ -234,8 +234,12 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
ret = -ENOMEM;
goto out;
}
- add_to_page_cache(page, mapping, idx);
+ ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
unlock_page(page);
+ if (ret) {
+ free_huge_page(page);
+ goto out;
+ }
}
set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
}
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 8d1e2c1e5148..0d33b4830d84 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -438,6 +438,16 @@ void __init mem_init(void)
bad_ppro = ppro_with_ram_bug();
+#ifdef CONFIG_HIGHMEM
+ /* check that fixmap and pkmap do not overlap */
+ if (PKMAP_BASE+LAST_PKMAP*PAGE_SIZE >= FIXADDR_START) {
+ printk(KERN_ERR "fixmap and kmap areas overlap - this will crash\n");
+ printk(KERN_ERR "pkstart: %lxh pkend: %lxh fixstart %lxh\n",
+ PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE, FIXADDR_START);
+ BUG();
+ }
+#endif
+
set_max_mapnr_init();
#ifdef CONFIG_HIGHMEM
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index ad20bedba50c..65860c3865a5 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -821,42 +821,6 @@ asmlinkage void buserr_c(struct frame *fp)
static int kstack_depth_to_print = 48;
-extern char _stext, _etext;
-
-#ifdef CONFIG_MODULES
-
-/* FIXME: Accessed without a lock --RR */
-extern struct list_head modules;
-
-static inline int kernel_text_address(unsigned long addr)
-{
- struct module *mod;
-
- if (addr >= (unsigned long) &_stext &&
- addr <= (unsigned long) &_etext)
- return 1;
-
- list_for_each_entry(mod, &modules, list) {
- /* mod_bound tests for addr being inside the vmalloc'ed
- * module area. Of course it'd be better to test only
- * for the .text subset... */
- if (mod_bound((void *)addr, 0, mod))
- return 1;
- }
-
- return 0;
-}
-
-#else // !CONFIG_MODULES
-
-static inline int kernel_text_address(unsigned long addr)
-{
- return (addr >= (unsigned long) &_stext &&
- addr <= (unsigned long) &_etext);
-}
-
-#endif // !CONFIG_MODULES
-
void show_trace(unsigned long *stack)
{
unsigned long *endstack;
diff --git a/arch/mips/kernel/pci.c b/arch/mips/kernel/pci.c
index 0437fc375d0c..a7672504939b 100644
--- a/arch/mips/kernel/pci.c
+++ b/arch/mips/kernel/pci.c
@@ -3,7 +3,7 @@
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
*
* Modified to be mips generic, ppopov@mvista.com
- * arch/mips/kernl/pci.c
+ * arch/mips/kernel/pci.c
* Common MIPS PCI routines.
*
* This program is free software; you can redistribute it and/or modify it
diff --git a/arch/mips64/sgi-ip27/ip27-rtc.c b/arch/mips64/sgi-ip27/ip27-rtc.c
index 3a71a4b8b2fd..084d341a8b5b 100644
--- a/arch/mips64/sgi-ip27/ip27-rtc.c
+++ b/arch/mips64/sgi-ip27/ip27-rtc.c
@@ -202,9 +202,15 @@ static int __init rtc_init(void)
KL_CONFIG_CH_CONS_INFO(nid)->memory_base + IOC3_BYTEBUS_DEV0;
printk(KERN_INFO "Real Time Clock Driver v%s\n", RTC_VERSION);
- if (misc_register(&rtc_dev))
+ if (misc_register(&rtc_dev)) {
+ printk(KERN_ERR "rtc: cannot register misc device.\n");
return -ENODEV;
- create_proc_read_entry ("rtc", 0, NULL, rtc_read_proc, NULL);
+ }
+ if (!create_proc_read_entry ("rtc", 0, NULL, rtc_read_proc, NULL)) {
+ printk(KERN_ERR "rtc: cannot create /proc/rtc.\n");
+ misc_deregister(&rtc_dev);
+ return -ENOENT;
+ }
save_flags(flags);
cli();
diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c
index e597f1478e46..e8544761df0a 100644
--- a/arch/parisc/kernel/perf.c
+++ b/arch/parisc/kernel/perf.c
@@ -500,6 +500,8 @@ static struct miscdevice perf_dev = {
*/
static int __init perf_init(void)
{
+ int retval;
+
/* Determine correct processor interface to use */
bitmask_array = perf_bitmasks;
@@ -518,11 +520,17 @@ static int __init perf_init(void)
return -ENODEV;
}
+ retval = misc_register(&perf_dev);
+ if (retval < 0) {
+ printk(KERN_ERR "Performance monitoring counters: "
+ "cannot register misc device.\n");
+ return retval;
+ }
+
/* Patch the images to match the system */
perf_patch_images();
spin_lock_init(&perf_lock);
- misc_register(&perf_dev);
/* TODO: this only lets us access the first cpu.. what to do for SMP? */
cpu_device = cpu_data[0].dev;
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index f108dbc1614e..ed250fadcd89 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -123,31 +123,6 @@ void dump_stack(void)
static int kstack_depth_to_print = 48;
-extern struct module kernel_module;
-
-static inline int kernel_text_address(unsigned long addr)
-{
-#ifdef CONFIG_MODULES
- struct module *mod;
-#endif
- extern char _stext, _etext;
-
- if (addr >= (unsigned long) &_stext &&
- addr <= (unsigned long) &_etext)
- return 1;
-
-#ifdef CONFIG_MODULES
- for (mod = module_list; mod != &kernel_module; mod = mod->next) {
- /* mod_bound tests for addr being inside the vmalloc'ed
- * module area. Of course it'd be better to test only
- * for the .text subset... */
- if (mod_bound(addr, 0, mod))
- return 1;
- }
-#endif
-
- return 0;
-}
void show_stack(unsigned long *sp)
{
diff --git a/arch/ppc/kernel/module.c b/arch/ppc/kernel/module.c
index 696a4faaeb3c..639b07c008ba 100644
--- a/arch/ppc/kernel/module.c
+++ b/arch/ppc/kernel/module.c
@@ -103,7 +103,7 @@ static unsigned long get_plt_size(const Elf32_Ehdr *hdr,
int module_frob_arch_sections(Elf32_Ehdr *hdr,
Elf32_Shdr *sechdrs,
- const char *secstrings,
+ char *secstrings,
struct module *me)
{
unsigned int i;
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index 16a8128d5aaa..9d4fc78b2dc9 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -29,6 +29,7 @@
#include <linux/interrupt.h>
#include <linux/config.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
@@ -115,7 +116,7 @@ void
MachineCheckException(struct pt_regs *regs)
{
#ifdef CONFIG_ALL_PPC
- unsigned long fixup;
+ const struct exception_table_entry *entry;
#endif /* CONFIG_ALL_PPC */
unsigned long msr = regs->msr;
@@ -148,7 +149,7 @@ MachineCheckException(struct pt_regs *regs)
* -- paulus.
*/
if (((msr & 0xffff0000) == 0 || (msr & (0x80000 | 0x40000)))
- && (fixup = search_exception_table(regs->nip)) != 0) {
+ && (entry = search_exception_tables(regs->nip)) != NULL) {
/*
* Check that it's a sync instruction, or somewhere
* in the twi; isync; nop sequence that inb/inw/inl uses.
diff --git a/arch/ppc/mm/extable.c b/arch/ppc/mm/extable.c
index aee3118d18d2..3b8f08b47ab3 100644
--- a/arch/ppc/mm/extable.c
+++ b/arch/ppc/mm/extable.c
@@ -6,6 +6,7 @@
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/init.h>
#include <asm/uaccess.h>
extern struct exception_table_entry __start___ex_table[];
@@ -40,16 +41,17 @@ sort_ex_table(struct exception_table_entry *start,
}
}
-void
+void __init
sort_exception_table(void)
{
sort_ex_table(__start___ex_table, __stop___ex_table);
}
-static inline unsigned long
-search_one_table(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value)
+/* Simple binary search */
+const struct exception_table_entry *
+search_extable(const struct exception_table_entry *first,
+ const struct exception_table_entry *last,
+ unsigned long value)
{
while (first <= last) {
const struct exception_table_entry *mid;
@@ -58,41 +60,11 @@ search_one_table(const struct exception_table_entry *first,
mid = (last - first) / 2 + first;
diff = mid->insn - value;
if (diff == 0)
- return mid->fixup;
+ return mid;
else if (diff < 0)
first = mid+1;
else
last = mid-1;
}
- return 0;
-}
-
-unsigned long
-search_exception_table(unsigned long addr)
-{
- unsigned long ret = 0;
-
-#ifndef CONFIG_MODULES
- /* There is only the kernel to search. */
- ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
-#else
- unsigned long flags;
- struct list_head *i;
-
- /* The kernel is the last "module" -- no need to treat it special. */
- spin_lock_irqsave(&modlist_lock, flags);
- list_for_each(i, &extables) {
- struct exception_table *ex
- = list_entry(i, struct exception_table, list);
- if (ex->num_entries == 0)
- continue;
- ret = search_one_table(ex->entry,
- ex->entry + ex->num_entries - 1, addr);
- if (ret)
- break;
- }
- spin_unlock_irqrestore(&modlist_lock, flags);
-#endif
-
- return ret;
+ return NULL;
}
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
index de7d090e7b47..686745055096 100644
--- a/arch/ppc/mm/fault.c
+++ b/arch/ppc/mm/fault.c
@@ -27,6 +27,7 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/highmem.h>
+#include <linux/module.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -263,12 +264,11 @@ void
bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
{
extern void die(const char *,struct pt_regs *,long);
-
- unsigned long fixup;
+ const struct exception_table_entry *entry;
/* Are we prepared to handle this fault? */
- if ((fixup = search_exception_table(regs->nip)) != 0) {
- regs->nip = fixup;
+ if ((entry = search_exception_tables(regs->nip)) != NULL) {
+ regs->nip = entry->fixup;
return;
}
diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c
index 4dce1e9e74f2..20e1d2bc0e2d 100644
--- a/arch/ppc64/kernel/rtc.c
+++ b/arch/ppc64/kernel/rtc.c
@@ -196,8 +196,17 @@ static struct miscdevice rtc_dev=
static int __init rtc_init(void)
{
- misc_register(&rtc_dev);
- create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL);
+ int retval;
+
+ retval = misc_register(&rtc_dev);
+ if(retval < 0)
+ return retval;
+
+#ifdef CONFIG_PROC_FS
+ if(create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL) == NULL)
+ misc_deregister(&rtc_dev);
+ return -ENOMEM;
+#endif
printk(KERN_INFO "i/pSeries Real Time Clock Driver v" RTC_VERSION "\n");
diff --git a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
index ef722cd2058f..1898fd9aeaa4 100644
--- a/arch/ppc64/kernel/signal32.c
+++ b/arch/ppc64/kernel/signal32.c
@@ -57,7 +57,7 @@
struct sigregs32 {
/*
* the gp_regs array is 32 bit representation of the pt_regs
- * structure that was stored on the kernle stack during the
+ * structure that was stored on the kernel stack during the
* system call that was interrupted for the signal.
*
* Note that the entire pt_regs regs structure will fit in
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c
index d1d4dd05c212..537a5e802070 100644
--- a/arch/s390/kernel/module.c
+++ b/arch/s390/kernel/module.c
@@ -51,9 +51,9 @@ void module_free(struct module *mod, void *module_region)
table entries. */
}
-int module_frob_arch_sections(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- const char *secstrings,
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ char *secstrings,
struct module *mod)
{
// FIXME: add space needed for GOT/PLT
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 5eb5923e001b..8706fc762fd7 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -63,50 +63,6 @@ static ext_int_info_t ext_int_pfault;
static int kstack_depth_to_print = 12;
-/*
- * If the address is either in the .text section of the
- * kernel, or in the vmalloc'ed module regions, it *may*
- * be the address of a calling routine
- */
-extern char _stext, _etext;
-
-#ifdef CONFIG_MODULES
-
-/* FIXME: Accessed without a lock --RR */
-extern struct list_head modules;
-
-static inline int kernel_text_address(unsigned long addr)
-{
- int retval = 0;
- struct module *mod;
-
- if (addr >= (unsigned long) &_stext &&
- addr <= (unsigned long) &_etext)
- return 1;
-
- list_for_each_entry(mod, &modules, list) {
- /* mod_bound tests for addr being inside the vmalloc'ed
- * module area. Of course it'd be better to test only
- * for the .text subset... */
- if (mod_bound((void*)addr, 0, mod)) {
- retval = 1;
- break;
- }
- }
-
- return retval;
-}
-
-#else
-
-static inline int kernel_text_address(unsigned long addr)
-{
- return (addr >= (unsigned long) &_stext &&
- addr <= (unsigned long) &_etext);
-}
-
-#endif
-
void show_trace(unsigned long * stack)
{
unsigned long backchain, low_addr, high_addr, ret_addr;
diff --git a/arch/s390x/kernel/module.c b/arch/s390x/kernel/module.c
index 61f3b34e90be..f35512379467 100644
--- a/arch/s390x/kernel/module.c
+++ b/arch/s390x/kernel/module.c
@@ -52,9 +52,9 @@ void module_free(struct module *mod, void *module_region)
}
/* s390/s390x needs additional memory for GOT/PLT sections. */
-int module_frob_arch_sections(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- const char *secstrings,
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ char *secstrings,
struct module *mod)
{
// FIXME: add space needed for GOT/PLT
diff --git a/arch/s390x/kernel/traps.c b/arch/s390x/kernel/traps.c
index e67855f55ac4..1c5cd64b3ecd 100644
--- a/arch/s390x/kernel/traps.c
+++ b/arch/s390x/kernel/traps.c
@@ -65,50 +65,6 @@ static ext_int_info_t ext_int_pfault;
static int kstack_depth_to_print = 20;
-/*
- * If the address is either in the .text section of the
- * kernel, or in the vmalloc'ed module regions, it *may*
- * be the address of a calling routine
- */
-extern char _stext, _etext;
-
-#ifdef CONFIG_MODULES
-
-/* FIXME: Accessed without a lock --RR */
-extern struct list_head modules;
-
-static inline int kernel_text_address(unsigned long addr)
-{
- int retval = 0;
- struct module *mod;
-
- if (addr >= (unsigned long) &_stext &&
- addr <= (unsigned long) &_etext)
- return 1;
-
- list_for_each_entry(mod, &modules, list) {
- /* mod_bound tests for addr being inside the vmalloc'ed
- * module area. Of course it'd be better to test only
- * for the .text subset... */
- if (mod_bound((void*)addr, 0, mod)) {
- retval = 1;
- break;
- }
- }
-
- return retval;
-}
-
-#else
-
-static inline int kernel_text_address(unsigned long addr)
-{
- return (addr >= (unsigned long) &_stext &&
- addr <= (unsigned long) &_etext);
-}
-
-#endif
-
void show_trace(unsigned long * stack)
{
unsigned long backchain, low_addr, high_addr, ret_addr;
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
index 348c24f63d85..26aa5e1259d4 100644
--- a/arch/sparc/kernel/module.c
+++ b/arch/sparc/kernel/module.c
@@ -37,9 +37,9 @@ void module_free(struct module *mod, void *module_region)
}
/* We don't need anything special. */
-int module_frob_arch_sections(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- const char *secstrings,
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ char *secstrings,
struct module *mod)
{
return 0;
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
index f6107871dfd3..035c7bf4232a 100644
--- a/arch/sparc64/kernel/ioctl32.c
+++ b/arch/sparc64/kernel/ioctl32.c
@@ -450,13 +450,13 @@ struct ifreq32 {
struct ifmap32 ifru_map;
char ifru_slave[IFNAMSIZ]; /* Just fits the size */
char ifru_newname[IFNAMSIZ];
- __kernel_caddr_t32 ifru_data;
+ compat_caddr_t ifru_data;
} ifr_ifru;
};
struct ifconf32 {
int ifc_len; /* size of buffer */
- __kernel_caddr_t32 ifcbuf;
+ compat_caddr_t ifcbuf;
};
#ifdef CONFIG_NET
@@ -1009,7 +1009,7 @@ static int fbiogscursor(unsigned int fd, unsigned int cmd, unsigned long arg)
struct fb_fix_screeninfo32 {
char id[16];
- __kernel_caddr_t32 smem_start;
+ compat_caddr_t smem_start;
__u32 smem_len;
__u32 type;
__u32 type_aux;
@@ -1018,7 +1018,7 @@ struct fb_fix_screeninfo32 {
__u16 ypanstep;
__u16 ywrapstep;
__u32 line_length;
- __kernel_caddr_t32 mmio_start;
+ compat_caddr_t mmio_start;
__u32 mmio_len;
__u32 accel;
__u16 reserved[3];
@@ -1027,10 +1027,10 @@ struct fb_fix_screeninfo32 {
struct fb_cmap32 {
__u32 start;
__u32 len;
- __kernel_caddr_t32 red;
- __kernel_caddr_t32 green;
- __kernel_caddr_t32 blue;
- __kernel_caddr_t32 transp;
+ compat_caddr_t red;
+ compat_caddr_t green;
+ compat_caddr_t blue;
+ compat_caddr_t transp;
};
static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
@@ -1169,7 +1169,7 @@ struct floppy_struct32 {
unsigned char rate;
unsigned char spec1;
unsigned char fmt_gap;
- const __kernel_caddr_t32 name;
+ const compat_caddr_t name;
};
struct floppy_drive_params32 {
@@ -1208,7 +1208,7 @@ struct floppy_drive_struct32 {
int fd_ref;
int fd_device;
int last_checked;
- __kernel_caddr_t32 dmabuf;
+ compat_caddr_t dmabuf;
int bufblocks;
};
@@ -1732,7 +1732,7 @@ static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigne
}
struct ppp_option_data32 {
- __kernel_caddr_t32 ptr;
+ compat_caddr_t ptr;
__u32 length;
int transmit;
};
@@ -1813,8 +1813,8 @@ struct mtget32 {
__u32 mt_dsreg;
__u32 mt_gstat;
__u32 mt_erreg;
- __kernel_daddr_t32 mt_fileno;
- __kernel_daddr_t32 mt_blkno;
+ compat_daddr_t mt_fileno;
+ compat_daddr_t mt_blkno;
};
#define MTIOCGET32 _IOR('m', 2, struct mtget32)
@@ -1932,7 +1932,7 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
struct cdrom_read32 {
int cdread_lba;
- __kernel_caddr_t32 cdread_bufaddr;
+ compat_caddr_t cdread_bufaddr;
int cdread_buflen;
};
@@ -1940,16 +1940,16 @@ struct cdrom_read_audio32 {
union cdrom_addr addr;
u_char addr_format;
int nframes;
- __kernel_caddr_t32 buf;
+ compat_caddr_t buf;
};
struct cdrom_generic_command32 {
unsigned char cmd[CDROM_PACKET_SIZE];
- __kernel_caddr_t32 buffer;
+ compat_caddr_t buffer;
unsigned int buflen;
int stat;
- __kernel_caddr_t32 sense;
- __kernel_caddr_t32 reserved[3];
+ compat_caddr_t sense;
+ compat_caddr_t reserved[3];
};
static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
@@ -1958,7 +1958,7 @@ static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long ar
struct cdrom_read cdread;
struct cdrom_read_audio cdreadaudio;
struct cdrom_generic_command cgc;
- __kernel_caddr_t32 addr;
+ compat_caddr_t addr;
char *data = 0;
void *karg;
int err = 0;
@@ -2041,9 +2041,9 @@ out: if (data)
struct loop_info32 {
int lo_number; /* ioctl r/o */
- __kernel_dev_t32 lo_device; /* ioctl r/o */
+ compat_dev_t lo_device; /* ioctl r/o */
unsigned int lo_inode; /* ioctl r/o */
- __kernel_dev_t32 lo_rdevice; /* ioctl r/o */
+ compat_dev_t lo_rdevice; /* ioctl r/o */
int lo_offset;
int lo_encrypt_type;
int lo_encrypt_key_size; /* ioctl w/o */
@@ -2248,7 +2248,7 @@ static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long a
set_fs(old_fs);
if (err >= 0)
- err = put_user(kuid, (__kernel_uid_t32 *)arg);
+ err = put_user(kuid, (compat_uid_t *)arg);
return err;
}
@@ -2256,7 +2256,7 @@ static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long a
struct ncp_ioctl_request_32 {
unsigned int function;
unsigned int size;
- __kernel_caddr_t32 data;
+ compat_caddr_t data;
};
struct ncp_fs_info_v2_32 {
@@ -2277,13 +2277,13 @@ struct ncp_objectname_ioctl_32
{
int auth_type;
unsigned int object_name_len;
- __kernel_caddr_t32 object_name; /* an userspace data, in most cases user name */
+ compat_caddr_t object_name; /* an userspace data, in most cases user name */
};
struct ncp_privatedata_ioctl_32
{
unsigned int len;
- __kernel_caddr_t32 data; /* ~1000 for NDS */
+ compat_caddr_t data; /* ~1000 for NDS */
};
#define NCP_IOC_NCPREQUEST_32 _IOR('n', 1, struct ncp_ioctl_request_32)
@@ -2557,12 +2557,12 @@ static int do_ncp_setprivatedata(unsigned int fd, unsigned int cmd, unsigned lon
struct atmif_sioc32 {
int number;
int length;
- __kernel_caddr_t32 arg;
+ compat_caddr_t arg;
};
struct atm_iobuf32 {
int length;
- __kernel_caddr_t32 buffer;
+ compat_caddr_t buffer;
};
#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32)
@@ -2623,7 +2623,7 @@ static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg)
iobuf.length = iobuf32.length;
- if (iobuf32.buffer == (__kernel_caddr_t32) NULL || iobuf32.length == 0) {
+ if (iobuf32.buffer == (compat_caddr_t) NULL || iobuf32.length == 0) {
iobuf.buffer = (void*)(unsigned long)iobuf32.buffer;
} else {
iobuf.buffer = kmalloc(iobuf.length, GFP_KERNEL);
@@ -2677,7 +2677,7 @@ static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg)
sioc.number = sioc32.number;
sioc.length = sioc32.length;
- if (sioc32.arg == (__kernel_caddr_t32) NULL || sioc32.length == 0) {
+ if (sioc32.arg == (compat_caddr_t) NULL || sioc32.length == 0) {
sioc.arg = (void*)(unsigned long)sioc32.arg;
} else {
sioc.arg = kmalloc(sioc.length, GFP_KERNEL);
@@ -2835,7 +2835,7 @@ typedef struct {
} lv_status_byindex_req32_t;
typedef struct {
- __kernel_dev_t32 dev;
+ compat_dev_t dev;
u32 lv;
} lv_status_bydev_req32_t;
@@ -5128,7 +5128,7 @@ HANDLE_IOCTL(VIDIOCSFBUF32, do_video_ioctl)
HANDLE_IOCTL(VIDIOCGFREQ32, do_video_ioctl)
HANDLE_IOCTL(VIDIOCSFREQ32, do_video_ioctl)
/* One SMB ioctl needs translations. */
-#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, __kernel_uid_t32)
+#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t)
HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid)
/* NCPFS */
HANDLE_IOCTL(NCP_IOC_NCPREQUEST_32, do_ncp_ncprequest)
diff --git a/arch/sparc64/kernel/module.c b/arch/sparc64/kernel/module.c
index dc0daa59aac1..cf6aa58b9564 100644
--- a/arch/sparc64/kernel/module.c
+++ b/arch/sparc64/kernel/module.c
@@ -144,9 +144,9 @@ void module_free(struct module *mod, void *module_region)
}
/* We don't need anything special. */
-int module_frob_arch_sections(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- const char *secstrings,
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ char *secstrings,
struct module *mod)
{
return 0;
diff --git a/arch/sparc64/kernel/sunos_ioctl32.c b/arch/sparc64/kernel/sunos_ioctl32.c
index bcfa77a396bf..c95f15885c18 100644
--- a/arch/sparc64/kernel/sunos_ioctl32.c
+++ b/arch/sparc64/kernel/sunos_ioctl32.c
@@ -22,6 +22,7 @@
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
+#include <linux/compat.h>
#include <asm/kbio.h>
/* Use this to get at 32-bit user passed pointers. */
@@ -80,13 +81,13 @@ struct ifreq32 {
int ifru_mtu;
struct ifmap32 ifru_map;
char ifru_slave[IFNAMSIZ]; /* Just fits the size */
- __kernel_caddr_t32 ifru_data;
+ compat_caddr_t ifru_data;
} ifr_ifru;
};
struct ifconf32 {
int ifc_len; /* size of buffer */
- __kernel_caddr_t32 ifcbuf;
+ compat_caddr_t ifcbuf;
};
extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index e22bbcc94a97..d18415e983c9 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -290,11 +290,11 @@ struct msgbuf32 { s32 mtype; char mtext[1]; };
struct ipc_perm32
{
key_t key;
- __kernel_uid_t32 uid;
- __kernel_gid_t32 gid;
- __kernel_uid_t32 cuid;
- __kernel_gid_t32 cgid;
- __kernel_mode_t32 mode;
+ compat_uid_t uid;
+ compat_gid_t gid;
+ compat_uid_t cuid;
+ compat_gid_t cgid;
+ compat_mode_t mode;
unsigned short seq;
};
@@ -333,8 +333,8 @@ struct msqid_ds32
unsigned short msg_cbytes;
unsigned short msg_qnum;
unsigned short msg_qbytes;
- __kernel_ipc_pid_t32 msg_lspid;
- __kernel_ipc_pid_t32 msg_lrpid;
+ compat_ipc_pid_t msg_lspid;
+ compat_ipc_pid_t msg_lrpid;
};
struct msqid64_ds32 {
@@ -348,8 +348,8 @@ struct msqid64_ds32 {
unsigned int msg_cbytes;
unsigned int msg_qnum;
unsigned int msg_qbytes;
- __kernel_pid_t32 msg_lspid;
- __kernel_pid_t32 msg_lrpid;
+ compat_pid_t msg_lspid;
+ compat_pid_t msg_lrpid;
unsigned int __unused1;
unsigned int __unused2;
};
@@ -361,8 +361,8 @@ struct shmid_ds32 {
compat_time_t shm_atime;
compat_time_t shm_dtime;
compat_time_t shm_ctime;
- __kernel_ipc_pid_t32 shm_cpid;
- __kernel_ipc_pid_t32 shm_lpid;
+ compat_ipc_pid_t shm_cpid;
+ compat_ipc_pid_t shm_lpid;
unsigned short shm_nattch;
};
@@ -375,8 +375,8 @@ struct shmid64_ds32 {
unsigned int __pad3;
compat_time_t shm_ctime;
compat_size_t shm_segsz;
- __kernel_pid_t32 shm_cpid;
- __kernel_pid_t32 shm_lpid;
+ compat_pid_t shm_cpid;
+ compat_pid_t shm_lpid;
unsigned int shm_nattch;
unsigned int __unused1;
unsigned int __unused2;
@@ -1378,6 +1378,9 @@ int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf)
{
int err;
+ if (stat->size > MAX_NON_LFS)
+ return -EOVERFLOW;
+
err = put_user(stat->dev, &statbuf->st_dev);
err |= put_user(stat->ino, &statbuf->st_ino);
err |= put_user(stat->mode, &statbuf->st_mode);
@@ -1385,8 +1388,6 @@ int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf)
err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
err |= put_user(stat->rdev, &statbuf->st_rdev);
- if (stat->size > MAX_NON_LFS)
- return -EOVERFLOW;
err |= put_user(stat->size, &statbuf->st_size);
err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
err |= put_user(0, &statbuf->__unused1);
@@ -1412,16 +1413,16 @@ asmlinkage int sys32_sysfs(int option, u32 arg1, u32 arg2)
struct ncp_mount_data32_v3 {
int version;
unsigned int ncp_fd;
- __kernel_uid_t32 mounted_uid;
- __kernel_pid_t32 wdog_pid;
+ compat_uid_t mounted_uid;
+ compat_pid_t wdog_pid;
unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
unsigned int time_out;
unsigned int retry_count;
unsigned int flags;
- __kernel_uid_t32 uid;
- __kernel_gid_t32 gid;
- __kernel_mode_t32 file_mode;
- __kernel_mode_t32 dir_mode;
+ compat_uid_t uid;
+ compat_gid_t gid;
+ compat_mode_t file_mode;
+ compat_mode_t dir_mode;
};
struct ncp_mount_data32_v4 {
@@ -1492,11 +1493,11 @@ static void *do_ncp_super_data_conv(void *raw_data)
struct smb_mount_data32 {
int version;
- __kernel_uid_t32 mounted_uid;
- __kernel_uid_t32 uid;
- __kernel_gid_t32 gid;
- __kernel_mode_t32 file_mode;
- __kernel_mode_t32 dir_mode;
+ compat_uid_t mounted_uid;
+ compat_uid_t uid;
+ compat_gid_t gid;
+ compat_mode_t file_mode;
+ compat_mode_t dir_mode;
};
static void *do_smb_super_data_conv(void *raw_data)
@@ -1656,7 +1657,7 @@ static int put_rusage (struct rusage32 *ru, struct rusage *r)
return err;
}
-asmlinkage int sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options, struct rusage32 *ru)
+asmlinkage int sys32_wait4(compat_pid_t pid, unsigned int *stat_addr, int options, struct rusage32 *ru)
{
if (!ru)
return sys_wait4(pid, stat_addr, options, NULL);
@@ -1718,7 +1719,7 @@ asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);
-asmlinkage int sys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct compat_timespec *interval)
+asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec *interval)
{
struct timespec t;
int ret;
@@ -3027,27 +3028,27 @@ struct nfsctl_client32 {
struct nfsctl_export32 {
s8 ex32_client[NFSCLNT_IDMAX+1];
s8 ex32_path[NFS_MAXPATHLEN+1];
- __kernel_dev_t32 ex32_dev;
- __kernel_ino_t32 ex32_ino;
+ compat_dev_t ex32_dev;
+ compat_ino_t ex32_ino;
s32 ex32_flags;
- __kernel_uid_t32 ex32_anon_uid;
- __kernel_gid_t32 ex32_anon_gid;
+ compat_uid_t ex32_anon_uid;
+ compat_gid_t ex32_anon_gid;
};
struct nfsctl_uidmap32 {
u32 ug32_ident; /* char * */
- __kernel_uid_t32 ug32_uidbase;
+ compat_uid_t ug32_uidbase;
s32 ug32_uidlen;
u32 ug32_udimap; /* uid_t * */
- __kernel_uid_t32 ug32_gidbase;
+ compat_uid_t ug32_gidbase;
s32 ug32_gidlen;
u32 ug32_gdimap; /* gid_t * */
};
struct nfsctl_fhparm32 {
struct sockaddr gf32_addr;
- __kernel_dev_t32 gf32_dev;
- __kernel_ino_t32 gf32_ino;
+ compat_dev_t gf32_dev;
+ compat_ino_t gf32_ino;
s32 gf32_version;
};
@@ -3176,7 +3177,7 @@ static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
return -ENOMEM;
for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
err |= __get_user(karg->ca_umap.ug_udimap[i],
- &(((__kernel_uid_t32 *)A(uaddr))[i]));
+ &(((compat_uid_t *)A(uaddr))[i]));
err |= __get_user(karg->ca_umap.ug_gidbase,
&arg32->ca32_umap.ug32_gidbase);
err |= __get_user(karg->ca_umap.ug_uidlen,
@@ -3190,7 +3191,7 @@ static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
return -ENOMEM;
for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
err |= __get_user(karg->ca_umap.ug_gdimap[i],
- &(((__kernel_gid_t32 *)A(uaddr))[i]));
+ &(((compat_gid_t *)A(uaddr))[i]));
return (err ? -EFAULT : 0);
}
@@ -3482,7 +3483,7 @@ asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 coun
extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
-asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count)
+asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count)
{
mm_segment_t old_fs = get_fs();
int ret;
@@ -3503,7 +3504,7 @@ asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s
extern asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count);
-asmlinkage int sys32_sendfile64(int out_fd, int in_fd, __kernel_loff_t32 *offset, s32 count)
+asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t *offset, s32 count)
{
mm_segment_t old_fs = get_fs();
int ret;
@@ -3737,7 +3738,7 @@ asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
extern asmlinkage int sys_sched_setaffinity(pid_t pid, unsigned int len,
unsigned long *user_mask_ptr);
-asmlinkage int sys32_sched_setaffinity(__kernel_pid_t32 pid, unsigned int len,
+asmlinkage int sys32_sched_setaffinity(compat_pid_t pid, unsigned int len,
u32 *user_mask_ptr)
{
unsigned long kernel_mask;
@@ -3761,7 +3762,7 @@ asmlinkage int sys32_sched_setaffinity(__kernel_pid_t32 pid, unsigned int len,
extern asmlinkage int sys_sched_getaffinity(pid_t pid, unsigned int len,
unsigned long *user_mask_ptr);
-asmlinkage int sys32_sched_getaffinity(__kernel_pid_t32 pid, unsigned int len,
+asmlinkage int sys32_sched_getaffinity(compat_pid_t pid, unsigned int len,
u32 *user_mask_ptr)
{
unsigned long kernel_mask;
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index cb27fd8fb5aa..3fae734358c5 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -798,14 +798,14 @@ asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid)
}
/* So stupid... */
-extern asmlinkage int sys32_wait4(__kernel_pid_t32 pid,
+extern asmlinkage int sys32_wait4(compat_pid_t pid,
u32 stat_addr, int options, u32 ru);
-asmlinkage int sunos_wait4(__kernel_pid_t32 pid, u32 stat_addr, int options, u32 ru)
+asmlinkage int sunos_wait4(compat_pid_t pid, u32 stat_addr, int options, u32 ru)
{
int ret;
- ret = sys32_wait4((pid ? pid : ((__kernel_pid_t32)-1)),
+ ret = sys32_wait4((pid ? pid : ((compat_pid_t)-1)),
stat_addr, options, ru);
return ret;
}
@@ -931,11 +931,11 @@ struct msgbuf32 {
struct ipc_perm32
{
key_t key;
- __kernel_uid_t32 uid;
- __kernel_gid_t32 gid;
- __kernel_uid_t32 cuid;
- __kernel_gid_t32 cgid;
- __kernel_mode_t32 mode;
+ compat_uid_t uid;
+ compat_gid_t gid;
+ compat_uid_t cuid;
+ compat_gid_t cgid;
+ compat_mode_t mode;
unsigned short seq;
};
@@ -952,8 +952,8 @@ struct msqid_ds32
unsigned short msg_cbytes;
unsigned short msg_qnum;
unsigned short msg_qbytes;
- __kernel_ipc_pid_t32 msg_lspid;
- __kernel_ipc_pid_t32 msg_lrpid;
+ compat_ipc_pid_t msg_lspid;
+ compat_ipc_pid_t msg_lrpid;
};
static inline int sunos_msqid_get(struct msqid_ds32 *user,
@@ -1084,8 +1084,8 @@ struct shmid_ds32 {
compat_time_t shm_atime;
compat_time_t shm_dtime;
compat_time_t shm_ctime;
- __kernel_ipc_pid_t32 shm_cpid;
- __kernel_ipc_pid_t32 shm_lpid;
+ compat_ipc_pid_t shm_cpid;
+ compat_ipc_pid_t shm_lpid;
unsigned short shm_nattch;
};
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 6c0db000fcf1..23e5a862f088 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -149,10 +149,10 @@ void data_access_exception (struct pt_regs *regs,
if (regs->tstate & TSTATE_PRIV) {
/* Test if this comes from uaccess places. */
- unsigned long fixup, g2;
+ unsigned long fixup;
+ unsigned long g2 = regs->u_regs[UREG_G2];
- g2 = regs->u_regs[UREG_G2];
- if ((fixup = search_exception_table (regs->tpc, &g2))) {
+ if ((fixup = search_extables_range(regs->tpc, &g2))) {
/* Ouch, somebody is trying ugly VM hole tricks on us... */
#ifdef DEBUG_EXCEPTIONS
printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc);
@@ -1370,7 +1370,7 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned
recoverable = 1;
} else {
unsigned long g2 = regs->u_regs[UREG_G2];
- unsigned long fixup = search_exception_table(regs->tpc, &g2);
+ unsigned long fixup = search_extables_range(regs->tpc, &g2);
if (fixup != 0UL) {
/* OK, kernel access to userspace. */
@@ -1390,7 +1390,7 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned
/* Only perform fixup if we still have a
* recoverable condition.
*/
- if (fixup != 0UL && recoverable) {
+ if (recoverable) {
regs->tpc = fixup;
regs->tnpc = regs->tpc + 4;
regs->u_regs[UREG_G2] = g2;
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
index d5f8f8eb0360..1d403a089e01 100644
--- a/arch/sparc64/kernel/unaligned.c
+++ b/arch/sparc64/kernel/unaligned.c
@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/module.h>
#include <asm/asi.h>
#include <asm/ptrace.h>
#include <asm/pstate.h>
@@ -360,7 +361,7 @@ void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn) __asm__ ("ke
void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
{
unsigned long g2 = regs->u_regs [UREG_G2];
- unsigned long fixup = search_exception_table (regs->tpc, &g2);
+ unsigned long fixup = search_extables_range(regs->tpc, &g2);
if (!fixup) {
unsigned long address = compute_effective_address(regs, insn, ((insn >> 25) & 0x1f));
diff --git a/arch/sparc64/mm/extable.c b/arch/sparc64/mm/extable.c
index 638a68166332..54a17bc63324 100644
--- a/arch/sparc64/mm/extable.c
+++ b/arch/sparc64/mm/extable.c
@@ -9,10 +9,11 @@
extern const struct exception_table_entry __start___ex_table[];
extern const struct exception_table_entry __stop___ex_table[];
-static unsigned long
-search_one_table(const struct exception_table_entry *start,
- const struct exception_table_entry *end,
- unsigned long value, unsigned long *g2)
+/* Caller knows they are in a range if ret->fixup == 0 */
+const struct exception_table_entry *
+search_extable(const struct exception_table_entry *start,
+ const struct exception_table_entry *last,
+ unsigned long value)
{
const struct exception_table_entry *walk;
@@ -30,7 +31,7 @@ search_one_table(const struct exception_table_entry *start,
*/
/* 1. Try to find an exact match. */
- for (walk = start; walk <= end; walk++) {
+ for (walk = start; walk <= last; walk++) {
if (walk->fixup == 0) {
/* A range entry, skip both parts. */
walk++;
@@ -38,55 +39,37 @@ search_one_table(const struct exception_table_entry *start,
}
if (walk->insn == value)
- return walk->fixup;
+ return walk;
}
/* 2. Try to find a range match. */
- for (walk = start; walk <= (end - 1); walk++) {
+ for (walk = start; walk <= (last - 1); walk++) {
if (walk->fixup)
continue;
- if (walk[0].insn <= value &&
- walk[1].insn > value) {
- *g2 = (value - walk[0].insn) / 4;
- return walk[1].fixup;
- }
+ if (walk[0].insn <= value && walk[1].insn > value)
+ return walk;
+
walk++;
}
- return 0;
+ return NULL;
}
-extern spinlock_t modlist_lock;
-
-unsigned long
-search_exception_table(unsigned long addr, unsigned long *g2)
+/* Special extable search, which handles ranges. Returns fixup */
+unsigned long search_extables_range(unsigned long addr, unsigned long *g2)
{
- unsigned long ret = 0;
+ const struct exception_table_entry *entry;
-#ifndef CONFIG_MODULES
- /* There is only the kernel to search. */
- ret = search_one_table(__start___ex_table,
- __stop___ex_table-1, addr, g2);
- return ret;
-#else
- unsigned long flags;
- struct list_head *i;
+ entry = search_exception_tables(addr);
+ if (!entry)
+ return 0;
- /* The kernel is the last "module" -- no need to treat it special. */
- spin_lock_irqsave(&modlist_lock, flags);
- list_for_each(i, &extables) {
- struct exception_table *ex =
- list_entry(i, struct exception_table, list);
- if (ex->num_entries == 0)
- continue;
- ret = search_one_table(ex->entry,
- ex->entry + ex->num_entries - 1,
- addr, g2);
- if (ret)
- break;
+ /* Inside range? Fix g2 and return correct fixup */
+ if (!entry->fixup) {
+ *g2 = (addr - entry->insn) / 4;
+ return (entry + 1)->fixup;
}
- spin_unlock_irqrestore(&modlist_lock, flags);
- return ret;
-#endif
+
+ return entry->fixup;
}
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index e5aa61b9f52d..5c4a56023668 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -14,6 +14,7 @@
#include <linux/mman.h>
#include <linux/signal.h>
#include <linux/mm.h>
+#include <linux/module.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/interrupt.h>
@@ -285,7 +286,7 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
/* Look in asi.h: All _S asis have LS bit set */
if ((asi & 0x1) &&
- (fixup = search_exception_table (regs->tpc, &g2))) {
+ (fixup = search_extables_range(regs->tpc, &g2))) {
regs->tpc = fixup;
regs->tnpc = regs->tpc + 4;
regs->u_regs[UREG_G2] = g2;
diff --git a/arch/sparc64/mm/hugetlbpage.c b/arch/sparc64/mm/hugetlbpage.c
index e48dbcb2c497..98045169d9c1 100644
--- a/arch/sparc64/mm/hugetlbpage.c
+++ b/arch/sparc64/mm/hugetlbpage.c
@@ -476,9 +476,16 @@ try_again:
page = alloc_hugetlb_page();
if (page == NULL) {
pte_unmap(pte);
+ retval = -ENOMEM;
+ goto out;
+ }
+ retval = add_to_page_cache(page, mapping,
+ idx, GFP_ATOMIC);
+ if (retval) {
+ pte_unmap(pte);
+ free_hugetlb_page(page);
goto out;
}
- add_to_page_cache(page, mapping, idx);
}
set_huge_pte(mm, vma, page, pte,
(vma->vm_flags & VM_WRITE));
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index 2bf29ad7ad27..4936445793b7 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -11,49 +11,6 @@
#include "sysrq.h"
#include "user_util.h"
- /*
- * If the address is either in the .text section of the
- * kernel, or in the vmalloc'ed module regions, it *may*
- * be the address of a calling routine
- */
-
-#ifdef CONFIG_MODULES
-
-/* FIXME: Accessed without a lock --RR */
-extern struct list_head modules;
-
-static inline int kernel_text_address(unsigned long addr)
-{
- int retval = 0;
- struct module *mod;
-
- if (addr >= (unsigned long) &_stext &&
- addr <= (unsigned long) &_etext)
- return 1;
-
- list_for_each_entry(mod, &modules, list) {
- /* mod_bound tests for addr being inside the vmalloc'ed
- * module area. Of course it'd be better to test only
- * for the .text subset... */
- if (mod_bound((void *) addr, 0, mod)) {
- retval = 1;
- break;
- }
- }
-
- return retval;
-}
-
-#else
-
-static inline int kernel_text_address(unsigned long addr)
-{
- return (addr >= (unsigned long) &_stext &&
- addr <= (unsigned long) &_etext);
-}
-
-#endif
-
void show_trace(unsigned long * stack)
{
int i;
diff --git a/arch/x86_64/kernel/module.c b/arch/x86_64/kernel/module.c
index c585076087db..9331fa3cda4d 100644
--- a/arch/x86_64/kernel/module.c
+++ b/arch/x86_64/kernel/module.c
@@ -26,9 +26,9 @@
#define DEBUGP(fmt...)
/* We don't need anything special. */
-int module_frob_arch_sections(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- const char *secstrings,
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ char *secstrings,
struct module *mod)
{
return 0;
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 20c4811bad6b..af118388f169 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -104,44 +104,6 @@ int printk_address(unsigned long address)
}
#endif
-
-#ifdef CONFIG_MODULES
-
-/* FIXME: Accessed without a lock --RR */
-extern struct list_head modules;
-
-static inline int kernel_text_address(unsigned long addr)
-{
- int retval = 0;
- struct module *mod;
-
- if (addr >= (unsigned long) &_stext &&
- addr <= (unsigned long) &_etext)
- return 1;
-
- list_for_each_entry(mod, &modules, list) {
- /* mod_bound tests for addr being inside the vmalloc'ed
- * module area. Of course it'd be better to test only
- * for the .text subset... */
- if (mod_bound((void *)addr, 0, mod)) {
- retval = 1;
- break;
- }
- }
-
- return retval;
-}
-
-#else
-
-static inline int kernel_text_address(unsigned long addr)
-{
- return (addr >= (unsigned long) &_stext &&
- addr <= (unsigned long) &_etext);
-}
-
-#endif
-
static inline unsigned long *in_exception_stack(int cpu, unsigned long stack)
{
int k;
diff --git a/arch/x86_64/mm/hugetlbpage.c b/arch/x86_64/mm/hugetlbpage.c
index bf5ea4753b28..d4515d57af34 100644
--- a/arch/x86_64/mm/hugetlbpage.c
+++ b/arch/x86_64/mm/hugetlbpage.c
@@ -232,8 +232,12 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
ret = -ENOMEM;
goto out;
}
- add_to_page_cache(page, mapping, idx);
+ ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
unlock_page(page);
+ if (ret) {
+ free_huge_page(page);
+ goto out;
+ }
}
set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
}
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index 8639f8bdaf15..bfa053f324f2 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -133,6 +133,7 @@ struct agp_bridge_data {
u32 *gatt_table;
u32 *gatt_table_real;
unsigned long scratch_page;
+ unsigned long scratch_page_real;
unsigned long gart_bus_addr;
unsigned long gatt_bus_addr;
u32 mode;
@@ -145,7 +146,6 @@ struct agp_bridge_data {
int needs_scratch_page;
int aperture_size_idx;
int num_aperture_sizes;
- int num_of_masks;
int capndx;
int cant_use_aperture;
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index a88b5bc7df27..b4c93c4bc398 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -198,7 +198,6 @@ static struct aper_size_info_32 ali_generic_sizes[7] =
static int __init ali_generic_setup (struct pci_dev *pdev)
{
agp_bridge.masks = ali_generic_masks;
- agp_bridge.num_of_masks = 1;
agp_bridge.aperture_sizes = (void *) ali_generic_sizes;
agp_bridge.size_type = U32_APER_SIZE;
agp_bridge.num_aperture_sizes = 7;
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index ac867494a63c..93ebe05ce412 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -308,7 +308,8 @@ static int amd_insert_memory(agp_memory * mem,
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
addr = (j * PAGE_SIZE) + agp_bridge.gart_bus_addr;
cur_gatt = GET_GATT(addr);
- cur_gatt[GET_GATT_OFF(addr)] = mem->memory[i];
+ cur_gatt[GET_GATT_OFF(addr)] =
+ agp_bridge.mask_memory(mem->memory[i], mem->type);
}
agp_bridge.tlb_flush(mem);
return 0;
@@ -354,7 +355,6 @@ static struct gatt_mask amd_irongate_masks[] =
static int __init amd_irongate_setup (struct pci_dev *pdev)
{
agp_bridge.masks = amd_irongate_masks;
- agp_bridge.num_of_masks = 1;
agp_bridge.aperture_sizes = (void *) amd_irongate_sizes;
agp_bridge.size_type = LVL2_APER_SIZE;
agp_bridge.num_aperture_sizes = 7;
diff --git a/drivers/char/agp/amd-k8-agp.c b/drivers/char/agp/amd-k8-agp.c
index aeb657b56c58..efa09382965f 100644
--- a/drivers/char/agp/amd-k8-agp.c
+++ b/drivers/char/agp/amd-k8-agp.c
@@ -81,7 +81,7 @@ static int x86_64_insert_memory(agp_memory * mem, off_t pg_start, int type)
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- addr = mem->memory[i];
+ addr = agp_bridge.mask_memory(mem->memory[i], mem->type);
tmp = addr;
BUG_ON(tmp & 0xffffff0000000ffc);
@@ -446,7 +446,6 @@ static void agp_x86_64_agp_enable(u32 mode)
static int __init amd_8151_setup (struct pci_dev *pdev)
{
agp_bridge.masks = amd_8151_masks;
- agp_bridge.num_of_masks = 1;
agp_bridge.aperture_sizes = (void *) amd_8151_sizes;
agp_bridge.size_type = U32_APER_SIZE;
agp_bridge.num_aperture_sizes = 7;
@@ -512,6 +511,7 @@ static struct __initdata pci_driver agp_amdk8_pci_driver = {
.probe = agp_amdk8_probe,
};
+/* Not static due to IOMMU code calling it early. */
int __init agp_amdk8_init(void)
{
int ret_val;
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 65cf115d48ce..1dbb93606c9a 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -86,7 +86,7 @@ static int agp_find_max (void)
{
long memory, index, result;
- memory = virt_to_phys(high_memory) >> 20;
+ memory = (num_physpages << PAGE_SHIFT) >> 20;
index = 1;
while ((memory > maxes_table[index].mem) && (index < 8))
@@ -123,8 +123,9 @@ static int agp_backend_initialize(struct pci_dev *dev)
printk(KERN_ERR PFX "unable to get memory for scratch page.\n");
return -ENOMEM;
}
- agp_bridge.scratch_page = virt_to_phys(addr);
- agp_bridge.scratch_page = agp_bridge.mask_memory(agp_bridge.scratch_page, 0);
+ agp_bridge.scratch_page_real = virt_to_phys(addr);
+ agp_bridge.scratch_page =
+ agp_bridge.mask_memory(agp_bridge.scratch_page_real, 0);
}
size_value = agp_bridge.fetch_size();
@@ -165,8 +166,7 @@ static int agp_backend_initialize(struct pci_dev *dev)
err_out:
if (agp_bridge.needs_scratch_page == TRUE) {
- agp_bridge.scratch_page &= ~(0x00000fff);
- agp_bridge.agp_destroy_page(phys_to_virt(agp_bridge.scratch_page));
+ agp_bridge.agp_destroy_page(phys_to_virt(agp_bridge.scratch_page_real));
}
if (got_gatt)
agp_bridge.free_gatt_table();
@@ -184,8 +184,7 @@ static void agp_backend_cleanup(void)
vfree(agp_bridge.key_list);
if (agp_bridge.needs_scratch_page == TRUE) {
- agp_bridge.scratch_page &= ~(0x00000fff);
- agp_bridge.agp_destroy_page(phys_to_virt(agp_bridge.scratch_page));
+ agp_bridge.agp_destroy_page(phys_to_virt(agp_bridge.scratch_page_real));
}
}
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index c952ec4fc751..835f241a0443 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -110,7 +110,6 @@ void agp_free_memory(agp_memory * curr)
}
if (curr->page_count != 0) {
for (i = 0; i < curr->page_count; i++) {
- curr->memory[i] &= ~(0x00000fff);
agp_bridge.agp_destroy_page(phys_to_virt(curr->memory[i]));
}
}
@@ -158,7 +157,7 @@ agp_memory *agp_allocate_memory(size_t page_count, u32 type)
agp_free_memory(new);
return NULL;
}
- new->memory[i] = agp_bridge.mask_memory(virt_to_phys(addr), type);
+ new->memory[i] = virt_to_phys(addr);
new->page_count++;
}
@@ -241,9 +240,6 @@ int agp_num_entries(void)
int agp_copy_info(agp_kern_info * info)
{
- unsigned long page_mask = 0;
- int i;
-
memset(info, 0, sizeof(agp_kern_info));
if (agp_bridge.type == NOT_SUPPORTED) {
info->chipset = agp_bridge.type;
@@ -259,11 +255,7 @@ int agp_copy_info(agp_kern_info * info)
info->max_memory = agp_bridge.max_memory_agp;
info->current_memory = atomic_read(&agp_bridge.current_memory_agp);
info->cant_use_aperture = agp_bridge.cant_use_aperture;
-
- for(i = 0; i < agp_bridge.num_of_masks; i++)
- page_mask |= agp_bridge.mask_memory(page_mask, i);
-
- info->page_mask = ~page_mask;
+ info->page_mask = ~0UL;
return 0;
}
@@ -640,7 +632,8 @@ int agp_generic_insert_memory(agp_memory * mem, off_t pg_start, int type)
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++)
- agp_bridge.gatt_table[j] = mem->memory[i];
+ agp_bridge.gatt_table[j] =
+ agp_bridge.mask_memory(mem->memory[i], mem->type);
agp_bridge.tlb_flush(mem);
return 0;
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 9d44cb858e99..4fb5cc400d0b 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -331,7 +331,6 @@ static unsigned long hp_zx1_mask_memory(unsigned long addr, int type)
static int __init hp_zx1_setup (struct pci_dev *pdev __attribute__((unused)))
{
agp_bridge.masks = hp_zx1_masks;
- agp_bridge.num_of_masks = 1;
agp_bridge.dev_private_data = NULL;
agp_bridge.size_type = FIXED_APER_SIZE;
agp_bridge.needs_scratch_page = FALSE;
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
index 9b9d676e971c..36256d815423 100644
--- a/drivers/char/agp/i460-agp.c
+++ b/drivers/char/agp/i460-agp.c
@@ -525,7 +525,6 @@ static unsigned long i460_mask_memory (unsigned long addr, int type)
static int __init intel_i460_setup (struct pci_dev *pdev __attribute__((unused)))
{
- agp_bridge.num_of_masks = 1;
agp_bridge.masks = i460_masks;
agp_bridge.aperture_sizes = (void *) i460_sizes;
agp_bridge.size_type = U8_APER_SIZE;
diff --git a/drivers/char/agp/i7x05-agp.c b/drivers/char/agp/i7x05-agp.c
index 0585d76548df..2b4b49af2b95 100644
--- a/drivers/char/agp/i7x05-agp.c
+++ b/drivers/char/agp/i7x05-agp.c
@@ -96,7 +96,6 @@ static void i7505_setup (u32 mode)
static int __init intel_7505_setup (struct pci_dev *pdev)
{
agp_bridge.masks = intel_generic_masks;
- agp_bridge.num_of_masks = 1;
agp_bridge.aperture_sizes = (void *) intel_7505_sizes;
agp_bridge.size_type = U16_APER_SIZE;
agp_bridge.num_aperture_sizes = 7;
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index c9457777eb64..7fae8df7e722 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -153,7 +153,8 @@ insert:
CACHE_FLUSH();
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
OUTREG32(intel_i810_private.registers,
- I810_PTE_BASE + (j * 4), mem->memory[i]);
+ I810_PTE_BASE + (j * 4),
+ agp_bridge.mask_memory(mem->memory[i], mem->type));
}
CACHE_FLUSH();
@@ -219,11 +220,11 @@ static agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
agp_free_memory(new);
return NULL;
}
- new->memory[0] = agp_bridge.mask_memory(virt_to_phys(addr), type);
+ new->memory[0] = virt_to_phys(addr);
new->page_count = 1;
new->num_scratch_pages = 1;
new->type = AGP_PHYS_MEMORY;
- new->physical = virt_to_phys((void *) new->memory[0]);
+ new->physical = new->memory[0];
return new;
}
return NULL;
@@ -251,7 +252,6 @@ static int __init intel_i810_setup(struct pci_dev *i810_dev)
intel_i810_private.i810_dev = i810_dev;
agp_bridge.masks = intel_i810_masks;
- agp_bridge.num_of_masks = 2;
agp_bridge.aperture_sizes = (void *) intel_i810_sizes;
agp_bridge.size_type = FIXED_APER_SIZE;
agp_bridge.num_aperture_sizes = 2;
@@ -454,7 +454,8 @@ static int intel_i830_insert_entries(agp_memory *mem,off_t pg_start,int type)
CACHE_FLUSH();
for (i = 0, j = pg_start; i < mem->page_count; i++, j++)
- OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (j * 4),mem->memory[i]);
+ OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (j * 4),
+ agp_bridge.mask_memory(mem->memory[i], mem->type));
CACHE_FLUSH();
@@ -514,11 +515,11 @@ static agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
return(NULL);
}
- nw->memory[0] = agp_bridge.mask_memory(virt_to_phys(addr),type);
+ nw->memory[0] = virt_to_phys(addr);
nw->page_count = 1;
nw->num_scratch_pages = 1;
nw->type = AGP_PHYS_MEMORY;
- nw->physical = virt_to_phys(addr);
+ nw->physical = nw->memory[0];
return(nw);
}
@@ -530,7 +531,6 @@ static int __init intel_i830_setup(struct pci_dev *i830_dev)
intel_i830_private.i830_dev = i830_dev;
agp_bridge.masks = intel_i810_masks;
- agp_bridge.num_of_masks = 3;
agp_bridge.aperture_sizes = (void *) intel_i830_sizes;
agp_bridge.size_type = FIXED_APER_SIZE;
agp_bridge.num_aperture_sizes = 2;
@@ -974,7 +974,6 @@ static struct aper_size_info_8 intel_830mp_sizes[4] =
static int __init intel_generic_setup (struct pci_dev *pdev)
{
agp_bridge.masks = intel_generic_masks;
- agp_bridge.num_of_masks = 1;
agp_bridge.aperture_sizes = (void *) intel_generic_sizes;
agp_bridge.size_type = U16_APER_SIZE;
agp_bridge.num_aperture_sizes = 7;
@@ -1004,7 +1003,6 @@ static int __init intel_generic_setup (struct pci_dev *pdev)
static int __init intel_815_setup (struct pci_dev *pdev)
{
agp_bridge.masks = intel_generic_masks;
- agp_bridge.num_of_masks = 1;
agp_bridge.aperture_sizes = (void *) intel_815_sizes;
agp_bridge.size_type = U8_APER_SIZE;
agp_bridge.num_aperture_sizes = 2;
@@ -1035,7 +1033,6 @@ static int __init intel_815_setup (struct pci_dev *pdev)
static int __init intel_820_setup (struct pci_dev *pdev)
{
agp_bridge.masks = intel_generic_masks;
- agp_bridge.num_of_masks = 1;
agp_bridge.aperture_sizes = (void *) intel_8xx_sizes;
agp_bridge.size_type = U8_APER_SIZE;
agp_bridge.num_aperture_sizes = 7;
@@ -1065,7 +1062,6 @@ static int __init intel_820_setup (struct pci_dev *pdev)
static int __init intel_830mp_setup (struct pci_dev *pdev)
{
agp_bridge.masks = intel_generic_masks;
- agp_bridge.num_of_masks = 1;
agp_bridge.aperture_sizes = (void *) intel_830mp_sizes;
agp_bridge.size_type = U8_APER_SIZE;
agp_bridge.num_aperture_sizes = 4;
@@ -1095,7 +1091,6 @@ static int __init intel_830mp_setup (struct pci_dev *pdev)
static int __init intel_840_setup (struct pci_dev *pdev)
{
agp_bridge.masks = intel_generic_masks;
- agp_bridge.num_of_masks = 1;
agp_bridge.aperture_sizes = (void *) intel_8xx_sizes;
agp_bridge.size_type = U8_APER_SIZE;
agp_bridge.num_aperture_sizes = 7;
@@ -1125,7 +1120,6 @@ static int __init intel_840_setup (struct pci_dev *pdev)
static int __init intel_845_setup (struct pci_dev *pdev)
{
agp_bridge.masks = intel_generic_masks;
- agp_bridge.num_of_masks = 1;
agp_bridge.aperture_sizes = (void *) intel_8xx_sizes;
agp_bridge.size_type = U8_APER_SIZE;
agp_bridge.num_aperture_sizes = 7;
@@ -1155,7 +1149,6 @@ static int __init intel_845_setup (struct pci_dev *pdev)
static int __init intel_850_setup (struct pci_dev *pdev)
{
agp_bridge.masks = intel_generic_masks;
- agp_bridge.num_of_masks = 1;
agp_bridge.aperture_sizes = (void *) intel_8xx_sizes;
agp_bridge.size_type = U8_APER_SIZE;
agp_bridge.num_aperture_sizes = 7;
@@ -1185,7 +1178,6 @@ static int __init intel_850_setup (struct pci_dev *pdev)
static int __init intel_860_setup (struct pci_dev *pdev)
{
agp_bridge.masks = intel_generic_masks;
- agp_bridge.num_of_masks = 1;
agp_bridge.aperture_sizes = (void *) intel_8xx_sizes;
agp_bridge.size_type = U8_APER_SIZE;
agp_bridge.num_aperture_sizes = 7;
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
index a2d1ae7df5a9..d70f2d4de524 100644
--- a/drivers/char/agp/sis-agp.c
+++ b/drivers/char/agp/sis-agp.c
@@ -89,7 +89,6 @@ static struct gatt_mask sis_generic_masks[] =
static int __init sis_generic_setup (struct pci_dev *pdev)
{
agp_bridge.masks = sis_generic_masks;
- agp_bridge.num_of_masks = 1;
agp_bridge.aperture_sizes = (void *) sis_generic_sizes;
agp_bridge.size_type = U8_APER_SIZE;
agp_bridge.num_aperture_sizes = 7;
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index d9d47c773c4e..8e8cb5290bd3 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -363,7 +363,8 @@ static int serverworks_insert_memory(agp_memory * mem,
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
addr = (j * PAGE_SIZE) + agp_bridge.gart_bus_addr;
cur_gatt = SVRWRKS_GET_GATT(addr);
- cur_gatt[GET_GATT_OFF(addr)] = mem->memory[i];
+ cur_gatt[GET_GATT_OFF(addr)] =
+ agp_bridge.mask_memory(mem->memory[i], mem->type);
}
agp_bridge.tlb_flush(mem);
return 0;
@@ -520,7 +521,6 @@ static int __init serverworks_setup (struct pci_dev *pdev)
serverworks_private.svrwrks_dev = pdev;
agp_bridge.masks = serverworks_masks;
- agp_bridge.num_of_masks = 1;
agp_bridge.aperture_sizes = (void *) serverworks_sizes;
agp_bridge.size_type = LVL2_APER_SIZE;
agp_bridge.num_aperture_sizes = 7;
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index b9ec5981f6ce..b3fc40fcbe3b 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -97,7 +97,6 @@ static struct gatt_mask via_generic_masks[] =
static int __init via_generic_setup (struct pci_dev *pdev)
{
agp_bridge.masks = via_generic_masks;
- agp_bridge.num_of_masks = 1;
agp_bridge.aperture_sizes = (void *) via_generic_sizes;
agp_bridge.size_type = U8_APER_SIZE;
agp_bridge.num_aperture_sizes = 7;
@@ -203,9 +202,9 @@ static struct agp_device_ids via_agp_device_ids[] __initdata =
.chipset_name = "Apollo ProSavage PM133"
},
{
- .device_id = PCI_DEVICE_ID_VIA_8235_0,
- .chipset = VIA_P4X400,
- .chipset_name = "P4X400"
+ .device_id = PCI_DEVICE_ID_VIA_8754,
+ .chipset = VIA_P4X,
+ .chipset_name = "Apollo P4X333/P4X400"
},
{ }, /* dummy final entry, always present */
};
diff --git a/drivers/char/agp/via-kt400.c b/drivers/char/agp/via-kt400.c
index b23b19ab90c9..235459ce7d38 100644
--- a/drivers/char/agp/via-kt400.c
+++ b/drivers/char/agp/via-kt400.c
@@ -122,7 +122,6 @@ static int __init agp_via_probe (struct pci_dev *dev, const struct pci_device_id
agp_bridge.type = VIA_APOLLO_KT400_3;
agp_bridge.capndx = cap_ptr;
agp_bridge.masks = via_generic_masks;
- agp_bridge.num_of_masks = 1;
agp_bridge.aperture_sizes = (void *) via_generic_sizes;
agp_bridge.size_type = U8_APER_SIZE;
agp_bridge.num_aperture_sizes = 7;
diff --git a/drivers/char/drm/radeon_mem.c b/drivers/char/drm/radeon_mem.c
index 5c07c1afe1d1..7ca10753a594 100644
--- a/drivers/char/drm/radeon_mem.c
+++ b/drivers/char/drm/radeon_mem.c
@@ -130,16 +130,6 @@ static void free_block( struct mem_block *p )
}
}
-static void print_heap( struct mem_block *heap )
-{
- struct mem_block *p;
-
- for (p = heap->next ; p != heap ; p = p->next)
- DRM_DEBUG("0x%x..0x%x (0x%x) -- owner %d\n",
- p->start, p->start + p->size,
- p->size, p->pid);
-}
-
/* Initialize. How to check for an uninitialized heap?
*/
static int init_heap(struct mem_block **heap, int start, int size)
diff --git a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c
index 6e7707bd4f9e..9bf169a196f1 100644
--- a/drivers/char/ftape/lowlevel/fdc-io.c
+++ b/drivers/char/ftape/lowlevel/fdc-io.c
@@ -1209,7 +1209,7 @@ static int fdc_request_regions(void)
TRACE_FUN(ft_t_flow);
if (ft_mach2 || ft_probe_fc10) {
- if (check_region(fdc.sra, 8) < 0) {
+ if (!request_region(fdc.sra, 8, "fdc (ft)")) {
#ifndef BROKEN_FLOPPY_DRIVER
TRACE_EXIT -EBUSY;
#else
@@ -1217,10 +1217,8 @@ static int fdc_request_regions(void)
"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra);
#endif
}
- request_region(fdc.sra, 8, "fdc (ft)");
} else {
- if (check_region(fdc.sra, 6) < 0 ||
- check_region(fdc.dir, 1) < 0) {
+ if (!request_region(fdc.sra, 6, "fdc (ft)")) {
#ifndef BROKEN_FLOPPY_DRIVER
TRACE_EXIT -EBUSY;
#else
@@ -1228,8 +1226,15 @@ static int fdc_request_regions(void)
"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra);
#endif
}
- request_region(fdc.sra, 6, "fdc (ft)");
- request_region(fdc.sra + 7, 1, "fdc (ft)");
+ if (!request_region(fdc.sra + 7, 1, "fdc (ft)")) {
+#ifndef BROKEN_FLOPPY_DRIVER
+ release_region(fdc.sra, 6);
+ TRACE_EXIT -EBUSY;
+#else
+ TRACE(ft_t_warn,
+"address 0x%03x occupied (by floppy driver?), using it anyway", fdc.sra + 7);
+#endif
+ }
}
TRACE_EXIT 0;
}
diff --git a/drivers/char/ftape/zftape/zftape-ctl.c b/drivers/char/ftape/zftape/zftape-ctl.c
index 67f8f6223422..72bb9b05f260 100644
--- a/drivers/char/ftape/zftape/zftape-ctl.c
+++ b/drivers/char/ftape/zftape/zftape-ctl.c
@@ -790,13 +790,6 @@ int _zft_close(void)
zft_uninit_mem();
going_offline = 0;
zft_offline = 1;
- } else if (zft_dirty()) {
- TRACE(ft_t_noise, "Keeping module locked in memory because:\n"
- KERN_INFO "header segments need updating: %s\n"
- KERN_INFO "tape not at BOT : %s",
- (zft_volume_table_changed || zft_header_changed)
- ? "yes" : "no",
- zft_tape_at_lbot(&zft_pos) ? "no" : "yes");
} else if (zft_cmpr_lock(0 /* don't load */) == 0) {
(*zft_cmpr_ops->reset)(); /* unlock it again */
}
diff --git a/drivers/char/ftape/zftape/zftape-ctl.h b/drivers/char/ftape/zftape/zftape-ctl.h
index 91a2f2db7796..6c5a2532a3cc 100644
--- a/drivers/char/ftape/zftape/zftape-ctl.h
+++ b/drivers/char/ftape/zftape/zftape-ctl.h
@@ -47,7 +47,6 @@ extern int zft_resid;
extern void zft_reset_position(zft_position *pos);
extern int zft_check_write_access(zft_position *pos);
extern int zft_def_idle_state(void);
-extern int zft_dirty(void);
/* hooks for the VFS interface
*/
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
index 9af004b642b5..6c787bf5172e 100644
--- a/drivers/char/genrtc.c
+++ b/drivers/char/genrtc.c
@@ -404,11 +404,20 @@ static struct miscdevice rtc_gen_dev =
int __init rtc_generic_init(void)
{
+ int retval;
- printk(KERN_INFO "Generic RTC Driver v%s\n", RTC_VERSION);
+ printk(KERN_INFO "Generic RTC Driver v%s\n", RTC_VERSION);
- misc_register(&rtc_gen_dev);
- create_proc_read_entry ("driver/rtc", 0, 0, gen_rtc_read_proc, NULL);
+ retval = misc_register(&rtc_gen_dev);
+ if(retval < 0)
+ return retval;
+
+#ifdef CONFIG_PROC_FS
+ if((create_proc_read_entry ("driver/rtc", 0, 0, gen_rtc_read_proc, NULL)) == NULL){
+ misc_deregister(&rtc_gen_dev);
+ return -ENOMEM;
+ }
+#endif
return 0;
}
diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c
index 4f3e16c394b8..dc026ce7a9f3 100644
--- a/drivers/char/nwflash.c
+++ b/drivers/char/nwflash.c
@@ -688,9 +688,10 @@ static int __init nwflash_init(void)
printk("Flash ROM driver v.%s, flash device ID 0x%04X, size %d Mb.\n",
NWFLASH_VERSION, id, gbFlashSize / (1024 * 1024));
- misc_register(&flash_miscdev);
-
- ret = 0;
+ ret = misc_register(&flash_miscdev);
+ if (ret < 0) {
+ iounmap((void *)FLASH_BASE);
+ }
}
out:
return ret;
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 6698a20041b0..29c856b8a5d3 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -2499,6 +2499,11 @@ static int __init sx_init(void)
sx_debug=-1;
}
+ if (misc_register(&sx_fw_device) < 0) {
+ printk(KERN_ERR "SX: Unable to register firmware loader driver.\n");
+ return -EIO;
+ }
+
#ifdef CONFIG_PCI
if (pci_present ()) {
#ifndef TWO_ZERO
@@ -2643,11 +2648,8 @@ static int __init sx_init(void)
}
if (found) {
printk (KERN_INFO "sx: total of %d boards detected.\n", found);
-
- if (misc_register(&sx_fw_device) < 0) {
- printk(KERN_ERR "SX: Unable to register firmware loader driver.\n");
- return -EIO;
- }
+ } else {
+ misc_deregister(&sx_fw_device);
}
func_exit();
diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c
index fc93acbc6dc1..7a1f939da5bb 100644
--- a/drivers/char/toshiba.c
+++ b/drivers/char/toshiba.c
@@ -474,6 +474,7 @@ int tosh_probe(void)
int __init tosh_init(void)
{
+ int retval;
/* are we running on a Toshiba laptop */
if (tosh_probe()!=0)
@@ -483,17 +484,21 @@ int __init tosh_init(void)
TOSH_VERSION"\n");
/* set the port to use for Fn status if not specified as a parameter */
-
if (tosh_fn==0x00)
tosh_set_fn_port();
/* register the device file */
+ retval = misc_register(&tosh_device);
+ if(retval < 0)
+ return retval;
- misc_register(&tosh_device);
-
+#ifdef CONFIG_PROC_FS
/* register the proc entry */
-
- create_proc_info_entry("toshiba", 0, NULL, tosh_get_info);
+ if(create_proc_info_entry("toshiba", 0, NULL, tosh_get_info) == NULL){
+ misc_deregister(&tosh_device);
+ return -ENOMEM;
+ }
+#endif
return 0;
}
diff --git a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c
index 849053231fb7..df7a7740b1d4 100644
--- a/drivers/isdn/hisax/asuscom.c
+++ b/drivers/isdn/hisax/asuscom.c
@@ -385,15 +385,14 @@ setup_asuscom(struct IsdnCard *card)
bytecnt = 8;
cs->hw.asus.cfg_reg = card->para[1];
cs->irq = card->para[0];
- if (check_region((cs->hw.asus.cfg_reg), bytecnt)) {
+ if (!request_region((cs->hw.asus.cfg_reg), bytecnt,
+ "asuscom isdn")) {
printk(KERN_WARNING
"HiSax: %s config port %x-%x already in use\n",
CardType[card->typ],
cs->hw.asus.cfg_reg,
cs->hw.asus.cfg_reg + bytecnt);
return (0);
- } else {
- request_region(cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn");
}
printk(KERN_INFO "ISDNLink: defined at 0x%x IRQ %d\n",
cs->hw.asus.cfg_reg, cs->irq);
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
index 12b11ba6b8fd..a796a9847651 100644
--- a/drivers/isdn/hisax/avm_pci.c
+++ b/drivers/isdn/hisax/avm_pci.c
@@ -746,16 +746,14 @@ setup_avm_pcipnp(struct IsdnCard *card)
}
ready:
cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
- if (check_region((cs->hw.avm.cfg_reg), 32)) {
+ if (!request_region((cs->hw.avm.cfg_reg), 32, (cs->subtyp == AVM_FRITZ_PCI)
+ ? "avm PCI" : "avm PnP")) {
printk(KERN_WARNING
"HiSax: %s config port %x-%x already in use\n",
CardType[card->typ],
cs->hw.avm.cfg_reg,
cs->hw.avm.cfg_reg + 31);
return (0);
- } else {
- request_region(cs->hw.avm.cfg_reg, 32,
- (cs->subtyp == AVM_FRITZ_PCI) ? "avm PCI" : "avm PnP");
}
switch (cs->subtyp) {
case AVM_FRITZ_PCI:
diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c
index 5f714ed7633b..0068a5154c81 100644
--- a/drivers/isdn/hisax/bkm_a8.c
+++ b/drivers/isdn/hisax/bkm_a8.c
@@ -270,13 +270,11 @@ BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
int __init
sct_alloc_io(u_int adr, u_int len)
{
- if (check_region(adr, len)) {
+ if (!request_region(adr, len, "scitel")) {
printk(KERN_WARNING
"HiSax: Scitel port %#x-%#x already in use\n",
adr, adr + len);
return (1);
- } else {
- request_region(adr, len, "scitel");
}
return(0);
}
diff --git a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c
index 6f44fa490fce..d7d4e5ff88a2 100644
--- a/drivers/isdn/hisax/enternow_pci.c
+++ b/drivers/isdn/hisax/enternow_pci.c
@@ -357,15 +357,13 @@ setup_enternow_pci(struct IsdnCard *card)
printk(KERN_INFO
"enter:now PCI: PCI card configured at 0x%lx IRQ %d\n",
cs->hw.njet.base, cs->irq);
- if (check_region(cs->hw.njet.base, bytecnt)) {
+ if (!request_region(cs->hw.njet.base, bytecnt, "Fn_ISDN")) {
printk(KERN_WARNING
"HiSax: %s config port %lx-%lx already in use\n",
CardType[card->typ],
cs->hw.njet.base,
cs->hw.njet.base + bytecnt);
return (0);
- } else {
- request_region(cs->hw.njet.base, bytecnt, "Fn_ISDN");
}
reset_enpci(cs);
cs->hw.njet.last_is0 = 0;
diff --git a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c
index 1f67738b849d..ba3fa3e4d5c4 100644
--- a/drivers/isdn/hisax/mic.c
+++ b/drivers/isdn/hisax/mic.c
@@ -214,15 +214,13 @@ setup_mic(struct IsdnCard *card)
cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC;
cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX;
- if (check_region((cs->hw.mic.cfg_reg), bytecnt)) {
+ if (!request_region((cs->hw.mic.cfg_reg), bytecnt, "mic isdn")) {
printk(KERN_WARNING
"HiSax: %s config port %x-%x already in use\n",
CardType[card->typ],
cs->hw.mic.cfg_reg,
cs->hw.mic.cfg_reg + bytecnt);
return (0);
- } else {
- request_region(cs->hw.mic.cfg_reg, bytecnt, "mic isdn");
}
printk(KERN_INFO
diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
index 289b330ee697..e7bddb35b6e1 100644
--- a/drivers/isdn/hisax/nj_u.c
+++ b/drivers/isdn/hisax/nj_u.c
@@ -213,15 +213,13 @@ setup_netjet_u(struct IsdnCard *card)
printk(KERN_INFO
"NETspider-U: PCI card configured at %#lx IRQ %d\n",
cs->hw.njet.base, cs->irq);
- if (check_region(cs->hw.njet.base, bytecnt)) {
+ if (!request_region(cs->hw.njet.base, bytecnt, "netspider-u isdn")) {
printk(KERN_WARNING
"HiSax: %s config port %#lx-%#lx already in use\n",
CardType[card->typ],
cs->hw.njet.base,
cs->hw.njet.base + bytecnt);
return (0);
- } else {
- request_region(cs->hw.njet.base, bytecnt, "netspider-u isdn");
}
reset_netjet_u(cs);
cs->dc_hw_ops = &netjet_dc_ops;
diff --git a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c
index 6944acbaea53..5ad32e1c365f 100644
--- a/drivers/isdn/hisax/s0box.c
+++ b/drivers/isdn/hisax/s0box.c
@@ -250,15 +250,14 @@ setup_s0box(struct IsdnCard *card)
cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
cs->irq = card->para[0];
- if (check_region(cs->hw.teles3.cfg_reg,8)) {
+ if (!request_region(cs->hw.teles3.cfg_reg,8, "S0Box parallel I/O")) {
printk(KERN_WARNING
"HiSax: %s ports %x-%x already in use\n",
CardType[cs->typ],
cs->hw.teles3.cfg_reg,
cs->hw.teles3.cfg_reg + 7);
return 0;
- } else
- request_region(cs->hw.teles3.cfg_reg, 8, "S0Box parallel I/O");
+ }
printk(KERN_INFO
"HiSax: %s config irq:%d isac:0x%x cfg:0x%x\n",
CardType[cs->typ], cs->irq,
diff --git a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c
index 1ce0d80ab433..29a97bab0a11 100644
--- a/drivers/isdn/hisax/saphir.c
+++ b/drivers/isdn/hisax/saphir.c
@@ -265,15 +265,14 @@ setup_saphir(struct IsdnCard *card)
cs->hw.saphir.hscx = card->para[1] + HSCX_DATA;
cs->hw.saphir.ale = card->para[1] + ADDRESS_REG;
cs->irq = card->para[0];
- if (check_region((cs->hw.saphir.cfg_reg), 6)) {
+ if (!request_region((cs->hw.saphir.cfg_reg), 6, "saphir")) {
printk(KERN_WARNING
"HiSax: %s config port %x-%x already in use\n",
CardType[card->typ],
cs->hw.saphir.cfg_reg,
cs->hw.saphir.cfg_reg + 5);
return (0);
- } else
- request_region(cs->hw.saphir.cfg_reg,6, "saphir");
+ }
printk(KERN_INFO
"HiSax: %s config irq:%d io:0x%X\n",
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
index 6f681a6374d1..8b1575d0af38 100644
--- a/drivers/isdn/hisax/sedlbauer.c
+++ b/drivers/isdn/hisax/sedlbauer.c
@@ -689,15 +689,13 @@ ready:
* here, it would fail.
*/
if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA &&
- check_region((cs->hw.sedl.cfg_reg), bytecnt)) {
+ (!request_region((cs->hw.sedl.cfg_reg), bytecnt, "sedlbauer isdn"))) {
printk(KERN_WARNING
"HiSax: %s config port %x-%x already in use\n",
CardType[card->typ],
cs->hw.sedl.cfg_reg,
cs->hw.sedl.cfg_reg + bytecnt);
return (0);
- } else {
- request_region(cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn");
}
printk(KERN_INFO
diff --git a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c
index e05f07b43e9c..80107b58067a 100644
--- a/drivers/isdn/hisax/sportster.c
+++ b/drivers/isdn/hisax/sportster.c
@@ -196,13 +196,12 @@ get_io_range(struct IsdnCardState *cs)
for (i=0;i<64;i++) {
adr = cs->hw.spt.cfg_reg + i *1024;
- if (check_region(adr, 8)) {
+ if (!request_region(adr, 8, "sportster")) {
printk(KERN_WARNING
"HiSax: %s config port %x-%x already in use\n",
CardType[cs->typ], adr, adr + 8);
break;
- } else
- request_region(adr, 8, "sportster");
+ }
}
if (i==64)
return(1);
diff --git a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c
index 7baa35361b2e..2df163c53331 100644
--- a/drivers/isdn/hisax/teles0.c
+++ b/drivers/isdn/hisax/teles0.c
@@ -249,15 +249,13 @@ setup_teles0(struct IsdnCard *card)
}
cs->irq = card->para[0];
if (cs->hw.teles0.cfg_reg) {
- if (check_region(cs->hw.teles0.cfg_reg, 8)) {
+ if (!request_region(cs->hw.teles0.cfg_reg, 8, "teles cfg")) {
printk(KERN_WARNING
"HiSax: %s config port %x-%x already in use\n",
CardType[card->typ],
cs->hw.teles0.cfg_reg,
cs->hw.teles0.cfg_reg + 8);
return (0);
- } else {
- request_region(cs->hw.teles0.cfg_reg, 8, "teles cfg");
}
}
if (cs->hw.teles0.cfg_reg) {
diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
index 904d1b08fffa..67805d213ba2 100644
--- a/drivers/isdn/hisax/w6692.c
+++ b/drivers/isdn/hisax/w6692.c
@@ -844,16 +844,14 @@ setup_w6692(struct IsdnCard *card)
printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n",
id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name,
pci_ioaddr, pci_irq);
- if (check_region((cs->hw.w6692.iobase), 256)) {
+ if (!request_region((cs->hw.w6692.iobase), 256,
+ id_list[cs->subtyp].card_name)) {
printk(KERN_WARNING
"HiSax: %s I/O ports %x-%x already in use\n",
id_list[cs->subtyp].card_name,
cs->hw.w6692.iobase,
cs->hw.w6692.iobase + 255);
return (0);
- } else {
- request_region(cs->hw.w6692.iobase, 256,
- id_list[cs->subtyp].card_name);
}
#else
printk(KERN_WARNING "HiSax: W6692 and NO_PCI_BIOS\n");
diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c
index 304b5f219bc5..c6073d342405 100644
--- a/drivers/macintosh/ans-lcd.c
+++ b/drivers/macintosh/ans-lcd.c
@@ -140,6 +140,7 @@ int __init
anslcd_init(void)
{
int a;
+ int retval;
struct device_node* node;
node = find_devices("lcd");
@@ -150,7 +151,12 @@ anslcd_init(void)
anslcd_ptr = (volatile unsigned char*)ioremap(ANSLCD_ADDR, 0x20);
- misc_register(&anslcd_dev);
+ retval = misc_register(&anslcd_dev);
+ if(retval < 0){
+ printk(KERN_INFO "LCD: misc_register failed\n");
+ iounmap(anslcd_ptr);
+ return retval;
+ }
#ifdef DEBUG
printk(KERN_DEBUG "LCD: init\n");
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 7bc47778135d..9161022d90c9 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -2702,8 +2702,10 @@ static struct miscdevice pmu_device = {
void pmu_device_init(void)
{
- if (via)
- misc_register(&pmu_device);
+ if (!via)
+ return;
+ if (misc_register(&pmu_device) < 0)
+ printk(KERN_ERR "via-pmu: cannot register misc device.\n");
}
#endif /* CONFIG_PMAC_PBOOK */
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
index 3bb653489391..ea592973e28f 100644
--- a/drivers/macintosh/via-pmu68k.c
+++ b/drivers/macintosh/via-pmu68k.c
@@ -1052,8 +1052,10 @@ static struct miscdevice pmu_device = {
void pmu_device_init(void)
{
- if (via)
- misc_register(&pmu_device);
+ if (!via)
+ return;
+ if (misc_register(&pmu_device) < 0)
+ printk(KERN_ERR "via-pmu68k: cannot register misc device.\n");
}
#endif /* CONFIG_PMAC_PBOOK */
diff --git a/drivers/md/md.c b/drivers/md/md.c
index a2c2d9649dfa..924f08aed568 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -578,10 +578,19 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
mddev->level = sb->level;
mddev->layout = sb->layout;
mddev->raid_disks = sb->raid_disks;
- mddev->state = sb->state;
mddev->size = sb->size;
mddev->events = md_event(sb);
-
+
+ if (sb->state & (1<<MD_SB_CLEAN))
+ mddev->recovery_cp = MaxSector;
+ else {
+ if (sb->events_hi == sb->cp_events_hi &&
+ sb->events_lo == sb->cp_events_lo) {
+ mddev->recovery_cp = sb->recovery_cp;
+ } else
+ mddev->recovery_cp = 0;
+ }
+
memcpy(mddev->uuid+0, &sb->set_uuid0, 4);
memcpy(mddev->uuid+4, &sb->set_uuid1, 4);
memcpy(mddev->uuid+8, &sb->set_uuid2, 4);
@@ -657,10 +666,22 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
sb->md_minor = mddev->__minor;
sb->not_persistent = !mddev->persistent;
sb->utime = mddev->utime;
- sb->state = mddev->state;
+ sb->state = 0;
sb->events_hi = (mddev->events>>32);
sb->events_lo = (u32)mddev->events;
+ if (mddev->in_sync)
+ {
+ sb->recovery_cp = mddev->recovery_cp;
+ sb->cp_events_hi = (mddev->events>>32);
+ sb->cp_events_lo = (u32)mddev->events;
+ if (mddev->recovery_cp == MaxSector) {
+ printk(KERN_INFO "md: marking sb clean...\n");
+ sb->state = (1<< MD_SB_CLEAN);
+ }
+ } else
+ sb->recovery_cp = 0;
+
sb->layout = mddev->layout;
sb->chunk_size = mddev->chunk_size;
@@ -1198,7 +1219,7 @@ static int analyze_sbs(mddev_t * mddev)
goto abort;
}
- if ((mddev->state != (1 << MD_SB_CLEAN)) && ((mddev->level == 1) ||
+ if ((mddev->recovery_cp != MaxSector) && ((mddev->level == 1) ||
(mddev->level == 4) || (mddev->level == 5)))
printk(NOT_CLEAN_IGNORE, mdidx(mddev));
@@ -1469,13 +1490,11 @@ static int do_md_run(mddev_t * mddev)
mddev->pers = NULL;
return -EINVAL;
}
-
- mddev->in_sync = (mddev->state & (1<<MD_SB_CLEAN));
- /* if personality doesn't have "sync_request", then
- * a dirty array doesn't mean anything
- */
if (mddev->pers->sync_request)
- mddev->state &= ~(1 << MD_SB_CLEAN);
+ mddev->in_sync = 0;
+ else
+ mddev->in_sync = 1;
+
md_update_sb(mddev);
md_recover_arrays();
set_capacity(disk, md_size[mdidx(mddev)]<<1);
@@ -1502,6 +1521,8 @@ static int restart_array(mddev_t *mddev)
if (!mddev->ro)
goto out;
+ mddev->in_sync = 0;
+ md_update_sb(mddev);
mddev->ro = 0;
set_disk_ro(disk, 0);
@@ -1541,7 +1562,7 @@ static int do_md_stop(mddev_t * mddev, int ro)
if (mddev->pers) {
if (mddev->sync_thread) {
if (mddev->recovery_running > 0)
- mddev->recovery_running = -EINTR;
+ mddev->recovery_running = -1;
md_unregister_thread(mddev->sync_thread);
mddev->sync_thread = NULL;
}
@@ -1567,14 +1588,8 @@ static int do_md_stop(mddev_t * mddev, int ro)
mddev->ro = 0;
}
if (mddev->raid_disks) {
- /*
- * mark it clean only if there was no resync
- * interrupted.
- */
- if (mddev->in_sync) {
- printk(KERN_INFO "md: marking sb clean...\n");
- mddev->state |= 1 << MD_SB_CLEAN;
- }
+ /* mark array as shutdown cleanly */
+ mddev->in_sync = 1;
md_update_sb(mddev);
}
if (ro)
@@ -1840,7 +1855,9 @@ static int get_array_info(mddev_t * mddev, void * arg)
info.not_persistent= !mddev->persistent;
info.utime = mddev->utime;
- info.state = mddev->state;
+ info.state = 0;
+ if (mddev->recovery_cp == MaxSector)
+ info.state = (1<<MD_SB_CLEAN);
info.active_disks = active;
info.working_disks = working;
info.failed_disks = failed;
@@ -2111,7 +2128,10 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
/* don't set __minor, it is determined by which /dev/md* was
* openned
*/
- mddev->state = info->state;
+ if (info->state & (1<<MD_SB_CLEAN))
+ mddev->recovery_cp = MaxSector;
+ else
+ mddev->recovery_cp = 0;
mddev->persistent = ! info->not_persistent;
mddev->layout = info->layout;
@@ -2742,7 +2762,7 @@ int unregister_md_personality(int pnum)
void md_sync_acct(mdk_rdev_t *rdev, unsigned long nr_sectors)
{
- rdev->bdev->bd_disk->sync_io += nr_sectors;
+ rdev->bdev->bd_contains->bd_disk->sync_io += nr_sectors;
}
static int is_mddev_idle(mddev_t *mddev)
@@ -2754,7 +2774,7 @@ static int is_mddev_idle(mddev_t *mddev)
idle = 1;
ITERATE_RDEV(mddev,rdev,tmp) {
- struct gendisk *disk = rdev->bdev->bd_disk;
+ struct gendisk *disk = rdev->bdev->bd_contains->bd_disk;
curr_events = disk->read_sectors + disk->write_sectors - disk->sync_io;
if ((curr_events - rdev->last_events) > 32) {
rdev->last_events = curr_events;
@@ -2770,7 +2790,8 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok)
atomic_sub(blocks, &mddev->recovery_active);
wake_up(&mddev->recovery_wait);
if (!ok) {
- mddev->recovery_running = -EIO;
+ mddev->recovery_error = -EIO;
+ mddev->recovery_running = -1;
md_recover_arrays();
// stop recovery, signal do_sync ....
}
@@ -2815,8 +2836,10 @@ static void md_do_sync(void *data)
printk(KERN_INFO "md: delaying resync of md%d until md%d "
"has finished resync (they share one or more physical units)\n",
mdidx(mddev), mdidx(mddev2));
- if (mddev < mddev2) /* arbitrarily yield */
+ if (mddev < mddev2) {/* arbitrarily yield */
mddev->curr_resync = 1;
+ yield();
+ }
if (wait_event_interruptible(resync_wait,
mddev2->curr_resync < 2)) {
flush_curr_signals();
@@ -2839,7 +2862,7 @@ static void md_do_sync(void *data)
is_mddev_idle(mddev); /* this also initializes IO event counters */
for (m = 0; m < SYNC_MARKS; m++) {
mark[m] = jiffies;
- mark_cnt[m] = 0;
+ mark_cnt[m] = mddev->recovery_cp;
}
last_mark = 0;
mddev->resync_mark = mark[last_mark];
@@ -2855,7 +2878,13 @@ static void md_do_sync(void *data)
atomic_set(&mddev->recovery_active, 0);
init_waitqueue_head(&mddev->recovery_wait);
last_check = 0;
- for (j = 0; j < max_sectors;) {
+
+ mddev->recovery_error = 0;
+
+ if (mddev->recovery_cp)
+ printk(KERN_INFO "md: resuming recovery of md%d from checkpoint.\n", mdidx(mddev));
+
+ for (j = mddev->recovery_cp; j < max_sectors;) {
int sectors;
sectors = mddev->pers->sync_request(mddev, j, currspeed < sysctl_speed_limit_min);
@@ -2925,16 +2954,25 @@ static void md_do_sync(void *data)
*/
out:
wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active));
+
+ if (mddev->recovery_running < 0 &&
+ !mddev->recovery_error && mddev->curr_resync > 2)
+ {
+ /* interrupted but no write errors */
+ printk(KERN_INFO "md: checkpointing recovery of md%d.\n", mdidx(mddev));
+ mddev->recovery_cp = mddev->curr_resync;
+ }
+
/* tell personality that we are finished */
mddev->pers->sync_request(mddev, max_sectors, 1);
skip:
mddev->curr_resync = 0;
if (err)
- mddev->recovery_running = err;
+ mddev->recovery_running = -1;
if (mddev->recovery_running > 0)
mddev->recovery_running = 0;
if (mddev->recovery_running == 0)
- mddev->in_sync = 1;
+ mddev->recovery_cp = MaxSector;
md_recover_arrays();
}
@@ -3015,14 +3053,16 @@ void md_do_recovery(void *data)
ITERATE_RDEV(mddev,rdev,rtmp)
if (rdev->raid_disk < 0
&& !rdev->faulty) {
- if (mddev->pers->hot_add_disk(mddev,rdev))
+ if (mddev->pers->hot_add_disk(mddev,rdev)) {
mddev->spares++;
+ mddev->recovery_cp = 0;
+ }
else
break;
}
}
- if (!mddev->spares && mddev->in_sync) {
+ if (!mddev->spares && (mddev->recovery_cp == MaxSector )) {
/* nothing we can do ... */
goto unlock;
}
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 55e9a01d4e29..9b3fcf9368c1 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -975,7 +975,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
sector_t max_sector, nr_sectors;
int disk, partial;
- if (sector_nr == 0)
+ if (!conf->r1buf_pool)
if (init_resync(conf))
return -ENOMEM;
@@ -1149,7 +1149,7 @@ static int run(mddev_t *mddev)
conf->mddev = mddev;
conf->device_lock = SPIN_LOCK_UNLOCKED;
if (conf->working_disks == 1)
- mddev->state |= (1 << MD_SB_CLEAN);
+ mddev->recovery_cp = MaxSector;
conf->resync_lock = SPIN_LOCK_UNLOCKED;
init_waitqueue_head(&conf->wait_idle);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 3ef80e69f864..090058085cc5 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1471,7 +1471,7 @@ static int run (mddev_t *mddev)
}
if (mddev->degraded == 1 &&
- !(mddev->state & (1<<MD_SB_CLEAN))) {
+ mddev->recovery_cp != MaxSector) {
printk(KERN_ERR "raid5: cannot start dirty degraded array for md%d\n", mdidx(mddev));
goto abort;
}
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index b93d978586be..3dbad22e6513 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -460,6 +460,7 @@ enum vortex_chips {
CH_3CCFEM656_1,
CH_3C450,
+ CH_3C920,
};
@@ -551,6 +552,8 @@ static struct vortex_chip_info {
MAX_COLLISION_RESET|HAS_HWCKSM, 128, },
{"3c450 HomePNA Tornado", /* AKPM: from Don's 0.99Q */
PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
+ {"3c920 Tornado",
+ PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
{0,}, /* 0 terminated list. */
};
@@ -594,6 +597,7 @@ static struct pci_device_id vortex_pci_tbl[] __devinitdata = {
{ 0x10B7, 0x6564, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656_1 },
{ 0x10B7, 0x4500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C450 },
+ { 0x10B7, 0x9201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C920 },
{0,} /* 0 terminated list. */
};
MODULE_DEVICE_TABLE(pci, vortex_pci_tbl);
diff --git a/drivers/net/aironet4500_proc.c b/drivers/net/aironet4500_proc.c
index e5c8d53833ad..42bc6c9d0046 100644
--- a/drivers/net/aironet4500_proc.c
+++ b/drivers/net/aironet4500_proc.c
@@ -42,6 +42,8 @@
#define DEV_AWC_INFO 1
#define DEV_AWC 1
+spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
+
struct awc_proc_private{
struct ctl_table_header * sysctl_header;
struct ctl_table * proc_table;
@@ -293,10 +295,9 @@ int awc_proc_fun(ctl_table *ctl, int write, struct file * filp,
};
if (!write && rid->selector->may_change) {
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&driver_lock, flags);
awc_readrid(dev,rid,rid_dir->buff + rid->offset);
- restore_flags(flags);
+ spin_unlock_irqrestore(&driver_lock, flags);
};
if (rid->array > 1 || rid->bits > 32){
@@ -325,9 +326,8 @@ int awc_proc_fun(ctl_table *ctl, int write, struct file * filp,
}
}
if (write) {
- save_flags(flags);
- cli();
-
+ spin_lock_irqsave(&driver_lock, flags);
+
if (rid->selector->MAC_Disable_at_write){
awc_disable_MAC(dev);
};
@@ -335,8 +335,7 @@ int awc_proc_fun(ctl_table *ctl, int write, struct file * filp,
if (rid->selector->MAC_Disable_at_write){
awc_enable_MAC(dev);
};
- restore_flags(flags);
-
+ spin_lock_irqsave(&driver_lock, flags);
};
DEBUG(0x20000,"awc proc ret %x \n",retv);
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index 5753cbd3c991..efa1d9db6d85 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -189,8 +189,7 @@ static int sa1100_irda_set_speed(struct sa1100_irda *si, int speed)
break;
case 4000000:
- save_flags(flags);
- cli();
+ local_irq_save(flags);
si->hscr0 = 0;
@@ -210,7 +209,7 @@ static int sa1100_irda_set_speed(struct sa1100_irda *si, int speed)
sa1100_irda_rx_alloc(si);
sa1100_irda_rx_dma_start(si);
- restore_flags(flags);
+ local_irq_restore(flags);
break;
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 794e8e5f131e..4ee9d0d8d767 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -1847,15 +1847,15 @@ static int netdev_close(struct net_device *dev)
#ifdef __i386__
if (debug > 2) {
- printk("\n"KERN_DEBUG" Tx ring at %8.8x:\n",
- np->tx_ring_dma);
+ printk("\n"KERN_DEBUG" Tx ring at %9.9Lx:\n",
+ (u64) np->tx_ring_dma);
for (i = 0; i < 8 /* TX_RING_SIZE is huge! */; i++)
printk(KERN_DEBUG " #%d desc. %8.8x %8.8x -> %8.8x.\n",
i, le32_to_cpu(np->tx_ring[i].status),
le32_to_cpu(np->tx_ring[i].first_addr),
le32_to_cpu(np->tx_done_q[i].status));
- printk(KERN_DEBUG " Rx ring at %8.8x -> %p:\n",
- np->rx_ring_dma, np->rx_done_q);
+ printk(KERN_DEBUG " Rx ring at %9.9Lx -> %p:\n",
+ (u64) np->rx_ring_dma, np->rx_done_q);
if (np->rx_done_q)
for (i = 0; i < 8 /* RX_RING_SIZE */; i++) {
printk(KERN_DEBUG " #%d desc. %8.8x -> %8.8x\n",
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 2c14942cbb00..687a9781ee71 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -558,9 +558,15 @@ struct pci_bus * __devinit pci_alloc_primary_bus_parented(struct device *parent,
b = pci_alloc_bus();
if (!b)
return NULL;
+
+ b->dev = kmalloc(sizeof(*(b->dev)),GFP_KERNEL);
+ if (!b->dev){
+ kfree(b);
+ return NULL;
+ }
+
list_add_tail(&b->node, &pci_root_buses);
- b->dev = kmalloc(sizeof(*(b->dev)),GFP_KERNEL);
memset(b->dev,0,sizeof(*(b->dev)));
sprintf(b->dev->bus_id,"pci%d",bus);
strcpy(b->dev->name,"Host/PCI Bridge");
diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c
index f3cd6bb7b18d..0361f8c1f9ef 100644
--- a/drivers/sbus/char/bpp.c
+++ b/drivers/sbus/char/bpp.c
@@ -886,7 +886,7 @@ static void probeLptPort(unsigned idx)
instances[idx].run_flag = 0;
init_timer(&instances[idx].timer_list);
instances[idx].timer_list.function = bpp_wake_up;
- if (check_region(lpAddr,3)) return;
+ if (!request_region(lpAddr,3, dev_name)) return;
/*
* First, make sure the instance exists. Do this by writing to
@@ -904,7 +904,6 @@ static void probeLptPort(unsigned idx)
unsigned save;
instances[idx].present = 1;
- request_region(lpAddr,3, dev_name);
save = inb_p(lpAddr+2);
for (testvalue=0; testvalue<BPP_DELAY; testvalue++)
;
@@ -921,7 +920,9 @@ static void probeLptPort(unsigned idx)
instances[idx].enhanced = 1;
outb_p(save, lpAddr+2);
}
-
+ else {
+ release_region(lpAddr,3);
+ }
/*
* Leave the port in compat idle mode.
*/
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index 586b3d61430d..f953eaf73d32 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -892,6 +892,10 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child,
}
pchild->tables = kmalloc(tbls_size, GFP_KERNEL);
+ if (pchild->tables == NULL){
+ printk("envctrl: Failed to allocate table.\n");
+ return;
+ }
len = prom_getproperty(node, "tables",
(char *) pchild->tables, tbls_size);
if (len <= 0) {
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 0eaded61130b..11112c7be145 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -36,7 +36,6 @@
#include <linux/fcntl.h>
#include <linux/ptrace.h>
#include <linux/mm.h>
-#include <linux/malloc.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/irq.h>
diff --git a/drivers/sgi/char/streamable.c b/drivers/sgi/char/streamable.c
index 6831e267dc3a..71d47b184d74 100644
--- a/drivers/sgi/char/streamable.c
+++ b/drivers/sgi/char/streamable.c
@@ -309,10 +309,27 @@ static struct miscdevice dev_input_mouse = {
void
streamable_init (void)
{
- printk ("streamable misc devices registered (keyb:%d, gfx:%d)\n",
+ if (misc_register (&dev_gfx) < 0) {
+ printk(KERN_ERR
+ "streamable: cannot register gfx misc device.\n");
+ return;
+ }
+
+ if (misc_register (&dev_input_keyboard) < 0) {
+ printk(KERN_ERR
+ "streamable: cannot register keyboard misc device.\n");
+ misc_deregister(&dev_gfx);
+ return;
+ }
+
+ if (misc_register (&dev_input_mouse) < 0) {
+ printk(KERN_ERR
+ "streamable: cannot register mouse misc device.\n");
+ misc_deregister(&dev_input_keyboard);
+ misc_deregister(&dev_gfx);
+ return;
+ }
+
+ printk ("streamable: misc devices registered (keyb:%d, gfx:%d)\n",
SGI_STREAMS_KEYBOARD, SGI_GFX_MINOR);
-
- misc_register (&dev_gfx);
- misc_register (&dev_input_keyboard);
- misc_register (&dev_input_mouse);
}
diff --git a/drivers/sgi/char/usema.c b/drivers/sgi/char/usema.c
index 76a425812a87..253e1cd537b0 100644
--- a/drivers/sgi/char/usema.c
+++ b/drivers/sgi/char/usema.c
@@ -176,9 +176,12 @@ static struct miscdevice dev_usemaclone = {
void
usema_init(void)
{
+ if (misc_register(&dev_usemaclone) < 0) {
+ printk(KERN_ERR "usemaclone: cannot register misc device.\n");
+ return;
+ }
printk("usemaclone misc device registered (minor: %d)\n",
- SGI_USEMACLONE);
- misc_register(&dev_usemaclone);
+ SGI_USEMACLONE);
}
EXPORT_SYMBOL(usema_init);
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index 1b56a5ddbfb9..e206645d0929 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -6906,21 +6906,19 @@ static int ixj_selfprobe(IXJ *j)
/* Internet PhoneJack Lite */
{
j->cardtype = QTI_PHONEJACK_LITE;
- if (check_region(j->XILINXbase, 4)) {
+ if (!request_region(j->XILINXbase, 4, "ixj control")) {
printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase);
return -1;
}
- request_region(j->XILINXbase, 4, "ixj control");
j->pld_slicw.pcib.e1 = 1;
outb_p(j->pld_slicw.byte, j->XILINXbase);
} else {
j->cardtype = QTI_LINEJACK;
- if (check_region(j->XILINXbase, 8)) {
+ if (!request_region(j->XILINXbase, 8, "ixj control")) {
printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase);
return -1;
}
- request_region(j->XILINXbase, 8, "ixj control");
}
} else if (j->dsp.low == 0x22) {
j->cardtype = QTI_PHONEJACK_PCI;
@@ -6941,19 +6939,17 @@ static int ixj_selfprobe(IXJ *j)
}
break;
case QTI_LINEJACK:
- if (check_region(j->XILINXbase, 8)) {
+ if (!request_region(j->XILINXbase, 8, "ixj control")) {
printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase);
return -1;
}
- request_region(j->XILINXbase, 8, "ixj control");
break;
case QTI_PHONEJACK_LITE:
case QTI_PHONEJACK_PCI:
- if (check_region(j->XILINXbase, 4)) {
+ if (!request_region(j->XILINXbase, 4, "ixj control")) {
printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase);
return -1;
}
- request_region(j->XILINXbase, 4, "ixj control");
j->pld_slicw.pcib.e1 = 1;
outb_p(j->pld_slicw.byte, j->XILINXbase);
break;
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 3246f790fed1..d98850e91055 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -181,6 +181,6 @@ config USB_XPAD
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
- The module will be called wacom.o. If you want to compile it as a
+ The module will be called xpad.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 6af6905572c9..5b4e92e6a616 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -386,6 +386,7 @@ static void __init fb_set_logocmap(struct fb_info *info)
palette_cmap.red = palette_red;
palette_cmap.green = palette_green;
palette_cmap.blue = palette_blue;
+ palette_cmap.transp = NULL;
for (i = 0; i < LINUX_LOGO_COLORS; i += n) {
n = LINUX_LOGO_COLORS - i;
@@ -767,6 +768,7 @@ fb_set_var(struct fb_var_screeninfo *var, struct fb_info *info)
int
fb_blank(int blank, struct fb_info *info)
{
+ /* ??? Varible sized stack allocation. */
u16 black[info->cmap.len];
struct fb_cmap cmap;
@@ -775,8 +777,7 @@ fb_blank(int blank, struct fb_info *info)
if (blank) {
memset(black, 0, info->cmap.len * sizeof(u16));
cmap.red = cmap.green = cmap.blue = black;
- if (info->cmap.transp)
- cmap.transp = black;
+ cmap.transp = info->cmap.transp ? black : NULL;
cmap.start = info->cmap.start;
cmap.len = info->cmap.len;
} else
diff --git a/fs/exec.c b/fs/exec.c
index 8f0b41fd3a28..7f6f6a06fa0a 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -45,6 +45,7 @@
#include <linux/ptrace.h>
#include <linux/mount.h>
#include <linux/security.h>
+#include <linux/rmap-locking.h>
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
@@ -292,12 +293,13 @@ void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long a
pgd_t * pgd;
pmd_t * pmd;
pte_t * pte;
+ struct pte_chain *pte_chain;
if (page_count(page) != 1)
printk(KERN_ERR "mem_map disagrees with %p at %08lx\n", page, address);
pgd = pgd_offset(tsk->mm, address);
-
+ pte_chain = pte_chain_alloc(GFP_KERNEL);
spin_lock(&tsk->mm->page_table_lock);
pmd = pmd_alloc(tsk->mm, pgd, address);
if (!pmd)
@@ -313,17 +315,19 @@ void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long a
flush_dcache_page(page);
flush_page_to_ram(page);
set_pte(pte, pte_mkdirty(pte_mkwrite(mk_pte(page, PAGE_COPY))));
- page_add_rmap(page, pte);
+ pte_chain = page_add_rmap(page, pte, pte_chain);
pte_unmap(pte);
tsk->mm->rss++;
spin_unlock(&tsk->mm->page_table_lock);
/* no need for flush_tlb */
+ pte_chain_free(pte_chain);
return;
out:
spin_unlock(&tsk->mm->page_table_lock);
__free_page(page);
force_sig(SIGKILL, tsk);
+ pte_chain_free(pte_chain);
return;
}
diff --git a/fs/mpage.c b/fs/mpage.c
index c2e3a2d4e8c4..a44993cd7927 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -275,7 +275,8 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages,
prefetchw(&page->flags);
list_del(&page->list);
- if (!add_to_page_cache(page, mapping, page->index)) {
+ if (!add_to_page_cache(page, mapping,
+ page->index, GFP_KERNEL)) {
bio = do_mpage_readpage(bio, page,
nr_pages - page_idx,
&last_block_in_bio, get_block);
diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c
index c5e66aab4e97..93ba7610dde0 100644
--- a/fs/ncpfs/sock.c
+++ b/fs/ncpfs/sock.c
@@ -587,7 +587,9 @@ static int __ncptcp_rcv_proc(struct ncp_server *server) {
}
#endif
type = ntohs(server->rcv.buf.type);
+#ifdef CONFIG_NCPFS_PACKET_SIGNING
cont:;
+#endif
if (type != NCP_REPLY) {
if (datalen - 8 <= sizeof(server->unexpected_packet.data)) {
*(__u16*)(server->unexpected_packet.data) = htons(type);
diff --git a/fs/nfsctl.c b/fs/nfsctl.c
index 195e1a6dc037..f5065ab668cb 100644
--- a/fs/nfsctl.c
+++ b/fs/nfsctl.c
@@ -54,16 +54,13 @@ static struct file *do_open(char *name, int flags)
static struct {
char *name; int wsize; int rsize;
} map[] = {
- [NFSCTL_SVC]={"svc", sizeof(struct nfsctl_svc)},
- [NFSCTL_ADDCLIENT]={"add", sizeof(struct nfsctl_client)},
- [NFSCTL_DELCLIENT]={"del", sizeof(struct nfsctl_client)},
- [NFSCTL_EXPORT]={"export", sizeof(struct nfsctl_export)},
- [NFSCTL_UNEXPORT]={"unexport", sizeof(struct nfsctl_export)},
-#ifdef notyet
- [NFSCTL_UGIDUPDATE]={"ugid", sizeof(struct nfsctl_uidmap)},
-#endif
- [NFSCTL_GETFD]={"getfd", sizeof(struct nfsctl_fdparm), NFS_FHSIZE},
- [NFSCTL_GETFS]={"getfs", sizeof(struct nfsctl_fsparm), sizeof(struct knfsd_fh)},
+ [NFSCTL_SVC]={".svc", sizeof(struct nfsctl_svc)},
+ [NFSCTL_ADDCLIENT]={".add", sizeof(struct nfsctl_client)},
+ [NFSCTL_DELCLIENT]={".del", sizeof(struct nfsctl_client)},
+ [NFSCTL_EXPORT]={".export", sizeof(struct nfsctl_export)},
+ [NFSCTL_UNEXPORT]={".unexport", sizeof(struct nfsctl_export)},
+ [NFSCTL_GETFD]={".getfd", sizeof(struct nfsctl_fdparm), NFS_FHSIZE},
+ [NFSCTL_GETFS]={".getfs", sizeof(struct nfsctl_fsparm), sizeof(struct knfsd_fh)},
};
long
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index b4b672ada9a5..fe8269fbc3bd 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -24,6 +24,7 @@
#include <linux/dcache.h>
#include <linux/namei.h>
#include <linux/mount.h>
+#include <linux/hash.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
@@ -59,12 +60,9 @@ static inline int svc_expkey_hash(struct svc_expkey *item)
int hash = item->ek_fsidtype;
char * cp = (char*)item->ek_fsid;
int len = (item->ek_fsidtype==0)?8:4;
- while (len--)
- hash += *cp++;
- cp = (char*)&item->ek_client;
- len = sizeof(item->ek_client);
- while (len--)
- hash += *cp++;
+
+ hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
+ hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS);
return hash & EXPKEY_HASHMASK;
}
@@ -239,17 +237,12 @@ static struct cache_head *export_table[EXPORT_HASHMAX];
static inline int svc_export_hash(struct svc_export *item)
{
- void *k[2];
- unsigned char *cp;
- int rv, i;
- k[0] = item->ex_client;
- k[1] = item->ex_dentry;
-
- cp = (char*)k;
- rv = 0;
- for (i=0; i<sizeof(k); i++)
- rv ^= cp[i];
- return rv & EXPORT_HASHMASK;
+ int rv;
+
+ rv = hash_ptr(item->ex_client, EXPORT_HASHBITS);
+ rv ^= hash_ptr(item->ex_dentry, EXPORT_HASHBITS);
+ rv ^= hash_ptr(item->ex_mnt, EXPORT_HASHBITS);
+ return rv;
}
void svc_export_put(struct cache_head *item, struct cache_detail *cd)
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 3cb91cc3cb03..7a6ef7e5a31a 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -58,7 +58,7 @@ decode_time3(u32 *p, struct timespec *time)
static inline u32 *
decode_fh(u32 *p, struct svc_fh *fhp)
{
- int size;
+ unsigned int size;
fh_init(fhp, NFS3_FHSIZE);
size = ntohl(*p++);
if (size > NFS3_FHSIZE)
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 99d89405387d..24a0a912e7c0 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -568,6 +568,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
resp->xbuf = &rqstp->rq_res;
resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len;
+ resp->tagp = resp->p + 1; /* skip over status */
+ /* reserve space for: status, taglen, tag, and opcnt */
resp->p += 3 + XDR_QUADLEN(args->taglen);
resp->end = rqstp->rq_res.head[0].iov_base + PAGE_SIZE;
resp->taglen = args->taglen;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 906b727f8873..fba884d7d8d6 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1728,8 +1728,17 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read
WRITE32(maxcount);
ADJUST_ARGS();
resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
- resp->p = resp->xbuf->tail[0].iov_base;
+
resp->xbuf->page_len = maxcount;
+
+ /* set up page for remaining responses */
+ svc_take_page(resp->rqstp);
+ resp->xbuf->tail[0].iov_base =
+ page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
+ resp->xbuf->tail[0].iov_len = 0;
+ resp->p = resp->xbuf->tail[0].iov_base;
+ resp->end = resp->p + PAGE_SIZE/4;
+
if (maxcount&3) {
*(resp->p)++ = 0;
resp->xbuf->tail[0].iov_base += maxcount&3;
@@ -1753,11 +1762,6 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r
svc_take_page(resp->rqstp);
page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
- svc_take_page(resp->rqstp);
- resp->xbuf->tail[0].iov_base =
- page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
- resp->xbuf->tail[0].iov_len = 0;
-
maxcount = PAGE_SIZE;
RESERVE_SPACE(4);
@@ -1774,7 +1778,14 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_r
WRITE32(maxcount);
ADJUST_ARGS();
resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
+
+ svc_take_page(resp->rqstp);
+ resp->xbuf->tail[0].iov_base =
+ page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
+ resp->xbuf->tail[0].iov_len = 0;
resp->p = resp->xbuf->tail[0].iov_base;
+ resp->end = resp->p + PAGE_SIZE/4;
+
resp->xbuf->page_len = maxcount;
if (maxcount&3) {
*(resp->p)++ = 0;
@@ -1803,6 +1814,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re
WRITE32(0);
WRITE32(0);
ADJUST_ARGS();
+ resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
maxcount = PAGE_SIZE;
if (maxcount > readdir->rd_maxcount)
@@ -1832,16 +1844,26 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_re
readdir->common.err == nfserr_readdir_nospc &&
readdir->buffer == page)
nfserr = nfserr_readdir_nospc;
- if (!nfserr) {
- if (readdir->offset)
- xdr_encode_hyper(readdir->offset, offset);
+ if (nfserr)
+ return nfserr;
- p = readdir->buffer;
- *p++ = 0; /* no more entries */
- *p++ = htonl(readdir->common.err == nfserr_eof);
- resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
- }
- return nfserr;
+ if (readdir->offset)
+ xdr_encode_hyper(readdir->offset, offset);
+
+ p = readdir->buffer;
+ *p++ = 0; /* no more entries */
+ *p++ = htonl(readdir->common.err == nfserr_eof);
+ resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
+
+ /* allocate a page for the tail */
+ svc_take_page(resp->rqstp);
+ resp->xbuf->tail[0].iov_base =
+ page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
+ resp->xbuf->tail[0].iov_len = 0;
+ resp->p = resp->xbuf->tail[0].iov_base;
+ resp->end = resp->p + PAGE_SIZE/4;
+
+ return 0;
}
static void
@@ -2066,6 +2088,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compound
* All that remains is to write the tag and operation count...
*/
struct iovec *iov;
+ p = resp->tagp;
*p++ = htonl(resp->taglen);
memcpy(p, resp->tag, resp->taglen);
p += XDR_QUADLEN(resp->taglen);
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 4d208cbaa5d9..7cc70b08b27d 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -46,20 +46,25 @@ enum {
NFSD_Getfd,
NFSD_Getfs,
NFSD_List,
+ NFSD_Fh,
+ NFSD_Threads,
+ NFSD_END
};
/*
* write() for these nodes.
*/
-static ssize_t write_svc(struct file *file, const char *buf, size_t size);
-static ssize_t write_add(struct file *file, const char *buf, size_t size);
-static ssize_t write_del(struct file *file, const char *buf, size_t size);
-static ssize_t write_export(struct file *file, const char *buf, size_t size);
-static ssize_t write_unexport(struct file *file, const char *buf, size_t size);
-static ssize_t write_getfd(struct file *file, const char *buf, size_t size);
-static ssize_t write_getfs(struct file *file, const char *buf, size_t size);
-
-static ssize_t (*write_op[])(struct file *, const char *, size_t) = {
+static ssize_t write_svc(struct file *file, char *buf, size_t size);
+static ssize_t write_add(struct file *file, char *buf, size_t size);
+static ssize_t write_del(struct file *file, char *buf, size_t size);
+static ssize_t write_export(struct file *file, char *buf, size_t size);
+static ssize_t write_unexport(struct file *file, char *buf, size_t size);
+static ssize_t write_getfd(struct file *file, char *buf, size_t size);
+static ssize_t write_getfs(struct file *file, char *buf, size_t size);
+static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
+static ssize_t write_threads(struct file *file, char *buf, size_t size);
+
+static ssize_t (*write_op[])(struct file *, char *, size_t) = {
[NFSD_Svc] = write_svc,
[NFSD_Add] = write_add,
[NFSD_Del] = write_del,
@@ -67,32 +72,81 @@ static ssize_t (*write_op[])(struct file *, const char *, size_t) = {
[NFSD_Unexport] = write_unexport,
[NFSD_Getfd] = write_getfd,
[NFSD_Getfs] = write_getfs,
+ [NFSD_Fh] = write_filehandle,
+ [NFSD_Threads] = write_threads,
};
-static ssize_t fs_write(struct file *file, const char *buf, size_t size, loff_t *pos)
+/* an argresp is stored in an allocated page and holds the
+ * size of the argument or response, along with it's content
+ */
+struct argresp {
+ ssize_t size;
+ char data[0];
+};
+
+/*
+ * transaction based IO methods.
+ * The file expects a single write which triggers the transaction, and then
+ * possibly a read which collects the result - which is stored in a
+ * file-local buffer.
+ */
+static ssize_t TA_write(struct file *file, const char *buf, size_t size, loff_t *pos)
{
ino_t ino = file->f_dentry->d_inode->i_ino;
+ struct argresp *ar;
+ ssize_t rv = 0;
+
if (ino >= sizeof(write_op)/sizeof(write_op[0]) || !write_op[ino])
return -EINVAL;
- return write_op[ino](file, buf, size);
+ if (file->private_data)
+ return -EINVAL; /* only one write allowed per open */
+ if (size > PAGE_SIZE - sizeof(struct argresp))
+ return -EFBIG;
+
+ ar = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!ar)
+ return -ENOMEM;
+ ar->size = 0;
+ down(&file->f_dentry->d_inode->i_sem);
+ if (file->private_data)
+ rv = -EINVAL;
+ else
+ file->private_data = ar;
+ up(&file->f_dentry->d_inode->i_sem);
+ if (rv) {
+ kfree(ar);
+ return rv;
+ }
+ if (copy_from_user(ar->data, buf, size))
+ return -EFAULT;
+
+ rv = write_op[ino](file, ar->data, size);
+ if (rv>0) {
+ ar->size = rv;
+ rv = size;
+ }
+ return rv;
}
-/*
- * read(), open() and release() for getfs and getfd (read/write ones).
- * IO on these is a simple transaction - you open() the file, write() to it
- * and that generates a (stored) response. After that read() will simply
- * access that response.
- */
static ssize_t TA_read(struct file *file, char *buf, size_t size, loff_t *pos)
{
- if (!file->private_data)
+ struct argresp *ar;
+ ssize_t rv = 0;
+
+ if (file->private_data == NULL)
+ rv = TA_write(file, buf, 0, pos);
+ if (rv < 0)
+ return rv;
+
+ ar = file->private_data;
+ if (!ar)
return 0;
- if (*pos >= file->f_dentry->d_inode->i_size)
+ if (*pos >= ar->size)
return 0;
- if (*pos + size > file->f_dentry->d_inode->i_size)
- size = file->f_dentry->d_inode->i_size - *pos;
- if (copy_to_user(buf, file->private_data + *pos, size))
+ if (*pos + size > ar->size)
+ size = ar->size - *pos;
+ if (copy_to_user(buf, ar->data + *pos, size))
return -EFAULT;
*pos += size;
return size;
@@ -112,12 +166,8 @@ static int TA_release(struct inode *inode, struct file *file)
return 0;
}
-static struct file_operations writer_ops = {
- .write = fs_write,
-};
-
-static struct file_operations reader_ops = {
- .write = fs_write,
+static struct file_operations transaction_ops = {
+ .write = TA_write,
.read = TA_read,
.open = TA_open,
.release = TA_release,
@@ -158,169 +208,224 @@ static struct file_operations exports_operations = {
* Description of fs contents.
*/
static struct { char *name; struct file_operations *ops; int mode; } files[] = {
- [NFSD_Svc] = {"svc", &writer_ops, S_IWUSR},
- [NFSD_Add] = {"add", &writer_ops, S_IWUSR},
- [NFSD_Del] = {"del", &writer_ops, S_IWUSR},
- [NFSD_Export] = {"export", &writer_ops, S_IWUSR},
- [NFSD_Unexport] = {"unexport", &writer_ops, S_IWUSR},
- [NFSD_Getfd] = {"getfd", &reader_ops, S_IWUSR|S_IRUSR},
- [NFSD_Getfs] = {"getfs", &reader_ops, S_IWUSR|S_IRUSR},
+ [NFSD_Svc] = {".svc", &transaction_ops, S_IWUSR},
+ [NFSD_Add] = {".add", &transaction_ops, S_IWUSR},
+ [NFSD_Del] = {".del", &transaction_ops, S_IWUSR},
+ [NFSD_Export] = {".export", &transaction_ops, S_IWUSR},
+ [NFSD_Unexport] = {".unexport", &transaction_ops, S_IWUSR},
+ [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
+ [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
[NFSD_List] = {"exports", &exports_operations, S_IRUGO},
+ [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
+ [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
};
/*----------------------------------------------------------------------------*/
/*
* payload - write methods
+ * If the method has a response, the response should be put in buf,
+ * and the length returned. Otherwise return 0 or and -error.
*/
-static ssize_t write_svc(struct file *file, const char *buf, size_t size)
+static ssize_t write_svc(struct file *file, char *buf, size_t size)
{
- struct nfsctl_svc data;
- if (size < sizeof(data))
+ struct nfsctl_svc *data;
+ if (size < sizeof(*data))
return -EINVAL;
- if (copy_from_user(&data, buf, size))
- return -EFAULT;
- return nfsd_svc(data.svc_port, data.svc_nthreads);
+ data = (struct nfsctl_svc*) buf;
+ return nfsd_svc(data->svc_port, data->svc_nthreads);
}
-static ssize_t write_add(struct file *file, const char *buf, size_t size)
+static ssize_t write_add(struct file *file, char *buf, size_t size)
{
- struct nfsctl_client data;
- if (size < sizeof(data))
+ struct nfsctl_client *data;
+ if (size < sizeof(*data))
return -EINVAL;
- if (copy_from_user(&data, buf, size))
- return -EFAULT;
- return exp_addclient(&data);
+ data = (struct nfsctl_client *)buf;
+ return exp_addclient(data);
}
-static ssize_t write_del(struct file *file, const char *buf, size_t size)
+static ssize_t write_del(struct file *file, char *buf, size_t size)
{
- struct nfsctl_client data;
- if (size < sizeof(data))
+ struct nfsctl_client *data;
+ if (size < sizeof(*data))
return -EINVAL;
- if (copy_from_user(&data, buf, size))
- return -EFAULT;
- return exp_delclient(&data);
+ data = (struct nfsctl_client *)buf;
+ return exp_delclient(data);
}
-static ssize_t write_export(struct file *file, const char *buf, size_t size)
+static ssize_t write_export(struct file *file, char *buf, size_t size)
{
- struct nfsctl_export data;
- if (size < sizeof(data))
+ struct nfsctl_export *data;
+ if (size < sizeof(*data))
return -EINVAL;
- if (copy_from_user(&data, buf, size))
- return -EFAULT;
- return exp_export(&data);
+ data = (struct nfsctl_export*)buf;
+ return exp_export(data);
}
-static ssize_t write_unexport(struct file *file, const char *buf, size_t size)
+static ssize_t write_unexport(struct file *file, char *buf, size_t size)
{
- struct nfsctl_export data;
- if (size < sizeof(data))
+ struct nfsctl_export *data;
+
+ if (size < sizeof(*data))
return -EINVAL;
- if (copy_from_user(&data, buf, size))
- return -EFAULT;
- return exp_unexport(&data);
+ data = (struct nfsctl_export*)buf;
+ return exp_unexport(data);
}
-static ssize_t write_getfs(struct file *file, const char *buf, size_t size)
+static ssize_t write_getfs(struct file *file, char *buf, size_t size)
{
- struct nfsctl_fsparm data;
+ struct nfsctl_fsparm *data;
struct sockaddr_in *sin;
struct auth_domain *clp;
int err = 0;
struct knfsd_fh *res;
- if (file->private_data)
+ if (size < sizeof(*data))
return -EINVAL;
- if (size < sizeof(data))
- return -EINVAL;
- if (copy_from_user(&data, buf, size))
- return -EFAULT;
- if (data.gd_addr.sa_family != AF_INET)
- return -EPROTONOSUPPORT;
- sin = (struct sockaddr_in *)&data.gd_addr;
- if (data.gd_maxlen > NFS3_FHSIZE)
- data.gd_maxlen = NFS3_FHSIZE;
- res = kmalloc(sizeof(struct knfsd_fh), GFP_KERNEL);
- if (!res)
- return -ENOMEM;
- memset(res, 0, sizeof(struct knfsd_fh));
+ data = (struct nfsctl_fsparm*)buf;
+ err = -EPROTONOSUPPORT;
+ if (data->gd_addr.sa_family != AF_INET)
+ goto out;
+ sin = (struct sockaddr_in *)&data->gd_addr;
+ if (data->gd_maxlen > NFS3_FHSIZE)
+ data->gd_maxlen = NFS3_FHSIZE;
+
+ res = (struct knfsd_fh*)buf;
+
exp_readlock();
if (!(clp = auth_unix_lookup(sin->sin_addr)))
err = -EPERM;
else {
- err = exp_rootfh(clp, data.gd_path, res, data.gd_maxlen);
+ err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
auth_domain_put(clp);
}
exp_readunlock();
-
- down(&file->f_dentry->d_inode->i_sem);
- if (file->private_data)
- err = -EINVAL;
- if (err)
- kfree(res);
- else {
- file->f_dentry->d_inode->i_size = res->fh_size + (int)&((struct knfsd_fh*)0)->fh_base;
- file->private_data = res;
- err = sizeof(data);
- }
- up(&file->f_dentry->d_inode->i_sem);
-
+ if (err == 0)
+ err = res->fh_size + (int)&((struct knfsd_fh*)0)->fh_base;
+ out:
return err;
}
-static ssize_t write_getfd(struct file *file, const char *buf, size_t size)
+static ssize_t write_getfd(struct file *file, char *buf, size_t size)
{
- struct nfsctl_fdparm data;
+ struct nfsctl_fdparm *data;
struct sockaddr_in *sin;
struct auth_domain *clp;
int err = 0;
struct knfsd_fh fh;
char *res;
- if (file->private_data)
+ if (size < sizeof(*data))
return -EINVAL;
- if (size < sizeof(data))
- return -EINVAL;
- if (copy_from_user(&data, buf, size))
- return -EFAULT;
- if (data.gd_addr.sa_family != AF_INET)
- return -EPROTONOSUPPORT;
- if (data.gd_version < 2 || data.gd_version > NFSSVC_MAXVERS)
- return -EINVAL;
- res = kmalloc(NFS_FHSIZE, GFP_KERNEL);
- if (!res)
- return -ENOMEM;
- sin = (struct sockaddr_in *)&data.gd_addr;
+ data = (struct nfsctl_fdparm*)buf;
+ err = -EPROTONOSUPPORT;
+ if (data->gd_addr.sa_family != AF_INET)
+ goto out;
+ err = -EINVAL;
+ if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS)
+ goto out;
+
+ res = buf;
+ sin = (struct sockaddr_in *)&data->gd_addr;
exp_readlock();
if (!(clp = auth_unix_lookup(sin->sin_addr)))
err = -EPERM;
else {
- err = exp_rootfh(clp, data.gd_path, &fh, NFS_FHSIZE);
+ err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
auth_domain_put(clp);
}
exp_readunlock();
- down(&file->f_dentry->d_inode->i_sem);
- if (file->private_data)
- err = -EINVAL;
- if (!err && fh.fh_size > NFS_FHSIZE)
- err = -EINVAL;
- if (err)
- kfree(res);
- else {
+ if (err == 0) {
memset(res,0, NFS_FHSIZE);
memcpy(res, &fh.fh_base, fh.fh_size);
- file->f_dentry->d_inode->i_size = NFS_FHSIZE;
- file->private_data = res;
- err = sizeof(data);
+ err = NFS_FHSIZE;
}
- up(&file->f_dentry->d_inode->i_sem);
-
+ out:
return err;
}
+static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
+{
+ /* request is:
+ * domain path maxsize
+ * response is
+ * filehandle
+ *
+ * qword quoting is used, so filehandle will be \x....
+ */
+ char *dname, *path;
+ int maxsize;
+ char *mesg = buf;
+ int len;
+ struct auth_domain *dom;
+ struct knfsd_fh fh;
+
+ if (buf[size-1] != '\n')
+ return -EINVAL;
+ buf[size-1] = 0;
+
+ dname = mesg;
+ len = qword_get(&mesg, dname, size);
+ if (len <= 0) return -EINVAL;
+
+ path = dname+len+1;
+ len = qword_get(&mesg, path, size);
+ if (len <= 0) return -EINVAL;
+
+ len = get_int(&mesg, &maxsize);
+ if (len)
+ return len;
+
+ if (maxsize < NFS_FHSIZE)
+ return -EINVAL;
+ if (maxsize > NFS3_FHSIZE)
+ maxsize = NFS3_FHSIZE;
+
+ if (qword_get(&mesg, mesg, size)>0)
+ return -EINVAL;
+
+ /* we have all the words, they are in buf.. */
+ dom = unix_domain_find(dname);
+ if (!dom)
+ return -ENOMEM;
+
+ len = exp_rootfh(dom, path, &fh, maxsize);
+ auth_domain_put(dom);
+ if (len)
+ return len;
+
+ mesg = buf; len = PAGE_SIZE-sizeof(struct argresp);
+ qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size);
+ mesg[-1] = '\n';
+ return mesg - buf;
+}
+
+extern int nfsd_nrthreads(void);
+
+static ssize_t write_threads(struct file *file, char *buf, size_t size)
+{
+ /* if size > 0, look for a number of threads and call nfsd_svc
+ * then write out number of threads as reply
+ */
+ char *mesg = buf;
+ int rv;
+ if (size > 0) {
+ int newthreads;
+ rv = get_int(&mesg, &newthreads);
+ if (rv)
+ return rv;
+ if (newthreads <0)
+ return -EINVAL;
+ rv = nfsd_svc(2049, newthreads);
+ if (rv)
+ return rv;
+ }
+ sprintf(buf, "%d\n", nfsd_nrthreads());
+ return strlen(buf);
+}
+
/*----------------------------------------------------------------------------*/
/*
* populating the filesystem.
@@ -357,7 +462,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
iput(inode);
return -ENOMEM;
}
- for (i = NFSD_Svc; i <= NFSD_List; i++) {
+ for (i = NFSD_Svc; i < NFSD_END; i++) {
struct qstr name;
name.name = files[i].name;
name.len = strlen(name.name);
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 1c50df32422b..78ead0520d8b 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -146,11 +146,11 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
}
error = nfserr_dropit;
- if (IS_ERR(exp))
+ if (IS_ERR(exp) && PTR_ERR(exp) == -EAGAIN)
goto out;
error = nfserr_stale;
- if (!exp)
+ if (!exp || IS_ERR(exp))
goto out;
/* Check if the request originated from a secure port. */
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index da4271183ef7..94f48ae35e95 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -66,6 +66,14 @@ struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list);
*/
#define NFSD_MAXSERVS 8192
+int nfsd_nrthreads(void)
+{
+ if (nfsd_serv == NULL)
+ return 0;
+ else
+ return nfsd_serv->sv_nrthreads;
+}
+
int
nfsd_svc(unsigned short port, int nrservs)
{
diff --git a/fs/readdir.c b/fs/readdir.c
index 74c0588af131..851091637310 100644
--- a/fs/readdir.c
+++ b/fs/readdir.c
@@ -11,6 +11,7 @@
#include <linux/file.h>
#include <linux/smp_lock.h>
#include <linux/fs.h>
+#include <linux/dirent.h>
#include <linux/security.h>
#include <asm/uaccess.h>
@@ -194,17 +195,6 @@ out:
return error;
}
-/*
- * And even better one including d_type field and 64bit d_ino and d_off.
- */
-struct linux_dirent64 {
- u64 d_ino;
- s64 d_off;
- unsigned short d_reclen;
- unsigned char d_type;
- char d_name[0];
-};
-
#define ROUND_UP64(x) (((x)+sizeof(u64)-1) & ~(sizeof(u64)-1))
struct getdents_callback64 {
diff --git a/include/asm-alpha/module.h b/include/asm-alpha/module.h
index edd833ab79dd..e2b59f65535c 100644
--- a/include/asm-alpha/module.h
+++ b/include/asm-alpha/module.h
@@ -1,6 +1,23 @@
-#ifndef _ASM_ALPHA_MODULE_H
-#define _ASM_ALPHA_MODULE_H
+#ifndef _ALPHA_MODULE_H
+#define _ALPHA_MODULE_H
-/* Module rewrite still in progress. */
+struct mod_arch_specific
+{
+ unsigned int gotsecindex;
+};
-#endif /* _ASM_ALPHA_MODULE_H */
+#define Elf_Sym Elf64_Sym
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Ehdr Elf64_Ehdr
+#define Elf_Phdr Elf64_Phdr
+#define Elf_Dyn Elf64_Dyn
+#define Elf_Rel Elf64_Rel
+#define Elf_Rela Elf64_Rela
+
+#define ARCH_SHF_SMALL SHF_ALPHA_GPREL
+
+#ifdef MODULE
+asm(".section .got,\"aws\",@nobits; .align 3; .previous");
+#endif
+
+#endif /*_ALPHA_MODULE_H*/
diff --git a/include/asm-alpha/uaccess.h b/include/asm-alpha/uaccess.h
index 5a3b8681f6af..a5985281aa7f 100644
--- a/include/asm-alpha/uaccess.h
+++ b/include/asm-alpha/uaccess.h
@@ -501,19 +501,14 @@ struct exception_table_entry
} fixup;
};
-/* Returns 0 if exception not found and fixup.unit otherwise. */
-extern unsigned search_exception_table(unsigned long);
-
/* Returns the new pc */
-#define fixup_exception(map_reg, fixup_unit, pc) \
+#define fixup_exception(map_reg, fixup, pc) \
({ \
- union exception_fixup __fie_fixup; \
- __fie_fixup.unit = fixup_unit; \
- if (__fie_fixup.bits.valreg != 31) \
- map_reg(__fie_fixup.bits.valreg) = 0; \
- if (__fie_fixup.bits.errreg != 31) \
- map_reg(__fie_fixup.bits.errreg) = -EFAULT; \
- (pc) + __fie_fixup.bits.nextinsn; \
+ if ((fixup)->fixup.bits.valreg != 31) \
+ map_reg((fixup)->fixup.bits.valreg) = 0; \
+ if ((fixup)->fixup.bits.errreg != 31) \
+ map_reg((fixup)->fixup.bits.errreg) = -EFAULT; \
+ (pc) + (fixup)->fixup.bits.nextinsn; \
})
diff --git a/include/asm-i386/highmem.h b/include/asm-i386/highmem.h
index 0c054078731b..a143e85d521e 100644
--- a/include/asm-i386/highmem.h
+++ b/include/asm-i386/highmem.h
@@ -39,7 +39,7 @@ extern void kmap_init(void);
* easily, subsequent pte tables have to be allocated in one physical
* chunk of RAM.
*/
-#define PKMAP_BASE (0xfe000000UL)
+#define PKMAP_BASE (0xff800000UL)
#ifdef CONFIG_X86_PAE
#define LAST_PKMAP 512
#else
diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
index 1bf8d4830649..adcd9a41c7d2 100644
--- a/include/asm-i386/thread_info.h
+++ b/include/asm-i386/thread_info.h
@@ -110,6 +110,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */
+#define TIF_IRET 5 /* return with iret */
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */
@@ -118,6 +119,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
+#define _TIF_IRET (1<<TIF_IRET)
#define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h
index 377038170a0b..ef7f1101a94c 100644
--- a/include/asm-i386/uaccess.h
+++ b/include/asm-i386/uaccess.h
@@ -92,10 +92,6 @@ struct exception_table_entry
unsigned long insn, fixup;
};
-/* Returns 0 if exception not found and fixup otherwise. */
-extern unsigned long search_exception_table(unsigned long);
-
-
/*
* These are the main single-value transfer routines. They automatically
* use the right size if we just have the right pointer type.
diff --git a/include/asm-ppc/uaccess.h b/include/asm-ppc/uaccess.h
index 1931d72ce8a9..51bb269cf589 100644
--- a/include/asm-ppc/uaccess.h
+++ b/include/asm-ppc/uaccess.h
@@ -56,8 +56,6 @@ struct exception_table_entry
unsigned long insn, fixup;
};
-/* Returns 0 if exception not found and fixup otherwise. */
-extern unsigned long search_exception_table(unsigned long);
extern void sort_exception_table(void);
/*
diff --git a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h
index f384c300e5e3..bf8792ec92bb 100644
--- a/include/asm-sparc64/compat.h
+++ b/include/asm-sparc64/compat.h
@@ -5,32 +5,25 @@
*/
#include <linux/types.h>
-#define COMPAT_USER_HZ 100
+#define COMPAT_USER_HZ 100
typedef u32 compat_size_t;
typedef s32 compat_ssize_t;
typedef s32 compat_time_t;
typedef s32 compat_clock_t;
-
-struct compat_stat {
- __kernel_dev_t32 st_dev;
- __kernel_ino_t32 st_ino;
- __kernel_mode_t32 st_mode;
- s16 st_nlink;
- __kernel_uid_t32 st_uid;
- __kernel_gid_t32 st_gid;
- __kernel_dev_t32 st_rdev;
- __kernel_off_t32 st_size;
- compat_time_t st_atime;
- u32 __unused1;
- compat_time_t st_mtime;
- u32 __unused2;
- compat_time_t st_ctime;
- u32 __unused3;
- __kernel_off_t32 st_blksize;
- __kernel_off_t32 st_blocks;
- u32 __unused4[2];
-};
+typedef s32 compat_pid_t;
+typedef u16 compat_uid_t;
+typedef u16 compat_gid_t;
+typedef u16 compat_mode_t;
+typedef u32 compat_ino_t;
+typedef u16 compat_dev_t;
+typedef s32 compat_off_t;
+typedef s64 compat_loff_t;
+typedef s16 compat_nlink_t;
+typedef u16 compat_ipc_pid_t;
+typedef s32 compat_daddr_t;
+typedef u32 compat_caddr_t;
+typedef __kernel_fsid_t compat_fsid_t;
struct compat_timespec {
compat_time_t tv_sec;
@@ -42,13 +35,33 @@ struct compat_timeval {
s32 tv_usec;
};
+struct compat_stat {
+ compat_dev_t st_dev;
+ compat_ino_t st_ino;
+ compat_mode_t st_mode;
+ compat_nlink_t st_nlink;
+ compat_uid_t st_uid;
+ compat_gid_t st_gid;
+ compat_dev_t st_rdev;
+ compat_off_t st_size;
+ compat_time_t st_atime;
+ u32 __unused1;
+ compat_time_t st_mtime;
+ u32 __unused2;
+ compat_time_t st_ctime;
+ u32 __unused3;
+ compat_off_t st_blksize;
+ compat_off_t st_blocks;
+ u32 __unused4[2];
+};
+
struct compat_flock {
- short l_type;
- short l_whence;
- __kernel_off_t32 l_start;
- __kernel_off_t32 l_len;
- __kernel_pid_t32 l_pid;
- short __unused;
+ short l_type;
+ short l_whence;
+ compat_off_t l_start;
+ compat_off_t l_len;
+ compat_pid_t l_pid;
+ short __unused;
};
#endif /* _ASM_SPARC64_COMPAT_H */
diff --git a/include/asm-sparc64/posix_types.h b/include/asm-sparc64/posix_types.h
index dee9441f02d7..b39c8781fb7e 100644
--- a/include/asm-sparc64/posix_types.h
+++ b/include/asm-sparc64/posix_types.h
@@ -47,23 +47,6 @@ typedef struct {
#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
} __kernel_fsid_t;
-/* Now 32bit compatibility types */
-typedef int __kernel_ptrdiff_t32;
-typedef int __kernel_pid_t32;
-typedef unsigned short __kernel_ipc_pid_t32;
-typedef unsigned short __kernel_uid_t32;
-typedef unsigned short __kernel_gid_t32;
-typedef unsigned short __kernel_dev_t32;
-typedef unsigned int __kernel_ino_t32;
-typedef unsigned short __kernel_mode_t32;
-typedef unsigned short __kernel_umode_t32;
-typedef short __kernel_nlink_t32;
-typedef int __kernel_daddr_t32;
-typedef int __kernel_off_t32;
-typedef unsigned int __kernel_caddr_t32;
-typedef long __kernel_loff_t32;
-typedef __kernel_fsid_t __kernel_fsid_t32;
-
#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
#undef __FD_SET
diff --git a/include/asm-sparc64/siginfo.h b/include/asm-sparc64/siginfo.h
index 5104c270ca25..72289f69991b 100644
--- a/include/asm-sparc64/siginfo.h
+++ b/include/asm-sparc64/siginfo.h
@@ -13,7 +13,7 @@
#ifdef __KERNEL__
-#include <asm/compat.h>
+#include <linux/compat.h>
typedef union sigval32 {
int sival_int;
@@ -30,7 +30,7 @@ typedef struct siginfo32 {
/* kill() */
struct {
- __kernel_pid_t32 _pid; /* sender's pid */
+ compat_pid_t _pid; /* sender's pid */
unsigned int _uid; /* sender's uid */
} _kill;
@@ -42,14 +42,14 @@ typedef struct siginfo32 {
/* POSIX.1b signals */
struct {
- __kernel_pid_t32 _pid; /* sender's pid */
+ compat_pid_t _pid; /* sender's pid */
unsigned int _uid; /* sender's uid */
sigval_t32 _sigval;
} _rt;
/* SIGCHLD */
struct {
- __kernel_pid_t32 _pid; /* which child */
+ compat_pid_t _pid; /* which child */
unsigned int _uid; /* sender's uid */
int _status; /* exit code */
compat_clock_t _utime;
diff --git a/include/asm-sparc64/statfs.h b/include/asm-sparc64/statfs.h
index 5aee11569fbd..116ae1814702 100644
--- a/include/asm-sparc64/statfs.h
+++ b/include/asm-sparc64/statfs.h
@@ -5,6 +5,7 @@
#ifndef __KERNEL_STRICT_NAMES
#include <linux/types.h>
+#include <linux/compat.h> /* for compat_fsid_t */
typedef __kernel_fsid_t fsid_t;
@@ -18,7 +19,7 @@ struct statfs32 {
int f_bavail;
int f_files;
int f_ffree;
- __kernel_fsid_t32 f_fsid;
+ compat_fsid_t f_fsid;
int f_namelen; /* SunOS ignores this field. */
int f_spare[6];
};
diff --git a/include/asm-sparc64/uaccess.h b/include/asm-sparc64/uaccess.h
index 5d9b9d4a070a..3f04ac105de9 100644
--- a/include/asm-sparc64/uaccess.h
+++ b/include/asm-sparc64/uaccess.h
@@ -84,8 +84,8 @@ struct exception_table_entry
unsigned insn, fixup;
};
-/* Returns 0 if exception not found and fixup otherwise. */
-extern unsigned long search_exception_table(unsigned long, unsigned long *);
+/* Special exable search, which handles ranges. Returns fixup */
+unsigned long search_extables_range(unsigned long addr, unsigned long *g2);
extern void __ret_efault(void);
diff --git a/include/linux/agp_backend.h b/include/linux/agp_backend.h
index 90890f4e9e6d..e8fec2776624 100644
--- a/include/linux/agp_backend.h
+++ b/include/linux/agp_backend.h
@@ -63,7 +63,7 @@ enum chipset_type {
VIA_APOLLO_KT400_3,
VIA_APOLLO_PRO_266,
VIA_VT8605,
- VIA_P4X400,
+ VIA_P4X,
SIS_GENERIC,
AMD_GENERIC,
AMD_IRONGATE,
diff --git a/include/linux/dirent.h b/include/linux/dirent.h
index bef1120cba96..5d6023b87800 100644
--- a/include/linux/dirent.h
+++ b/include/linux/dirent.h
@@ -16,4 +16,17 @@ struct dirent64 {
char d_name[256];
};
+#ifdef __KERNEL__
+
+struct linux_dirent64 {
+ u64 d_ino;
+ s64 d_off;
+ unsigned short d_reclen;
+ unsigned char d_type;
+ char d_name[0];
+};
+
+#endif /* __KERNEL__ */
+
+
#endif
diff --git a/include/linux/elf.h b/include/linux/elf.h
index 2745227ff929..4435d0be3575 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -159,6 +159,9 @@ typedef __s64 Elf64_Sxword;
#define ELF32_ST_BIND(x) ((x) >> 4)
#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf)
+#define ELF64_ST_BIND(x) ((x) >> 4)
+#define ELF64_ST_TYPE(x) (((unsigned int) x) & 0xf)
+
/* Symbolic values for the entries in the auxiliary table
put on the initial stack */
#define AT_NULL 0 /* end of vector */
@@ -362,22 +365,30 @@ typedef struct {
#define R_ALPHA_SREL16 9 /* PC relative 16 bit */
#define R_ALPHA_SREL32 10 /* PC relative 32 bit */
#define R_ALPHA_SREL64 11 /* PC relative 64 bit */
-#define R_ALPHA_OP_PUSH 12 /* OP stack push */
-#define R_ALPHA_OP_STORE 13 /* OP stack pop and store */
-#define R_ALPHA_OP_PSUB 14 /* OP stack subtract */
-#define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */
-#define R_ALPHA_GPVALUE 16
-#define R_ALPHA_GPRELHIGH 17
-#define R_ALPHA_GPRELLOW 18
-#define R_ALPHA_IMMED_GP_16 19
-#define R_ALPHA_IMMED_GP_HI32 20
-#define R_ALPHA_IMMED_SCN_HI32 21
-#define R_ALPHA_IMMED_BR_HI32 22
-#define R_ALPHA_IMMED_LO32 23
+#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */
+#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */
+#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */
#define R_ALPHA_COPY 24 /* Copy symbol at runtime */
#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */
#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */
#define R_ALPHA_RELATIVE 27 /* Adjust by program base */
+#define R_ALPHA_BRSGP 28
+#define R_ALPHA_TLSGD 29
+#define R_ALPHA_TLS_LDM 30
+#define R_ALPHA_DTPMOD64 31
+#define R_ALPHA_GOTDTPREL 32
+#define R_ALPHA_DTPREL64 33
+#define R_ALPHA_DTPRELHI 34
+#define R_ALPHA_DTPRELLO 35
+#define R_ALPHA_DTPREL16 36
+#define R_ALPHA_GOTTPREL 37
+#define R_ALPHA_TPREL64 38
+#define R_ALPHA_TPRELHI 39
+#define R_ALPHA_TPRELLO 40
+#define R_ALPHA_TPREL16 41
+
+#define SHF_ALPHA_GPREL 0x10000000
+
/* PowerPC relocations defined by the ABIs */
#define R_PPC_NONE 0
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 1586beac00fb..b8334a2df0d8 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -14,8 +14,6 @@ extern struct page *highmem_start_page;
/* declarations for linux/mm/highmem.c */
unsigned int nr_free_highpages(void);
-extern void check_highmem_ptes(void);
-
#else /* CONFIG_HIGHMEM */
static inline unsigned int nr_free_highpages(void) { return 0; }
@@ -30,6 +28,13 @@ static inline void *kmap(struct page *page) { return page_address(page); }
#endif /* CONFIG_HIGHMEM */
+#if defined(CONFIG_DEBUG_HIGHMEM) && defined(CONFIG_HIGHMEM)
+extern void check_highmem_ptes(void);
+#else
+static inline void check_highmem_ptes(void)
+{}
+#endif
+
/* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */
static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
{
diff --git a/include/linux/init.h b/include/linux/init.h
index b7c6363478aa..a3ad7dd1a38f 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -111,7 +111,8 @@ struct obs_kernel_param {
*
* module_init() will either be called during do_initcalls (if
* builtin) or at module insertion time (if a module). There can only
- * be one per module. */
+ * be one per module.
+ */
#define module_init(x) __initcall(x);
/**
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 9cb6277f5b86..7eedbb751856 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -84,6 +84,7 @@ extern unsigned long long memparse(char *ptr, char **retptr);
extern void dev_probe_lock(void);
extern void dev_probe_unlock(void);
+extern int kernel_text_address(unsigned long addr);
extern int session_of_pgrp(int pgrp);
asmlinkage int printk(const char * fmt, ...)
@@ -105,7 +106,7 @@ extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in
extern int tainted;
extern const char *print_tainted(void);
-#define TAINT_PROPRIETORY_MODULE (1<<0)
+#define TAINT_PROPRIETARY_MODULE (1<<0)
#define TAINT_FORCED_MODULE (1<<1)
#define TAINT_UNSAFE_SMP (1<<2)
#define TAINT_FORCED_RMMOD (1<<3)
diff --git a/include/linux/module.h b/include/linux/module.h
index 8e1954a89913..54214da9a651 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -21,7 +21,6 @@
#include <asm/uaccess.h> /* For struct exception_table_entry */
/* Not Yet Implemented */
-#define MODULE_LICENSE(name)
#define MODULE_AUTHOR(name)
#define MODULE_DESCRIPTION(desc)
#define MODULE_SUPPORTED_DEVICE(name)
@@ -44,6 +43,12 @@ struct kernel_symbol
extern int init_module(void);
extern void cleanup_module(void);
+/* Archs provide a method of finding the correct exception table. */
+const struct exception_table_entry *
+search_extable(const struct exception_table_entry *first,
+ const struct exception_table_entry *last,
+ unsigned long value);
+
#ifdef MODULE
/* For replacement modutils, use an alias not a pointer. */
@@ -57,11 +62,41 @@ extern const struct gtype##_id __mod_##gtype##_table \
#define THIS_MODULE (&__this_module)
+/*
+ * The following license idents are currently accepted as indicating free
+ * software modules
+ *
+ * "GPL" [GNU Public License v2 or later]
+ * "GPL v2" [GNU Public License v2]
+ * "GPL and additional rights" [GNU Public License v2 rights and more]
+ * "Dual BSD/GPL" [GNU Public License v2
+ * or BSD license choice]
+ * "Dual MPL/GPL" [GNU Public License v2
+ * or Mozilla license choice]
+ *
+ * The following other idents are available
+ *
+ * "Proprietary" [Non free products]
+ *
+ * There are dual licensed components, but when running with Linux it is the
+ * GPL that is relevant so this is a non issue. Similarly LGPL linked with GPL
+ * is a GPL combined work.
+ *
+ * This exists for several reasons
+ * 1. So modinfo can show license info for users wanting to vet their setup
+ * is free
+ * 2. So the community can ignore bug reports including proprietary modules
+ * 3. So vendors can do likewise based on their own policies
+ */
+#define MODULE_LICENSE(license) \
+ static const char __module_license[] \
+ __attribute__((section(".init.license"))) = license
+
#else /* !MODULE */
#define MODULE_GENERIC_TABLE(gtype,name)
#define THIS_MODULE ((struct module *)0)
-
+#define MODULE_LICENSE(license)
#endif
#define MODULE_DEVICE_TABLE(type,name) \
@@ -75,10 +110,16 @@ struct kernel_symbol_group
/* Module which owns it (if any) */
struct module *owner;
+ /* Are we internal use only? */
+ int gplonly;
+
unsigned int num_syms;
const struct kernel_symbol *syms;
};
+/* Given an address, look for it in the exception tables */
+const struct exception_table_entry *search_exception_tables(unsigned long add);
+
struct exception_table
{
struct list_head list;
@@ -101,7 +142,11 @@ void *__symbol_get_gpl(const char *symbol);
= { (unsigned long)&sym, MODULE_SYMBOL_PREFIX #sym }
#define EXPORT_SYMBOL_NOVERS(sym) EXPORT_SYMBOL(sym)
-#define EXPORT_SYMBOL_GPL(sym) EXPORT_SYMBOL(sym)
+
+#define EXPORT_SYMBOL_GPL(sym) \
+ const struct kernel_symbol __ksymtab_##sym \
+ __attribute__((section("__gpl_ksymtab"))) \
+ = { (unsigned long)&sym, #sym }
struct module_ref
{
@@ -128,6 +173,9 @@ struct module
/* Exported symbols */
struct kernel_symbol_group symbols;
+ /* GPL-only exported symbols. */
+ struct kernel_symbol_group gpl_symbols;
+
/* Exception tables */
struct exception_table extable;
@@ -149,6 +197,9 @@ struct module
/* Am I unsafe to unload? */
int unsafe;
+ /* Am I GPL-compatible */
+ int license_gplok;
+
#ifdef CONFIG_MODULE_UNLOAD
/* Reference counts */
struct module_ref ref[NR_CPUS];
@@ -183,6 +234,9 @@ static inline int module_is_live(struct module *mod)
return mod->state != MODULE_STATE_GOING;
}
+/* Is this address in a module? */
+int module_text_address(unsigned long addr);
+
#ifdef CONFIG_MODULE_UNLOAD
void __symbol_put(const char *symbol);
@@ -258,18 +312,40 @@ const char *module_address_lookup(unsigned long addr,
unsigned long *offset,
char **modname);
+/* For extable.c to search modules' exception tables. */
+const struct exception_table_entry *search_module_extables(unsigned long addr);
+
#else /* !CONFIG_MODULES... */
#define EXPORT_SYMBOL(sym)
#define EXPORT_SYMBOL_GPL(sym)
#define EXPORT_SYMBOL_NOVERS(sym)
+/* Given an address, look for it in the exception tables. */
+static inline const struct exception_table_entry *
+search_module_extables(unsigned long addr)
+{
+ return NULL;
+}
+
+/* Is this address in a module? */
+static int module_text_address(unsigned long addr)
+{
+ return 0;
+}
+
/* Get/put a kernel symbol (calls should be symmetric) */
#define symbol_get(x) (&(x))
#define symbol_put(x) do { } while(0)
#define symbol_put_addr(x) do { } while(0)
-#define try_module_get(module) 1
-#define module_put(module) do { } while(0)
+static inline int try_module_get(struct module *module)
+{
+ return 1;
+}
+
+static inline void module_put(struct module *module)
+{
+}
#define module_name(mod) "kernel"
@@ -293,6 +369,7 @@ struct module __this_module
__attribute__((section(".gnu.linkonce.this_module"))) = {
.name = __stringify(KBUILD_MODNAME),
.symbols = { .owner = &__this_module },
+ .gpl_symbols = { .owner = &__this_module, .gplonly = 1 },
.init = init_module,
#ifdef CONFIG_MODULE_UNLOAD
.exit = cleanup_module,
@@ -301,10 +378,6 @@ __attribute__((section(".gnu.linkonce.this_module"))) = {
#endif /* KBUILD_MODNAME */
#endif /* MODULE */
-/* For archs to search exception tables */
-extern struct list_head extables;
-extern spinlock_t modlist_lock;
-
#define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x)
/* BELOW HERE ALL THESE ARE OBSOLETE AND WILL VANISH */
@@ -362,14 +435,6 @@ extern int module_dummy_usage;
#define GET_USE_COUNT(module) (module_dummy_usage)
#define MOD_IN_USE 0
#define __MODULE_STRING(x) __stringify(x)
-#define __mod_between(a_start, a_len, b_start, b_len) \
-(((a_start) >= (b_start) && (a_start) <= (b_start)+(b_len)) \
- || ((a_start)+(a_len) >= (b_start) \
- && (a_start)+(a_len) <= (b_start)+(b_len)))
-#define mod_bound(p, n, m) \
-(((m)->module_init \
- && __mod_between((p),(n),(m)->module_init,(m)->init_size)) \
- || __mod_between((p),(n),(m)->module_core,(m)->core_size))
/*
* The exception and symbol tables, and the lock
diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h
index 5001ff39204d..991e9cdf3213 100644
--- a/include/linux/moduleloader.h
+++ b/include/linux/moduleloader.h
@@ -16,9 +16,9 @@ unsigned long find_symbol_internal(Elf_Shdr *sechdrs,
/* These must be implemented by the specific architecture */
/* Adjust arch-specific sections. Return 0 on success. */
-int module_frob_arch_sections(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- const char *secstrings,
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ char *secstrings,
struct module *mod);
/* Allocator used for allocating struct module, core sections and init
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 8359679908ab..c29972812936 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -320,6 +320,7 @@ struct nfsd4_compoundres {
u32 taglen;
char * tag;
u32 opcnt;
+ u32 * tagp; /* where to encode tag and opcount */
};
#define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs)
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 9707f467b2be..1a297ca9d00a 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -66,10 +66,10 @@ extern struct page * read_cache_page(struct address_space *mapping,
extern int read_cache_pages(struct address_space *mapping,
struct list_head *pages, filler_t *filler, void *data);
-extern int add_to_page_cache(struct page *page,
- struct address_space *mapping, unsigned long index);
-extern int add_to_page_cache_lru(struct page *page,
- struct address_space *mapping, unsigned long index);
+int add_to_page_cache(struct page *page, struct address_space *mapping,
+ unsigned long index, int gfp_mask);
+int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
+ unsigned long index, int gfp_mask);
extern void remove_from_page_cache(struct page *page);
extern void __remove_from_page_cache(struct page *page);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 89874d8eeee7..0cab668cbfc6 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1092,7 +1092,7 @@
#define PCI_DEVICE_ID_VIA_8233C_0 0x3109
#define PCI_DEVICE_ID_VIA_8361 0x3112
#define PCI_DEVICE_ID_VIA_8233A 0x3147
-#define PCI_DEVICE_ID_VIA_8235_0 0x3168
+#define PCI_DEVICE_ID_VIA_8754 0x3168
#define PCI_DEVICE_ID_VIA_8235 0x3177
#define PCI_DEVICE_ID_VIA_8377_0 0x3189
#define PCI_DEVICE_ID_VIA_86C100A 0x6100
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index 4e58eb79abeb..f4a78d52b5ce 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -19,6 +19,8 @@
#ifndef _LINUX_RADIX_TREE_H
#define _LINUX_RADIX_TREE_H
+#include <linux/preempt.h>
+
struct radix_tree_node;
struct radix_tree_root {
@@ -45,5 +47,11 @@ extern int radix_tree_delete(struct radix_tree_root *, unsigned long);
extern unsigned int
radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
unsigned long first_index, unsigned int max_items);
+int radix_tree_preload(int gfp_mask);
+
+static inline void radix_tree_preload_end(void)
+{
+ preempt_enable();
+}
#endif /* _LINUX_RADIX_TREE_H */
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index f658735d28b2..d6f2928fc8c7 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -28,6 +28,8 @@
#define LEVEL_MULTIPATH (-4)
#define LEVEL_LINEAR (-1)
+#define MaxSector (~(sector_t)0)
+
static inline int pers_to_level (int pers)
{
switch (pers) {
@@ -198,7 +200,6 @@ struct mddev_s
int level, layout;
int raid_disks;
int max_disks;
- unsigned long state;
sector_t size; /* used size of component devices */
__u64 events;
@@ -215,6 +216,7 @@ struct mddev_s
* it can only be set > 0 under reconfig_sem
*/
int recovery_running;
+ int recovery_error; /* error from recovery write */
int in_sync; /* know to not need resync */
struct semaphore reconfig_sem;
atomic_t active;
@@ -226,6 +228,7 @@ struct mddev_s
atomic_t recovery_active; /* blocks scheduled, but not written */
wait_queue_head_t recovery_wait;
+ sector_t recovery_cp;
request_queue_t queue; /* for plugging ... */
diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
index d6bb37a810b3..cb002ba3556f 100644
--- a/include/linux/raid/md_p.h
+++ b/include/linux/raid/md_p.h
@@ -131,11 +131,16 @@ typedef struct mdp_superblock_s {
#ifdef __BIG_ENDIAN
__u32 events_hi; /* 7 high-order of superblock update count */
__u32 events_lo; /* 8 low-order of superblock update count */
+ __u32 cp_events_hi; /* 9 high-order of checkpoint update count */
+ __u32 cp_events_lo; /* 10 low-order of checkpoint update count */
#else
__u32 events_lo; /* 7 low-order of superblock update count */
__u32 events_hi; /* 8 high-order of superblock update count */
+ __u32 cp_events_lo; /* 9 low-order of checkpoint update count */
+ __u32 cp_events_hi; /* 10 high-order of checkpoint update count */
#endif
- __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 9];
+ __u32 recovery_cp; /* 11 recovery checkpoint sector count */
+ __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 12];
/*
* Personality information
diff --git a/include/linux/rmap-locking.h b/include/linux/rmap-locking.h
index 302a58f54ca3..51f6697f3794 100644
--- a/include/linux/rmap-locking.h
+++ b/include/linux/rmap-locking.h
@@ -5,6 +5,11 @@
* pte chain.
*/
+#include <linux/slab.h>
+
+struct pte_chain;
+extern kmem_cache_t *pte_chain_cache;
+
static inline void pte_chain_lock(struct page *page)
{
/*
@@ -31,3 +36,12 @@ static inline void pte_chain_unlock(struct page *page)
#endif
preempt_enable();
}
+
+struct pte_chain *pte_chain_alloc(int gfp_flags);
+void __pte_chain_free(struct pte_chain *pte_chain);
+
+static inline void pte_chain_free(struct pte_chain *pte_chain)
+{
+ if (pte_chain)
+ __pte_chain_free(pte_chain);
+}
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 8243c6bec130..06ac1c4f1530 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -86,6 +86,7 @@ int cpu_up(unsigned int cpu);
void smp_prepare_boot_cpu(void);
#else /* !SMP */
+#include <asm/page.h> /* For BUG() */
/*
* These macros fold the SMP functionality into a single CPU system
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
index 74e53a04907e..a3cdc080dd85 100644
--- a/include/linux/sunrpc/cache.h
+++ b/include/linux/sunrpc/cache.h
@@ -78,6 +78,11 @@ struct cache_detail {
int (*cache_parse)(struct cache_detail *,
char *buf, int len);
+ int (*cache_show)(struct seq_file *m,
+ struct cache_detail *cd,
+ struct cache_head *h,
+ char *pbuf);
+
/* fields below this comment are for internal use
* and should not be touched by cache owners
*/
@@ -171,7 +176,7 @@ RTN *FNAME ARGS \
if (!new) break; \
\
new->MEMBER.next = tmp->MEMBER.next; \
- *head = &new->MEMBER; \
+ *hp = &new->MEMBER; \
tmp->MEMBER.next = NULL; \
set_bit(CACHE_HASHED, &new->MEMBER.flags); \
clear_bit(CACHE_HASHED, &tmp->MEMBER.flags); \
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
index 9c6bf43a26b8..95a45edc2f99 100644
--- a/include/linux/sunrpc/svcauth.h
+++ b/include/linux/sunrpc/svcauth.h
@@ -11,8 +11,10 @@
#ifdef __KERNEL__
+#include <linux/string.h>
#include <linux/sunrpc/msg_prot.h>
#include <linux/sunrpc/cache.h>
+#include <linux/string.h>
struct svc_cred {
uid_t cr_uid;
@@ -111,7 +113,11 @@ extern struct auth_domain *auth_unix_lookup(struct in_addr addr);
extern int auth_unix_forget_old(struct auth_domain *dom);
extern void svcauth_unix_purge(void);
-extern int name_hash(char *name, int size);
+extern int hash_mem(char *buf, int len, int bits);
+static inline int hash_str(char *name, int bits)
+{
+ return hash_mem(name, strlen(name), bits);
+}
extern struct cache_detail auth_domain_cache, ip_map_cache;
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 9ab02098aad5..d20061e6cb08 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -169,11 +169,13 @@ extern int vm_swappiness;
extern void out_of_memory(void);
/* linux/mm/rmap.c */
-extern int FASTCALL(page_referenced(struct page *));
-extern void FASTCALL(page_add_rmap(struct page *, pte_t *));
-extern void FASTCALL(page_remove_rmap(struct page *, pte_t *));
-extern int FASTCALL(try_to_unmap(struct page *));
-extern int FASTCALL(page_over_rsslimit(struct page *));
+struct pte_chain;
+int FASTCALL(page_referenced(struct page *));
+struct pte_chain *FASTCALL(page_add_rmap(struct page *, pte_t *,
+ struct pte_chain *));
+void FASTCALL(page_remove_rmap(struct page *, pte_t *));
+int FASTCALL(try_to_unmap(struct page *));
+int FASTCALL(page_over_rsslimit(struct page *));
/* return values of try_to_unmap */
#define SWAP_SUCCESS 0
diff --git a/init/Kconfig b/init/Kconfig
index 962d16696ef9..2868e39049c0 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -82,6 +82,51 @@ config SYSCTL
building a kernel for install/rescue disks or your system is very
limited in memory.
+choice
+ prompt "Kernel log buffer size"
+ default LOG_BUF_SHIFT_17 if ARCH_S390
+ default LOG_BUF_SHIFT_16 if X86_NUMAQ || IA64
+ default LOG_BUF_SHIFT_15 if SMP
+ default LOG_BUF_SHIFT_14
+ help
+ Select kernel log buffer size from this list (power of 2).
+ Defaults: 17 (=> 128 KB for S/390)
+ 16 (=> 64 KB for x86 NUMAQ or IA-64)
+ 15 (=> 32 KB for SMP)
+ 14 (=> 16 KB for uniprocessor)
+
+config LOG_BUF_SHIFT_17
+ bool "128 KB"
+ default y if ARCH_S390
+
+config LOG_BUF_SHIFT_16
+ bool "64 KB"
+ default y if X86_NUMAQ || IA64
+
+config LOG_BUF_SHIFT_15
+ bool "32 KB"
+ default y if SMP
+
+config LOG_BUF_SHIFT_14
+ bool "16 KB"
+
+config LOG_BUF_SHIFT_13
+ bool "8 KB"
+
+config LOG_BUF_SHIFT_12
+ bool "4 KB"
+
+endchoice
+
+config LOG_BUF_SHIFT
+ int
+ default 17 if LOG_BUF_SHIFT_17=y
+ default 16 if LOG_BUF_SHIFT_16=y
+ default 15 if LOG_BUF_SHIFT_15=y
+ default 14 if LOG_BUF_SHIFT_14=y
+ default 13 if LOG_BUF_SHIFT_13=y
+ default 12 if LOG_BUF_SHIFT_12=y
+
endmenu
diff --git a/init/do_mounts.c b/init/do_mounts.c
index d66050501009..316e29d758d3 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -13,6 +13,7 @@
#include <linux/suspend.h>
#include <linux/root_dev.h>
#include <linux/mount.h>
+#include <linux/dirent.h>
#include <linux/security.h>
#include <linux/nfs_fs.h>
@@ -324,22 +325,32 @@ static int __init mount_nfs_root(void)
#endif
#ifdef CONFIG_DEVFS_FS
+
+/*
+ * If the dir will fit in *buf, return its length. If it won't fit, return
+ * zero. Return -ve on error.
+ */
static int __init do_read_dir(int fd, void *buf, int len)
{
long bytes, n;
char *p = buf;
lseek(fd, 0, 0);
- for (bytes = 0, p = buf; bytes < len; bytes += n, p+=n) {
- n = sys_getdents64(fd, p, len - bytes);
+ for (bytes = 0; bytes < len; bytes += n) {
+ n = sys_getdents64(fd, p + bytes, len - bytes);
if (n < 0)
- return -1;
+ return n;
if (n == 0)
return bytes;
}
return 0;
}
+/*
+ * Try to read all of a directory. Returns the contents at *p, which
+ * is kmalloced memory. Returns the number of bytes read at *len. Returns
+ * NULL on error.
+ */
static void * __init read_dir(char *path, int *len)
{
int size;
@@ -349,7 +360,7 @@ static void * __init read_dir(char *path, int *len)
if (fd < 0)
return NULL;
- for (size = 1<<9; size < (1<<18); size <<= 1) {
+ for (size = 1 << 9; size <= (1 << MAX_ORDER); size <<= 1) {
void *p = kmalloc(size, GFP_KERNEL);
int n;
if (!p)
@@ -361,6 +372,8 @@ static void * __init read_dir(char *path, int *len)
return p;
}
kfree(p);
+ if (n == -EINVAL)
+ continue; /* Try a larger buffer */
if (n < 0)
break;
}
@@ -369,14 +382,6 @@ static void * __init read_dir(char *path, int *len)
}
#endif
-struct linux_dirent64 {
- u64 d_ino;
- s64 d_off;
- unsigned short d_reclen;
- unsigned char d_type;
- char d_name[0];
-};
-
static int __init find_in_devfs(char *path, dev_t dev)
{
#ifdef CONFIG_DEVFS_FS
diff --git a/init/main.c b/init/main.c
index b07fac4e9f02..ec70f2fa704c 100644
--- a/init/main.c
+++ b/init/main.c
@@ -58,16 +58,15 @@ extern char *linux_banner;
static int init(void *);
extern void init_IRQ(void);
-extern void init_modules(void);
extern void sock_init(void);
extern void fork_init(unsigned long);
-extern void extable_init(void);
extern void mca_init(void);
extern void sbus_init(void);
extern void sysctl_init(void);
extern void signals_init(void);
extern void buffer_init(void);
extern void pidhash_init(void);
+extern void pidmap_init(void);
extern void pte_chain_init(void);
extern void radix_tree_init(void);
extern void free_initmem(void);
@@ -391,9 +390,9 @@ asmlinkage void __init start_kernel(void)
&__stop___param - &__start___param,
&unknown_bootoption);
trap_init();
- extable_init();
rcu_init();
init_IRQ();
+ pidhash_init();
sched_init();
softirq_init();
time_init();
@@ -419,7 +418,7 @@ asmlinkage void __init start_kernel(void)
page_address_init();
mem_init();
kmem_cache_sizes_init();
- pidhash_init();
+ pidmap_init();
pgtable_cache_init();
pte_chain_init();
fork_init(num_physpages);
diff --git a/kernel/cpufreq.c b/kernel/cpufreq.c
index 5dff6da1a73f..c0be78462c81 100644
--- a/kernel/cpufreq.c
+++ b/kernel/cpufreq.c
@@ -927,17 +927,27 @@ EXPORT_SYMBOL(cpufreq_set_policy);
* adjust_jiffies - adjust the system "loops_per_jiffy"
*
* This function alters the system "loops_per_jiffy" for the clock
- * speed change. Note that loops_per_jiffy is only updated if all
- * CPUs are affected - else there is a need for per-CPU loops_per_jiffy
- * values which are provided by various architectures.
+ * speed change. Note that loops_per_jiffy cannot be updated on SMP
+ * systems as each CPU might be scaled differently. So, use the arch
+ * per-CPU loops_per_jiffy value wherever possible.
*/
+#ifndef CONFIG_SMP
+static unsigned long l_p_j_ref = 0;
+static unsigned int l_p_j_ref_freq = 0;
+
static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
{
+ if (!l_p_j_ref_freq) {
+ l_p_j_ref = loops_per_jiffy;
+ l_p_j_ref_freq = ci->old;
+ }
if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) ||
(val == CPUFREQ_POSTCHANGE && ci->old > ci->new))
- if (ci->cpu == CPUFREQ_ALL_CPUS)
- loops_per_jiffy = cpufreq_scale(loops_per_jiffy, ci->old, ci->new);
+ loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new);
}
+#else
+#define adjust_jiffies(...)
+#endif
/**
diff --git a/kernel/extable.c b/kernel/extable.c
index e26ef5349d23..388995324d1c 100644
--- a/kernel/extable.c
+++ b/kernel/extable.c
@@ -16,36 +16,27 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/module.h>
-#include <linux/init.h>
-
-#include <asm/semaphore.h>
extern const struct exception_table_entry __start___ex_table[];
extern const struct exception_table_entry __stop___ex_table[];
-extern const struct kernel_symbol __start___ksymtab[];
-extern const struct kernel_symbol __stop___ksymtab[];
-
-/* Protects extables and symbol tables */
-spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED;
-
-/* The exception and symbol tables: start with kernel only. */
-LIST_HEAD(extables);
-LIST_HEAD(symbols);
-
-static struct exception_table kernel_extable;
-static struct kernel_symbol_group kernel_symbols;
+extern char _stext[], _etext[];
-void __init extable_init(void)
+/* Given an address, look for it in the exception tables. */
+const struct exception_table_entry *search_exception_tables(unsigned long addr)
{
- /* Add kernel symbols to symbol table */
- kernel_symbols.num_syms = (__stop___ksymtab - __start___ksymtab);
- kernel_symbols.syms = __start___ksymtab;
- list_add(&kernel_symbols.list, &symbols);
-
- /* Add kernel exception table to exception tables */
- kernel_extable.num_entries = (__stop___ex_table -__start___ex_table);
- kernel_extable.entry = __start___ex_table;
- list_add(&kernel_extable.list, &extables);
+ const struct exception_table_entry *e;
+
+ e = search_extable(__start___ex_table, __stop___ex_table-1, addr);
+ if (!e)
+ e = search_module_extables(addr);
+ return e;
}
+int kernel_text_address(unsigned long addr)
+{
+ if (addr >= (unsigned long)_stext &&
+ addr <= (unsigned long)_etext)
+ return 1;
+ return module_text_address(addr);
+}
diff --git a/kernel/module.c b/kernel/module.c
index ff961f21135f..bd289a331692 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -51,9 +51,14 @@
#define symbol_is(literal, string) \
(strcmp(MODULE_SYMBOL_PREFIX literal, (string)) == 0)
-/* List of modules, protected by module_mutex */
+/* Protects extables and symbols lists */
+static spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED;
+
+/* List of modules, protected by module_mutex AND modlist_lock */
static DECLARE_MUTEX(module_mutex);
-LIST_HEAD(modules); /* FIXME: Accessed w/o lock on oops by some archs */
+static LIST_HEAD(modules);
+static LIST_HEAD(symbols);
+static LIST_HEAD(extables);
/* We require a truly strong try_module_get() */
static inline int strong_try_module_get(struct module *mod)
@@ -72,13 +77,16 @@ EXPORT_SYMBOL(init_module);
/* Find a symbol, return value and the symbol group */
static unsigned long __find_symbol(const char *name,
- struct kernel_symbol_group **group)
+ struct kernel_symbol_group **group,
+ int gplok)
{
struct kernel_symbol_group *ks;
list_for_each_entry(ks, &symbols, list) {
unsigned int i;
+ if (ks->gplonly && !gplok)
+ continue;
for (i = 0; i < ks->num_syms; i++) {
if (strcmp(ks->syms[i].name, name) == 0) {
*group = ks;
@@ -481,19 +489,29 @@ sys_delete_module(const char *name_user, unsigned int flags)
static void print_unload_info(struct seq_file *m, struct module *mod)
{
struct module_use *use;
+ int printed_something = 0;
- seq_printf(m, " %u", module_refcount(mod));
+ seq_printf(m, " %u ", module_refcount(mod));
- list_for_each_entry(use, &mod->modules_which_use_me, list)
- seq_printf(m, " %s", use->module_which_uses->name);
+ /* Always include a trailing , so userspace can differentiate
+ between this and the old multi-field proc format. */
+ list_for_each_entry(use, &mod->modules_which_use_me, list) {
+ printed_something = 1;
+ seq_printf(m, "%s,", use->module_which_uses->name);
+ }
- if (mod->unsafe)
- seq_printf(m, " [unsafe]");
+ if (mod->unsafe) {
+ printed_something = 1;
+ seq_printf(m, "[unsafe],");
+ }
- if (mod->init != init_module && mod->exit == cleanup_module)
- seq_printf(m, " [permanent]");
+ if (mod->init != init_module && mod->exit == cleanup_module) {
+ printed_something = 1;
+ seq_printf(m, "[permanent],");
+ }
- seq_printf(m, "\n");
+ if (!printed_something)
+ seq_printf(m, "-");
}
void __symbol_put(const char *symbol)
@@ -502,7 +520,7 @@ void __symbol_put(const char *symbol)
unsigned long flags;
spin_lock_irqsave(&modlist_lock, flags);
- if (!__find_symbol(symbol, &ksg))
+ if (!__find_symbol(symbol, &ksg, 1))
BUG();
module_put(ksg->owner);
spin_unlock_irqrestore(&modlist_lock, flags);
@@ -534,7 +552,8 @@ EXPORT_SYMBOL_GPL(symbol_put_addr);
#else /* !CONFIG_MODULE_UNLOAD */
static void print_unload_info(struct seq_file *m, struct module *mod)
{
- seq_printf(m, "\n");
+ /* We don't know the usage count, or what modules are using. */
+ seq_printf(m, " - -");
}
static inline void module_unload_free(struct module *mod)
@@ -721,7 +740,7 @@ unsigned long find_symbol_internal(Elf_Shdr *sechdrs,
}
/* Look in other modules... */
spin_lock_irq(&modlist_lock);
- ret = __find_symbol(name, ksg);
+ ret = __find_symbol(name, ksg, mod->license_gplok);
if (ret) {
/* This can fail due to OOM, or module unloading */
if (!use_module(mod, (*ksg)->owner))
@@ -735,9 +754,10 @@ unsigned long find_symbol_internal(Elf_Shdr *sechdrs,
static void free_module(struct module *mod)
{
/* Delete from various lists */
- list_del(&mod->list);
spin_lock_irq(&modlist_lock);
+ list_del(&mod->list);
list_del(&mod->symbols.list);
+ list_del(&mod->gpl_symbols.list);
list_del(&mod->extable.list);
spin_unlock_irq(&modlist_lock);
@@ -758,7 +778,7 @@ void *__symbol_get(const char *symbol)
unsigned long value, flags;
spin_lock_irqsave(&modlist_lock, flags);
- value = __find_symbol(symbol, &ksg);
+ value = __find_symbol(symbol, &ksg, 1);
if (value && !strong_try_module_get(ksg->owner))
value = 0;
spin_unlock_irqrestore(&modlist_lock, flags);
@@ -930,7 +950,34 @@ static void layout_sections(struct module *mod,
}
}
-/* Allocate and load the module */
+static inline int license_is_gpl_compatible(const char *license)
+{
+ return (strcmp(license, "GPL") == 0
+ || strcmp(license, "GPL v2") == 0
+ || strcmp(license, "GPL and additional rights") == 0
+ || strcmp(license, "Dual BSD/GPL") == 0
+ || strcmp(license, "Dual MPL/GPL") == 0);
+}
+
+static void set_license(struct module *mod, Elf_Shdr *sechdrs, int licenseidx)
+{
+ char *license;
+
+ if (licenseidx)
+ license = (char *)sechdrs[licenseidx].sh_addr;
+ else
+ license = "unspecified";
+
+ mod->license_gplok = license_is_gpl_compatible(license);
+ if (!mod->license_gplok) {
+ printk(KERN_WARNING "%s: module license '%s' taints kernel.\n",
+ mod->name, license);
+ tainted |= TAINT_PROPRIETARY_MODULE;
+ }
+}
+
+/* Allocate and load the module: note that size of section 0 is always
+ zero, and we rely on this for optional sections. */
static struct module *load_module(void *umod,
unsigned long len,
const char *uargs)
@@ -939,7 +986,7 @@ static struct module *load_module(void *umod,
Elf_Shdr *sechdrs;
char *secstrings, *args;
unsigned int i, symindex, exportindex, strindex, setupindex, exindex,
- modindex, obsparmindex;
+ modindex, obsparmindex, licenseindex, gplindex;
long arglen;
struct module *mod;
long err = 0;
@@ -975,7 +1022,7 @@ static struct module *load_module(void *umod,
/* May not export symbols, or have setup params, so these may
not exist */
- exportindex = setupindex = obsparmindex = 0;
+ exportindex = setupindex = obsparmindex = gplindex = licenseindex = 0;
/* And these should exist, but gcc whinges if we don't init them */
symindex = strindex = exindex = modindex = 0;
@@ -1018,6 +1065,16 @@ static struct module *load_module(void *umod,
/* Obsolete MODULE_PARM() table */
DEBUGP("Obsolete param found in section %u\n", i);
obsparmindex = i;
+ } else if (strcmp(secstrings+sechdrs[i].sh_name,".init.license")
+ == 0) {
+ /* MODULE_LICENSE() */
+ DEBUGP("Licence found in section %u\n", i);
+ licenseindex = i;
+ } else if (strcmp(secstrings+sechdrs[i].sh_name,
+ "__gpl_ksymtab") == 0) {
+ /* EXPORT_SYMBOL_GPL() */
+ DEBUGP("GPL symbols found in section %u\n", i);
+ gplindex = i;
}
#ifdef CONFIG_KALLSYMS
/* symbol and string tables for decoding later. */
@@ -1113,17 +1170,21 @@ static struct module *load_module(void *umod,
/* Now we've moved module, initialize linked lists, etc. */
module_unload_init(mod);
+ /* Set up license info based on contents of section */
+ set_license(mod, sechdrs, licenseindex);
+
/* Fix up syms, so that st_value is a pointer to location. */
err = simplify_symbols(sechdrs, symindex, strindex, mod);
if (err < 0)
goto cleanup;
- /* Set up EXPORTed symbols */
- if (exportindex) {
- mod->symbols.num_syms = (sechdrs[exportindex].sh_size
- / sizeof(*mod->symbols.syms));
- mod->symbols.syms = (void *)sechdrs[exportindex].sh_addr;
- }
+ /* Set up EXPORTed & EXPORT_GPLed symbols (section 0 is 0 length) */
+ mod->symbols.num_syms = (sechdrs[exportindex].sh_size
+ / sizeof(*mod->symbols.syms));
+ mod->symbols.syms = (void *)sechdrs[exportindex].sh_addr;
+ mod->gpl_symbols.num_syms = (sechdrs[gplindex].sh_size
+ / sizeof(*mod->symbols.syms));
+ mod->gpl_symbols.syms = (void *)sechdrs[gplindex].sh_addr;
/* Set up exception table */
if (exindex) {
@@ -1228,8 +1289,9 @@ sys_init_module(void *umod,
spin_lock_irq(&modlist_lock);
list_add(&mod->extable.list, &extables);
list_add_tail(&mod->symbols.list, &symbols);
- spin_unlock_irq(&modlist_lock);
+ list_add_tail(&mod->gpl_symbols.list, &symbols);
list_add(&mod->list, &modules);
+ spin_unlock_irq(&modlist_lock);
/* Drop lock so they can recurse */
up(&module_mutex);
@@ -1256,28 +1318,17 @@ sys_init_module(void *umod,
mod->state = MODULE_STATE_LIVE;
module_free(mod, mod->module_init);
mod->module_init = NULL;
+ mod->init_size = 0;
return 0;
}
-#ifdef CONFIG_KALLSYMS
-static inline int inside_init(struct module *mod, unsigned long addr)
+static inline int within(unsigned long addr, void *start, unsigned long size)
{
- if (mod->module_init
- && (unsigned long)mod->module_init <= addr
- && (unsigned long)mod->module_init + mod->init_size > addr)
- return 1;
- return 0;
-}
-
-static inline int inside_core(struct module *mod, unsigned long addr)
-{
- if ((unsigned long)mod->module_core <= addr
- && (unsigned long)mod->module_core + mod->core_size > addr)
- return 1;
- return 0;
+ return ((void *)addr >= start && (void *)addr < start + size);
}
+#ifdef CONFIG_KALLSYMS
static const char *get_ksymbol(struct module *mod,
unsigned long addr,
unsigned long *size,
@@ -1287,7 +1338,7 @@ static const char *get_ksymbol(struct module *mod,
unsigned long nextval;
/* At worse, next value is at end of module */
- if (inside_core(mod, addr))
+ if (within(addr, mod->module_init, mod->init_size))
nextval = (unsigned long)mod->module_core+mod->core_size;
else
nextval = (unsigned long)mod->module_init+mod->init_size;
@@ -1325,7 +1376,8 @@ const char *module_address_lookup(unsigned long addr,
struct module *mod;
list_for_each_entry(mod, &modules, list) {
- if (inside_core(mod, addr) || inside_init(mod, addr)) {
+ if (within(addr, mod->module_init, mod->init_size)
+ || within(addr, mod->module_core, mod->core_size)) {
*modname = mod->name;
return get_ksymbol(mod, addr, size, offset);
}
@@ -1370,8 +1422,15 @@ static int m_show(struct seq_file *m, void *p)
seq_printf(m, "%s %lu",
mod->name, mod->init_size + mod->core_size);
print_unload_info(m, mod);
+ seq_printf(m, "\n");
return 0;
}
+
+/* Format: modulename size refcount deps
+
+ Where refcount is a number or -, and deps is a comma-separated list
+ of depends or -.
+*/
struct seq_operations modules_op = {
.start = m_start,
.next = m_next,
@@ -1379,6 +1438,67 @@ struct seq_operations modules_op = {
.show = m_show
};
+/* Given an address, look for it in the module exception tables. */
+const struct exception_table_entry *search_module_extables(unsigned long addr)
+{
+ unsigned long flags;
+ const struct exception_table_entry *e = NULL;
+ struct exception_table *i;
+
+ spin_lock_irqsave(&modlist_lock, flags);
+ list_for_each_entry(i, &extables, list) {
+ if (i->num_entries == 0)
+ continue;
+
+ e = search_extable(i->entry, i->entry+i->num_entries-1, addr);
+ if (e)
+ break;
+ }
+ spin_unlock_irqrestore(&modlist_lock, flags);
+
+ /* Now, if we found one, we are running inside it now, hence
+ we cannot unload the module, hence no refcnt needed. */
+ return e;
+}
+
+/* Is this a valid kernel address? We don't grab the lock: we are oopsing. */
+int module_text_address(unsigned long addr)
+{
+ struct module *mod;
+
+ list_for_each_entry(mod, &modules, list)
+ if (within(addr, mod->module_init, mod->init_size)
+ || within(addr, mod->module_core, mod->core_size))
+ return 1;
+ return 0;
+}
+
+/* Provided by the linker */
+extern const struct kernel_symbol __start___ksymtab[];
+extern const struct kernel_symbol __stop___ksymtab[];
+extern const struct kernel_symbol __start___gpl_ksymtab[];
+extern const struct kernel_symbol __stop___gpl_ksymtab[];
+
+static struct kernel_symbol_group kernel_symbols, kernel_gpl_symbols;
+
+static int __init symbols_init(void)
+{
+ /* Add kernel symbols to symbol table */
+ kernel_symbols.num_syms = (__stop___ksymtab - __start___ksymtab);
+ kernel_symbols.syms = __start___ksymtab;
+ kernel_symbols.gplonly = 0;
+ list_add(&kernel_symbols.list, &symbols);
+ kernel_gpl_symbols.num_syms = (__stop___gpl_ksymtab
+ - __start___gpl_ksymtab);
+ kernel_gpl_symbols.syms = __start___gpl_ksymtab;
+ kernel_gpl_symbols.gplonly = 1;
+ list_add(&kernel_gpl_symbols.list, &symbols);
+
+ return 0;
+}
+
+__initcall(symbols_init);
+
/* Obsolete lvalue for broken code which asks about usage */
int module_dummy_usage = 1;
EXPORT_SYMBOL(module_dummy_usage);
diff --git a/kernel/panic.c b/kernel/panic.c
index 7be1f98be629..4f4e36663617 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -103,7 +103,7 @@ NORET_TYPE void panic(const char * fmt, ...)
/**
* print_tainted - return a string to represent the kernel taint state.
*
- * 'P' - Proprietory module has been loaded.
+ * 'P' - Proprietary module has been loaded.
* 'F' - Module has been forcibly loaded.
* 'S' - SMP with CPUs not designed for SMP.
*
@@ -115,7 +115,7 @@ const char *print_tainted()
static char buf[20];
if (tainted) {
snprintf(buf, sizeof(buf), "Tainted: %c%c%c",
- tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G',
+ tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G',
tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
tainted & TAINT_UNSAFE_SMP ? 'S' : ' ');
}
diff --git a/kernel/pid.c b/kernel/pid.c
index ed6adbba677b..f5afb3137e74 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -23,10 +23,11 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/bootmem.h>
+#include <linux/hash.h>
-#define PIDHASH_SIZE 4096
-#define pid_hashfn(nr) ((nr >> 8) ^ nr) & (PIDHASH_SIZE - 1)
-static struct list_head pid_hash[PIDTYPE_MAX][PIDHASH_SIZE];
+#define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
+static struct list_head *pid_hash[PIDTYPE_MAX];
+static int pidhash_shift;
int pid_max = PID_MAX_DEFAULT;
int last_pid;
@@ -258,20 +259,46 @@ void switch_exec_pids(task_t *leader, task_t *thread)
attach_pid(leader, PIDTYPE_SID, leader->session);
}
+/*
+ * The pid hash table is scaled according to the amount of memory in the
+ * machine. From a minimum of 16 slots up to 4096 slots at one gigabyte or
+ * more.
+ */
void __init pidhash_init(void)
{
- int i, j;
+ int i, j, pidhash_size;
+ unsigned long megabytes = max_pfn >> (20 - PAGE_SHIFT);
+
+ pidhash_shift = max(4, fls(megabytes * 4));
+ pidhash_shift = min(12, pidhash_shift);
+ pidhash_size = 1 << pidhash_shift;
+
+ printk("PID hash table entries: %d (order %d: %Zd bytes)\n",
+ pidhash_size, pidhash_shift,
+ pidhash_size * sizeof(struct list_head));
+
+ for (i = 0; i < PIDTYPE_MAX; i++) {
+ pid_hash[i] = alloc_bootmem(pidhash_size *
+ sizeof(struct list_head));
+ if (!pid_hash[i])
+ panic("Could not alloc pidhash!\n");
+ for (j = 0; j < pidhash_size; j++)
+ INIT_LIST_HEAD(&pid_hash[i][j]);
+ }
+}
+
+void __init pidmap_init(void)
+{
+ int i;
- /*
- * Allocate PID 0, and hash it via all PID types:
- */
pidmap_array->page = (void *)get_zeroed_page(GFP_KERNEL);
set_bit(0, pidmap_array->page);
atomic_dec(&pidmap_array->nr_free);
- for (i = 0; i < PIDTYPE_MAX; i++) {
- for (j = 0; j < PIDHASH_SIZE; j++)
- INIT_LIST_HEAD(&pid_hash[i][j]);
+ /*
+ * Allocate PID 0, and hash it via all PID types:
+ */
+
+ for (i = 0; i < PIDTYPE_MAX; i++)
attach_pid(current, i, 0);
- }
}
diff --git a/kernel/printk.c b/kernel/printk.c
index ffe724fabc0e..9a599c57bf9b 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -31,16 +31,7 @@
#include <asm/uaccess.h>
-#if defined(CONFIG_X86_NUMAQ) || defined(CONFIG_IA64)
-#define LOG_BUF_LEN (65536)
-#elif defined(CONFIG_ARCH_S390)
-#define LOG_BUF_LEN (131072)
-#elif defined(CONFIG_SMP)
-#define LOG_BUF_LEN (32768)
-#else
-#define LOG_BUF_LEN (16384) /* This must be a power of two */
-#endif
-
+#define LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
#define LOG_BUF_MASK (LOG_BUF_LEN-1)
/* printk's without a loglevel use this.. */
diff --git a/kernel/sched.c b/kernel/sched.c
index 11678e2b7f09..152d8f7bad9a 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -986,9 +986,7 @@ asmlinkage void schedule(void)
}
}
-#if CONFIG_DEBUG_HIGHMEM
check_highmem_ptes();
-#endif
need_resched:
preempt_disable();
prev = current;
diff --git a/lib/crc32.c b/lib/crc32.c
index b3defb2db345..01db3a187bc1 100644
--- a/lib/crc32.c
+++ b/lib/crc32.c
@@ -92,7 +92,7 @@ u32 attribute((pure)) crc32_le(u32 crc, unsigned char const *p, size_t len)
crc = __cpu_to_le32(crc);
/* Align it */
- for ( ; ((u32)b)&3 && len ; len--){
+ for ( ; ((long)b)&3 && len ; len--){
# ifdef __LITTLE_ENDIAN
crc = (crc>>8) ^ crc32table_le[ (crc ^ *((u8 *)b)++) & 0xff ];
# else
@@ -201,7 +201,7 @@ u32 attribute((pure)) crc32_be(u32 crc, unsigned char const *p, size_t len)
crc = __cpu_to_be32(crc);
/* Align it */
- for ( ; ((u32)b)&3 && len ; len--){
+ for ( ; ((long)b)&3 && len ; len--){
# ifdef __LITTLE_ENDIAN
crc = (crc>>8) ^ crc32table_be[ (crc ^ *((u8 *)b)++) & 0xff ];
# else
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index c13196a91c7a..dc20f8513946 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -20,10 +20,11 @@
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/mempool.h>
#include <linux/module.h>
#include <linux/radix-tree.h>
+#include <linux/percpu.h>
#include <linux/slab.h>
+#include <linux/gfp.h>
#include <linux/string.h>
/*
@@ -49,18 +50,74 @@ struct radix_tree_path {
* Radix tree node cache.
*/
static kmem_cache_t *radix_tree_node_cachep;
-static mempool_t *radix_tree_node_pool;
-static inline struct radix_tree_node *
+/*
+ * Per-cpu pool of preloaded nodes
+ */
+struct radix_tree_preload {
+ int nr;
+ struct radix_tree_node *nodes[RADIX_TREE_MAX_PATH];
+};
+DEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads) = { 0, };
+
+/*
+ * This assumes that the caller has performed appropriate preallocation, and
+ * that the caller has pinned this thread of control to the current CPU.
+ */
+static struct radix_tree_node *
radix_tree_node_alloc(struct radix_tree_root *root)
{
- return mempool_alloc(radix_tree_node_pool, root->gfp_mask);
+ struct radix_tree_node *ret;
+
+ ret = kmem_cache_alloc(radix_tree_node_cachep, root->gfp_mask);
+ if (ret == NULL && !(root->gfp_mask & __GFP_WAIT)) {
+ struct radix_tree_preload *rtp;
+
+ rtp = &__get_cpu_var(radix_tree_preloads);
+ if (rtp->nr) {
+ ret = rtp->nodes[rtp->nr - 1];
+ rtp->nodes[rtp->nr - 1] = NULL;
+ rtp->nr--;
+ }
+ }
+ return ret;
}
static inline void
radix_tree_node_free(struct radix_tree_node *node)
{
- mempool_free(node, radix_tree_node_pool);
+ kmem_cache_free(radix_tree_node_cachep, node);
+}
+
+/*
+ * Load up this CPU's radix_tree_node buffer with sufficient objects to
+ * ensure that the addition of a single element in the tree cannot fail. On
+ * success, return zero, with preemption disabled. On error, return -ENOMEM
+ * with preemption not disabled.
+ */
+int radix_tree_preload(int gfp_mask)
+{
+ struct radix_tree_preload *rtp;
+ struct radix_tree_node *node;
+ int ret = -ENOMEM;
+
+ preempt_disable();
+ rtp = &__get_cpu_var(radix_tree_preloads);
+ while (rtp->nr < ARRAY_SIZE(rtp->nodes)) {
+ preempt_enable();
+ node = kmem_cache_alloc(radix_tree_node_cachep, gfp_mask);
+ if (node == NULL)
+ goto out;
+ preempt_disable();
+ rtp = &__get_cpu_var(radix_tree_preloads);
+ if (rtp->nr < ARRAY_SIZE(rtp->nodes))
+ rtp->nodes[rtp->nr++] = node;
+ else
+ kmem_cache_free(radix_tree_node_cachep, node);
+ }
+ ret = 0;
+out:
+ return ret;
}
/*
@@ -339,26 +396,12 @@ int radix_tree_delete(struct radix_tree_root *root, unsigned long index)
}
EXPORT_SYMBOL(radix_tree_delete);
-static void radix_tree_node_ctor(void *node, kmem_cache_t *cachep, unsigned long flags)
+static void
+radix_tree_node_ctor(void *node, kmem_cache_t *cachep, unsigned long flags)
{
memset(node, 0, sizeof(struct radix_tree_node));
}
-static void *radix_tree_node_pool_alloc(int gfp_mask, void *data)
-{
- return kmem_cache_alloc(radix_tree_node_cachep, gfp_mask);
-}
-
-static void radix_tree_node_pool_free(void *node, void *data)
-{
- kmem_cache_free(radix_tree_node_cachep, node);
-}
-
-/*
- * FIXME! 512 nodes is 200-300k of memory. This needs to be
- * scaled by the amount of available memory, and hopefully
- * reduced also.
- */
void __init radix_tree_init(void)
{
radix_tree_node_cachep = kmem_cache_create("radix_tree_node",
@@ -366,8 +409,4 @@ void __init radix_tree_init(void)
0, radix_tree_node_ctor, NULL);
if (!radix_tree_node_cachep)
panic ("Failed to create radix_tree_node cache\n");
- radix_tree_node_pool = mempool_create(512, radix_tree_node_pool_alloc,
- radix_tree_node_pool_free, NULL);
- if (!radix_tree_node_pool)
- panic ("Failed to create radix_tree_node pool\n");
}
diff --git a/mm/filemap.c b/mm/filemap.c
index 35137c389b42..18fddd3026f1 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -202,28 +202,31 @@ restart:
*
* This function does not add the page to the LRU. The caller must do that.
*/
-int add_to_page_cache(struct page *page,
- struct address_space *mapping, pgoff_t offset)
+int add_to_page_cache(struct page *page, struct address_space *mapping,
+ pgoff_t offset, int gfp_mask)
{
- int error;
+ int error = radix_tree_preload(gfp_mask & ~__GFP_HIGHMEM);
- page_cache_get(page);
- write_lock(&mapping->page_lock);
- error = radix_tree_insert(&mapping->page_tree, offset, page);
- if (!error) {
- SetPageLocked(page);
- ___add_to_page_cache(page, mapping, offset);
- } else {
- page_cache_release(page);
+ if (error == 0) {
+ page_cache_get(page);
+ write_lock(&mapping->page_lock);
+ error = radix_tree_insert(&mapping->page_tree, offset, page);
+ if (!error) {
+ SetPageLocked(page);
+ ___add_to_page_cache(page, mapping, offset);
+ } else {
+ page_cache_release(page);
+ }
+ write_unlock(&mapping->page_lock);
+ radix_tree_preload_end();
}
- write_unlock(&mapping->page_lock);
return error;
}
-int add_to_page_cache_lru(struct page *page,
- struct address_space *mapping, pgoff_t offset)
+int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
+ pgoff_t offset, int gfp_mask)
{
- int ret = add_to_page_cache(page, mapping, offset);
+ int ret = add_to_page_cache(page, mapping, offset, gfp_mask);
if (ret == 0)
lru_cache_add(page);
return ret;
@@ -432,7 +435,8 @@ repeat:
if (!cached_page)
return NULL;
}
- err = add_to_page_cache_lru(cached_page, mapping, index);
+ err = add_to_page_cache_lru(cached_page, mapping,
+ index, gfp_mask);
if (!err) {
page = cached_page;
cached_page = NULL;
@@ -488,6 +492,7 @@ struct page *
grab_cache_page_nowait(struct address_space *mapping, unsigned long index)
{
struct page *page = find_get_page(mapping, index);
+ int gfp_mask;
if (page) {
if (!TestSetPageLocked(page))
@@ -495,8 +500,9 @@ grab_cache_page_nowait(struct address_space *mapping, unsigned long index)
page_cache_release(page);
return NULL;
}
- page = alloc_pages(mapping->gfp_mask & ~__GFP_FS, 0);
- if (page && add_to_page_cache_lru(page, mapping, index)) {
+ gfp_mask = mapping->gfp_mask & ~__GFP_FS;
+ page = alloc_pages(gfp_mask, 0);
+ if (page && add_to_page_cache_lru(page, mapping, index, gfp_mask)) {
page_cache_release(page);
page = NULL;
}
@@ -648,7 +654,8 @@ no_cached_page:
break;
}
}
- error = add_to_page_cache_lru(cached_page, mapping, index);
+ error = add_to_page_cache_lru(cached_page, mapping,
+ index, GFP_KERNEL);
if (error) {
if (error == -EEXIST)
goto find_page;
@@ -940,7 +947,7 @@ static int page_cache_read(struct file * file, unsigned long offset)
if (!page)
return -ENOMEM;
- error = add_to_page_cache_lru(page, mapping, offset);
+ error = add_to_page_cache_lru(page, mapping, offset, GFP_KERNEL);
if (!error) {
error = mapping->a_ops->readpage(file, page);
page_cache_release(page);
@@ -1327,7 +1334,8 @@ repeat:
if (!cached_page)
return ERR_PTR(-ENOMEM);
}
- err = add_to_page_cache_lru(cached_page, mapping, index);
+ err = add_to_page_cache_lru(cached_page, mapping,
+ index, GFP_KERNEL);
if (err == -EEXIST)
goto repeat;
if (err < 0) {
@@ -1406,7 +1414,8 @@ repeat:
if (!*cached_page)
return NULL;
}
- err = add_to_page_cache(*cached_page, mapping, index);
+ err = add_to_page_cache(*cached_page, mapping,
+ index, GFP_KERNEL);
if (err == -EEXIST)
goto repeat;
if (err == 0) {
diff --git a/mm/fremap.c b/mm/fremap.c
index 6954430034f4..a8caa89e312c 100644
--- a/mm/fremap.c
+++ b/mm/fremap.c
@@ -11,6 +11,7 @@
#include <linux/mman.h>
#include <linux/pagemap.h>
#include <linux/swapops.h>
+#include <linux/rmap-locking.h>
#include <asm/mmu_context.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
@@ -52,6 +53,7 @@ int install_page(struct mm_struct *mm, struct vm_area_struct *vma,
pte_t *pte, entry;
pgd_t *pgd;
pmd_t *pmd;
+ struct pte_chain *pte_chain = NULL;
pgd = pgd_offset(mm, addr);
spin_lock(&mm->page_table_lock);
@@ -60,6 +62,7 @@ int install_page(struct mm_struct *mm, struct vm_area_struct *vma,
if (!pmd)
goto err_unlock;
+ pte_chain = pte_chain_alloc(GFP_KERNEL);
pte = pte_alloc_map(mm, pmd, addr);
if (!pte)
goto err_unlock;
@@ -73,16 +76,17 @@ int install_page(struct mm_struct *mm, struct vm_area_struct *vma,
if (prot & PROT_WRITE)
entry = pte_mkwrite(pte_mkdirty(entry));
set_pte(pte, entry);
- page_add_rmap(page, pte);
+ pte_chain = page_add_rmap(page, pte, pte_chain);
pte_unmap(pte);
flush_tlb_page(vma, addr);
spin_unlock(&mm->page_table_lock);
-
+ pte_chain_free(pte_chain);
return 0;
err_unlock:
spin_unlock(&mm->page_table_lock);
+ pte_chain_free(pte_chain);
return err;
}
diff --git a/mm/memory.c b/mm/memory.c
index 309ba607c62f..c98bf54855a5 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -44,6 +44,7 @@
#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/vcache.h>
+#include <linux/rmap-locking.h>
#include <asm/pgalloc.h>
#include <asm/rmap.h>
@@ -209,11 +210,22 @@ int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
pgd_t * src_pgd, * dst_pgd;
unsigned long address = vma->vm_start;
unsigned long end = vma->vm_end;
- unsigned long cow = (vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
+ unsigned long cow;
+ struct pte_chain *pte_chain = NULL;
if (is_vm_hugetlb_page(vma))
return copy_hugetlb_page_range(dst, src, vma);
+ pte_chain = pte_chain_alloc(GFP_ATOMIC);
+ if (!pte_chain) {
+ spin_unlock(&dst->page_table_lock);
+ pte_chain = pte_chain_alloc(GFP_KERNEL);
+ spin_lock(&dst->page_table_lock);
+ if (!pte_chain)
+ goto nomem;
+ }
+
+ cow = (vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
src_pgd = pgd_offset(src, address)-1;
dst_pgd = pgd_offset(dst, address)-1;
@@ -250,7 +262,8 @@ skip_copy_pmd_range: address = (address + PGDIR_SIZE) & PGDIR_MASK;
if (pmd_bad(*src_pmd)) {
pmd_ERROR(*src_pmd);
pmd_clear(src_pmd);
-skip_copy_pte_range: address = (address + PMD_SIZE) & PMD_MASK;
+skip_copy_pte_range:
+ address = (address + PMD_SIZE) & PMD_MASK;
if (address >= end)
goto out;
goto cont_copy_pmd_range;
@@ -259,13 +272,13 @@ skip_copy_pte_range: address = (address + PMD_SIZE) & PMD_MASK;
dst_pte = pte_alloc_map(dst, dst_pmd, address);
if (!dst_pte)
goto nomem;
- spin_lock(&src->page_table_lock);
+ spin_lock(&src->page_table_lock);
src_pte = pte_offset_map_nested(src_pmd, address);
do {
pte_t pte = *src_pte;
- struct page *ptepage;
+ struct page *page;
unsigned long pfn;
-
+
/* copy_one_pte */
if (pte_none(pte))
@@ -276,30 +289,60 @@ skip_copy_pte_range: address = (address + PMD_SIZE) & PMD_MASK;
set_pte(dst_pte, pte);
goto cont_copy_pte_range_noset;
}
- ptepage = pte_page(pte);
pfn = pte_pfn(pte);
+ page = pfn_to_page(pfn);
if (!pfn_valid(pfn))
goto cont_copy_pte_range;
- ptepage = pfn_to_page(pfn);
- if (PageReserved(ptepage))
+ if (PageReserved(page))
goto cont_copy_pte_range;
- /* If it's a COW mapping, write protect it both in the parent and the child */
+ /*
+ * If it's a COW mapping, write protect it both
+ * in the parent and the child
+ */
if (cow) {
ptep_set_wrprotect(src_pte);
pte = *src_pte;
}
- /* If it's a shared mapping, mark it clean in the child */
+ /*
+ * If it's a shared mapping, mark it clean in
+ * the child
+ */
if (vma->vm_flags & VM_SHARED)
pte = pte_mkclean(pte);
pte = pte_mkold(pte);
- get_page(ptepage);
+ get_page(page);
dst->rss++;
-cont_copy_pte_range: set_pte(dst_pte, pte);
- page_add_rmap(ptepage, dst_pte);
-cont_copy_pte_range_noset: address += PAGE_SIZE;
+cont_copy_pte_range:
+ set_pte(dst_pte, pte);
+ pte_chain = page_add_rmap(page, dst_pte,
+ pte_chain);
+ if (pte_chain)
+ goto cont_copy_pte_range_noset;
+ pte_chain = pte_chain_alloc(GFP_ATOMIC);
+ if (pte_chain)
+ goto cont_copy_pte_range_noset;
+
+ /*
+ * pte_chain allocation failed, and we need to
+ * run page reclaim.
+ */
+ pte_unmap_nested(src_pte);
+ pte_unmap(dst_pte);
+ spin_unlock(&src->page_table_lock);
+ spin_unlock(&dst->page_table_lock);
+ pte_chain = pte_chain_alloc(GFP_KERNEL);
+ spin_lock(&dst->page_table_lock);
+ if (!pte_chain)
+ goto nomem;
+ spin_lock(&src->page_table_lock);
+ dst_pte = pte_offset_map(dst_pmd, address);
+ src_pte = pte_offset_map_nested(src_pmd,
+ address);
+cont_copy_pte_range_noset:
+ address += PAGE_SIZE;
if (address >= end) {
pte_unmap_nested(src_pte);
pte_unmap(dst_pte);
@@ -312,19 +355,23 @@ cont_copy_pte_range_noset: address += PAGE_SIZE;
pte_unmap(dst_pte-1);
spin_unlock(&src->page_table_lock);
-cont_copy_pmd_range: src_pmd++;
+cont_copy_pmd_range:
+ src_pmd++;
dst_pmd++;
} while ((unsigned long)src_pmd & PMD_TABLE_MASK);
}
out_unlock:
spin_unlock(&src->page_table_lock);
out:
+ pte_chain_free(pte_chain);
return 0;
nomem:
+ pte_chain_free(pte_chain);
return -ENOMEM;
}
-static void zap_pte_range(mmu_gather_t *tlb, pmd_t * pmd, unsigned long address, unsigned long size)
+static void
+zap_pte_range(mmu_gather_t *tlb, pmd_t * pmd, unsigned long address, unsigned long size)
{
unsigned long offset;
pte_t *ptep;
@@ -806,6 +853,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
{
struct page *old_page, *new_page;
unsigned long pfn = pte_pfn(pte);
+ struct pte_chain *pte_chain = NULL;
if (!pfn_valid(pfn))
goto bad_wp_page;
@@ -834,6 +882,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
if (!new_page)
goto no_mem;
copy_cow_page(old_page,new_page,address);
+ pte_chain = pte_chain_alloc(GFP_KERNEL);
/*
* Re-check the pte - we dropped the lock
@@ -845,7 +894,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
++mm->rss;
page_remove_rmap(old_page, page_table);
break_cow(vma, new_page, address, page_table);
- page_add_rmap(new_page, page_table);
+ pte_chain = page_add_rmap(new_page, page_table, pte_chain);
lru_cache_add_active(new_page);
/* Free the old page.. */
@@ -855,6 +904,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
spin_unlock(&mm->page_table_lock);
page_cache_release(new_page);
page_cache_release(old_page);
+ pte_chain_free(pte_chain);
return VM_FAULT_MINOR;
bad_wp_page:
@@ -992,6 +1042,7 @@ static int do_swap_page(struct mm_struct * mm,
swp_entry_t entry = pte_to_swp_entry(orig_pte);
pte_t pte;
int ret = VM_FAULT_MINOR;
+ struct pte_chain *pte_chain = NULL;
pte_unmap(page_table);
spin_unlock(&mm->page_table_lock);
@@ -1021,6 +1072,11 @@ static int do_swap_page(struct mm_struct * mm,
}
mark_page_accessed(page);
+ pte_chain = pte_chain_alloc(GFP_KERNEL);
+ if (!pte_chain) {
+ ret = -ENOMEM;
+ goto out;
+ }
lock_page(page);
/*
@@ -1053,13 +1109,14 @@ static int do_swap_page(struct mm_struct * mm,
flush_page_to_ram(page);
flush_icache_page(vma, page);
set_pte(page_table, pte);
- page_add_rmap(page, page_table);
+ pte_chain = page_add_rmap(page, page_table, pte_chain);
/* No need to invalidate - it was non-present before */
update_mmu_cache(vma, address, pte);
pte_unmap(page_table);
spin_unlock(&mm->page_table_lock);
out:
+ pte_chain_free(pte_chain);
return ret;
}
@@ -1068,11 +1125,27 @@ out:
* spinlock held to protect against concurrent faults in
* multithreaded programs.
*/
-static int do_anonymous_page(struct mm_struct * mm, struct vm_area_struct * vma, pte_t *page_table, pmd_t *pmd, int write_access, unsigned long addr)
+static int
+do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
+ pte_t *page_table, pmd_t *pmd, int write_access,
+ unsigned long addr)
{
pte_t entry;
struct page * page = ZERO_PAGE(addr);
+ struct pte_chain *pte_chain;
+ int ret;
+ pte_chain = pte_chain_alloc(GFP_ATOMIC);
+ if (!pte_chain) {
+ pte_unmap(page_table);
+ spin_unlock(&mm->page_table_lock);
+ pte_chain = pte_chain_alloc(GFP_KERNEL);
+ if (!pte_chain)
+ goto no_mem;
+ spin_lock(&mm->page_table_lock);
+ page_table = pte_offset_map(pmd, addr);
+ }
+
/* Read-only mapping of ZERO_PAGE. */
entry = pte_wrprotect(mk_pte(ZERO_PAGE(addr), vma->vm_page_prot));
@@ -1094,7 +1167,8 @@ static int do_anonymous_page(struct mm_struct * mm, struct vm_area_struct * vma,
pte_unmap(page_table);
page_cache_release(page);
spin_unlock(&mm->page_table_lock);
- return VM_FAULT_MINOR;
+ ret = VM_FAULT_MINOR;
+ goto out;
}
mm->rss++;
flush_page_to_ram(page);
@@ -1104,16 +1178,21 @@ static int do_anonymous_page(struct mm_struct * mm, struct vm_area_struct * vma,
}
set_pte(page_table, entry);
- page_add_rmap(page, page_table); /* ignores ZERO_PAGE */
+ /* ignores ZERO_PAGE */
+ pte_chain = page_add_rmap(page, page_table, pte_chain);
pte_unmap(page_table);
/* No need to invalidate - it was non-present before */
update_mmu_cache(vma, addr, entry);
spin_unlock(&mm->page_table_lock);
- return VM_FAULT_MINOR;
+ ret = VM_FAULT_MINOR;
+ goto out;
no_mem:
- return VM_FAULT_OOM;
+ ret = VM_FAULT_OOM;
+out:
+ pte_chain_free(pte_chain);
+ return ret;
}
/*
@@ -1128,14 +1207,17 @@ no_mem:
* This is called with the MM semaphore held and the page table
* spinlock held. Exit with the spinlock released.
*/
-static int do_no_page(struct mm_struct * mm, struct vm_area_struct * vma,
+static int
+do_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
unsigned long address, int write_access, pte_t *page_table, pmd_t *pmd)
{
struct page * new_page;
pte_t entry;
+ struct pte_chain *pte_chain;
if (!vma->vm_ops || !vma->vm_ops->nopage)
- return do_anonymous_page(mm, vma, page_table, pmd, write_access, address);
+ return do_anonymous_page(mm, vma, page_table,
+ pmd, write_access, address);
pte_unmap(page_table);
spin_unlock(&mm->page_table_lock);
@@ -1162,6 +1244,7 @@ static int do_no_page(struct mm_struct * mm, struct vm_area_struct * vma,
new_page = page;
}
+ pte_chain = pte_chain_alloc(GFP_KERNEL);
spin_lock(&mm->page_table_lock);
page_table = pte_offset_map(pmd, address);
@@ -1184,19 +1267,21 @@ static int do_no_page(struct mm_struct * mm, struct vm_area_struct * vma,
if (write_access)
entry = pte_mkwrite(pte_mkdirty(entry));
set_pte(page_table, entry);
- page_add_rmap(new_page, page_table);
+ pte_chain = page_add_rmap(new_page, page_table, pte_chain);
pte_unmap(page_table);
} else {
/* One of our sibling threads was faster, back out. */
pte_unmap(page_table);
page_cache_release(new_page);
spin_unlock(&mm->page_table_lock);
+ pte_chain_free(pte_chain);
return VM_FAULT_MINOR;
}
/* no need to invalidate: a not-present page shouldn't be cached */
update_mmu_cache(vma, address, entry);
spin_unlock(&mm->page_table_lock);
+ pte_chain_free(pte_chain);
return VM_FAULT_MAJOR;
}
diff --git a/mm/mempool.c b/mm/mempool.c
index bfa262857358..027e93c450a2 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -87,7 +87,13 @@ mempool_t * mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
}
return pool;
}
+EXPORT_SYMBOL(mempool_create);
+/*
+ * mempool_resize is disabled for now, because it has no callers. Feel free
+ * to turn it back on if needed.
+ */
+#if 0
/**
* mempool_resize - resize an existing memory pool
* @pool: pointer to the memory pool which was allocated via
@@ -143,16 +149,21 @@ int mempool_resize(mempool_t *pool, int new_min_nr, int gfp_mask)
if (!element)
goto out;
spin_lock_irqsave(&pool->lock, flags);
- if (pool->curr_nr < pool->min_nr)
+ if (pool->curr_nr < pool->min_nr) {
add_element(pool, element);
- else
- kfree(element); /* Raced */
+ } else {
+ spin_unlock_irqrestore(&pool->lock, flags);
+ pool->free(element, pool->pool_data); /* Raced */
+ spin_lock_irqsave(&pool->lock, flags);
+ }
}
out_unlock:
spin_unlock_irqrestore(&pool->lock, flags);
out:
return 0;
}
+EXPORT_SYMBOL(mempool_resize);
+#endif
/**
* mempool_destroy - deallocate a memory pool
@@ -169,6 +180,7 @@ void mempool_destroy(mempool_t *pool)
BUG(); /* There were outstanding elements */
free_pool(pool);
}
+EXPORT_SYMBOL(mempool_destroy);
/**
* mempool_alloc - allocate an element from a specific memory pool
@@ -230,6 +242,7 @@ repeat_alloc:
goto repeat_alloc;
}
+EXPORT_SYMBOL(mempool_alloc);
/**
* mempool_free - return an element to the pool.
@@ -255,6 +268,7 @@ void mempool_free(void *element, mempool_t *pool)
}
pool->free(element, pool->pool_data);
}
+EXPORT_SYMBOL(mempool_free);
/*
* A commonly used alloc and free fn.
@@ -264,17 +278,11 @@ void *mempool_alloc_slab(int gfp_mask, void *pool_data)
kmem_cache_t *mem = (kmem_cache_t *) pool_data;
return kmem_cache_alloc(mem, gfp_mask);
}
+EXPORT_SYMBOL(mempool_alloc_slab);
void mempool_free_slab(void *element, void *pool_data)
{
kmem_cache_t *mem = (kmem_cache_t *) pool_data;
kmem_cache_free(mem, element);
}
-
-EXPORT_SYMBOL(mempool_create);
-EXPORT_SYMBOL(mempool_resize);
-EXPORT_SYMBOL(mempool_destroy);
-EXPORT_SYMBOL(mempool_alloc);
-EXPORT_SYMBOL(mempool_free);
-EXPORT_SYMBOL(mempool_alloc_slab);
EXPORT_SYMBOL(mempool_free_slab);
diff --git a/mm/mremap.c b/mm/mremap.c
index f295a0d88c0c..c94c9da3f4b5 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -15,6 +15,7 @@
#include <linux/swap.h>
#include <linux/fs.h>
#include <linux/highmem.h>
+#include <linux/rmap-locking.h>
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
@@ -81,7 +82,9 @@ static inline pte_t *alloc_one_pte_map(struct mm_struct *mm, unsigned long addr)
return pte;
}
-static int copy_one_pte(struct mm_struct *mm, pte_t * src, pte_t * dst)
+static int
+copy_one_pte(struct mm_struct *mm, pte_t *src, pte_t *dst,
+ struct pte_chain **pte_chainp)
{
int error = 0;
pte_t pte;
@@ -101,17 +104,25 @@ static int copy_one_pte(struct mm_struct *mm, pte_t * src, pte_t * dst)
}
set_pte(dst, pte);
if (page)
- page_add_rmap(page, dst);
+ *pte_chainp = page_add_rmap(page, dst, *pte_chainp);
}
return error;
}
-static int move_one_page(struct vm_area_struct *vma, unsigned long old_addr, unsigned long new_addr)
+static int
+move_one_page(struct vm_area_struct *vma, unsigned long old_addr,
+ unsigned long new_addr)
{
struct mm_struct *mm = vma->vm_mm;
int error = 0;
pte_t *src, *dst;
+ struct pte_chain *pte_chain;
+ pte_chain = pte_chain_alloc(GFP_KERNEL);
+ if (!pte_chain) {
+ error = -ENOMEM;
+ goto out;
+ }
spin_lock(&mm->page_table_lock);
src = get_one_pte_map_nested(mm, old_addr);
if (src) {
@@ -127,12 +138,14 @@ static int move_one_page(struct vm_area_struct *vma, unsigned long old_addr, uns
dst = alloc_one_pte_map(mm, new_addr);
if (src == NULL)
src = get_one_pte_map_nested(mm, old_addr);
- error = copy_one_pte(mm, src, dst);
+ error = copy_one_pte(mm, src, dst, &pte_chain);
pte_unmap_nested(src);
pte_unmap(dst);
}
flush_tlb_page(vma, old_addr);
spin_unlock(&mm->page_table_lock);
+ pte_chain_free(pte_chain);
+out:
return error;
}
diff --git a/mm/readahead.c b/mm/readahead.c
index 460ca8a0d149..00de3dcc2829 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -65,7 +65,7 @@ int read_cache_pages(struct address_space *mapping, struct list_head *pages,
while (!list_empty(pages)) {
page = list_entry(pages->prev, struct page, list);
list_del(&page->list);
- if (add_to_page_cache(page, mapping, page->index)) {
+ if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
page_cache_release(page);
continue;
}
@@ -93,7 +93,8 @@ static int read_pages(struct address_space *mapping, struct file *filp,
for (page_idx = 0; page_idx < nr_pages; page_idx++) {
struct page *page = list_entry(pages->prev, struct page, list);
list_del(&page->list);
- if (!add_to_page_cache(page, mapping, page->index)) {
+ if (!add_to_page_cache(page, mapping,
+ page->index, GFP_KERNEL)) {
mapping->a_ops->readpage(filp, page);
if (!pagevec_add(&lru_pvec, page))
__pagevec_lru_add(&lru_pvec);
diff --git a/mm/rmap.c b/mm/rmap.c
index b1fc8c10e3f3..da277624459e 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -27,6 +27,7 @@
#include <linux/init.h>
#include <linux/rmap-locking.h>
#include <linux/cache.h>
+#include <linux/percpu.h>
#include <asm/pgalloc.h>
#include <asm/rmap.h>
@@ -51,7 +52,7 @@ struct pte_chain {
pte_addr_t ptes[NRPTE];
} ____cacheline_aligned;
-static kmem_cache_t *pte_chain_cache;
+kmem_cache_t *pte_chain_cache;
/*
* pte_chain list management policy:
@@ -71,39 +72,6 @@ static kmem_cache_t *pte_chain_cache;
*/
/**
- * pte_chain_alloc - allocate a pte_chain struct
- *
- * Returns a pointer to a fresh pte_chain structure. Allocates new
- * pte_chain structures as required.
- * Caller needs to hold the page's pte_chain_lock.
- */
-static inline struct pte_chain *pte_chain_alloc(void)
-{
- struct pte_chain *ret;
-
- ret = kmem_cache_alloc(pte_chain_cache, GFP_ATOMIC);
-#ifdef DEBUG_RMAP
- {
- int i;
- for (i = 0; i < NRPTE; i++)
- BUG_ON(ret->ptes[i]);
- BUG_ON(ret->next);
- }
-#endif
- return ret;
-}
-
-/**
- * pte_chain_free - free pte_chain structure
- * @pte_chain: pte_chain struct to free
- */
-static inline void pte_chain_free(struct pte_chain *pte_chain)
-{
- pte_chain->next = NULL;
- kmem_cache_free(pte_chain_cache, pte_chain);
-}
-
-/**
** VM stuff below this comment
**/
@@ -156,7 +124,7 @@ int page_referenced(struct page * page)
page->pte.direct = pc->ptes[NRPTE-1];
SetPageDirect(page);
pc->ptes[NRPTE-1] = 0;
- pte_chain_free(pc);
+ __pte_chain_free(pc);
}
}
return referenced;
@@ -170,10 +138,11 @@ int page_referenced(struct page * page)
* Add a new pte reverse mapping to a page.
* The caller needs to hold the mm->page_table_lock.
*/
-void page_add_rmap(struct page * page, pte_t * ptep)
+struct pte_chain *
+page_add_rmap(struct page *page, pte_t *ptep, struct pte_chain *pte_chain)
{
pte_addr_t pte_paddr = ptep_to_paddr(ptep);
- struct pte_chain *pte_chain;
+ struct pte_chain *cur_pte_chain;
int i;
#ifdef DEBUG_RMAP
@@ -186,7 +155,7 @@ void page_add_rmap(struct page * page, pte_t * ptep)
#endif
if (!pfn_valid(page_to_pfn(page)) || PageReserved(page))
- return;
+ return pte_chain;
pte_chain_lock(page);
@@ -222,30 +191,28 @@ void page_add_rmap(struct page * page, pte_t * ptep)
if (PageDirect(page)) {
/* Convert a direct pointer into a pte_chain */
ClearPageDirect(page);
- pte_chain = pte_chain_alloc();
pte_chain->ptes[NRPTE-1] = page->pte.direct;
pte_chain->ptes[NRPTE-2] = pte_paddr;
page->pte.direct = 0;
page->pte.chain = pte_chain;
+ pte_chain = NULL; /* We consumed it */
goto out;
}
- pte_chain = page->pte.chain;
- if (pte_chain->ptes[0]) { /* It's full */
- struct pte_chain *new;
-
- new = pte_chain_alloc();
- new->next = pte_chain;
- page->pte.chain = new;
- new->ptes[NRPTE-1] = pte_paddr;
+ cur_pte_chain = page->pte.chain;
+ if (cur_pte_chain->ptes[0]) { /* It's full */
+ pte_chain->next = cur_pte_chain;
+ page->pte.chain = pte_chain;
+ pte_chain->ptes[NRPTE-1] = pte_paddr;
+ pte_chain = NULL; /* We consumed it */
goto out;
}
- BUG_ON(!pte_chain->ptes[NRPTE-1]);
+ BUG_ON(!cur_pte_chain->ptes[NRPTE-1]);
for (i = NRPTE-2; i >= 0; i--) {
- if (!pte_chain->ptes[i]) {
- pte_chain->ptes[i] = pte_paddr;
+ if (!cur_pte_chain->ptes[i]) {
+ cur_pte_chain->ptes[i] = pte_paddr;
goto out;
}
}
@@ -253,7 +220,7 @@ void page_add_rmap(struct page * page, pte_t * ptep)
out:
pte_chain_unlock(page);
inc_page_state(nr_reverse_maps);
- return;
+ return pte_chain;
}
/**
@@ -311,7 +278,7 @@ void page_remove_rmap(struct page * page, pte_t * ptep)
if (victim_i == NRPTE-1) {
/* Emptied a pte_chain */
page->pte.chain = start->next;
- pte_chain_free(start);
+ __pte_chain_free(start);
} else {
/* Do singleton->PageDirect here */
}
@@ -486,7 +453,7 @@ int try_to_unmap(struct page * page)
victim_i++;
if (victim_i == NRPTE) {
page->pte.chain = start->next;
- pte_chain_free(start);
+ __pte_chain_free(start);
start = page->pte.chain;
victim_i = 0;
}
@@ -522,6 +489,58 @@ static void pte_chain_ctor(void *p, kmem_cache_t *cachep, unsigned long flags)
memset(pc, 0, sizeof(*pc));
}
+DEFINE_PER_CPU(struct pte_chain *, local_pte_chain) = 0;
+
+/**
+ * __pte_chain_free - free pte_chain structure
+ * @pte_chain: pte_chain struct to free
+ */
+void __pte_chain_free(struct pte_chain *pte_chain)
+{
+ int cpu = get_cpu();
+ struct pte_chain **pte_chainp;
+
+ if (pte_chain->next)
+ pte_chain->next = NULL;
+ pte_chainp = &per_cpu(local_pte_chain, cpu);
+ if (*pte_chainp)
+ kmem_cache_free(pte_chain_cache, *pte_chainp);
+ *pte_chainp = pte_chain;
+ put_cpu();
+}
+
+/*
+ * pte_chain_alloc(): allocate a pte_chain structure for use by page_add_rmap().
+ *
+ * The caller of page_add_rmap() must perform the allocation because
+ * page_add_rmap() is invariably called under spinlock. Often, page_add_rmap()
+ * will not actually use the pte_chain, because there is space available in one
+ * of the existing pte_chains which are attached to the page. So the case of
+ * allocating and then freeing a single pte_chain is specially optimised here,
+ * with a one-deep per-cpu cache.
+ */
+struct pte_chain *pte_chain_alloc(int gfp_flags)
+{
+ int cpu;
+ struct pte_chain *ret;
+ struct pte_chain **pte_chainp;
+
+ if (gfp_flags & __GFP_WAIT)
+ might_sleep();
+
+ cpu = get_cpu();
+ pte_chainp = &per_cpu(local_pte_chain, cpu);
+ if (*pte_chainp) {
+ ret = *pte_chainp;
+ *pte_chainp = NULL;
+ put_cpu();
+ } else {
+ put_cpu();
+ ret = kmem_cache_alloc(pte_chain_cache, gfp_flags);
+ }
+ return ret;
+}
+
void __init pte_chain_init(void)
{
pte_chain_cache = kmem_cache_create( "pte_chain",
diff --git a/mm/shmem.c b/mm/shmem.c
index d283ef97b644..2bb1a4e0ab18 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -889,7 +889,7 @@ repeat:
}
if (error || swap.val ||
(error = add_to_page_cache_lru(
- filepage, mapping, idx))) {
+ filepage, mapping, idx, GFP_ATOMIC))) {
spin_unlock(&info->lock);
page_cache_release(filepage);
shmem_free_block(inode);
diff --git a/mm/slab.c b/mm/slab.c
index c0fed9f01b4c..c6740a88a703 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -335,8 +335,8 @@ struct kmem_cache_s {
/* Magic nums for obj red zoning.
* Placed in the first word before and the first word after an obj.
*/
-#define RED_MAGIC1 0x5A2CF071UL /* when obj is active */
-#define RED_MAGIC2 0x170FC2A5UL /* when obj is inactive */
+#define RED_INACTIVE 0x5A2CF071UL /* when obj is inactive */
+#define RED_ACTIVE 0x170FC2A5UL /* when obj is active */
/* ...and for poisoning */
#define POISON_BEFORE 0x5a /* for use-uninitialised poisoning */
@@ -498,6 +498,19 @@ static void cache_estimate (unsigned long gfporder, size_t size,
*left_over = wastage;
}
+#if DEBUG
+
+#define slab_error(cachep, msg) __slab_error(__FUNCTION__, cachep, msg)
+
+static void __slab_error(char *function, kmem_cache_t *cachep, char *msg)
+{
+ printk(KERN_ERR "slab error in %s(): cache `%s': %s\n",
+ function, cachep->name, msg);
+ dump_stack();
+}
+
+#endif
+
/*
* Start the reap timer running on the target CPU. We run at around 1 to 2Hz.
* Add the CPU number into the expiry time to minimize the possibility of the
@@ -780,16 +793,19 @@ static void slab_destroy (kmem_cache_t *cachep, struct slab *slabp)
#if DEBUG
int i;
for (i = 0; i < cachep->num; i++) {
- void* objp = slabp->s_mem+cachep->objsize*i;
+ void *objp = slabp->s_mem + cachep->objsize * i;
+
if (cachep->flags & SLAB_POISON)
check_poison_obj(cachep, objp);
if (cachep->flags & SLAB_RED_ZONE) {
- if (*((unsigned long*)(objp)) != RED_MAGIC1)
- BUG();
+ if (*((unsigned long*)(objp)) != RED_INACTIVE)
+ slab_error(cachep, "start of a freed object "
+ "was overwritten");
if (*((unsigned long*)(objp + cachep->objsize -
- BYTES_PER_WORD)) != RED_MAGIC1)
- BUG();
+ BYTES_PER_WORD)) != RED_INACTIVE)
+ slab_error(cachep, "end of a freed object "
+ "was overwritten");
objp += BYTES_PER_WORD;
}
if (cachep->dtor && !(cachep->flags & SLAB_POISON))
@@ -1270,9 +1286,9 @@ static void cache_init_objs (kmem_cache_t * cachep,
poison_obj(cachep, objp, POISON_BEFORE);
if (cachep->flags & SLAB_RED_ZONE) {
- *((unsigned long*)(objp)) = RED_MAGIC1;
+ *((unsigned long*)(objp)) = RED_INACTIVE;
*((unsigned long*)(objp + cachep->objsize -
- BYTES_PER_WORD)) = RED_MAGIC1;
+ BYTES_PER_WORD)) = RED_INACTIVE;
objp += BYTES_PER_WORD;
}
/*
@@ -1285,11 +1301,13 @@ static void cache_init_objs (kmem_cache_t * cachep,
if (cachep->flags & SLAB_RED_ZONE) {
objp -= BYTES_PER_WORD;
- if (*((unsigned long*)(objp)) != RED_MAGIC1)
- BUG();
+ if (*((unsigned long*)(objp)) != RED_INACTIVE)
+ slab_error(cachep, "constructor overwrote the"
+ " start of an object");
if (*((unsigned long*)(objp + cachep->objsize -
- BYTES_PER_WORD)) != RED_MAGIC1)
- BUG();
+ BYTES_PER_WORD)) != RED_INACTIVE)
+ slab_error(cachep, "constructor overwrote the"
+ " end of an object");
}
#else
if (cachep->ctor)
@@ -1444,13 +1462,13 @@ static inline void *cache_free_debugcheck (kmem_cache_t * cachep, void * objp)
if (cachep->flags & SLAB_RED_ZONE) {
objp -= BYTES_PER_WORD;
- if (xchg((unsigned long *)objp, RED_MAGIC1) != RED_MAGIC2)
- /* Either write before start, or a double free. */
- BUG();
+ if (xchg((unsigned long *)objp, RED_INACTIVE) != RED_ACTIVE)
+ slab_error(cachep, "double free, or memory before"
+ " object was overwritten");
if (xchg((unsigned long *)(objp+cachep->objsize -
- BYTES_PER_WORD), RED_MAGIC1) != RED_MAGIC2)
- /* Either write past end, or a double free. */
- BUG();
+ BYTES_PER_WORD), RED_INACTIVE) != RED_ACTIVE)
+ slab_error(cachep, "double free, or memory after "
+ " object was overwritten");
}
objnr = (objp-slabp->s_mem)/cachep->objsize;
@@ -1614,12 +1632,13 @@ cache_alloc_debugcheck_after(kmem_cache_t *cachep,
BUG();
if (cachep->flags & SLAB_RED_ZONE) {
/* Set alloc red-zone, and check old one. */
- if (xchg((unsigned long *)objp, RED_MAGIC2) !=
- RED_MAGIC1)
- BUG();
+ if (xchg((unsigned long *)objp, RED_ACTIVE) != RED_INACTIVE)
+ slab_error(cachep, "memory before object was "
+ "overwritten");
if (xchg((unsigned long *)(objp+cachep->objsize -
- BYTES_PER_WORD), RED_MAGIC2) != RED_MAGIC1)
- BUG();
+ BYTES_PER_WORD), RED_ACTIVE) != RED_INACTIVE)
+ slab_error(cachep, "memory after object was "
+ "overwritten");
objp += BYTES_PER_WORD;
}
if (cachep->ctor && cachep->flags & SLAB_POISON) {
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 47269578b689..97f2c21c449c 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -78,7 +78,7 @@ int add_to_swap_cache(struct page *page, swp_entry_t entry)
INC_CACHE_INFO(noent_race);
return -ENOENT;
}
- error = add_to_page_cache(page, &swapper_space, entry.val);
+ error = add_to_page_cache(page, &swapper_space, entry.val, GFP_ATOMIC);
/*
* Anon pages are already on the LRU, we don't run lru_cache_add here.
*/
@@ -149,7 +149,8 @@ int add_to_swap(struct page * page)
/*
* Add it to the swap cache and mark it dirty
*/
- err = add_to_page_cache(page, &swapper_space, entry.val);
+ err = add_to_page_cache(page, &swapper_space,
+ entry.val, GFP_ATOMIC);
if (pf_flags & PF_MEMALLOC)
current->flags |= PF_MEMALLOC;
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 067c3095225a..8ce8a1ab91dc 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -20,6 +20,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/init.h>
+#include <linux/rmap-locking.h>
#include <asm/pgtable.h>
#include <linux/swapops.h>
@@ -377,8 +378,9 @@ void free_swap_and_cache(swp_entry_t entry)
* what to do if a write is requested later.
*/
/* mmlist_lock and vma->vm_mm->page_table_lock are held */
-static inline void unuse_pte(struct vm_area_struct * vma, unsigned long address,
- pte_t *dir, swp_entry_t entry, struct page* page)
+static void
+unuse_pte(struct vm_area_struct *vma, unsigned long address, pte_t *dir,
+ swp_entry_t entry, struct page *page, struct pte_chain **pte_chainp)
{
pte_t pte = *dir;
@@ -388,7 +390,7 @@ static inline void unuse_pte(struct vm_area_struct * vma, unsigned long address,
return;
get_page(page);
set_pte(dir, pte_mkold(mk_pte(page, vma->vm_page_prot)));
- page_add_rmap(page, dir);
+ *pte_chainp = page_add_rmap(page, dir, *pte_chainp);
swap_free(entry);
++vma->vm_mm->rss;
}
@@ -400,6 +402,7 @@ static void unuse_pmd(struct vm_area_struct * vma, pmd_t *dir,
{
pte_t * pte;
unsigned long end;
+ struct pte_chain *pte_chain = NULL;
if (pmd_none(*dir))
return;
@@ -415,11 +418,18 @@ static void unuse_pmd(struct vm_area_struct * vma, pmd_t *dir,
if (end > PMD_SIZE)
end = PMD_SIZE;
do {
- unuse_pte(vma, offset+address-vma->vm_start, pte, entry, page);
+ /*
+ * FIXME: handle pte_chain_alloc() failures
+ */
+ if (pte_chain == NULL)
+ pte_chain = pte_chain_alloc(GFP_ATOMIC);
+ unuse_pte(vma, offset+address-vma->vm_start,
+ pte, entry, page, &pte_chain);
address += PAGE_SIZE;
pte++;
} while (address && (address < end));
pte_unmap(pte - 1);
+ pte_chain_free(pte_chain);
}
/* mmlist_lock and vma->vm_mm->page_table_lock are held */
diff --git a/net/core/dv.c b/net/core/dv.c
index 6b152aa1cf98..d2b2920312d1 100644
--- a/net/core/dv.c
+++ b/net/core/dv.c
@@ -97,7 +97,7 @@ void free_divert_blk(struct net_device *dev)
/*
* Adds a tcp/udp (source or dest) port to an array
*/
-int add_port(u16 ports[], u16 port)
+static int add_port(u16 ports[], u16 port)
{
int i;
@@ -127,7 +127,7 @@ int add_port(u16 ports[], u16 port)
/*
* Removes a port from an array tcp/udp (source or dest)
*/
-int remove_port(u16 ports[], u16 port)
+static int remove_port(u16 ports[], u16 port)
{
int i;
@@ -150,7 +150,7 @@ int remove_port(u16 ports[], u16 port)
}
/* Some basic sanity checks on the arguments passed to divert_ioctl() */
-int check_args(struct divert_cf *div_cf, struct net_device **dev)
+static int check_args(struct divert_cf *div_cf, struct net_device **dev)
{
char devname[32];
int ret;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index d1d7cf33713a..9ca1db5863ad 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -234,7 +234,7 @@ static struct rtable *rt_cache_get_next(struct seq_file *seq, struct rtable *r)
{
struct rt_cache_iter_state *st = seq->private;
- read_barrier_depends();
+ smp_read_barrier_depends();
r = r->u.rt_next;
while (!r) {
rcu_read_unlock();
@@ -718,7 +718,18 @@ restart:
if (compare_keys(&rth->fl, &rt->fl)) {
/* Put it first */
*rthp = rth->u.rt_next;
+ /*
+ * Since lookup is lockfree, the deletion
+ * must be visible to another weakly ordered CPU before
+ * the insertion at the start of the hash chain.
+ */
+ smp_wmb();
rth->u.rt_next = rt_hash_table[hash].chain;
+ /*
+ * Since lookup is lockfree, the update writes
+ * must be ordered for consistency on SMP.
+ */
+ smp_wmb();
rt_hash_table[hash].chain = rth;
rth->u.dst.__use++;
@@ -900,7 +911,7 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
while ((rth = *rthp) != NULL) {
struct rtable *rt;
- read_barrier_depends();
+ smp_read_barrier_depends();
if (rth->fl.fl4_dst != daddr ||
rth->fl.fl4_src != skeys[i] ||
rth->fl.fl4_tos != tos ||
@@ -1148,7 +1159,7 @@ unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu)
rcu_read_lock();
for (rth = rt_hash_table[hash].chain; rth;
rth = rth->u.rt_next) {
- read_barrier_depends();
+ smp_read_barrier_depends();
if (rth->fl.fl4_dst == daddr &&
rth->fl.fl4_src == skeys[i] &&
rth->rt_dst == daddr &&
@@ -1740,7 +1751,7 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
rcu_read_lock();
for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) {
- read_barrier_depends();
+ smp_read_barrier_depends();
if (rth->fl.fl4_dst == daddr &&
rth->fl.fl4_src == saddr &&
rth->fl.iif == iif &&
@@ -2105,7 +2116,7 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp)
rcu_read_lock();
for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) {
- read_barrier_depends();
+ smp_read_barrier_depends();
if (rth->fl.fl4_dst == flp->fl4_dst &&
rth->fl.fl4_src == flp->fl4_src &&
rth->fl.iif == 0 &&
@@ -2335,7 +2346,7 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb)
rcu_read_lock();
for (rt = rt_hash_table[h].chain, idx = 0; rt;
rt = rt->u.rt_next, idx++) {
- read_barrier_depends();
+ smp_read_barrier_depends();
if (idx < s_idx)
continue;
skb->dst = dst_clone(&rt->u.dst);
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index d405be5dc1ce..2b20154fe0f5 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -402,7 +402,13 @@ static int ipv6_auth_hdr(struct sk_buff **skb_ptr, int nhoff)
if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8))
goto fail;
- len = (skb->h.raw[1]+1)<<2;
+ /*
+ * RFC2402 2.2 Payload Length
+ * The 8-bit field specifies the length of AH in 32-bit words
+ * (4-byte units), minus "2".
+ * -- Noriaki Takamiya @USAGI Project
+ */
+ len = (skb->h.raw[1]+2)<<2;
if (len&7)
goto fail;
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 546d38101aa8..9494ca19aa54 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -22,6 +22,7 @@
#include <linux/ctype.h>
#include <asm/uaccess.h>
#include <linux/poll.h>
+#include <linux/seq_file.h>
#include <linux/proc_fs.h>
#include <linux/net.h>
#include <asm/ioctls.h>
@@ -160,7 +161,9 @@ static spinlock_t cache_list_lock = SPIN_LOCK_UNLOCKED;
static struct cache_detail *current_detail;
static int current_index;
-struct file_operations cache_file_operations;
+static struct file_operations cache_file_operations;
+static struct file_operations content_file_operations;
+static struct file_operations cache_flush_operations;
void cache_register(struct cache_detail *cd)
{
@@ -169,13 +172,32 @@ void cache_register(struct cache_detail *cd)
struct proc_dir_entry *p;
cd->proc_ent->owner = THIS_MODULE;
- p = create_proc_entry("channel", S_IFREG|S_IRUSR|S_IWUSR,
- cd->proc_ent);
- if (p) {
- p->proc_fops = &cache_file_operations;
- p->owner = THIS_MODULE;
- p->data = cd;
+ p = create_proc_entry("flush", S_IFREG|S_IRUSR|S_IWUSR,
+ cd->proc_ent);
+ if (p) {
+ p->proc_fops = &cache_flush_operations;
+ p->owner = THIS_MODULE;
+ p->data = cd;
+ }
+
+ if (cd->cache_request || cd->cache_parse) {
+ p = create_proc_entry("channel", S_IFREG|S_IRUSR|S_IWUSR,
+ cd->proc_ent);
+ if (p) {
+ p->proc_fops = &cache_file_operations;
+ p->owner = THIS_MODULE;
+ p->data = cd;
+ }
}
+ if (cd->cache_show) {
+ p = create_proc_entry("content", S_IFREG|S_IRUSR|S_IWUSR,
+ cd->proc_ent);
+ if (p) {
+ p->proc_fops = &content_file_operations;
+ p->owner = THIS_MODULE;
+ p->data = cd;
+ }
+ }
}
rwlock_init(&cd->hash_lock);
INIT_LIST_HEAD(&cd->queue);
@@ -183,7 +205,7 @@ void cache_register(struct cache_detail *cd)
cd->nextcheck = 0;
cd->entries = 0;
atomic_set(&cd->readers, 0);
- cd->last_close = get_seconds();
+ cd->last_close = 0;
list_add(&cd->others, &cache_list);
spin_unlock(&cache_list_lock);
}
@@ -710,7 +732,7 @@ cache_release(struct inode *inode, struct file *filp)
-struct file_operations cache_file_operations = {
+static struct file_operations cache_file_operations = {
.llseek = no_llseek,
.read = cache_read,
.write = cache_write,
@@ -799,8 +821,8 @@ void qword_addhex(char **bpp, int *lp, char *buf, int blen)
len -= 2;
while (blen && len >= 2) {
unsigned char c = *buf++;
- *bp++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'0');
- *bp++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'0');
+ *bp++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1);
+ *bp++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1);
len -= 2;
blen--;
}
@@ -902,7 +924,7 @@ int qword_get(char **bpp, char *dest, int bufsize)
}
} else {
/* text with \nnn octal quoting */
- while (*bp != ' ' && *bp && len < bufsize-1) {
+ while (*bp != ' ' && *bp != '\n' && *bp && len < bufsize-1) {
if (*bp == '\\' &&
isodigit(bp[1]) && (bp[1] <= '3') &&
isodigit(bp[2]) &&
@@ -918,11 +940,205 @@ int qword_get(char **bpp, char *dest, int bufsize)
len++;
}
}
- *dest = '\0';
}
+ if (*bp != ' ' && *bp != '\n' && *bp != '\0')
+ return -1;
+ while (*bp == ' ') bp++;
*bpp = bp;
- if (*bp == ' ' || *bp == '\n' || *bp == '\0')
- return len;
- return -1;
+ *dest = '\0';
+ return len;
}
+
+
+/*
+ * support /proc/sunrpc/cache/$CACHENAME/content
+ * as a seqfile.
+ * We call ->cache_show passing NULL for the item to
+ * get a header, then pass each real item in the cache
+ */
+
+struct handle {
+ struct cache_detail *cd;
+ char *pbuf;
+};
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+ loff_t n = *pos;
+ unsigned hash, entry;
+ struct cache_head *ch;
+ struct cache_detail *cd = ((struct handle*)m->private)->cd;
+
+
+ read_lock(&cd->hash_lock);
+ if (!n--)
+ return (void *)1;
+ hash = n >> 32;
+ entry = n & ((1LL<<32) - 1);
+
+ for (ch=cd->hash_table[hash]; ch; ch=ch->next)
+ if (!entry--)
+ return ch;
+ n &= ~((1LL<<32) - 1);
+ do {
+ hash++;
+ n += 1LL<<32;
+ } while(hash < cd->hash_size &&
+ cd->hash_table[hash]==NULL);
+ if (hash >= cd->hash_size)
+ return NULL;
+ *pos = n+1;
+ return cd->hash_table[hash];
+}
+
+static void *c_next(struct seq_file *m, void *p, loff_t *pos)
+{
+ struct cache_head *ch = p;
+ int hash = (*pos >> 32);
+ struct cache_detail *cd = ((struct handle*)m->private)->cd;
+
+ if (p == (void *)1)
+ hash = 0;
+ else if (ch->next == NULL) {
+ hash++;
+ *pos += 1LL<<32;
+ } else {
+ ++*pos;
+ return ch->next;
+ }
+ *pos &= ~((1LL<<32) - 1);
+ while (hash < cd->hash_size &&
+ cd->hash_table[hash] == NULL) {
+ hash++;
+ *pos += 1LL<<32;
+ }
+ if (hash >= cd->hash_size)
+ return NULL;
+ ++*pos;
+ return cd->hash_table[hash];
+}
+
+static void c_stop(struct seq_file *m, void *p)
+{
+ struct cache_detail *cd = ((struct handle*)m->private)->cd;
+ read_unlock(&cd->hash_lock);
+}
+
+static int c_show(struct seq_file *m, void *p)
+{
+ struct cache_head *cp = p;
+ struct cache_detail *cd = ((struct handle*)m->private)->cd;
+ char *pbuf = ((struct handle*)m->private)->pbuf;
+
+ if (p == (void *)1)
+ return cd->cache_show(m, cd, NULL, pbuf);
+
+ cache_get(cp);
+ if (cache_check(cd, cp, NULL))
+ return 0;
+ cache_put(cp, cd);
+
+ return cd->cache_show(m, cd, cp, pbuf);
+}
+
+struct seq_operations cache_content_op = {
+ .start = c_start,
+ .next = c_next,
+ .stop = c_stop,
+ .show = c_show,
+};
+
+static int content_open(struct inode *inode, struct file *file)
+{
+ int res;
+ char *namebuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ struct handle *han;
+ struct cache_detail *cd = PDE(inode)->data;
+
+ if (namebuf == NULL)
+ return -ENOMEM;
+
+ han = kmalloc(sizeof(*han), GFP_KERNEL);
+ if (han == NULL) {
+ kfree(namebuf);
+ return -ENOMEM;
+ }
+ han->pbuf = namebuf;
+ han->cd = cd;
+
+ res = seq_open(file, &cache_content_op);
+ if (res) {
+ kfree(namebuf);
+ kfree(han);
+ } else
+ ((struct seq_file *)file->private_data)->private = han;
+
+ return res;
+}
+static int content_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *m = (struct seq_file *)file->private_data;
+ struct handle *han = m->private;
+ kfree(han->pbuf);
+ kfree(han);
+ m->private = NULL;
+ return seq_release(inode, file);
+}
+
+static struct file_operations content_file_operations = {
+ .open = content_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = content_release,
+};
+
+static ssize_t read_flush(struct file *file, char *buf,
+ size_t count, loff_t *ppos)
+{
+ struct cache_detail *cd = PDE(file->f_dentry->d_inode)->data;
+ char tbuf[20];
+ unsigned long p = *ppos;
+ int len;
+
+ sprintf(tbuf, "%lu\n", cd->flush_time);
+ len = strlen(tbuf);
+ if (p >= len)
+ return 0;
+ len -= p;
+ if (len > count) len = count;
+ if (copy_to_user(buf, (void*)(tbuf+p), len))
+ len = -EFAULT;
+ else
+ *ppos += len;
+ return len;
+}
+
+static ssize_t write_flush(struct file * file, const char * buf,
+ size_t count, loff_t *ppos)
+{
+ struct cache_detail *cd = PDE(file->f_dentry->d_inode)->data;
+ char tbuf[20];
+ char *ep;
+ long flushtime;
+ if (*ppos || count > sizeof(tbuf)-1)
+ return -EINVAL;
+ if (copy_from_user(tbuf, buf, count))
+ return -EFAULT;
+ tbuf[count] = 0;
+ flushtime = simple_strtoul(tbuf, &ep, 0);
+ if (*ep && *ep != '\n')
+ return -EINVAL;
+
+ cd->flush_time = flushtime;
+ cd->nextcheck = get_seconds();
+ cache_flush();
+
+ *ppos += count;
+ return count;
+}
+
+static struct file_operations cache_flush_operations = {
+ .read = read_flush,
+ .write = write_flush,
+};
diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
index 39a46f7a12f5..8f7db60bb89c 100644
--- a/net/sunrpc/svcauth.c
+++ b/net/sunrpc/svcauth.c
@@ -16,6 +16,7 @@
#include <linux/sunrpc/svcsock.h>
#include <linux/sunrpc/svcauth.h>
#include <linux/err.h>
+#include <linux/hash.h>
#define RPCDBG_FACILITY RPCDBG_AUTH
@@ -111,14 +112,22 @@ svc_auth_unregister(rpc_authflavor_t flavor)
* it will complain.
*/
-int name_hash(char *name, int size)
+int hash_mem(char *buf, int len, int bits)
{
int hash = 0;
- while (*name) {
- hash += *name;
- name++;
+ unsigned long l;
+ while (len >= BITS_PER_LONG/8) {
+ l = *(unsigned long *)buf;
+ buf += BITS_PER_LONG/8;
+ len -= BITS_PER_LONG/8;
+ hash ^= hash_long(l, bits);
}
- return hash % size;
+ if (len) {
+ l=0;
+ memcpy((char*)&l, buf, len);
+ hash ^= hash_long(l, bits);
+ }
+ return hash;
}
@@ -161,7 +170,7 @@ void auth_domain_put(struct auth_domain *dom)
static inline int auth_domain_hash(struct auth_domain *item)
{
- return name_hash(item->name, DN_HASHMAX);
+ return hash_str(item->name, DN_HASHBITS);
}
static inline int auth_domain_match(struct auth_domain *tmp, struct auth_domain *item)
{
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 37e74850f362..fb54ca13737d 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -5,6 +5,8 @@
#include <linux/sunrpc/svcsock.h>
#include <linux/sunrpc/svcauth.h>
#include <linux/err.h>
+#include <linux/seq_file.h>
+#include <linux/hash.h>
#define RPCDBG_FACILITY RPCDBG_AUTH
@@ -107,7 +109,8 @@ void ip_map_put(struct cache_head *item, struct cache_detail *cd)
static inline int ip_map_hash(struct ip_map *item)
{
- return (name_hash(item->m_class, IP_HASHMAX) ^ item->m_addr.s_addr) & IP_HASHMASK;
+ return hash_str(item->m_class, IP_HASHBITS) ^
+ hash_long((unsigned long)item->m_addr.s_addr, IP_HASHBITS);
}
static inline int ip_map_match(struct ip_map *item, struct ip_map *tmp)
{
@@ -210,6 +213,33 @@ static int ip_map_parse(struct cache_detail *cd,
return 0;
}
+static int ip_map_show(struct seq_file *m,
+ struct cache_detail *cd,
+ struct cache_head *h,
+ char *pbuf)
+{
+ struct ip_map *im;
+ struct in_addr addr;
+
+ if (h == NULL) {
+ seq_puts(m, "#class IP domain\n");
+ return 0;
+ }
+ im = container_of(h, struct ip_map, h);
+ /* class addr domain */
+ addr = im->m_addr;
+ seq_printf(m, "%s %d.%d.%d.%d %s\n",
+ im->m_class,
+ htonl(addr.s_addr) >> 24 & 0xff,
+ htonl(addr.s_addr) >> 16 & 0xff,
+ htonl(addr.s_addr) >> 8 & 0xff,
+ htonl(addr.s_addr) >> 0 & 0xff,
+ im->m_client->h.name
+ );
+ return 0;
+}
+
+
struct cache_detail ip_map_cache = {
.hash_size = IP_HASHMAX,
.hash_table = ip_table,
@@ -217,6 +247,7 @@ struct cache_detail ip_map_cache = {
.cache_put = ip_map_put,
.cache_request = ip_map_request,
.cache_parse = ip_map_parse,
+ .cache_show = ip_map_show,
};
static DefineSimpleCacheLookup(ip_map)
@@ -268,20 +299,17 @@ struct auth_domain *auth_unix_lookup(struct in_addr addr)
if (!ipm)
return NULL;
+ if (cache_check(&ip_map_cache, &ipm->h, NULL))
+ return NULL;
- if (test_bit(CACHE_VALID, &ipm->h.flags) &&
- (ipm->m_client->addr_changes - ipm->m_add_change) >0)
+ if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) {
set_bit(CACHE_NEGATIVE, &ipm->h.flags);
-
- if (!test_bit(CACHE_VALID, &ipm->h.flags))
- rv = NULL;
- else if (test_bit(CACHE_NEGATIVE, &ipm->h.flags))
rv = NULL;
- else {
+ } else {
rv = &ipm->m_client->h;
cache_get(&rv->h);
}
- if (ipm) ip_map_put(&ipm->h, &ip_map_cache);
+ ip_map_put(&ipm->h, &ip_map_cache);
return rv;
}
diff --git a/sound/sound_firmware.c b/sound/sound_firmware.c
index 49c122d62d7a..cfd9a322e463 100644
--- a/sound/sound_firmware.c
+++ b/sound/sound_firmware.c
@@ -7,7 +7,6 @@
#include <linux/unistd.h>
#include <asm/uaccess.h>
-static int errno;
static int do_mod_firmware_load(const char *fn, char **fp)
{
int fd;