diff options
64 files changed, 703 insertions, 486 deletions
diff --git a/Documentation/filesystems/9p.txt b/Documentation/filesystems/9p.txt index 43b89c214d20..4d075a4558f9 100644 --- a/Documentation/filesystems/9p.txt +++ b/Documentation/filesystems/9p.txt | |||
| @@ -73,8 +73,22 @@ OPTIONS | |||
| 73 | RESOURCES | 73 | RESOURCES |
| 74 | ========= | 74 | ========= |
| 75 | 75 | ||
| 76 | The Linux version of the 9p server is now maintained under the npfs project | 76 | Our current recommendation is to use Inferno (http://www.vitanuova.com/inferno) |
| 77 | on sourceforge (http://sourceforge.net/projects/npfs). | 77 | as the 9p server. You can start a 9p server under Inferno by issuing the |
| 78 | following command: | ||
| 79 | ; styxlisten -A tcp!*!564 export '#U*' | ||
| 80 | |||
| 81 | The -A specifies an unauthenticated export. The 564 is the port # (you may | ||
| 82 | have to choose a higher port number if running as a normal user). The '#U*' | ||
| 83 | specifies exporting the root of the Linux name space. You may specify a | ||
| 84 | subset of the namespace by extending the path: '#U*'/tmp would just export | ||
| 85 | /tmp. For more information, see the Inferno manual pages covering styxlisten | ||
| 86 | and export. | ||
| 87 | |||
| 88 | A Linux version of the 9p server is now maintained under the npfs project | ||
| 89 | on sourceforge (http://sourceforge.net/projects/npfs). There is also a | ||
| 90 | more stable single-threaded version of the server (named spfs) available from | ||
| 91 | the same CVS repository. | ||
| 78 | 92 | ||
| 79 | There are user and developer mailing lists available through the v9fs project | 93 | There are user and developer mailing lists available through the v9fs project |
| 80 | on sourceforge (http://sourceforge.net/projects/v9fs). | 94 | on sourceforge (http://sourceforge.net/projects/v9fs). |
| @@ -96,5 +110,5 @@ STATUS | |||
| 96 | 110 | ||
| 97 | The 2.6 kernel support is working on PPC and x86. | 111 | The 2.6 kernel support is working on PPC and x86. |
| 98 | 112 | ||
| 99 | PLEASE USE THE SOURCEFORGE BUG-TRACKER TO REPORT PROBLEMS. | 113 | PLEASE USE THE KERNEL BUGZILLA TO REPORT PROBLEMS. (http://bugzilla.kernel.org) |
| 100 | 114 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index d6f04a81f761..f0596e452c5c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -1137,9 +1137,9 @@ T: git kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git | |||
| 1137 | S: Maintained | 1137 | S: Maintained |
| 1138 | 1138 | ||
| 1139 | DSCC4 DRIVER | 1139 | DSCC4 DRIVER |
| 1140 | P: François Romieu | 1140 | P: Francois Romieu |
| 1141 | M: romieu@cogenit.fr | 1141 | M: romieu@fr.zoreil.com |
| 1142 | M: romieu@ensta.fr | 1142 | L: netdev@vger.kernel.org |
| 1143 | S: Maintained | 1143 | S: Maintained |
| 1144 | 1144 | ||
| 1145 | DVB SUBSYSTEM AND DRIVERS | 1145 | DVB SUBSYSTEM AND DRIVERS |
| @@ -1928,11 +1928,10 @@ S: Maintained | |||
| 1928 | 1928 | ||
| 1929 | KERNEL NFSD | 1929 | KERNEL NFSD |
| 1930 | P: Neil Brown | 1930 | P: Neil Brown |
| 1931 | M: neilb@cse.unsw.edu.au | 1931 | M: neilb@suse.de |
| 1932 | L: nfs@lists.sourceforge.net | 1932 | L: nfs@lists.sourceforge.net |
| 1933 | W: http://nfs.sourceforge.net/ | 1933 | W: http://nfs.sourceforge.net/ |
| 1934 | W: http://www.cse.unsw.edu.au/~neilb/patches/linux-devel/ | 1934 | S: Supported |
| 1935 | S: Maintained | ||
| 1936 | 1935 | ||
| 1937 | KERNEL VIRTUAL MACHINE (KVM) | 1936 | KERNEL VIRTUAL MACHINE (KVM) |
| 1938 | P: Avi Kivity | 1937 | P: Avi Kivity |
| @@ -2993,9 +2992,9 @@ SOFTWARE RAID (Multiple Disks) SUPPORT | |||
| 2993 | P: Ingo Molnar | 2992 | P: Ingo Molnar |
| 2994 | M: mingo@redhat.com | 2993 | M: mingo@redhat.com |
| 2995 | P: Neil Brown | 2994 | P: Neil Brown |
| 2996 | M: neilb@cse.unsw.edu.au | 2995 | M: neilb@suse.de |
| 2997 | L: linux-raid@vger.kernel.org | 2996 | L: linux-raid@vger.kernel.org |
| 2998 | S: Maintained | 2997 | S: Supported |
| 2999 | 2998 | ||
| 3000 | SOFTWARE SUSPEND: | 2999 | SOFTWARE SUSPEND: |
| 3001 | P: Pavel Machek | 3000 | P: Pavel Machek |
| @@ -3575,6 +3574,12 @@ M: khali@linux-fr.org | |||
| 3575 | L: i2c@lm-sensors.org | 3574 | L: i2c@lm-sensors.org |
| 3576 | S: Maintained | 3575 | S: Maintained |
| 3577 | 3576 | ||
| 3577 | VIA VELOCITY NETWORK DRIVER | ||
| 3578 | P: Francois Romieu | ||
| 3579 | M: romieu@fr.zoreil.com | ||
| 3580 | L: netdev@vger.kernel.org | ||
| 3581 | S: Maintained | ||
| 3582 | |||
| 3578 | UCLINUX (AND M68KNOMMU) | 3583 | UCLINUX (AND M68KNOMMU) |
| 3579 | P: Greg Ungerer | 3584 | P: Greg Ungerer |
| 3580 | M: gerg@uclinux.org | 3585 | M: gerg@uclinux.org |
| @@ -1,7 +1,7 @@ | |||
| 1 | VERSION = 2 | 1 | VERSION = 2 |
| 2 | PATCHLEVEL = 6 | 2 | PATCHLEVEL = 6 |
| 3 | SUBLEVEL = 20 | 3 | SUBLEVEL = 20 |
| 4 | EXTRAVERSION =-rc5 | 4 | EXTRAVERSION =-rc6 |
| 5 | NAME = Homicidal Dwarf Hamster | 5 | NAME = Homicidal Dwarf Hamster |
| 6 | 6 | ||
| 7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 06461b8b715d..5e47683fc63a 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S | |||
| @@ -302,12 +302,16 @@ sysenter_past_esp: | |||
| 302 | pushl $(__USER_CS) | 302 | pushl $(__USER_CS) |
| 303 | CFI_ADJUST_CFA_OFFSET 4 | 303 | CFI_ADJUST_CFA_OFFSET 4 |
| 304 | /*CFI_REL_OFFSET cs, 0*/ | 304 | /*CFI_REL_OFFSET cs, 0*/ |
| 305 | #ifndef CONFIG_COMPAT_VDSO | ||
| 305 | /* | 306 | /* |
| 306 | * Push current_thread_info()->sysenter_return to the stack. | 307 | * Push current_thread_info()->sysenter_return to the stack. |
| 307 | * A tiny bit of offset fixup is necessary - 4*4 means the 4 words | 308 | * A tiny bit of offset fixup is necessary - 4*4 means the 4 words |
| 308 | * pushed above; +8 corresponds to copy_thread's esp0 setting. | 309 | * pushed above; +8 corresponds to copy_thread's esp0 setting. |
| 309 | */ | 310 | */ |
| 310 | pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp) | 311 | pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp) |
| 312 | #else | ||
| 313 | pushl $SYSENTER_RETURN | ||
| 314 | #endif | ||
| 311 | CFI_ADJUST_CFA_OFFSET 4 | 315 | CFI_ADJUST_CFA_OFFSET 4 |
| 312 | CFI_REL_OFFSET eip, 0 | 316 | CFI_REL_OFFSET eip, 0 |
| 313 | 317 | ||
diff --git a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c index 7de9117b5a3a..5da744204d10 100644 --- a/arch/i386/kernel/sysenter.c +++ b/arch/i386/kernel/sysenter.c | |||
| @@ -79,11 +79,6 @@ int __init sysenter_setup(void) | |||
| 79 | #ifdef CONFIG_COMPAT_VDSO | 79 | #ifdef CONFIG_COMPAT_VDSO |
| 80 | __set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_READONLY); | 80 | __set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_READONLY); |
| 81 | printk("Compat vDSO mapped to %08lx.\n", __fix_to_virt(FIX_VDSO)); | 81 | printk("Compat vDSO mapped to %08lx.\n", __fix_to_virt(FIX_VDSO)); |
| 82 | #else | ||
| 83 | /* | ||
| 84 | * In the non-compat case the ELF coredumping code needs the fixmap: | ||
| 85 | */ | ||
| 86 | __set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_KERNEL_RO); | ||
| 87 | #endif | 82 | #endif |
| 88 | 83 | ||
| 89 | if (!boot_cpu_has(X86_FEATURE_SEP)) { | 84 | if (!boot_cpu_has(X86_FEATURE_SEP)) { |
| @@ -100,6 +95,7 @@ int __init sysenter_setup(void) | |||
| 100 | return 0; | 95 | return 0; |
| 101 | } | 96 | } |
| 102 | 97 | ||
| 98 | #ifndef CONFIG_COMPAT_VDSO | ||
| 103 | static struct page *syscall_nopage(struct vm_area_struct *vma, | 99 | static struct page *syscall_nopage(struct vm_area_struct *vma, |
| 104 | unsigned long adr, int *type) | 100 | unsigned long adr, int *type) |
| 105 | { | 101 | { |
| @@ -146,6 +142,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack) | |||
| 146 | vma->vm_end = addr + PAGE_SIZE; | 142 | vma->vm_end = addr + PAGE_SIZE; |
| 147 | /* MAYWRITE to allow gdb to COW and set breakpoints */ | 143 | /* MAYWRITE to allow gdb to COW and set breakpoints */ |
| 148 | vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE; | 144 | vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE; |
| 145 | /* | ||
| 146 | * Make sure the vDSO gets into every core dump. | ||
| 147 | * Dumping its contents makes post-mortem fully interpretable later | ||
| 148 | * without matching up the same kernel and hardware config to see | ||
| 149 | * what PC values meant. | ||
| 150 | */ | ||
| 151 | vma->vm_flags |= VM_ALWAYSDUMP; | ||
| 149 | vma->vm_flags |= mm->def_flags; | 152 | vma->vm_flags |= mm->def_flags; |
| 150 | vma->vm_page_prot = protection_map[vma->vm_flags & 7]; | 153 | vma->vm_page_prot = protection_map[vma->vm_flags & 7]; |
| 151 | vma->vm_ops = &syscall_vm_ops; | 154 | vma->vm_ops = &syscall_vm_ops; |
| @@ -187,3 +190,4 @@ int in_gate_area_no_task(unsigned long addr) | |||
| 187 | { | 190 | { |
| 188 | return 0; | 191 | return 0; |
| 189 | } | 192 | } |
| 193 | #endif | ||
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index a4b28c73bba0..ae0ede19879d 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c | |||
| @@ -284,6 +284,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, | |||
| 284 | * pages though | 284 | * pages though |
| 285 | */ | 285 | */ |
| 286 | vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC; | 286 | vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC; |
| 287 | /* | ||
| 288 | * Make sure the vDSO gets into every core dump. | ||
| 289 | * Dumping its contents makes post-mortem fully interpretable later | ||
| 290 | * without matching up the same kernel and hardware config to see | ||
| 291 | * what PC values meant. | ||
| 292 | */ | ||
| 293 | vma->vm_flags |= VM_ALWAYSDUMP; | ||
| 287 | vma->vm_flags |= mm->def_flags; | 294 | vma->vm_flags |= mm->def_flags; |
| 288 | vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; | 295 | vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; |
| 289 | vma->vm_ops = &vdso_vmops; | 296 | vma->vm_ops = &vdso_vmops; |
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index f191a550a079..77558a88a2fe 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 | |||
| @@ -19,22 +19,22 @@ config SEMAPHORE_SLEEPERS | |||
| 19 | choice | 19 | choice |
| 20 | prompt "Host memory split" | 20 | prompt "Host memory split" |
| 21 | default HOST_VMSPLIT_3G | 21 | default HOST_VMSPLIT_3G |
| 22 | ---help--- | 22 | help |
| 23 | This is needed when the host kernel on which you run has a non-default | 23 | This is needed when the host kernel on which you run has a non-default |
| 24 | (like 2G/2G) memory split, instead of the customary 3G/1G. If you did | 24 | (like 2G/2G) memory split, instead of the customary 3G/1G. If you did |
| 25 | not recompile your own kernel but use the default distro's one, you can | 25 | not recompile your own kernel but use the default distro's one, you can |
| 26 | safely accept the "Default split" option. | 26 | safely accept the "Default split" option. |
| 27 | 27 | ||
| 28 | It can be enabled on recent (>=2.6.16-rc2) vanilla kernels via | 28 | It can be enabled on recent (>=2.6.16-rc2) vanilla kernels via |
| 29 | CONFIG_VM_SPLIT_*, or on previous kernels with special patches (-ck | 29 | CONFIG_VM_SPLIT_*, or on previous kernels with special patches (-ck |
| 30 | patchset by Con Kolivas, or other ones) - option names match closely the | 30 | patchset by Con Kolivas, or other ones) - option names match closely the |
| 31 | host CONFIG_VM_SPLIT_* ones. | 31 | host CONFIG_VM_SPLIT_* ones. |
| 32 | 32 | ||
| 33 | A lower setting (where 1G/3G is lowest and 3G/1G is higher) will | 33 | A lower setting (where 1G/3G is lowest and 3G/1G is higher) will |
| 34 | tolerate even more "normal" host kernels, but an higher setting will be | 34 | tolerate even more "normal" host kernels, but an higher setting will be |
| 35 | stricter. | 35 | stricter. |
| 36 | 36 | ||
| 37 | So, if you do not know what to do here, say 'Default split'. | 37 | So, if you do not know what to do here, say 'Default split'. |
| 38 | 38 | ||
| 39 | config HOST_VMSPLIT_3G | 39 | config HOST_VMSPLIT_3G |
| 40 | bool "Default split (3G/1G user/kernel host split)" | 40 | bool "Default split (3G/1G user/kernel host split)" |
| @@ -67,13 +67,13 @@ config 3_LEVEL_PGTABLES | |||
| 67 | 67 | ||
| 68 | config STUB_CODE | 68 | config STUB_CODE |
| 69 | hex | 69 | hex |
| 70 | default 0xbfffe000 if !HOST_2G_2G | 70 | default 0xbfffe000 if !HOST_VMSPLIT_2G |
| 71 | default 0x7fffe000 if HOST_2G_2G | 71 | default 0x7fffe000 if HOST_VMSPLIT_2G |
| 72 | 72 | ||
| 73 | config STUB_DATA | 73 | config STUB_DATA |
| 74 | hex | 74 | hex |
| 75 | default 0xbffff000 if !HOST_2G_2G | 75 | default 0xbffff000 if !HOST_VMSPLIT_2G |
| 76 | default 0x7ffff000 if HOST_2G_2G | 76 | default 0x7ffff000 if HOST_VMSPLIT_2G |
| 77 | 77 | ||
| 78 | config STUB_START | 78 | config STUB_START |
| 79 | hex | 79 | hex |
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index 543ef4f405e9..5ce0bd486bbf 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c | |||
| @@ -64,55 +64,6 @@ typedef unsigned int elf_greg_t; | |||
| 64 | #define ELF_NGREG (sizeof (struct user_regs_struct32) / sizeof(elf_greg_t)) | 64 | #define ELF_NGREG (sizeof (struct user_regs_struct32) / sizeof(elf_greg_t)) |
| 65 | typedef elf_greg_t elf_gregset_t[ELF_NGREG]; | 65 | typedef elf_greg_t elf_gregset_t[ELF_NGREG]; |
| 66 | 66 | ||
| 67 | /* | ||
| 68 | * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out | ||
| 69 | * extra segments containing the vsyscall DSO contents. Dumping its | ||
| 70 | * contents makes post-mortem fully interpretable later without matching up | ||
| 71 | * the same kernel and hardware config to see what PC values meant. | ||
| 72 | * Dumping its extra ELF program headers includes all the other information | ||
| 73 | * a debugger needs to easily find how the vsyscall DSO was being used. | ||
| 74 | */ | ||
| 75 | #define ELF_CORE_EXTRA_PHDRS (find_vma(current->mm, VSYSCALL32_BASE) ? \ | ||
| 76 | (VSYSCALL32_EHDR->e_phnum) : 0) | ||
| 77 | #define ELF_CORE_WRITE_EXTRA_PHDRS \ | ||
| 78 | do { \ | ||
| 79 | if (find_vma(current->mm, VSYSCALL32_BASE)) { \ | ||
| 80 | const struct elf32_phdr *const vsyscall_phdrs = \ | ||
| 81 | (const struct elf32_phdr *) (VSYSCALL32_BASE \ | ||
| 82 | + VSYSCALL32_EHDR->e_phoff);\ | ||
| 83 | int i; \ | ||
| 84 | Elf32_Off ofs = 0; \ | ||
| 85 | for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \ | ||
| 86 | struct elf32_phdr phdr = vsyscall_phdrs[i]; \ | ||
| 87 | if (phdr.p_type == PT_LOAD) { \ | ||
| 88 | BUG_ON(ofs != 0); \ | ||
| 89 | ofs = phdr.p_offset = offset; \ | ||
| 90 | phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \ | ||
| 91 | phdr.p_filesz = phdr.p_memsz; \ | ||
| 92 | offset += phdr.p_filesz; \ | ||
| 93 | } \ | ||
| 94 | else \ | ||
| 95 | phdr.p_offset += ofs; \ | ||
| 96 | phdr.p_paddr = 0; /* match other core phdrs */ \ | ||
| 97 | DUMP_WRITE(&phdr, sizeof(phdr)); \ | ||
| 98 | } \ | ||
| 99 | } \ | ||
| 100 | } while (0) | ||
| 101 | #define ELF_CORE_WRITE_EXTRA_DATA \ | ||
| 102 | do { \ | ||
| 103 | if (find_vma(current->mm, VSYSCALL32_BASE)) { \ | ||
| 104 | const struct elf32_phdr *const vsyscall_phdrs = \ | ||
| 105 | (const struct elf32_phdr *) (VSYSCALL32_BASE \ | ||
| 106 | + VSYSCALL32_EHDR->e_phoff); \ | ||
| 107 | int i; \ | ||
| 108 | for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \ | ||
| 109 | if (vsyscall_phdrs[i].p_type == PT_LOAD) \ | ||
| 110 | DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr,\ | ||
| 111 | PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \ | ||
| 112 | } \ | ||
| 113 | } \ | ||
| 114 | } while (0) | ||
| 115 | |||
| 116 | struct elf_siginfo | 67 | struct elf_siginfo |
| 117 | { | 68 | { |
| 118 | int si_signo; /* signal number */ | 69 | int si_signo; /* signal number */ |
diff --git a/arch/x86_64/ia32/syscall32.c b/arch/x86_64/ia32/syscall32.c index 3e5ed20cba45..59f1fa155915 100644 --- a/arch/x86_64/ia32/syscall32.c +++ b/arch/x86_64/ia32/syscall32.c | |||
| @@ -59,6 +59,13 @@ int syscall32_setup_pages(struct linux_binprm *bprm, int exstack) | |||
| 59 | vma->vm_end = VSYSCALL32_END; | 59 | vma->vm_end = VSYSCALL32_END; |
| 60 | /* MAYWRITE to allow gdb to COW and set breakpoints */ | 60 | /* MAYWRITE to allow gdb to COW and set breakpoints */ |
| 61 | vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE; | 61 | vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE; |
| 62 | /* | ||
| 63 | * Make sure the vDSO gets into every core dump. | ||
| 64 | * Dumping its contents makes post-mortem fully interpretable later | ||
| 65 | * without matching up the same kernel and hardware config to see | ||
| 66 | * what PC values meant. | ||
| 67 | */ | ||
| 68 | vma->vm_flags |= VM_ALWAYSDUMP; | ||
| 62 | vma->vm_flags |= mm->def_flags; | 69 | vma->vm_flags |= mm->def_flags; |
| 63 | vma->vm_page_prot = protection_map[vma->vm_flags & 7]; | 70 | vma->vm_page_prot = protection_map[vma->vm_flags & 7]; |
| 64 | vma->vm_ops = &syscall32_vm_ops; | 71 | vma->vm_ops = &syscall32_vm_ops; |
| @@ -75,6 +82,14 @@ int syscall32_setup_pages(struct linux_binprm *bprm, int exstack) | |||
| 75 | return 0; | 82 | return 0; |
| 76 | } | 83 | } |
| 77 | 84 | ||
| 85 | const char *arch_vma_name(struct vm_area_struct *vma) | ||
| 86 | { | ||
| 87 | if (vma->vm_start == VSYSCALL32_BASE && | ||
| 88 | vma->vm_mm && vma->vm_mm->task_size == IA32_PAGE_OFFSET) | ||
| 89 | return "[vdso]"; | ||
| 90 | return NULL; | ||
| 91 | } | ||
| 92 | |||
| 78 | static int __init init_syscall32(void) | 93 | static int __init init_syscall32(void) |
| 79 | { | 94 | { |
| 80 | syscall32_page = (void *)get_zeroed_page(GFP_KERNEL); | 95 | syscall32_page = (void *)get_zeroed_page(GFP_KERNEL); |
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 5207f9e4b443..cbb6f0814ce2 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
| @@ -322,10 +322,6 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr) | |||
| 322 | if (result) | 322 | if (result) |
| 323 | return result; | 323 | return result; |
| 324 | 324 | ||
| 325 | result = acpi_processor_get_platform_limit(pr); | ||
| 326 | if (result) | ||
| 327 | return result; | ||
| 328 | |||
| 329 | return 0; | 325 | return 0; |
| 330 | } | 326 | } |
| 331 | 327 | ||
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 5ab5e393b882..c6281ccd4fe7 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c | |||
| @@ -122,8 +122,6 @@ struct efivar_entry { | |||
| 122 | struct kobject kobj; | 122 | struct kobject kobj; |
| 123 | }; | 123 | }; |
| 124 | 124 | ||
| 125 | #define get_efivar_entry(n) list_entry(n, struct efivar_entry, list) | ||
| 126 | |||
| 127 | struct efivar_attribute { | 125 | struct efivar_attribute { |
| 128 | struct attribute attr; | 126 | struct attribute attr; |
| 129 | ssize_t (*show) (struct efivar_entry *entry, char *buf); | 127 | ssize_t (*show) (struct efivar_entry *entry, char *buf); |
| @@ -386,9 +384,6 @@ static struct sysfs_ops efivar_attr_ops = { | |||
| 386 | static void efivar_release(struct kobject *kobj) | 384 | static void efivar_release(struct kobject *kobj) |
| 387 | { | 385 | { |
| 388 | struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj); | 386 | struct efivar_entry *var = container_of(kobj, struct efivar_entry, kobj); |
| 389 | spin_lock(&efivars_lock); | ||
| 390 | list_del(&var->list); | ||
| 391 | spin_unlock(&efivars_lock); | ||
| 392 | kfree(var); | 387 | kfree(var); |
| 393 | } | 388 | } |
| 394 | 389 | ||
| @@ -430,9 +425,8 @@ static ssize_t | |||
| 430 | efivar_create(struct subsystem *sub, const char *buf, size_t count) | 425 | efivar_create(struct subsystem *sub, const char *buf, size_t count) |
| 431 | { | 426 | { |
| 432 | struct efi_variable *new_var = (struct efi_variable *)buf; | 427 | struct efi_variable *new_var = (struct efi_variable *)buf; |
| 433 | struct efivar_entry *search_efivar = NULL; | 428 | struct efivar_entry *search_efivar, *n; |
| 434 | unsigned long strsize1, strsize2; | 429 | unsigned long strsize1, strsize2; |
| 435 | struct list_head *pos, *n; | ||
| 436 | efi_status_t status = EFI_NOT_FOUND; | 430 | efi_status_t status = EFI_NOT_FOUND; |
| 437 | int found = 0; | 431 | int found = 0; |
| 438 | 432 | ||
| @@ -444,8 +438,7 @@ efivar_create(struct subsystem *sub, const char *buf, size_t count) | |||
| 444 | /* | 438 | /* |
| 445 | * Does this variable already exist? | 439 | * Does this variable already exist? |
| 446 | */ | 440 | */ |
| 447 | list_for_each_safe(pos, n, &efivar_list) { | 441 | list_for_each_entry_safe(search_efivar, n, &efivar_list, list) { |
| 448 | search_efivar = get_efivar_entry(pos); | ||
| 449 | strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024); | 442 | strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024); |
| 450 | strsize2 = utf8_strsize(new_var->VariableName, 1024); | 443 | strsize2 = utf8_strsize(new_var->VariableName, 1024); |
| 451 | if (strsize1 == strsize2 && | 444 | if (strsize1 == strsize2 && |
| @@ -490,9 +483,8 @@ static ssize_t | |||
| 490 | efivar_delete(struct subsystem *sub, const char *buf, size_t count) | 483 | efivar_delete(struct subsystem *sub, const char *buf, size_t count) |
| 491 | { | 484 | { |
| 492 | struct efi_variable *del_var = (struct efi_variable *)buf; | 485 | struct efi_variable *del_var = (struct efi_variable *)buf; |
| 493 | struct efivar_entry *search_efivar = NULL; | 486 | struct efivar_entry *search_efivar, *n; |
| 494 | unsigned long strsize1, strsize2; | 487 | unsigned long strsize1, strsize2; |
| 495 | struct list_head *pos, *n; | ||
| 496 | efi_status_t status = EFI_NOT_FOUND; | 488 | efi_status_t status = EFI_NOT_FOUND; |
| 497 | int found = 0; | 489 | int found = 0; |
| 498 | 490 | ||
| @@ -504,8 +496,7 @@ efivar_delete(struct subsystem *sub, const char *buf, size_t count) | |||
| 504 | /* | 496 | /* |
| 505 | * Does this variable already exist? | 497 | * Does this variable already exist? |
| 506 | */ | 498 | */ |
| 507 | list_for_each_safe(pos, n, &efivar_list) { | 499 | list_for_each_entry_safe(search_efivar, n, &efivar_list, list) { |
| 508 | search_efivar = get_efivar_entry(pos); | ||
| 509 | strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024); | 500 | strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024); |
| 510 | strsize2 = utf8_strsize(del_var->VariableName, 1024); | 501 | strsize2 = utf8_strsize(del_var->VariableName, 1024); |
| 511 | if (strsize1 == strsize2 && | 502 | if (strsize1 == strsize2 && |
| @@ -537,9 +528,9 @@ efivar_delete(struct subsystem *sub, const char *buf, size_t count) | |||
| 537 | spin_unlock(&efivars_lock); | 528 | spin_unlock(&efivars_lock); |
| 538 | return -EIO; | 529 | return -EIO; |
| 539 | } | 530 | } |
| 531 | list_del(&search_efivar->list); | ||
| 540 | /* We need to release this lock before unregistering. */ | 532 | /* We need to release this lock before unregistering. */ |
| 541 | spin_unlock(&efivars_lock); | 533 | spin_unlock(&efivars_lock); |
| 542 | |||
| 543 | efivar_unregister(search_efivar); | 534 | efivar_unregister(search_efivar); |
| 544 | 535 | ||
| 545 | /* It's dead Jim.... */ | 536 | /* It's dead Jim.... */ |
| @@ -768,10 +759,14 @@ out_free: | |||
| 768 | static void __exit | 759 | static void __exit |
| 769 | efivars_exit(void) | 760 | efivars_exit(void) |
| 770 | { | 761 | { |
| 771 | struct list_head *pos, *n; | 762 | struct efivar_entry *entry, *n; |
| 772 | 763 | ||
| 773 | list_for_each_safe(pos, n, &efivar_list) | 764 | list_for_each_entry_safe(entry, n, &efivar_list, list) { |
| 774 | efivar_unregister(get_efivar_entry(pos)); | 765 | spin_lock(&efivars_lock); |
| 766 | list_del(&entry->list); | ||
| 767 | spin_unlock(&efivars_lock); | ||
| 768 | efivar_unregister(entry); | ||
| 769 | } | ||
| 775 | 770 | ||
| 776 | subsystem_unregister(&vars_subsys); | 771 | subsystem_unregister(&vars_subsys); |
| 777 | firmware_unregister(&efi_subsys); | 772 | firmware_unregister(&efi_subsys); |
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 95eff3b2917a..4f75cce6fdff 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c | |||
| @@ -356,16 +356,17 @@ static struct cardstate *alloc_cs(struct gigaset_driver *drv) | |||
| 356 | { | 356 | { |
| 357 | unsigned long flags; | 357 | unsigned long flags; |
| 358 | unsigned i; | 358 | unsigned i; |
| 359 | static struct cardstate *ret = NULL; | 359 | struct cardstate *ret = NULL; |
| 360 | 360 | ||
| 361 | spin_lock_irqsave(&drv->lock, flags); | 361 | spin_lock_irqsave(&drv->lock, flags); |
| 362 | for (i = 0; i < drv->minors; ++i) { | 362 | for (i = 0; i < drv->minors; ++i) { |
| 363 | if (!(drv->flags[i] & VALID_MINOR)) { | 363 | if (!(drv->flags[i] & VALID_MINOR)) { |
| 364 | drv->flags[i] = VALID_MINOR; | 364 | if (try_module_get(drv->owner)) { |
| 365 | ret = drv->cs + i; | 365 | drv->flags[i] = VALID_MINOR; |
| 366 | } | 366 | ret = drv->cs + i; |
| 367 | if (ret) | 367 | } |
| 368 | break; | 368 | break; |
| 369 | } | ||
| 369 | } | 370 | } |
| 370 | spin_unlock_irqrestore(&drv->lock, flags); | 371 | spin_unlock_irqrestore(&drv->lock, flags); |
| 371 | return ret; | 372 | return ret; |
| @@ -376,6 +377,8 @@ static void free_cs(struct cardstate *cs) | |||
| 376 | unsigned long flags; | 377 | unsigned long flags; |
| 377 | struct gigaset_driver *drv = cs->driver; | 378 | struct gigaset_driver *drv = cs->driver; |
| 378 | spin_lock_irqsave(&drv->lock, flags); | 379 | spin_lock_irqsave(&drv->lock, flags); |
| 380 | if (drv->flags[cs->minor_index] & VALID_MINOR) | ||
| 381 | module_put(drv->owner); | ||
| 379 | drv->flags[cs->minor_index] = 0; | 382 | drv->flags[cs->minor_index] = 0; |
| 380 | spin_unlock_irqrestore(&drv->lock, flags); | 383 | spin_unlock_irqrestore(&drv->lock, flags); |
| 381 | } | 384 | } |
| @@ -579,7 +582,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, | |||
| 579 | } else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) | 582 | } else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) |
| 580 | skb_reserve(bcs->skb, HW_HDR_LEN); | 583 | skb_reserve(bcs->skb, HW_HDR_LEN); |
| 581 | else { | 584 | else { |
| 582 | warn("could not allocate skb\n"); | 585 | warn("could not allocate skb"); |
| 583 | bcs->inputstate |= INS_skip_frame; | 586 | bcs->inputstate |= INS_skip_frame; |
| 584 | } | 587 | } |
| 585 | 588 | ||
| @@ -632,17 +635,25 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
| 632 | int i; | 635 | int i; |
| 633 | 636 | ||
| 634 | gig_dbg(DEBUG_INIT, "allocating cs"); | 637 | gig_dbg(DEBUG_INIT, "allocating cs"); |
| 635 | cs = alloc_cs(drv); | 638 | if (!(cs = alloc_cs(drv))) { |
| 636 | if (!cs) | 639 | err("maximum number of devices exceeded"); |
| 637 | goto error; | 640 | return NULL; |
| 641 | } | ||
| 642 | mutex_init(&cs->mutex); | ||
| 643 | mutex_lock(&cs->mutex); | ||
| 644 | |||
| 638 | gig_dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1); | 645 | gig_dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1); |
| 639 | cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL); | 646 | cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL); |
| 640 | if (!cs->bcs) | 647 | if (!cs->bcs) { |
| 648 | err("out of memory"); | ||
| 641 | goto error; | 649 | goto error; |
| 650 | } | ||
| 642 | gig_dbg(DEBUG_INIT, "allocating inbuf"); | 651 | gig_dbg(DEBUG_INIT, "allocating inbuf"); |
| 643 | cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL); | 652 | cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL); |
| 644 | if (!cs->inbuf) | 653 | if (!cs->inbuf) { |
| 654 | err("out of memory"); | ||
| 645 | goto error; | 655 | goto error; |
| 656 | } | ||
| 646 | 657 | ||
| 647 | cs->cs_init = 0; | 658 | cs->cs_init = 0; |
| 648 | cs->channels = channels; | 659 | cs->channels = channels; |
| @@ -654,8 +665,6 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
| 654 | spin_lock_init(&cs->ev_lock); | 665 | spin_lock_init(&cs->ev_lock); |
| 655 | cs->ev_tail = 0; | 666 | cs->ev_tail = 0; |
| 656 | cs->ev_head = 0; | 667 | cs->ev_head = 0; |
| 657 | mutex_init(&cs->mutex); | ||
| 658 | mutex_lock(&cs->mutex); | ||
| 659 | 668 | ||
| 660 | tasklet_init(&cs->event_tasklet, &gigaset_handle_event, | 669 | tasklet_init(&cs->event_tasklet, &gigaset_handle_event, |
| 661 | (unsigned long) cs); | 670 | (unsigned long) cs); |
| @@ -684,8 +693,10 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
| 684 | 693 | ||
| 685 | for (i = 0; i < channels; ++i) { | 694 | for (i = 0; i < channels; ++i) { |
| 686 | gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i); | 695 | gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i); |
| 687 | if (!gigaset_initbcs(cs->bcs + i, cs, i)) | 696 | if (!gigaset_initbcs(cs->bcs + i, cs, i)) { |
| 697 | err("could not allocate channel %d data", i); | ||
| 688 | goto error; | 698 | goto error; |
| 699 | } | ||
| 689 | } | 700 | } |
| 690 | 701 | ||
| 691 | ++cs->cs_init; | 702 | ++cs->cs_init; |
| @@ -720,8 +731,10 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
| 720 | make_valid(cs, VALID_ID); | 731 | make_valid(cs, VALID_ID); |
| 721 | ++cs->cs_init; | 732 | ++cs->cs_init; |
| 722 | gig_dbg(DEBUG_INIT, "setting up hw"); | 733 | gig_dbg(DEBUG_INIT, "setting up hw"); |
| 723 | if (!cs->ops->initcshw(cs)) | 734 | if (!cs->ops->initcshw(cs)) { |
| 735 | err("could not allocate device specific data"); | ||
| 724 | goto error; | 736 | goto error; |
| 737 | } | ||
| 725 | 738 | ||
| 726 | ++cs->cs_init; | 739 | ++cs->cs_init; |
| 727 | 740 | ||
| @@ -743,8 +756,8 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
| 743 | mutex_unlock(&cs->mutex); | 756 | mutex_unlock(&cs->mutex); |
| 744 | return cs; | 757 | return cs; |
| 745 | 758 | ||
| 746 | error: if (cs) | 759 | error: |
| 747 | mutex_unlock(&cs->mutex); | 760 | mutex_unlock(&cs->mutex); |
| 748 | gig_dbg(DEBUG_INIT, "failed"); | 761 | gig_dbg(DEBUG_INIT, "failed"); |
| 749 | gigaset_freecs(cs); | 762 | gigaset_freecs(cs); |
| 750 | return NULL; | 763 | return NULL; |
| @@ -1040,7 +1053,6 @@ void gigaset_freedriver(struct gigaset_driver *drv) | |||
| 1040 | spin_unlock_irqrestore(&driver_lock, flags); | 1053 | spin_unlock_irqrestore(&driver_lock, flags); |
| 1041 | 1054 | ||
| 1042 | gigaset_if_freedriver(drv); | 1055 | gigaset_if_freedriver(drv); |
| 1043 | module_put(drv->owner); | ||
| 1044 | 1056 | ||
| 1045 | kfree(drv->cs); | 1057 | kfree(drv->cs); |
| 1046 | kfree(drv->flags); | 1058 | kfree(drv->flags); |
| @@ -1072,10 +1084,6 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, | |||
| 1072 | if (!drv) | 1084 | if (!drv) |
| 1073 | return NULL; | 1085 | return NULL; |
| 1074 | 1086 | ||
| 1075 | if (!try_module_get(owner)) | ||
| 1076 | goto out1; | ||
| 1077 | |||
| 1078 | drv->cs = NULL; | ||
| 1079 | drv->have_tty = 0; | 1087 | drv->have_tty = 0; |
| 1080 | drv->minor = minor; | 1088 | drv->minor = minor; |
| 1081 | drv->minors = minors; | 1089 | drv->minors = minors; |
| @@ -1087,11 +1095,11 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, | |||
| 1087 | 1095 | ||
| 1088 | drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL); | 1096 | drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL); |
| 1089 | if (!drv->cs) | 1097 | if (!drv->cs) |
| 1090 | goto out2; | 1098 | goto error; |
| 1091 | 1099 | ||
| 1092 | drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL); | 1100 | drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL); |
| 1093 | if (!drv->flags) | 1101 | if (!drv->flags) |
| 1094 | goto out3; | 1102 | goto error; |
| 1095 | 1103 | ||
| 1096 | for (i = 0; i < minors; ++i) { | 1104 | for (i = 0; i < minors; ++i) { |
| 1097 | drv->flags[i] = 0; | 1105 | drv->flags[i] = 0; |
| @@ -1108,11 +1116,8 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, | |||
| 1108 | 1116 | ||
| 1109 | return drv; | 1117 | return drv; |
| 1110 | 1118 | ||
| 1111 | out3: | 1119 | error: |
| 1112 | kfree(drv->cs); | 1120 | kfree(drv->cs); |
| 1113 | out2: | ||
| 1114 | module_put(owner); | ||
| 1115 | out1: | ||
| 1116 | kfree(drv); | 1121 | kfree(drv); |
| 1117 | return NULL; | 1122 | return NULL; |
| 1118 | } | 1123 | } |
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index 91e0c75aca8f..2db1ca4c6800 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h | |||
| @@ -242,6 +242,7 @@ struct kvm_vcpu { | |||
| 242 | u64 pdptrs[4]; /* pae */ | 242 | u64 pdptrs[4]; /* pae */ |
| 243 | u64 shadow_efer; | 243 | u64 shadow_efer; |
| 244 | u64 apic_base; | 244 | u64 apic_base; |
| 245 | u64 ia32_misc_enable_msr; | ||
| 245 | int nmsrs; | 246 | int nmsrs; |
| 246 | struct vmx_msr_entry *guest_msrs; | 247 | struct vmx_msr_entry *guest_msrs; |
| 247 | struct vmx_msr_entry *host_msrs; | 248 | struct vmx_msr_entry *host_msrs; |
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index be4651abe72c..b10972ed0c9f 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
| @@ -1226,6 +1226,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) | |||
| 1226 | case MSR_IA32_APICBASE: | 1226 | case MSR_IA32_APICBASE: |
| 1227 | data = vcpu->apic_base; | 1227 | data = vcpu->apic_base; |
| 1228 | break; | 1228 | break; |
| 1229 | case MSR_IA32_MISC_ENABLE: | ||
| 1230 | data = vcpu->ia32_misc_enable_msr; | ||
| 1231 | break; | ||
| 1229 | #ifdef CONFIG_X86_64 | 1232 | #ifdef CONFIG_X86_64 |
| 1230 | case MSR_EFER: | 1233 | case MSR_EFER: |
| 1231 | data = vcpu->shadow_efer; | 1234 | data = vcpu->shadow_efer; |
| @@ -1297,6 +1300,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) | |||
| 1297 | case MSR_IA32_APICBASE: | 1300 | case MSR_IA32_APICBASE: |
| 1298 | vcpu->apic_base = data; | 1301 | vcpu->apic_base = data; |
| 1299 | break; | 1302 | break; |
| 1303 | case MSR_IA32_MISC_ENABLE: | ||
| 1304 | vcpu->ia32_misc_enable_msr = data; | ||
| 1305 | break; | ||
| 1300 | default: | 1306 | default: |
| 1301 | printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr); | 1307 | printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr); |
| 1302 | return 1; | 1308 | return 1; |
| @@ -1600,6 +1606,10 @@ static u32 msrs_to_save[] = { | |||
| 1600 | 1606 | ||
| 1601 | static unsigned num_msrs_to_save; | 1607 | static unsigned num_msrs_to_save; |
| 1602 | 1608 | ||
| 1609 | static u32 emulated_msrs[] = { | ||
| 1610 | MSR_IA32_MISC_ENABLE, | ||
| 1611 | }; | ||
| 1612 | |||
| 1603 | static __init void kvm_init_msr_list(void) | 1613 | static __init void kvm_init_msr_list(void) |
| 1604 | { | 1614 | { |
| 1605 | u32 dummy[2]; | 1615 | u32 dummy[2]; |
| @@ -1925,7 +1935,7 @@ static long kvm_dev_ioctl(struct file *filp, | |||
| 1925 | if (copy_from_user(&msr_list, user_msr_list, sizeof msr_list)) | 1935 | if (copy_from_user(&msr_list, user_msr_list, sizeof msr_list)) |
| 1926 | goto out; | 1936 | goto out; |
| 1927 | n = msr_list.nmsrs; | 1937 | n = msr_list.nmsrs; |
| 1928 | msr_list.nmsrs = num_msrs_to_save; | 1938 | msr_list.nmsrs = num_msrs_to_save + ARRAY_SIZE(emulated_msrs); |
| 1929 | if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list)) | 1939 | if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list)) |
| 1930 | goto out; | 1940 | goto out; |
| 1931 | r = -E2BIG; | 1941 | r = -E2BIG; |
| @@ -1935,6 +1945,11 @@ static long kvm_dev_ioctl(struct file *filp, | |||
| 1935 | if (copy_to_user(user_msr_list->indices, &msrs_to_save, | 1945 | if (copy_to_user(user_msr_list->indices, &msrs_to_save, |
| 1936 | num_msrs_to_save * sizeof(u32))) | 1946 | num_msrs_to_save * sizeof(u32))) |
| 1937 | goto out; | 1947 | goto out; |
| 1948 | if (copy_to_user(user_msr_list->indices | ||
| 1949 | + num_msrs_to_save * sizeof(u32), | ||
| 1950 | &emulated_msrs, | ||
| 1951 | ARRAY_SIZE(emulated_msrs) * sizeof(u32))) | ||
| 1952 | goto out; | ||
| 1938 | r = 0; | 1953 | r = 0; |
| 1939 | break; | 1954 | break; |
| 1940 | } | 1955 | } |
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c index c6f972914f08..22c426cd8cb2 100644 --- a/drivers/kvm/mmu.c +++ b/drivers/kvm/mmu.c | |||
| @@ -143,6 +143,7 @@ static int dbg = 1; | |||
| 143 | #define PFERR_PRESENT_MASK (1U << 0) | 143 | #define PFERR_PRESENT_MASK (1U << 0) |
| 144 | #define PFERR_WRITE_MASK (1U << 1) | 144 | #define PFERR_WRITE_MASK (1U << 1) |
| 145 | #define PFERR_USER_MASK (1U << 2) | 145 | #define PFERR_USER_MASK (1U << 2) |
| 146 | #define PFERR_FETCH_MASK (1U << 4) | ||
| 146 | 147 | ||
| 147 | #define PT64_ROOT_LEVEL 4 | 148 | #define PT64_ROOT_LEVEL 4 |
| 148 | #define PT32_ROOT_LEVEL 2 | 149 | #define PT32_ROOT_LEVEL 2 |
| @@ -168,6 +169,11 @@ static int is_cpuid_PSE36(void) | |||
| 168 | return 1; | 169 | return 1; |
| 169 | } | 170 | } |
| 170 | 171 | ||
| 172 | static int is_nx(struct kvm_vcpu *vcpu) | ||
| 173 | { | ||
| 174 | return vcpu->shadow_efer & EFER_NX; | ||
| 175 | } | ||
| 176 | |||
| 171 | static int is_present_pte(unsigned long pte) | 177 | static int is_present_pte(unsigned long pte) |
| 172 | { | 178 | { |
| 173 | return pte & PT_PRESENT_MASK; | 179 | return pte & PT_PRESENT_MASK; |
| @@ -992,16 +998,6 @@ static inline int fix_read_pf(u64 *shadow_ent) | |||
| 992 | return 0; | 998 | return 0; |
| 993 | } | 999 | } |
| 994 | 1000 | ||
| 995 | static int may_access(u64 pte, int write, int user) | ||
| 996 | { | ||
| 997 | |||
| 998 | if (user && !(pte & PT_USER_MASK)) | ||
| 999 | return 0; | ||
| 1000 | if (write && !(pte & PT_WRITABLE_MASK)) | ||
| 1001 | return 0; | ||
| 1002 | return 1; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | static void paging_free(struct kvm_vcpu *vcpu) | 1001 | static void paging_free(struct kvm_vcpu *vcpu) |
| 1006 | { | 1002 | { |
| 1007 | nonpaging_free(vcpu); | 1003 | nonpaging_free(vcpu); |
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h index 6bc41950fbb3..149fa45fd9a5 100644 --- a/drivers/kvm/paging_tmpl.h +++ b/drivers/kvm/paging_tmpl.h | |||
| @@ -63,13 +63,15 @@ struct guest_walker { | |||
| 63 | pt_element_t *ptep; | 63 | pt_element_t *ptep; |
| 64 | pt_element_t inherited_ar; | 64 | pt_element_t inherited_ar; |
| 65 | gfn_t gfn; | 65 | gfn_t gfn; |
| 66 | u32 error_code; | ||
| 66 | }; | 67 | }; |
| 67 | 68 | ||
| 68 | /* | 69 | /* |
| 69 | * Fetch a guest pte for a guest virtual address | 70 | * Fetch a guest pte for a guest virtual address |
| 70 | */ | 71 | */ |
| 71 | static void FNAME(walk_addr)(struct guest_walker *walker, | 72 | static int FNAME(walk_addr)(struct guest_walker *walker, |
| 72 | struct kvm_vcpu *vcpu, gva_t addr) | 73 | struct kvm_vcpu *vcpu, gva_t addr, |
| 74 | int write_fault, int user_fault, int fetch_fault) | ||
| 73 | { | 75 | { |
| 74 | hpa_t hpa; | 76 | hpa_t hpa; |
| 75 | struct kvm_memory_slot *slot; | 77 | struct kvm_memory_slot *slot; |
| @@ -86,7 +88,7 @@ static void FNAME(walk_addr)(struct guest_walker *walker, | |||
| 86 | walker->ptep = &vcpu->pdptrs[(addr >> 30) & 3]; | 88 | walker->ptep = &vcpu->pdptrs[(addr >> 30) & 3]; |
| 87 | root = *walker->ptep; | 89 | root = *walker->ptep; |
| 88 | if (!(root & PT_PRESENT_MASK)) | 90 | if (!(root & PT_PRESENT_MASK)) |
| 89 | return; | 91 | goto not_present; |
| 90 | --walker->level; | 92 | --walker->level; |
| 91 | } | 93 | } |
| 92 | #endif | 94 | #endif |
| @@ -111,11 +113,23 @@ static void FNAME(walk_addr)(struct guest_walker *walker, | |||
| 111 | ASSERT(((unsigned long)walker->table & PAGE_MASK) == | 113 | ASSERT(((unsigned long)walker->table & PAGE_MASK) == |
| 112 | ((unsigned long)ptep & PAGE_MASK)); | 114 | ((unsigned long)ptep & PAGE_MASK)); |
| 113 | 115 | ||
| 114 | if (is_present_pte(*ptep) && !(*ptep & PT_ACCESSED_MASK)) | ||
| 115 | *ptep |= PT_ACCESSED_MASK; | ||
| 116 | |||
| 117 | if (!is_present_pte(*ptep)) | 116 | if (!is_present_pte(*ptep)) |
| 118 | break; | 117 | goto not_present; |
| 118 | |||
| 119 | if (write_fault && !is_writeble_pte(*ptep)) | ||
| 120 | if (user_fault || is_write_protection(vcpu)) | ||
| 121 | goto access_error; | ||
| 122 | |||
| 123 | if (user_fault && !(*ptep & PT_USER_MASK)) | ||
| 124 | goto access_error; | ||
| 125 | |||
| 126 | #if PTTYPE == 64 | ||
| 127 | if (fetch_fault && is_nx(vcpu) && (*ptep & PT64_NX_MASK)) | ||
| 128 | goto access_error; | ||
| 129 | #endif | ||
| 130 | |||
| 131 | if (!(*ptep & PT_ACCESSED_MASK)) | ||
| 132 | *ptep |= PT_ACCESSED_MASK; /* avoid rmw */ | ||
| 119 | 133 | ||
| 120 | if (walker->level == PT_PAGE_TABLE_LEVEL) { | 134 | if (walker->level == PT_PAGE_TABLE_LEVEL) { |
| 121 | walker->gfn = (*ptep & PT_BASE_ADDR_MASK) | 135 | walker->gfn = (*ptep & PT_BASE_ADDR_MASK) |
| @@ -146,6 +160,23 @@ static void FNAME(walk_addr)(struct guest_walker *walker, | |||
| 146 | } | 160 | } |
| 147 | walker->ptep = ptep; | 161 | walker->ptep = ptep; |
| 148 | pgprintk("%s: pte %llx\n", __FUNCTION__, (u64)*ptep); | 162 | pgprintk("%s: pte %llx\n", __FUNCTION__, (u64)*ptep); |
| 163 | return 1; | ||
| 164 | |||
| 165 | not_present: | ||
| 166 | walker->error_code = 0; | ||
| 167 | goto err; | ||
| 168 | |||
| 169 | access_error: | ||
| 170 | walker->error_code = PFERR_PRESENT_MASK; | ||
| 171 | |||
| 172 | err: | ||
| 173 | if (write_fault) | ||
| 174 | walker->error_code |= PFERR_WRITE_MASK; | ||
| 175 | if (user_fault) | ||
| 176 | walker->error_code |= PFERR_USER_MASK; | ||
| 177 | if (fetch_fault) | ||
| 178 | walker->error_code |= PFERR_FETCH_MASK; | ||
| 179 | return 0; | ||
| 149 | } | 180 | } |
| 150 | 181 | ||
| 151 | static void FNAME(release_walker)(struct guest_walker *walker) | 182 | static void FNAME(release_walker)(struct guest_walker *walker) |
| @@ -347,8 +378,8 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, | |||
| 347 | u32 error_code) | 378 | u32 error_code) |
| 348 | { | 379 | { |
| 349 | int write_fault = error_code & PFERR_WRITE_MASK; | 380 | int write_fault = error_code & PFERR_WRITE_MASK; |
| 350 | int pte_present = error_code & PFERR_PRESENT_MASK; | ||
| 351 | int user_fault = error_code & PFERR_USER_MASK; | 381 | int user_fault = error_code & PFERR_USER_MASK; |
| 382 | int fetch_fault = error_code & PFERR_FETCH_MASK; | ||
| 352 | struct guest_walker walker; | 383 | struct guest_walker walker; |
| 353 | u64 *shadow_pte; | 384 | u64 *shadow_pte; |
| 354 | int fixed; | 385 | int fixed; |
| @@ -365,19 +396,20 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, | |||
| 365 | /* | 396 | /* |
| 366 | * Look up the shadow pte for the faulting address. | 397 | * Look up the shadow pte for the faulting address. |
| 367 | */ | 398 | */ |
| 368 | FNAME(walk_addr)(&walker, vcpu, addr); | 399 | r = FNAME(walk_addr)(&walker, vcpu, addr, write_fault, user_fault, |
| 369 | shadow_pte = FNAME(fetch)(vcpu, addr, &walker); | 400 | fetch_fault); |
| 370 | 401 | ||
| 371 | /* | 402 | /* |
| 372 | * The page is not mapped by the guest. Let the guest handle it. | 403 | * The page is not mapped by the guest. Let the guest handle it. |
| 373 | */ | 404 | */ |
| 374 | if (!shadow_pte) { | 405 | if (!r) { |
| 375 | pgprintk("%s: not mapped\n", __FUNCTION__); | 406 | pgprintk("%s: guest page fault\n", __FUNCTION__); |
| 376 | inject_page_fault(vcpu, addr, error_code); | 407 | inject_page_fault(vcpu, addr, walker.error_code); |
| 377 | FNAME(release_walker)(&walker); | 408 | FNAME(release_walker)(&walker); |
| 378 | return 0; | 409 | return 0; |
| 379 | } | 410 | } |
| 380 | 411 | ||
| 412 | shadow_pte = FNAME(fetch)(vcpu, addr, &walker); | ||
| 381 | pgprintk("%s: shadow pte %p %llx\n", __FUNCTION__, | 413 | pgprintk("%s: shadow pte %p %llx\n", __FUNCTION__, |
| 382 | shadow_pte, *shadow_pte); | 414 | shadow_pte, *shadow_pte); |
| 383 | 415 | ||
| @@ -399,22 +431,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, | |||
| 399 | * mmio: emulate if accessible, otherwise its a guest fault. | 431 | * mmio: emulate if accessible, otherwise its a guest fault. |
| 400 | */ | 432 | */ |
| 401 | if (is_io_pte(*shadow_pte)) { | 433 | if (is_io_pte(*shadow_pte)) { |
| 402 | if (may_access(*shadow_pte, write_fault, user_fault)) | 434 | return 1; |
| 403 | return 1; | ||
| 404 | pgprintk("%s: io work, no access\n", __FUNCTION__); | ||
| 405 | inject_page_fault(vcpu, addr, | ||
| 406 | error_code | PFERR_PRESENT_MASK); | ||
| 407 | kvm_mmu_audit(vcpu, "post page fault (io)"); | ||
| 408 | return 0; | ||
| 409 | } | ||
| 410 | |||
| 411 | /* | ||
| 412 | * pte not present, guest page fault. | ||
| 413 | */ | ||
| 414 | if (pte_present && !fixed && !write_pt) { | ||
| 415 | inject_page_fault(vcpu, addr, error_code); | ||
| 416 | kvm_mmu_audit(vcpu, "post page fault (guest)"); | ||
| 417 | return 0; | ||
| 418 | } | 435 | } |
| 419 | 436 | ||
| 420 | ++kvm_stat.pf_fixed; | 437 | ++kvm_stat.pf_fixed; |
| @@ -429,7 +446,7 @@ static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr) | |||
| 429 | pt_element_t guest_pte; | 446 | pt_element_t guest_pte; |
| 430 | gpa_t gpa; | 447 | gpa_t gpa; |
| 431 | 448 | ||
| 432 | FNAME(walk_addr)(&walker, vcpu, vaddr); | 449 | FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0, 0); |
| 433 | guest_pte = *walker.ptep; | 450 | guest_pte = *walker.ptep; |
| 434 | FNAME(release_walker)(&walker); | 451 | FNAME(release_walker)(&walker); |
| 435 | 452 | ||
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index 7397bfbbcb1c..9c70ff65e6b7 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c | |||
| @@ -502,6 +502,7 @@ static void init_vmcb(struct vmcb *vmcb) | |||
| 502 | (1ULL << INTERCEPT_IOIO_PROT) | | 502 | (1ULL << INTERCEPT_IOIO_PROT) | |
| 503 | (1ULL << INTERCEPT_MSR_PROT) | | 503 | (1ULL << INTERCEPT_MSR_PROT) | |
| 504 | (1ULL << INTERCEPT_TASK_SWITCH) | | 504 | (1ULL << INTERCEPT_TASK_SWITCH) | |
| 505 | (1ULL << INTERCEPT_SHUTDOWN) | | ||
| 505 | (1ULL << INTERCEPT_VMRUN) | | 506 | (1ULL << INTERCEPT_VMRUN) | |
| 506 | (1ULL << INTERCEPT_VMMCALL) | | 507 | (1ULL << INTERCEPT_VMMCALL) | |
| 507 | (1ULL << INTERCEPT_VMLOAD) | | 508 | (1ULL << INTERCEPT_VMLOAD) | |
| @@ -680,14 +681,14 @@ static void svm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l) | |||
| 680 | 681 | ||
| 681 | static void svm_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) | 682 | static void svm_get_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) |
| 682 | { | 683 | { |
| 683 | dt->limit = vcpu->svm->vmcb->save.ldtr.limit; | 684 | dt->limit = vcpu->svm->vmcb->save.idtr.limit; |
| 684 | dt->base = vcpu->svm->vmcb->save.ldtr.base; | 685 | dt->base = vcpu->svm->vmcb->save.idtr.base; |
| 685 | } | 686 | } |
| 686 | 687 | ||
| 687 | static void svm_set_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) | 688 | static void svm_set_idt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) |
| 688 | { | 689 | { |
| 689 | vcpu->svm->vmcb->save.ldtr.limit = dt->limit; | 690 | vcpu->svm->vmcb->save.idtr.limit = dt->limit; |
| 690 | vcpu->svm->vmcb->save.ldtr.base = dt->base ; | 691 | vcpu->svm->vmcb->save.idtr.base = dt->base ; |
| 691 | } | 692 | } |
| 692 | 693 | ||
| 693 | static void svm_get_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) | 694 | static void svm_get_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt) |
| @@ -892,6 +893,19 @@ static int pf_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
| 892 | return 0; | 893 | return 0; |
| 893 | } | 894 | } |
| 894 | 895 | ||
| 896 | static int shutdown_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | ||
| 897 | { | ||
| 898 | /* | ||
| 899 | * VMCB is undefined after a SHUTDOWN intercept | ||
| 900 | * so reinitialize it. | ||
| 901 | */ | ||
| 902 | memset(vcpu->svm->vmcb, 0, PAGE_SIZE); | ||
| 903 | init_vmcb(vcpu->svm->vmcb); | ||
| 904 | |||
| 905 | kvm_run->exit_reason = KVM_EXIT_SHUTDOWN; | ||
| 906 | return 0; | ||
| 907 | } | ||
| 908 | |||
| 895 | static int io_get_override(struct kvm_vcpu *vcpu, | 909 | static int io_get_override(struct kvm_vcpu *vcpu, |
| 896 | struct vmcb_seg **seg, | 910 | struct vmcb_seg **seg, |
| 897 | int *addr_override) | 911 | int *addr_override) |
| @@ -1249,6 +1263,7 @@ static int (*svm_exit_handlers[])(struct kvm_vcpu *vcpu, | |||
| 1249 | [SVM_EXIT_IOIO] = io_interception, | 1263 | [SVM_EXIT_IOIO] = io_interception, |
| 1250 | [SVM_EXIT_MSR] = msr_interception, | 1264 | [SVM_EXIT_MSR] = msr_interception, |
| 1251 | [SVM_EXIT_TASK_SWITCH] = task_switch_interception, | 1265 | [SVM_EXIT_TASK_SWITCH] = task_switch_interception, |
| 1266 | [SVM_EXIT_SHUTDOWN] = shutdown_interception, | ||
| 1252 | [SVM_EXIT_VMRUN] = invalid_op_interception, | 1267 | [SVM_EXIT_VMRUN] = invalid_op_interception, |
| 1253 | [SVM_EXIT_VMMCALL] = invalid_op_interception, | 1268 | [SVM_EXIT_VMMCALL] = invalid_op_interception, |
| 1254 | [SVM_EXIT_VMLOAD] = invalid_op_interception, | 1269 | [SVM_EXIT_VMLOAD] = invalid_op_interception, |
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 5432d07c074d..11108165e264 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
| @@ -479,9 +479,12 @@ static int bitmap_read_sb(struct bitmap *bitmap) | |||
| 479 | int err = -EINVAL; | 479 | int err = -EINVAL; |
| 480 | 480 | ||
| 481 | /* page 0 is the superblock, read it... */ | 481 | /* page 0 is the superblock, read it... */ |
| 482 | if (bitmap->file) | 482 | if (bitmap->file) { |
| 483 | bitmap->sb_page = read_page(bitmap->file, 0, bitmap, PAGE_SIZE); | 483 | loff_t isize = i_size_read(bitmap->file->f_mapping->host); |
| 484 | else { | 484 | int bytes = isize > PAGE_SIZE ? PAGE_SIZE : isize; |
| 485 | |||
| 486 | bitmap->sb_page = read_page(bitmap->file, 0, bitmap, bytes); | ||
| 487 | } else { | ||
| 485 | bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset, 0); | 488 | bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset, 0); |
| 486 | } | 489 | } |
| 487 | if (IS_ERR(bitmap->sb_page)) { | 490 | if (IS_ERR(bitmap->sb_page)) { |
| @@ -877,7 +880,8 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) | |||
| 877 | int count; | 880 | int count; |
| 878 | /* unmap the old page, we're done with it */ | 881 | /* unmap the old page, we're done with it */ |
| 879 | if (index == num_pages-1) | 882 | if (index == num_pages-1) |
| 880 | count = bytes - index * PAGE_SIZE; | 883 | count = bytes + sizeof(bitmap_super_t) |
| 884 | - index * PAGE_SIZE; | ||
| 881 | else | 885 | else |
| 882 | count = PAGE_SIZE; | 886 | count = PAGE_SIZE; |
| 883 | if (index == 0) { | 887 | if (index == 0) { |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index fe7c56e10435..3668b170ea68 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
| @@ -1116,7 +1116,8 @@ static int __bind(struct mapped_device *md, struct dm_table *t) | |||
| 1116 | if (size != get_capacity(md->disk)) | 1116 | if (size != get_capacity(md->disk)) |
| 1117 | memset(&md->geometry, 0, sizeof(md->geometry)); | 1117 | memset(&md->geometry, 0, sizeof(md->geometry)); |
| 1118 | 1118 | ||
| 1119 | __set_size(md, size); | 1119 | if (md->suspended_bdev) |
| 1120 | __set_size(md, size); | ||
| 1120 | if (size == 0) | 1121 | if (size == 0) |
| 1121 | return 0; | 1122 | return 0; |
| 1122 | 1123 | ||
| @@ -1264,6 +1265,11 @@ int dm_swap_table(struct mapped_device *md, struct dm_table *table) | |||
| 1264 | if (!dm_suspended(md)) | 1265 | if (!dm_suspended(md)) |
| 1265 | goto out; | 1266 | goto out; |
| 1266 | 1267 | ||
| 1268 | /* without bdev, the device size cannot be changed */ | ||
| 1269 | if (!md->suspended_bdev) | ||
| 1270 | if (get_capacity(md->disk) != dm_table_get_size(table)) | ||
| 1271 | goto out; | ||
| 1272 | |||
| 1267 | __unbind(md); | 1273 | __unbind(md); |
| 1268 | r = __bind(md, table); | 1274 | r = __bind(md, table); |
| 1269 | 1275 | ||
| @@ -1341,11 +1347,14 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) | |||
| 1341 | /* This does not get reverted if there's an error later. */ | 1347 | /* This does not get reverted if there's an error later. */ |
| 1342 | dm_table_presuspend_targets(map); | 1348 | dm_table_presuspend_targets(map); |
| 1343 | 1349 | ||
| 1344 | md->suspended_bdev = bdget_disk(md->disk, 0); | 1350 | /* bdget() can stall if the pending I/Os are not flushed */ |
| 1345 | if (!md->suspended_bdev) { | 1351 | if (!noflush) { |
| 1346 | DMWARN("bdget failed in dm_suspend"); | 1352 | md->suspended_bdev = bdget_disk(md->disk, 0); |
| 1347 | r = -ENOMEM; | 1353 | if (!md->suspended_bdev) { |
| 1348 | goto flush_and_out; | 1354 | DMWARN("bdget failed in dm_suspend"); |
| 1355 | r = -ENOMEM; | ||
| 1356 | goto flush_and_out; | ||
| 1357 | } | ||
| 1349 | } | 1358 | } |
| 1350 | 1359 | ||
| 1351 | /* | 1360 | /* |
| @@ -1473,8 +1482,10 @@ int dm_resume(struct mapped_device *md) | |||
| 1473 | 1482 | ||
| 1474 | unlock_fs(md); | 1483 | unlock_fs(md); |
| 1475 | 1484 | ||
| 1476 | bdput(md->suspended_bdev); | 1485 | if (md->suspended_bdev) { |
| 1477 | md->suspended_bdev = NULL; | 1486 | bdput(md->suspended_bdev); |
| 1487 | md->suspended_bdev = NULL; | ||
| 1488 | } | ||
| 1478 | 1489 | ||
| 1479 | clear_bit(DMF_SUSPENDED, &md->flags); | 1490 | clear_bit(DMF_SUSPENDED, &md->flags); |
| 1480 | 1491 | ||
diff --git a/drivers/md/md.c b/drivers/md/md.c index d1cb45f6d6a9..e8807ea5377d 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -1633,7 +1633,8 @@ repeat: | |||
| 1633 | * and 'events' is odd, we can roll back to the previous clean state */ | 1633 | * and 'events' is odd, we can roll back to the previous clean state */ |
| 1634 | if (nospares | 1634 | if (nospares |
| 1635 | && (mddev->in_sync && mddev->recovery_cp == MaxSector) | 1635 | && (mddev->in_sync && mddev->recovery_cp == MaxSector) |
| 1636 | && (mddev->events & 1)) | 1636 | && (mddev->events & 1) |
| 1637 | && mddev->events != 1) | ||
| 1637 | mddev->events--; | 1638 | mddev->events--; |
| 1638 | else { | 1639 | else { |
| 1639 | /* otherwise we have to go forward and ... */ | 1640 | /* otherwise we have to go forward and ... */ |
| @@ -3563,6 +3564,8 @@ static int get_bitmap_file(mddev_t * mddev, void __user * arg) | |||
| 3563 | char *ptr, *buf = NULL; | 3564 | char *ptr, *buf = NULL; |
| 3564 | int err = -ENOMEM; | 3565 | int err = -ENOMEM; |
| 3565 | 3566 | ||
| 3567 | md_allow_write(mddev); | ||
| 3568 | |||
| 3566 | file = kmalloc(sizeof(*file), GFP_KERNEL); | 3569 | file = kmalloc(sizeof(*file), GFP_KERNEL); |
| 3567 | if (!file) | 3570 | if (!file) |
| 3568 | goto out; | 3571 | goto out; |
| @@ -5031,6 +5034,33 @@ void md_write_end(mddev_t *mddev) | |||
| 5031 | } | 5034 | } |
| 5032 | } | 5035 | } |
| 5033 | 5036 | ||
| 5037 | /* md_allow_write(mddev) | ||
| 5038 | * Calling this ensures that the array is marked 'active' so that writes | ||
| 5039 | * may proceed without blocking. It is important to call this before | ||
| 5040 | * attempting a GFP_KERNEL allocation while holding the mddev lock. | ||
| 5041 | * Must be called with mddev_lock held. | ||
| 5042 | */ | ||
| 5043 | void md_allow_write(mddev_t *mddev) | ||
| 5044 | { | ||
| 5045 | if (!mddev->pers) | ||
| 5046 | return; | ||
| 5047 | if (mddev->ro) | ||
| 5048 | return; | ||
| 5049 | |||
| 5050 | spin_lock_irq(&mddev->write_lock); | ||
| 5051 | if (mddev->in_sync) { | ||
| 5052 | mddev->in_sync = 0; | ||
| 5053 | set_bit(MD_CHANGE_CLEAN, &mddev->flags); | ||
| 5054 | if (mddev->safemode_delay && | ||
| 5055 | mddev->safemode == 0) | ||
| 5056 | mddev->safemode = 1; | ||
| 5057 | spin_unlock_irq(&mddev->write_lock); | ||
| 5058 | md_update_sb(mddev, 0); | ||
| 5059 | } else | ||
| 5060 | spin_unlock_irq(&mddev->write_lock); | ||
| 5061 | } | ||
| 5062 | EXPORT_SYMBOL_GPL(md_allow_write); | ||
| 5063 | |||
| 5034 | static DECLARE_WAIT_QUEUE_HEAD(resync_wait); | 5064 | static DECLARE_WAIT_QUEUE_HEAD(resync_wait); |
| 5035 | 5065 | ||
| 5036 | #define SYNC_MARKS 10 | 5066 | #define SYNC_MARKS 10 |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 164b25dca101..97ee870b265d 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
| @@ -1266,6 +1266,11 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) | |||
| 1266 | sbio->bi_sector = r1_bio->sector + | 1266 | sbio->bi_sector = r1_bio->sector + |
| 1267 | conf->mirrors[i].rdev->data_offset; | 1267 | conf->mirrors[i].rdev->data_offset; |
| 1268 | sbio->bi_bdev = conf->mirrors[i].rdev->bdev; | 1268 | sbio->bi_bdev = conf->mirrors[i].rdev->bdev; |
| 1269 | for (j = 0; j < vcnt ; j++) | ||
| 1270 | memcpy(page_address(sbio->bi_io_vec[j].bv_page), | ||
| 1271 | page_address(pbio->bi_io_vec[j].bv_page), | ||
| 1272 | PAGE_SIZE); | ||
| 1273 | |||
| 1269 | } | 1274 | } |
| 1270 | } | 1275 | } |
| 1271 | } | 1276 | } |
| @@ -2099,6 +2104,8 @@ static int raid1_reshape(mddev_t *mddev) | |||
| 2099 | return -EINVAL; | 2104 | return -EINVAL; |
| 2100 | } | 2105 | } |
| 2101 | 2106 | ||
| 2107 | md_allow_write(mddev); | ||
| 2108 | |||
| 2102 | raid_disks = mddev->raid_disks + mddev->delta_disks; | 2109 | raid_disks = mddev->raid_disks + mddev->delta_disks; |
| 2103 | 2110 | ||
| 2104 | if (raid_disks < conf->raid_disks) { | 2111 | if (raid_disks < conf->raid_disks) { |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index be008f034ada..467c16982d02 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -405,6 +405,8 @@ static int resize_stripes(raid5_conf_t *conf, int newsize) | |||
| 405 | if (newsize <= conf->pool_size) | 405 | if (newsize <= conf->pool_size) |
| 406 | return 0; /* never bother to shrink */ | 406 | return 0; /* never bother to shrink */ |
| 407 | 407 | ||
| 408 | md_allow_write(conf->mddev); | ||
| 409 | |||
| 408 | /* Step 1 */ | 410 | /* Step 1 */ |
| 409 | sc = kmem_cache_create(conf->cache_name[1-conf->active_name], | 411 | sc = kmem_cache_create(conf->cache_name[1-conf->active_name], |
| 410 | sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev), | 412 | sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev), |
| @@ -2678,7 +2680,7 @@ static int chunk_aligned_read(request_queue_t *q, struct bio * raid_bio) | |||
| 2678 | mdk_rdev_t *rdev; | 2680 | mdk_rdev_t *rdev; |
| 2679 | 2681 | ||
| 2680 | if (!in_chunk_boundary(mddev, raid_bio)) { | 2682 | if (!in_chunk_boundary(mddev, raid_bio)) { |
| 2681 | printk("chunk_aligned_read : non aligned\n"); | 2683 | PRINTK("chunk_aligned_read : non aligned\n"); |
| 2682 | return 0; | 2684 | return 0; |
| 2683 | } | 2685 | } |
| 2684 | /* | 2686 | /* |
| @@ -3250,6 +3252,7 @@ raid5_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len) | |||
| 3250 | else | 3252 | else |
| 3251 | break; | 3253 | break; |
| 3252 | } | 3254 | } |
| 3255 | md_allow_write(mddev); | ||
| 3253 | while (new > conf->max_nr_stripes) { | 3256 | while (new > conf->max_nr_stripes) { |
| 3254 | if (grow_one_stripe(conf)) | 3257 | if (grow_one_stripe(conf)) |
| 3255 | conf->max_nr_stripes++; | 3258 | conf->max_nr_stripes++; |
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index 9418a59fb368..2ddd0cf07140 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c | |||
| @@ -78,7 +78,7 @@ static struct attribute_group rtc_attr_group = { | |||
| 78 | .attrs = rtc_attrs, | 78 | .attrs = rtc_attrs, |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | static int __devinit rtc_sysfs_add_device(struct class_device *class_dev, | 81 | static int rtc_sysfs_add_device(struct class_device *class_dev, |
| 82 | struct class_interface *class_intf) | 82 | struct class_interface *class_intf) |
| 83 | { | 83 | { |
| 84 | int err; | 84 | int err; |
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 6ed3f1da9296..8b41f9cc2560 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c | |||
| @@ -1169,8 +1169,9 @@ static int setup(struct spi_device *spi) | |||
| 1169 | spi->bits_per_word - 16 : spi->bits_per_word) | 1169 | spi->bits_per_word - 16 : spi->bits_per_word) |
| 1170 | | SSCR0_SSE | 1170 | | SSCR0_SSE |
| 1171 | | (spi->bits_per_word > 16 ? SSCR0_EDSS : 0); | 1171 | | (spi->bits_per_word > 16 ? SSCR0_EDSS : 0); |
| 1172 | chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) << 4) | 1172 | chip->cr1 &= ~(SSCR1_SPO | SSCR1_SPH); |
| 1173 | | (((spi->mode & SPI_CPOL) != 0) << 3); | 1173 | chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0) |
| 1174 | | (((spi->mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0); | ||
| 1174 | 1175 | ||
| 1175 | /* NOTE: PXA25x_SSP _could_ use external clocking ... */ | 1176 | /* NOTE: PXA25x_SSP _could_ use external clocking ... */ |
| 1176 | if (drv_data->ssp_type != PXA25x_SSP) | 1177 | if (drv_data->ssp_type != PXA25x_SSP) |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 270e6211c2e3..6307428d2c94 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
| @@ -366,7 +366,6 @@ spi_alloc_master(struct device *dev, unsigned size) | |||
| 366 | 366 | ||
| 367 | class_device_initialize(&master->cdev); | 367 | class_device_initialize(&master->cdev); |
| 368 | master->cdev.class = &spi_master_class; | 368 | master->cdev.class = &spi_master_class; |
| 369 | kobj_set_kset_s(&master->cdev, spi_master_class.subsys); | ||
| 370 | master->cdev.dev = get_device(dev); | 369 | master->cdev.dev = get_device(dev); |
| 371 | spi_master_set_devdata(master, &master[1]); | 370 | spi_master_set_devdata(master, &master[1]); |
| 372 | 371 | ||
| @@ -466,14 +465,20 @@ EXPORT_SYMBOL_GPL(spi_unregister_master); | |||
| 466 | */ | 465 | */ |
| 467 | struct spi_master *spi_busnum_to_master(u16 bus_num) | 466 | struct spi_master *spi_busnum_to_master(u16 bus_num) |
| 468 | { | 467 | { |
| 469 | char name[9]; | 468 | struct class_device *cdev; |
| 470 | struct kobject *bus; | 469 | struct spi_master *master = NULL; |
| 471 | 470 | struct spi_master *m; | |
| 472 | snprintf(name, sizeof name, "spi%u", bus_num); | 471 | |
| 473 | bus = kset_find_obj(&spi_master_class.subsys.kset, name); | 472 | down(&spi_master_class.sem); |
| 474 | if (bus) | 473 | list_for_each_entry(cdev, &spi_master_class.children, node) { |
| 475 | return container_of(bus, struct spi_master, cdev.kobj); | 474 | m = container_of(cdev, struct spi_master, cdev); |
| 476 | return NULL; | 475 | if (m->bus_num == bus_num) { |
| 476 | master = spi_master_get(m); | ||
| 477 | break; | ||
| 478 | } | ||
| 479 | } | ||
| 480 | up(&spi_master_class.sem); | ||
| 481 | return master; | ||
| 477 | } | 482 | } |
| 478 | EXPORT_SYMBOL_GPL(spi_busnum_to_master); | 483 | EXPORT_SYMBOL_GPL(spi_busnum_to_master); |
| 479 | 484 | ||
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c index 8ca08713528e..651379c51ae6 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi_s3c24xx.c | |||
| @@ -10,9 +10,6 @@ | |||
| 10 | * | 10 | * |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | |||
| 14 | //#define DEBUG | ||
| 15 | |||
| 16 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 17 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
| 18 | #include <linux/workqueue.h> | 15 | #include <linux/workqueue.h> |
| @@ -44,6 +41,9 @@ struct s3c24xx_spi { | |||
| 44 | int len; | 41 | int len; |
| 45 | int count; | 42 | int count; |
| 46 | 43 | ||
| 44 | int (*set_cs)(struct s3c2410_spi_info *spi, | ||
| 45 | int cs, int pol); | ||
| 46 | |||
| 47 | /* data buffers */ | 47 | /* data buffers */ |
| 48 | const unsigned char *tx; | 48 | const unsigned char *tx; |
| 49 | unsigned char *rx; | 49 | unsigned char *rx; |
| @@ -64,6 +64,11 @@ static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev) | |||
| 64 | return spi_master_get_devdata(sdev->master); | 64 | return spi_master_get_devdata(sdev->master); |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | static void s3c24xx_spi_gpiocs(struct s3c2410_spi_info *spi, int cs, int pol) | ||
| 68 | { | ||
| 69 | s3c2410_gpio_setpin(spi->pin_cs, pol); | ||
| 70 | } | ||
| 71 | |||
| 67 | static void s3c24xx_spi_chipsel(struct spi_device *spi, int value) | 72 | static void s3c24xx_spi_chipsel(struct spi_device *spi, int value) |
| 68 | { | 73 | { |
| 69 | struct s3c24xx_spi *hw = to_hw(spi); | 74 | struct s3c24xx_spi *hw = to_hw(spi); |
| @@ -72,10 +77,7 @@ static void s3c24xx_spi_chipsel(struct spi_device *spi, int value) | |||
| 72 | 77 | ||
| 73 | switch (value) { | 78 | switch (value) { |
| 74 | case BITBANG_CS_INACTIVE: | 79 | case BITBANG_CS_INACTIVE: |
| 75 | if (hw->pdata->set_cs) | 80 | hw->pdata->set_cs(hw->pdata, spi->chip_select, cspol^1); |
| 76 | hw->pdata->set_cs(hw->pdata, value, cspol); | ||
| 77 | else | ||
| 78 | s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol ^ 1); | ||
| 79 | break; | 81 | break; |
| 80 | 82 | ||
| 81 | case BITBANG_CS_ACTIVE: | 83 | case BITBANG_CS_ACTIVE: |
| @@ -96,14 +98,9 @@ static void s3c24xx_spi_chipsel(struct spi_device *spi, int value) | |||
| 96 | /* write new configration */ | 98 | /* write new configration */ |
| 97 | 99 | ||
| 98 | writeb(spcon, hw->regs + S3C2410_SPCON); | 100 | writeb(spcon, hw->regs + S3C2410_SPCON); |
| 99 | 101 | hw->pdata->set_cs(hw->pdata, spi->chip_select, cspol); | |
| 100 | if (hw->pdata->set_cs) | ||
| 101 | hw->pdata->set_cs(hw->pdata, value, cspol); | ||
| 102 | else | ||
| 103 | s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol); | ||
| 104 | 102 | ||
| 105 | break; | 103 | break; |
| 106 | |||
| 107 | } | 104 | } |
| 108 | } | 105 | } |
| 109 | 106 | ||
| @@ -330,9 +327,12 @@ static int s3c24xx_spi_probe(struct platform_device *pdev) | |||
| 330 | /* setup any gpio we can */ | 327 | /* setup any gpio we can */ |
| 331 | 328 | ||
| 332 | if (!hw->pdata->set_cs) { | 329 | if (!hw->pdata->set_cs) { |
| 330 | hw->set_cs = s3c24xx_spi_gpiocs; | ||
| 331 | |||
| 333 | s3c2410_gpio_setpin(hw->pdata->pin_cs, 1); | 332 | s3c2410_gpio_setpin(hw->pdata->pin_cs, 1); |
| 334 | s3c2410_gpio_cfgpin(hw->pdata->pin_cs, S3C2410_GPIO_OUTPUT); | 333 | s3c2410_gpio_cfgpin(hw->pdata->pin_cs, S3C2410_GPIO_OUTPUT); |
| 335 | } | 334 | } else |
| 335 | hw->set_cs = hw->pdata->set_cs; | ||
| 336 | 336 | ||
| 337 | /* register our spi controller */ | 337 | /* register our spi controller */ |
| 338 | 338 | ||
diff --git a/fs/9p/error.c b/fs/9p/error.c index ae91555c1558..0d7fa4e08812 100644 --- a/fs/9p/error.c +++ b/fs/9p/error.c | |||
| @@ -83,6 +83,7 @@ int v9fs_errstr2errno(char *errstr, int len) | |||
| 83 | 83 | ||
| 84 | if (errno == 0) { | 84 | if (errno == 0) { |
| 85 | /* TODO: if error isn't found, add it dynamically */ | 85 | /* TODO: if error isn't found, add it dynamically */ |
| 86 | errstr[len] = 0; | ||
| 86 | printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__, | 87 | printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__, |
| 87 | errstr); | 88 | errstr); |
| 88 | errno = 1; | 89 | errno = 1; |
diff --git a/fs/9p/fid.c b/fs/9p/fid.c index 27507201f9e7..a9b6301a04fc 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
| 26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
| 27 | #include <linux/idr.h> | 27 | #include <linux/idr.h> |
| 28 | #include <asm/semaphore.h> | ||
| 28 | 29 | ||
| 29 | #include "debug.h" | 30 | #include "debug.h" |
| 30 | #include "v9fs.h" | 31 | #include "v9fs.h" |
| @@ -84,6 +85,7 @@ struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *v9ses, int fid) | |||
| 84 | new->iounit = 0; | 85 | new->iounit = 0; |
| 85 | new->rdir_pos = 0; | 86 | new->rdir_pos = 0; |
| 86 | new->rdir_fcall = NULL; | 87 | new->rdir_fcall = NULL; |
| 88 | init_MUTEX(&new->lock); | ||
| 87 | INIT_LIST_HEAD(&new->list); | 89 | INIT_LIST_HEAD(&new->list); |
| 88 | 90 | ||
| 89 | return new; | 91 | return new; |
| @@ -102,11 +104,11 @@ void v9fs_fid_destroy(struct v9fs_fid *fid) | |||
| 102 | } | 104 | } |
| 103 | 105 | ||
| 104 | /** | 106 | /** |
| 105 | * v9fs_fid_lookup - retrieve the right fid from a particular dentry | 107 | * v9fs_fid_lookup - return a locked fid from a dentry |
| 106 | * @dentry: dentry to look for fid in | 108 | * @dentry: dentry to look for fid in |
| 107 | * @type: intent of lookup (operation or traversal) | ||
| 108 | * | 109 | * |
| 109 | * find a fid in the dentry | 110 | * find a fid in the dentry, obtain its semaphore and return a reference to it. |
| 111 | * code calling lookup is responsible for releasing lock | ||
| 110 | * | 112 | * |
| 111 | * TODO: only match fids that have the same uid as current user | 113 | * TODO: only match fids that have the same uid as current user |
| 112 | * | 114 | * |
| @@ -124,7 +126,68 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry) | |||
| 124 | 126 | ||
| 125 | if (!return_fid) { | 127 | if (!return_fid) { |
| 126 | dprintk(DEBUG_ERROR, "Couldn't find a fid in dentry\n"); | 128 | dprintk(DEBUG_ERROR, "Couldn't find a fid in dentry\n"); |
| 129 | return_fid = ERR_PTR(-EBADF); | ||
| 127 | } | 130 | } |
| 128 | 131 | ||
| 132 | if(down_interruptible(&return_fid->lock)) | ||
| 133 | return ERR_PTR(-EINTR); | ||
| 134 | |||
| 129 | return return_fid; | 135 | return return_fid; |
| 130 | } | 136 | } |
| 137 | |||
| 138 | /** | ||
| 139 | * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and release it | ||
| 140 | * @dentry: dentry to look for fid in | ||
| 141 | * | ||
| 142 | * find a fid in the dentry and then clone to a new private fid | ||
| 143 | * | ||
| 144 | * TODO: only match fids that have the same uid as current user | ||
| 145 | * | ||
| 146 | */ | ||
| 147 | |||
| 148 | struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry) | ||
| 149 | { | ||
| 150 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | ||
| 151 | struct v9fs_fid *base_fid, *new_fid = ERR_PTR(-EBADF); | ||
| 152 | struct v9fs_fcall *fcall = NULL; | ||
| 153 | int fid, err; | ||
| 154 | |||
| 155 | base_fid = v9fs_fid_lookup(dentry); | ||
| 156 | |||
| 157 | if(IS_ERR(base_fid)) | ||
| 158 | return base_fid; | ||
| 159 | |||
| 160 | if(base_fid) { /* clone fid */ | ||
| 161 | fid = v9fs_get_idpool(&v9ses->fidpool); | ||
| 162 | if (fid < 0) { | ||
| 163 | eprintk(KERN_WARNING, "newfid fails!\n"); | ||
| 164 | new_fid = ERR_PTR(-ENOSPC); | ||
| 165 | goto Release_Fid; | ||
| 166 | } | ||
| 167 | |||
| 168 | err = v9fs_t_walk(v9ses, base_fid->fid, fid, NULL, &fcall); | ||
| 169 | if (err < 0) { | ||
| 170 | dprintk(DEBUG_ERROR, "clone walk didn't work\n"); | ||
| 171 | v9fs_put_idpool(fid, &v9ses->fidpool); | ||
| 172 | new_fid = ERR_PTR(err); | ||
| 173 | goto Free_Fcall; | ||
| 174 | } | ||
| 175 | new_fid = v9fs_fid_create(v9ses, fid); | ||
| 176 | if (new_fid == NULL) { | ||
| 177 | dprintk(DEBUG_ERROR, "out of memory\n"); | ||
| 178 | new_fid = ERR_PTR(-ENOMEM); | ||
| 179 | } | ||
| 180 | Free_Fcall: | ||
| 181 | kfree(fcall); | ||
| 182 | } | ||
| 183 | |||
| 184 | Release_Fid: | ||
| 185 | up(&base_fid->lock); | ||
| 186 | return new_fid; | ||
| 187 | } | ||
| 188 | |||
| 189 | void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid) | ||
| 190 | { | ||
| 191 | v9fs_t_clunk(v9ses, fid->fid); | ||
| 192 | v9fs_fid_destroy(fid); | ||
| 193 | } | ||
diff --git a/fs/9p/fid.h b/fs/9p/fid.h index aa974d6875c3..48fc170c26c8 100644 --- a/fs/9p/fid.h +++ b/fs/9p/fid.h | |||
| @@ -30,6 +30,8 @@ struct v9fs_fid { | |||
| 30 | struct list_head list; /* list of fids associated with a dentry */ | 30 | struct list_head list; /* list of fids associated with a dentry */ |
| 31 | struct list_head active; /* XXX - debug */ | 31 | struct list_head active; /* XXX - debug */ |
| 32 | 32 | ||
| 33 | struct semaphore lock; | ||
| 34 | |||
| 33 | u32 fid; | 35 | u32 fid; |
| 34 | unsigned char fidopen; /* set when fid is opened */ | 36 | unsigned char fidopen; /* set when fid is opened */ |
| 35 | unsigned char fidclunked; /* set when fid has already been clunked */ | 37 | unsigned char fidclunked; /* set when fid has already been clunked */ |
| @@ -55,3 +57,6 @@ struct v9fs_fid *v9fs_fid_get_created(struct dentry *); | |||
| 55 | void v9fs_fid_destroy(struct v9fs_fid *fid); | 57 | void v9fs_fid_destroy(struct v9fs_fid *fid); |
| 56 | struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *, int fid); | 58 | struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *, int fid); |
| 57 | int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry); | 59 | int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry); |
| 60 | struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry); | ||
| 61 | void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid); | ||
| 62 | |||
diff --git a/fs/9p/mux.c b/fs/9p/mux.c index 944273c3dbff..147ceef8e537 100644 --- a/fs/9p/mux.c +++ b/fs/9p/mux.c | |||
| @@ -132,8 +132,10 @@ int v9fs_mux_global_init(void) | |||
| 132 | v9fs_mux_poll_tasks[i].task = NULL; | 132 | v9fs_mux_poll_tasks[i].task = NULL; |
| 133 | 133 | ||
| 134 | v9fs_mux_wq = create_workqueue("v9fs"); | 134 | v9fs_mux_wq = create_workqueue("v9fs"); |
| 135 | if (!v9fs_mux_wq) | 135 | if (!v9fs_mux_wq) { |
| 136 | printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n"); | ||
| 136 | return -ENOMEM; | 137 | return -ENOMEM; |
| 138 | } | ||
| 137 | 139 | ||
| 138 | return 0; | 140 | return 0; |
| 139 | } | 141 | } |
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 0b96fae8b479..d9b561ba5e58 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c | |||
| @@ -457,14 +457,19 @@ static int __init init_v9fs(void) | |||
| 457 | 457 | ||
| 458 | v9fs_error_init(); | 458 | v9fs_error_init(); |
| 459 | 459 | ||
| 460 | printk(KERN_INFO "Installing v9fs 9P2000 file system support\n"); | 460 | printk(KERN_INFO "Installing v9fs 9p2000 file system support\n"); |
| 461 | 461 | ||
| 462 | ret = v9fs_mux_global_init(); | 462 | ret = v9fs_mux_global_init(); |
| 463 | if (!ret) | 463 | if (ret) { |
| 464 | printk(KERN_WARNING "v9fs: starting mux failed\n"); | ||
| 464 | return ret; | 465 | return ret; |
| 466 | } | ||
| 465 | ret = register_filesystem(&v9fs_fs_type); | 467 | ret = register_filesystem(&v9fs_fs_type); |
| 466 | if (!ret) | 468 | if (ret) { |
| 469 | printk(KERN_WARNING "v9fs: registering file system failed\n"); | ||
| 467 | v9fs_mux_global_exit(); | 470 | v9fs_mux_global_exit(); |
| 471 | } | ||
| 472 | |||
| 468 | return ret; | 473 | return ret; |
| 469 | } | 474 | } |
| 470 | 475 | ||
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index e86a07151280..9f17b0cacdd0 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
| @@ -55,53 +55,22 @@ int v9fs_file_open(struct inode *inode, struct file *file) | |||
| 55 | struct v9fs_fid *vfid; | 55 | struct v9fs_fid *vfid; |
| 56 | struct v9fs_fcall *fcall = NULL; | 56 | struct v9fs_fcall *fcall = NULL; |
| 57 | int omode; | 57 | int omode; |
| 58 | int fid = V9FS_NOFID; | ||
| 59 | int err; | 58 | int err; |
| 60 | 59 | ||
| 61 | dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); | 60 | dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); |
| 62 | 61 | ||
| 63 | vfid = v9fs_fid_lookup(file->f_path.dentry); | 62 | vfid = v9fs_fid_clone(file->f_path.dentry); |
| 64 | if (!vfid) { | 63 | if (IS_ERR(vfid)) |
| 65 | dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n"); | 64 | return PTR_ERR(vfid); |
| 66 | return -EBADF; | ||
| 67 | } | ||
| 68 | |||
| 69 | fid = v9fs_get_idpool(&v9ses->fidpool); | ||
| 70 | if (fid < 0) { | ||
| 71 | eprintk(KERN_WARNING, "newfid fails!\n"); | ||
| 72 | return -ENOSPC; | ||
| 73 | } | ||
| 74 | 65 | ||
| 75 | err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, &fcall); | ||
| 76 | if (err < 0) { | ||
| 77 | dprintk(DEBUG_ERROR, "rewalk didn't work\n"); | ||
| 78 | if (fcall && fcall->id == RWALK) | ||
| 79 | goto clunk_fid; | ||
| 80 | else { | ||
| 81 | v9fs_put_idpool(fid, &v9ses->fidpool); | ||
| 82 | goto free_fcall; | ||
| 83 | } | ||
| 84 | } | ||
| 85 | kfree(fcall); | ||
| 86 | |||
| 87 | /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */ | ||
| 88 | /* translate open mode appropriately */ | ||
| 89 | omode = v9fs_uflags2omode(file->f_flags); | 66 | omode = v9fs_uflags2omode(file->f_flags); |
| 90 | err = v9fs_t_open(v9ses, fid, omode, &fcall); | 67 | err = v9fs_t_open(v9ses, vfid->fid, omode, &fcall); |
| 91 | if (err < 0) { | 68 | if (err < 0) { |
| 92 | PRINT_FCALL_ERROR("open failed", fcall); | 69 | PRINT_FCALL_ERROR("open failed", fcall); |
| 93 | goto clunk_fid; | 70 | goto Clunk_Fid; |
| 94 | } | ||
| 95 | |||
| 96 | vfid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); | ||
| 97 | if (vfid == NULL) { | ||
| 98 | dprintk(DEBUG_ERROR, "out of memory\n"); | ||
| 99 | err = -ENOMEM; | ||
| 100 | goto clunk_fid; | ||
| 101 | } | 71 | } |
| 102 | 72 | ||
| 103 | file->private_data = vfid; | 73 | file->private_data = vfid; |
| 104 | vfid->fid = fid; | ||
| 105 | vfid->fidopen = 1; | 74 | vfid->fidopen = 1; |
| 106 | vfid->fidclunked = 0; | 75 | vfid->fidclunked = 0; |
| 107 | vfid->iounit = fcall->params.ropen.iounit; | 76 | vfid->iounit = fcall->params.ropen.iounit; |
| @@ -112,10 +81,8 @@ int v9fs_file_open(struct inode *inode, struct file *file) | |||
| 112 | 81 | ||
| 113 | return 0; | 82 | return 0; |
| 114 | 83 | ||
| 115 | clunk_fid: | 84 | Clunk_Fid: |
| 116 | v9fs_t_clunk(v9ses, fid); | 85 | v9fs_fid_clunk(v9ses, vfid); |
| 117 | |||
| 118 | free_fcall: | ||
| 119 | kfree(fcall); | 86 | kfree(fcall); |
| 120 | 87 | ||
| 121 | return err; | 88 | return err; |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 18f26cdfd882..9109ba1d6969 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
| @@ -416,12 +416,8 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | |||
| 416 | sb = file_inode->i_sb; | 416 | sb = file_inode->i_sb; |
| 417 | v9ses = v9fs_inode2v9ses(file_inode); | 417 | v9ses = v9fs_inode2v9ses(file_inode); |
| 418 | v9fid = v9fs_fid_lookup(file); | 418 | v9fid = v9fs_fid_lookup(file); |
| 419 | 419 | if(IS_ERR(v9fid)) | |
| 420 | if (!v9fid) { | 420 | return PTR_ERR(v9fid); |
| 421 | dprintk(DEBUG_ERROR, | ||
| 422 | "no v9fs_fid\n"); | ||
| 423 | return -EBADF; | ||
| 424 | } | ||
| 425 | 421 | ||
| 426 | fid = v9fid->fid; | 422 | fid = v9fid->fid; |
| 427 | if (fid < 0) { | 423 | if (fid < 0) { |
| @@ -433,11 +429,13 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | |||
| 433 | result = v9fs_t_remove(v9ses, fid, &fcall); | 429 | result = v9fs_t_remove(v9ses, fid, &fcall); |
| 434 | if (result < 0) { | 430 | if (result < 0) { |
| 435 | PRINT_FCALL_ERROR("remove fails", fcall); | 431 | PRINT_FCALL_ERROR("remove fails", fcall); |
| 432 | goto Error; | ||
| 436 | } | 433 | } |
| 437 | 434 | ||
| 438 | v9fs_put_idpool(fid, &v9ses->fidpool); | 435 | v9fs_put_idpool(fid, &v9ses->fidpool); |
| 439 | v9fs_fid_destroy(v9fid); | 436 | v9fs_fid_destroy(v9fid); |
| 440 | 437 | ||
| 438 | Error: | ||
| 441 | kfree(fcall); | 439 | kfree(fcall); |
| 442 | return result; | 440 | return result; |
| 443 | } | 441 | } |
| @@ -473,9 +471,13 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
| 473 | inode = NULL; | 471 | inode = NULL; |
| 474 | vfid = NULL; | 472 | vfid = NULL; |
| 475 | v9ses = v9fs_inode2v9ses(dir); | 473 | v9ses = v9fs_inode2v9ses(dir); |
| 476 | dfid = v9fs_fid_lookup(dentry->d_parent); | 474 | dfid = v9fs_fid_clone(dentry->d_parent); |
| 477 | perm = unixmode2p9mode(v9ses, mode); | 475 | if(IS_ERR(dfid)) { |
| 476 | err = PTR_ERR(dfid); | ||
| 477 | goto error; | ||
| 478 | } | ||
| 478 | 479 | ||
| 480 | perm = unixmode2p9mode(v9ses, mode); | ||
| 479 | if (nd && nd->flags & LOOKUP_OPEN) | 481 | if (nd && nd->flags & LOOKUP_OPEN) |
| 480 | flags = nd->intent.open.flags - 1; | 482 | flags = nd->intent.open.flags - 1; |
| 481 | else | 483 | else |
| @@ -485,9 +487,10 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
| 485 | perm, v9fs_uflags2omode(flags), NULL, &fid, &qid, &iounit); | 487 | perm, v9fs_uflags2omode(flags), NULL, &fid, &qid, &iounit); |
| 486 | 488 | ||
| 487 | if (err) | 489 | if (err) |
| 488 | goto error; | 490 | goto clunk_dfid; |
| 489 | 491 | ||
| 490 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); | 492 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); |
| 493 | v9fs_fid_clunk(v9ses, dfid); | ||
| 491 | if (IS_ERR(vfid)) { | 494 | if (IS_ERR(vfid)) { |
| 492 | err = PTR_ERR(vfid); | 495 | err = PTR_ERR(vfid); |
| 493 | vfid = NULL; | 496 | vfid = NULL; |
| @@ -525,6 +528,9 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
| 525 | 528 | ||
| 526 | return 0; | 529 | return 0; |
| 527 | 530 | ||
| 531 | clunk_dfid: | ||
| 532 | v9fs_fid_clunk(v9ses, dfid); | ||
| 533 | |||
| 528 | error: | 534 | error: |
| 529 | if (vfid) | 535 | if (vfid) |
| 530 | v9fs_fid_destroy(vfid); | 536 | v9fs_fid_destroy(vfid); |
| @@ -551,7 +557,12 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 551 | inode = NULL; | 557 | inode = NULL; |
| 552 | vfid = NULL; | 558 | vfid = NULL; |
| 553 | v9ses = v9fs_inode2v9ses(dir); | 559 | v9ses = v9fs_inode2v9ses(dir); |
| 554 | dfid = v9fs_fid_lookup(dentry->d_parent); | 560 | dfid = v9fs_fid_clone(dentry->d_parent); |
| 561 | if(IS_ERR(dfid)) { | ||
| 562 | err = PTR_ERR(dfid); | ||
| 563 | goto error; | ||
| 564 | } | ||
| 565 | |||
| 555 | perm = unixmode2p9mode(v9ses, mode | S_IFDIR); | 566 | perm = unixmode2p9mode(v9ses, mode | S_IFDIR); |
| 556 | 567 | ||
| 557 | err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, | 568 | err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, |
| @@ -559,37 +570,36 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 559 | 570 | ||
| 560 | if (err) { | 571 | if (err) { |
| 561 | dprintk(DEBUG_ERROR, "create error %d\n", err); | 572 | dprintk(DEBUG_ERROR, "create error %d\n", err); |
| 562 | goto error; | 573 | goto clean_up_dfid; |
| 563 | } | ||
| 564 | |||
| 565 | err = v9fs_t_clunk(v9ses, fid); | ||
| 566 | if (err) { | ||
| 567 | dprintk(DEBUG_ERROR, "clunk error %d\n", err); | ||
| 568 | goto error; | ||
| 569 | } | 574 | } |
| 570 | 575 | ||
| 571 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); | 576 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); |
| 572 | if (IS_ERR(vfid)) { | 577 | if (IS_ERR(vfid)) { |
| 573 | err = PTR_ERR(vfid); | 578 | err = PTR_ERR(vfid); |
| 574 | vfid = NULL; | 579 | vfid = NULL; |
| 575 | goto error; | 580 | goto clean_up_dfid; |
| 576 | } | 581 | } |
| 577 | 582 | ||
| 583 | v9fs_fid_clunk(v9ses, dfid); | ||
| 578 | inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); | 584 | inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); |
| 579 | if (IS_ERR(inode)) { | 585 | if (IS_ERR(inode)) { |
| 580 | err = PTR_ERR(inode); | 586 | err = PTR_ERR(inode); |
| 581 | inode = NULL; | 587 | inode = NULL; |
| 582 | goto error; | 588 | goto clean_up_fids; |
| 583 | } | 589 | } |
| 584 | 590 | ||
| 585 | dentry->d_op = &v9fs_dentry_operations; | 591 | dentry->d_op = &v9fs_dentry_operations; |
| 586 | d_instantiate(dentry, inode); | 592 | d_instantiate(dentry, inode); |
| 587 | return 0; | 593 | return 0; |
| 588 | 594 | ||
| 589 | error: | 595 | clean_up_fids: |
| 590 | if (vfid) | 596 | if (vfid) |
| 591 | v9fs_fid_destroy(vfid); | 597 | v9fs_fid_destroy(vfid); |
| 592 | 598 | ||
| 599 | clean_up_dfid: | ||
| 600 | v9fs_fid_clunk(v9ses, dfid); | ||
| 601 | |||
| 602 | error: | ||
| 593 | return err; | 603 | return err; |
| 594 | } | 604 | } |
| 595 | 605 | ||
| @@ -622,28 +632,23 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 622 | dentry->d_op = &v9fs_dentry_operations; | 632 | dentry->d_op = &v9fs_dentry_operations; |
| 623 | dirfid = v9fs_fid_lookup(dentry->d_parent); | 633 | dirfid = v9fs_fid_lookup(dentry->d_parent); |
| 624 | 634 | ||
| 625 | if (!dirfid) { | 635 | if(IS_ERR(dirfid)) |
| 626 | dprintk(DEBUG_ERROR, "no dirfid\n"); | 636 | return ERR_PTR(PTR_ERR(dirfid)); |
| 627 | return ERR_PTR(-EINVAL); | ||
| 628 | } | ||
| 629 | 637 | ||
| 630 | dirfidnum = dirfid->fid; | 638 | dirfidnum = dirfid->fid; |
| 631 | 639 | ||
| 632 | if (dirfidnum < 0) { | ||
| 633 | dprintk(DEBUG_ERROR, "no dirfid for inode %p, #%lu\n", | ||
| 634 | dir, dir->i_ino); | ||
| 635 | return ERR_PTR(-EBADF); | ||
| 636 | } | ||
| 637 | |||
| 638 | newfid = v9fs_get_idpool(&v9ses->fidpool); | 640 | newfid = v9fs_get_idpool(&v9ses->fidpool); |
| 639 | if (newfid < 0) { | 641 | if (newfid < 0) { |
| 640 | eprintk(KERN_WARNING, "newfid fails!\n"); | 642 | eprintk(KERN_WARNING, "newfid fails!\n"); |
| 641 | return ERR_PTR(-ENOSPC); | 643 | result = -ENOSPC; |
| 644 | goto Release_Dirfid; | ||
| 642 | } | 645 | } |
| 643 | 646 | ||
| 644 | result = v9fs_t_walk(v9ses, dirfidnum, newfid, | 647 | result = v9fs_t_walk(v9ses, dirfidnum, newfid, |
| 645 | (char *)dentry->d_name.name, &fcall); | 648 | (char *)dentry->d_name.name, &fcall); |
| 646 | 649 | ||
| 650 | up(&dirfid->lock); | ||
| 651 | |||
| 647 | if (result < 0) { | 652 | if (result < 0) { |
| 648 | if (fcall && fcall->id == RWALK) | 653 | if (fcall && fcall->id == RWALK) |
| 649 | v9fs_t_clunk(v9ses, newfid); | 654 | v9fs_t_clunk(v9ses, newfid); |
| @@ -701,8 +706,12 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 701 | 706 | ||
| 702 | return NULL; | 707 | return NULL; |
| 703 | 708 | ||
| 704 | FreeFcall: | 709 | Release_Dirfid: |
| 710 | up(&dirfid->lock); | ||
| 711 | |||
| 712 | FreeFcall: | ||
| 705 | kfree(fcall); | 713 | kfree(fcall); |
| 714 | |||
| 706 | return ERR_PTR(result); | 715 | return ERR_PTR(result); |
| 707 | } | 716 | } |
| 708 | 717 | ||
| @@ -746,10 +755,8 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 746 | struct inode *old_inode = old_dentry->d_inode; | 755 | struct inode *old_inode = old_dentry->d_inode; |
| 747 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode); | 756 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode); |
| 748 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); | 757 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); |
| 749 | struct v9fs_fid *olddirfid = | 758 | struct v9fs_fid *olddirfid; |
| 750 | v9fs_fid_lookup(old_dentry->d_parent); | 759 | struct v9fs_fid *newdirfid; |
| 751 | struct v9fs_fid *newdirfid = | ||
| 752 | v9fs_fid_lookup(new_dentry->d_parent); | ||
| 753 | struct v9fs_wstat wstat; | 760 | struct v9fs_wstat wstat; |
| 754 | struct v9fs_fcall *fcall = NULL; | 761 | struct v9fs_fcall *fcall = NULL; |
| 755 | int fid = -1; | 762 | int fid = -1; |
| @@ -759,16 +766,26 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 759 | 766 | ||
| 760 | dprintk(DEBUG_VFS, "\n"); | 767 | dprintk(DEBUG_VFS, "\n"); |
| 761 | 768 | ||
| 762 | if ((!oldfid) || (!olddirfid) || (!newdirfid)) { | 769 | if(IS_ERR(oldfid)) |
| 763 | dprintk(DEBUG_ERROR, "problem with arguments\n"); | 770 | return PTR_ERR(oldfid); |
| 764 | return -EBADF; | 771 | |
| 772 | olddirfid = v9fs_fid_clone(old_dentry->d_parent); | ||
| 773 | if(IS_ERR(olddirfid)) { | ||
| 774 | retval = PTR_ERR(olddirfid); | ||
| 775 | goto Release_lock; | ||
| 776 | } | ||
| 777 | |||
| 778 | newdirfid = v9fs_fid_clone(new_dentry->d_parent); | ||
| 779 | if(IS_ERR(newdirfid)) { | ||
| 780 | retval = PTR_ERR(newdirfid); | ||
| 781 | goto Clunk_olddir; | ||
| 765 | } | 782 | } |
| 766 | 783 | ||
| 767 | /* 9P can only handle file rename in the same directory */ | 784 | /* 9P can only handle file rename in the same directory */ |
| 768 | if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) { | 785 | if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) { |
| 769 | dprintk(DEBUG_ERROR, "old dir and new dir are different\n"); | 786 | dprintk(DEBUG_ERROR, "old dir and new dir are different\n"); |
| 770 | retval = -EPERM; | 787 | retval = -EXDEV; |
| 771 | goto FreeFcallnBail; | 788 | goto Clunk_newdir; |
| 772 | } | 789 | } |
| 773 | 790 | ||
| 774 | fid = oldfid->fid; | 791 | fid = oldfid->fid; |
| @@ -779,7 +796,7 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 779 | dprintk(DEBUG_ERROR, "no fid for old file #%lu\n", | 796 | dprintk(DEBUG_ERROR, "no fid for old file #%lu\n", |
| 780 | old_inode->i_ino); | 797 | old_inode->i_ino); |
| 781 | retval = -EBADF; | 798 | retval = -EBADF; |
| 782 | goto FreeFcallnBail; | 799 | goto Clunk_newdir; |
| 783 | } | 800 | } |
| 784 | 801 | ||
| 785 | v9fs_blank_wstat(&wstat); | 802 | v9fs_blank_wstat(&wstat); |
| @@ -788,11 +805,20 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 788 | 805 | ||
| 789 | retval = v9fs_t_wstat(v9ses, fid, &wstat, &fcall); | 806 | retval = v9fs_t_wstat(v9ses, fid, &wstat, &fcall); |
| 790 | 807 | ||
| 791 | FreeFcallnBail: | ||
| 792 | if (retval < 0) | 808 | if (retval < 0) |
| 793 | PRINT_FCALL_ERROR("wstat error", fcall); | 809 | PRINT_FCALL_ERROR("wstat error", fcall); |
| 794 | 810 | ||
| 795 | kfree(fcall); | 811 | kfree(fcall); |
| 812 | |||
| 813 | Clunk_newdir: | ||
| 814 | v9fs_fid_clunk(v9ses, newdirfid); | ||
| 815 | |||
| 816 | Clunk_olddir: | ||
| 817 | v9fs_fid_clunk(v9ses, olddirfid); | ||
| 818 | |||
| 819 | Release_lock: | ||
| 820 | up(&oldfid->lock); | ||
| 821 | |||
| 796 | return retval; | 822 | return retval; |
| 797 | } | 823 | } |
| 798 | 824 | ||
| @@ -810,15 +836,12 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
| 810 | { | 836 | { |
| 811 | struct v9fs_fcall *fcall = NULL; | 837 | struct v9fs_fcall *fcall = NULL; |
| 812 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 838 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
| 813 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); | 839 | struct v9fs_fid *fid = v9fs_fid_clone(dentry); |
| 814 | int err = -EPERM; | 840 | int err = -EPERM; |
| 815 | 841 | ||
| 816 | dprintk(DEBUG_VFS, "dentry: %p\n", dentry); | 842 | dprintk(DEBUG_VFS, "dentry: %p\n", dentry); |
| 817 | if (!fid) { | 843 | if(IS_ERR(fid)) |
| 818 | dprintk(DEBUG_ERROR, | 844 | return PTR_ERR(fid); |
| 819 | "couldn't find fid associated with dentry\n"); | ||
| 820 | return -EBADF; | ||
| 821 | } | ||
| 822 | 845 | ||
| 823 | err = v9fs_t_stat(v9ses, fid->fid, &fcall); | 846 | err = v9fs_t_stat(v9ses, fid->fid, &fcall); |
| 824 | 847 | ||
| @@ -831,6 +854,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
| 831 | } | 854 | } |
| 832 | 855 | ||
| 833 | kfree(fcall); | 856 | kfree(fcall); |
| 857 | v9fs_fid_clunk(v9ses, fid); | ||
| 834 | return err; | 858 | return err; |
| 835 | } | 859 | } |
| 836 | 860 | ||
| @@ -844,18 +868,14 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
| 844 | static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) | 868 | static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) |
| 845 | { | 869 | { |
| 846 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 870 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
| 847 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); | 871 | struct v9fs_fid *fid = v9fs_fid_clone(dentry); |
| 848 | struct v9fs_fcall *fcall = NULL; | 872 | struct v9fs_fcall *fcall = NULL; |
| 849 | struct v9fs_wstat wstat; | 873 | struct v9fs_wstat wstat; |
| 850 | int res = -EPERM; | 874 | int res = -EPERM; |
| 851 | 875 | ||
| 852 | dprintk(DEBUG_VFS, "\n"); | 876 | dprintk(DEBUG_VFS, "\n"); |
| 853 | 877 | if(IS_ERR(fid)) | |
| 854 | if (!fid) { | 878 | return PTR_ERR(fid); |
| 855 | dprintk(DEBUG_ERROR, | ||
| 856 | "Couldn't find fid associated with dentry\n"); | ||
| 857 | return -EBADF; | ||
| 858 | } | ||
| 859 | 879 | ||
| 860 | v9fs_blank_wstat(&wstat); | 880 | v9fs_blank_wstat(&wstat); |
| 861 | if (iattr->ia_valid & ATTR_MODE) | 881 | if (iattr->ia_valid & ATTR_MODE) |
| @@ -887,6 +907,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
| 887 | if (res >= 0) | 907 | if (res >= 0) |
| 888 | res = inode_setattr(dentry->d_inode, iattr); | 908 | res = inode_setattr(dentry->d_inode, iattr); |
| 889 | 909 | ||
| 910 | v9fs_fid_clunk(v9ses, fid); | ||
| 890 | return res; | 911 | return res; |
| 891 | } | 912 | } |
| 892 | 913 | ||
| @@ -987,18 +1008,15 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
| 987 | 1008 | ||
| 988 | struct v9fs_fcall *fcall = NULL; | 1009 | struct v9fs_fcall *fcall = NULL; |
| 989 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 1010 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
| 990 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); | 1011 | struct v9fs_fid *fid = v9fs_fid_clone(dentry); |
| 991 | 1012 | ||
| 992 | if (!fid) { | 1013 | if(IS_ERR(fid)) |
| 993 | dprintk(DEBUG_ERROR, "could not resolve fid from dentry\n"); | 1014 | return PTR_ERR(fid); |
| 994 | retval = -EBADF; | ||
| 995 | goto FreeFcall; | ||
| 996 | } | ||
| 997 | 1015 | ||
| 998 | if (!v9ses->extended) { | 1016 | if (!v9ses->extended) { |
| 999 | retval = -EBADF; | 1017 | retval = -EBADF; |
| 1000 | dprintk(DEBUG_ERROR, "not extended\n"); | 1018 | dprintk(DEBUG_ERROR, "not extended\n"); |
| 1001 | goto FreeFcall; | 1019 | goto ClunkFid; |
| 1002 | } | 1020 | } |
| 1003 | 1021 | ||
| 1004 | dprintk(DEBUG_VFS, " %s\n", dentry->d_name.name); | 1022 | dprintk(DEBUG_VFS, " %s\n", dentry->d_name.name); |
| @@ -1009,8 +1027,10 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
| 1009 | goto FreeFcall; | 1027 | goto FreeFcall; |
| 1010 | } | 1028 | } |
| 1011 | 1029 | ||
| 1012 | if (!fcall) | 1030 | if (!fcall) { |
| 1013 | return -EIO; | 1031 | retval = -EIO; |
| 1032 | goto ClunkFid; | ||
| 1033 | } | ||
| 1014 | 1034 | ||
| 1015 | if (!(fcall->params.rstat.stat.mode & V9FS_DMSYMLINK)) { | 1035 | if (!(fcall->params.rstat.stat.mode & V9FS_DMSYMLINK)) { |
| 1016 | retval = -EINVAL; | 1036 | retval = -EINVAL; |
| @@ -1028,9 +1048,12 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
| 1028 | fcall->params.rstat.stat.extension.str, buffer); | 1048 | fcall->params.rstat.stat.extension.str, buffer); |
| 1029 | retval = buflen; | 1049 | retval = buflen; |
| 1030 | 1050 | ||
| 1031 | FreeFcall: | 1051 | FreeFcall: |
| 1032 | kfree(fcall); | 1052 | kfree(fcall); |
| 1033 | 1053 | ||
| 1054 | ClunkFid: | ||
| 1055 | v9fs_fid_clunk(v9ses, fid); | ||
| 1056 | |||
| 1034 | return retval; | 1057 | return retval; |
| 1035 | } | 1058 | } |
| 1036 | 1059 | ||
| @@ -1123,52 +1146,58 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, | |||
| 1123 | int err; | 1146 | int err; |
| 1124 | u32 fid, perm; | 1147 | u32 fid, perm; |
| 1125 | struct v9fs_session_info *v9ses; | 1148 | struct v9fs_session_info *v9ses; |
| 1126 | struct v9fs_fid *dfid, *vfid; | 1149 | struct v9fs_fid *dfid, *vfid = NULL; |
| 1127 | struct inode *inode; | 1150 | struct inode *inode = NULL; |
| 1128 | 1151 | ||
| 1129 | inode = NULL; | ||
| 1130 | vfid = NULL; | ||
| 1131 | v9ses = v9fs_inode2v9ses(dir); | 1152 | v9ses = v9fs_inode2v9ses(dir); |
| 1132 | dfid = v9fs_fid_lookup(dentry->d_parent); | ||
| 1133 | perm = unixmode2p9mode(v9ses, mode); | ||
| 1134 | |||
| 1135 | if (!v9ses->extended) { | 1153 | if (!v9ses->extended) { |
| 1136 | dprintk(DEBUG_ERROR, "not extended\n"); | 1154 | dprintk(DEBUG_ERROR, "not extended\n"); |
| 1137 | return -EPERM; | 1155 | return -EPERM; |
| 1138 | } | 1156 | } |
| 1139 | 1157 | ||
| 1158 | dfid = v9fs_fid_clone(dentry->d_parent); | ||
| 1159 | if(IS_ERR(dfid)) { | ||
| 1160 | err = PTR_ERR(dfid); | ||
| 1161 | goto error; | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | perm = unixmode2p9mode(v9ses, mode); | ||
| 1165 | |||
| 1140 | err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, | 1166 | err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, |
| 1141 | perm, V9FS_OREAD, (char *) extension, &fid, NULL, NULL); | 1167 | perm, V9FS_OREAD, (char *) extension, &fid, NULL, NULL); |
| 1142 | 1168 | ||
| 1143 | if (err) | 1169 | if (err) |
| 1144 | goto error; | 1170 | goto clunk_dfid; |
| 1145 | 1171 | ||
| 1146 | err = v9fs_t_clunk(v9ses, fid); | 1172 | err = v9fs_t_clunk(v9ses, fid); |
| 1147 | if (err) | 1173 | if (err) |
| 1148 | goto error; | 1174 | goto clunk_dfid; |
| 1149 | 1175 | ||
| 1150 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); | 1176 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); |
| 1151 | if (IS_ERR(vfid)) { | 1177 | if (IS_ERR(vfid)) { |
| 1152 | err = PTR_ERR(vfid); | 1178 | err = PTR_ERR(vfid); |
| 1153 | vfid = NULL; | 1179 | vfid = NULL; |
| 1154 | goto error; | 1180 | goto clunk_dfid; |
| 1155 | } | 1181 | } |
| 1156 | 1182 | ||
| 1157 | inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); | 1183 | inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); |
| 1158 | if (IS_ERR(inode)) { | 1184 | if (IS_ERR(inode)) { |
| 1159 | err = PTR_ERR(inode); | 1185 | err = PTR_ERR(inode); |
| 1160 | inode = NULL; | 1186 | inode = NULL; |
| 1161 | goto error; | 1187 | goto free_vfid; |
| 1162 | } | 1188 | } |
| 1163 | 1189 | ||
| 1164 | dentry->d_op = &v9fs_dentry_operations; | 1190 | dentry->d_op = &v9fs_dentry_operations; |
| 1165 | d_instantiate(dentry, inode); | 1191 | d_instantiate(dentry, inode); |
| 1166 | return 0; | 1192 | return 0; |
| 1167 | 1193 | ||
| 1168 | error: | 1194 | free_vfid: |
| 1169 | if (vfid) | 1195 | v9fs_fid_destroy(vfid); |
| 1170 | v9fs_fid_destroy(vfid); | 1196 | |
| 1197 | clunk_dfid: | ||
| 1198 | v9fs_fid_clunk(v9ses, dfid); | ||
| 1171 | 1199 | ||
| 1200 | error: | ||
| 1172 | return err; | 1201 | return err; |
| 1173 | 1202 | ||
| 1174 | } | 1203 | } |
| @@ -1209,26 +1238,29 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, | |||
| 1209 | struct dentry *dentry) | 1238 | struct dentry *dentry) |
| 1210 | { | 1239 | { |
| 1211 | int retval; | 1240 | int retval; |
| 1241 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); | ||
| 1212 | struct v9fs_fid *oldfid; | 1242 | struct v9fs_fid *oldfid; |
| 1213 | char *name; | 1243 | char *name; |
| 1214 | 1244 | ||
| 1215 | dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, | 1245 | dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, |
| 1216 | old_dentry->d_name.name); | 1246 | old_dentry->d_name.name); |
| 1217 | 1247 | ||
| 1218 | oldfid = v9fs_fid_lookup(old_dentry); | 1248 | oldfid = v9fs_fid_clone(old_dentry); |
| 1219 | if (!oldfid) { | 1249 | if(IS_ERR(oldfid)) |
| 1220 | dprintk(DEBUG_ERROR, "can't find oldfid\n"); | 1250 | return PTR_ERR(oldfid); |
| 1221 | return -EPERM; | ||
| 1222 | } | ||
| 1223 | 1251 | ||
| 1224 | name = __getname(); | 1252 | name = __getname(); |
| 1225 | if (unlikely(!name)) | 1253 | if (unlikely(!name)) { |
| 1226 | return -ENOMEM; | 1254 | retval = -ENOMEM; |
| 1255 | goto clunk_fid; | ||
| 1256 | } | ||
| 1227 | 1257 | ||
| 1228 | sprintf(name, "%d\n", oldfid->fid); | 1258 | sprintf(name, "%d\n", oldfid->fid); |
| 1229 | retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name); | 1259 | retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name); |
| 1230 | __putname(name); | 1260 | __putname(name); |
| 1231 | 1261 | ||
| 1262 | clunk_fid: | ||
| 1263 | v9fs_fid_clunk(v9ses, oldfid); | ||
| 1232 | return retval; | 1264 | return retval; |
| 1233 | } | 1265 | } |
| 1234 | 1266 | ||
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 7cb28720f90e..669dbe5b0317 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
| @@ -682,6 +682,15 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
| 682 | retval = PTR_ERR(interpreter); | 682 | retval = PTR_ERR(interpreter); |
| 683 | if (IS_ERR(interpreter)) | 683 | if (IS_ERR(interpreter)) |
| 684 | goto out_free_interp; | 684 | goto out_free_interp; |
| 685 | |||
| 686 | /* | ||
| 687 | * If the binary is not readable then enforce | ||
| 688 | * mm->dumpable = 0 regardless of the interpreter's | ||
| 689 | * permissions. | ||
| 690 | */ | ||
| 691 | if (file_permission(interpreter, MAY_READ) < 0) | ||
| 692 | bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP; | ||
| 693 | |||
| 685 | retval = kernel_read(interpreter, 0, bprm->buf, | 694 | retval = kernel_read(interpreter, 0, bprm->buf, |
| 686 | BINPRM_BUF_SIZE); | 695 | BINPRM_BUF_SIZE); |
| 687 | if (retval != BINPRM_BUF_SIZE) { | 696 | if (retval != BINPRM_BUF_SIZE) { |
| @@ -1178,6 +1187,10 @@ static int dump_seek(struct file *file, loff_t off) | |||
| 1178 | */ | 1187 | */ |
| 1179 | static int maydump(struct vm_area_struct *vma) | 1188 | static int maydump(struct vm_area_struct *vma) |
| 1180 | { | 1189 | { |
| 1190 | /* The vma can be set up to tell us the answer directly. */ | ||
| 1191 | if (vma->vm_flags & VM_ALWAYSDUMP) | ||
| 1192 | return 1; | ||
| 1193 | |||
| 1181 | /* Do not dump I/O mapped devices or special mappings */ | 1194 | /* Do not dump I/O mapped devices or special mappings */ |
| 1182 | if (vma->vm_flags & (VM_IO | VM_RESERVED)) | 1195 | if (vma->vm_flags & (VM_IO | VM_RESERVED)) |
| 1183 | return 0; | 1196 | return 0; |
| @@ -1424,6 +1437,32 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t) | |||
| 1424 | return sz; | 1437 | return sz; |
| 1425 | } | 1438 | } |
| 1426 | 1439 | ||
| 1440 | static struct vm_area_struct *first_vma(struct task_struct *tsk, | ||
| 1441 | struct vm_area_struct *gate_vma) | ||
| 1442 | { | ||
| 1443 | struct vm_area_struct *ret = tsk->mm->mmap; | ||
| 1444 | |||
| 1445 | if (ret) | ||
| 1446 | return ret; | ||
| 1447 | return gate_vma; | ||
| 1448 | } | ||
| 1449 | /* | ||
| 1450 | * Helper function for iterating across a vma list. It ensures that the caller | ||
| 1451 | * will visit `gate_vma' prior to terminating the search. | ||
| 1452 | */ | ||
| 1453 | static struct vm_area_struct *next_vma(struct vm_area_struct *this_vma, | ||
| 1454 | struct vm_area_struct *gate_vma) | ||
| 1455 | { | ||
| 1456 | struct vm_area_struct *ret; | ||
| 1457 | |||
| 1458 | ret = this_vma->vm_next; | ||
| 1459 | if (ret) | ||
| 1460 | return ret; | ||
| 1461 | if (this_vma == gate_vma) | ||
| 1462 | return NULL; | ||
| 1463 | return gate_vma; | ||
| 1464 | } | ||
| 1465 | |||
| 1427 | /* | 1466 | /* |
| 1428 | * Actual dumper | 1467 | * Actual dumper |
| 1429 | * | 1468 | * |
| @@ -1439,7 +1478,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) | |||
| 1439 | int segs; | 1478 | int segs; |
| 1440 | size_t size = 0; | 1479 | size_t size = 0; |
| 1441 | int i; | 1480 | int i; |
| 1442 | struct vm_area_struct *vma; | 1481 | struct vm_area_struct *vma, *gate_vma; |
| 1443 | struct elfhdr *elf = NULL; | 1482 | struct elfhdr *elf = NULL; |
| 1444 | loff_t offset = 0, dataoff, foffset; | 1483 | loff_t offset = 0, dataoff, foffset; |
| 1445 | unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; | 1484 | unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; |
| @@ -1525,6 +1564,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) | |||
| 1525 | segs += ELF_CORE_EXTRA_PHDRS; | 1564 | segs += ELF_CORE_EXTRA_PHDRS; |
| 1526 | #endif | 1565 | #endif |
| 1527 | 1566 | ||
| 1567 | gate_vma = get_gate_vma(current); | ||
| 1568 | if (gate_vma != NULL) | ||
| 1569 | segs++; | ||
| 1570 | |||
| 1528 | /* Set up header */ | 1571 | /* Set up header */ |
| 1529 | fill_elf_header(elf, segs + 1); /* including notes section */ | 1572 | fill_elf_header(elf, segs + 1); /* including notes section */ |
| 1530 | 1573 | ||
| @@ -1592,7 +1635,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) | |||
| 1592 | dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); | 1635 | dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); |
| 1593 | 1636 | ||
| 1594 | /* Write program headers for segments dump */ | 1637 | /* Write program headers for segments dump */ |
| 1595 | for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { | 1638 | for (vma = first_vma(current, gate_vma); vma != NULL; |
| 1639 | vma = next_vma(vma, gate_vma)) { | ||
| 1596 | struct elf_phdr phdr; | 1640 | struct elf_phdr phdr; |
| 1597 | size_t sz; | 1641 | size_t sz; |
| 1598 | 1642 | ||
| @@ -1641,7 +1685,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) | |||
| 1641 | /* Align to page */ | 1685 | /* Align to page */ |
| 1642 | DUMP_SEEK(dataoff - foffset); | 1686 | DUMP_SEEK(dataoff - foffset); |
| 1643 | 1687 | ||
| 1644 | for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { | 1688 | for (vma = first_vma(current, gate_vma); vma != NULL; |
| 1689 | vma = next_vma(vma, gate_vma)) { | ||
| 1645 | unsigned long addr; | 1690 | unsigned long addr; |
| 1646 | 1691 | ||
| 1647 | if (!maydump(vma)) | 1692 | if (!maydump(vma)) |
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 6e6d4568d548..a4d933a51208 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
| @@ -234,6 +234,14 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, | |||
| 234 | goto error; | 234 | goto error; |
| 235 | } | 235 | } |
| 236 | 236 | ||
| 237 | /* | ||
| 238 | * If the binary is not readable then enforce | ||
| 239 | * mm->dumpable = 0 regardless of the interpreter's | ||
| 240 | * permissions. | ||
| 241 | */ | ||
| 242 | if (file_permission(interpreter, MAY_READ) < 0) | ||
| 243 | bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP; | ||
| 244 | |||
| 237 | retval = kernel_read(interpreter, 0, bprm->buf, | 245 | retval = kernel_read(interpreter, 0, bprm->buf, |
| 238 | BINPRM_BUF_SIZE); | 246 | BINPRM_BUF_SIZE); |
| 239 | if (retval < 0) | 247 | if (retval < 0) |
diff --git a/fs/buffer.c b/fs/buffer.c index 3b116078b4c3..460f1c43238e 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -2834,7 +2834,7 @@ int try_to_free_buffers(struct page *page) | |||
| 2834 | int ret = 0; | 2834 | int ret = 0; |
| 2835 | 2835 | ||
| 2836 | BUG_ON(!PageLocked(page)); | 2836 | BUG_ON(!PageLocked(page)); |
| 2837 | if (PageDirty(page) || PageWriteback(page)) | 2837 | if (PageWriteback(page)) |
| 2838 | return 0; | 2838 | return 0; |
| 2839 | 2839 | ||
| 2840 | if (mapping == NULL) { /* can this still happen? */ | 2840 | if (mapping == NULL) { /* can this still happen? */ |
| @@ -2845,6 +2845,19 @@ int try_to_free_buffers(struct page *page) | |||
| 2845 | spin_lock(&mapping->private_lock); | 2845 | spin_lock(&mapping->private_lock); |
| 2846 | ret = drop_buffers(page, &buffers_to_free); | 2846 | ret = drop_buffers(page, &buffers_to_free); |
| 2847 | spin_unlock(&mapping->private_lock); | 2847 | spin_unlock(&mapping->private_lock); |
| 2848 | |||
| 2849 | /* | ||
| 2850 | * If the filesystem writes its buffers by hand (eg ext3) | ||
| 2851 | * then we can have clean buffers against a dirty page. We | ||
| 2852 | * clean the page here; otherwise the VM will never notice | ||
| 2853 | * that the filesystem did any IO at all. | ||
| 2854 | * | ||
| 2855 | * Also, during truncate, discard_buffer will have marked all | ||
| 2856 | * the page's buffers clean. We discover that here and clean | ||
| 2857 | * the page also. | ||
| 2858 | */ | ||
| 2859 | if (ret) | ||
| 2860 | cancel_dirty_page(page, PAGE_CACHE_SIZE); | ||
| 2848 | out: | 2861 | out: |
| 2849 | if (buffers_to_free) { | 2862 | if (buffers_to_free) { |
| 2850 | struct buffer_head *bh = buffers_to_free; | 2863 | struct buffer_head *bh = buffers_to_free; |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index c403b66ec83c..a4b142a6a2c7 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
| @@ -251,8 +251,19 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
| 251 | WARN_ON(inode->i_state & I_WILL_FREE); | 251 | WARN_ON(inode->i_state & I_WILL_FREE); |
| 252 | 252 | ||
| 253 | if ((wbc->sync_mode != WB_SYNC_ALL) && (inode->i_state & I_LOCK)) { | 253 | if ((wbc->sync_mode != WB_SYNC_ALL) && (inode->i_state & I_LOCK)) { |
| 254 | struct address_space *mapping = inode->i_mapping; | ||
| 255 | int ret; | ||
| 256 | |||
| 254 | list_move(&inode->i_list, &inode->i_sb->s_dirty); | 257 | list_move(&inode->i_list, &inode->i_sb->s_dirty); |
| 255 | return 0; | 258 | |
| 259 | /* | ||
| 260 | * Even if we don't actually write the inode itself here, | ||
| 261 | * we can at least start some of the data writeout.. | ||
| 262 | */ | ||
| 263 | spin_unlock(&inode_lock); | ||
| 264 | ret = do_writepages(mapping, wbc); | ||
| 265 | spin_lock(&inode_lock); | ||
| 266 | return ret; | ||
| 256 | } | 267 | } |
| 257 | 268 | ||
| 258 | /* | 269 | /* |
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 277df40f098d..e695660921ec 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c | |||
| @@ -990,15 +990,16 @@ encode_entry(struct readdir_cd *ccd, const char *name, | |||
| 990 | } | 990 | } |
| 991 | 991 | ||
| 992 | int | 992 | int |
| 993 | nfs3svc_encode_entry(struct readdir_cd *cd, const char *name, | 993 | nfs3svc_encode_entry(void *cd, const char *name, |
| 994 | int namlen, loff_t offset, ino_t ino, unsigned int d_type) | 994 | int namlen, loff_t offset, u64 ino, unsigned int d_type) |
| 995 | { | 995 | { |
| 996 | return encode_entry(cd, name, namlen, offset, ino, d_type, 0); | 996 | return encode_entry(cd, name, namlen, offset, ino, d_type, 0); |
| 997 | } | 997 | } |
| 998 | 998 | ||
| 999 | int | 999 | int |
| 1000 | nfs3svc_encode_entry_plus(struct readdir_cd *cd, const char *name, | 1000 | nfs3svc_encode_entry_plus(void *cd, const char *name, |
| 1001 | int namlen, loff_t offset, ino_t ino, unsigned int d_type) | 1001 | int namlen, loff_t offset, u64 ino, |
| 1002 | unsigned int d_type) | ||
| 1002 | { | 1003 | { |
| 1003 | return encode_entry(cd, name, namlen, offset, ino, d_type, 1); | 1004 | return encode_entry(cd, name, namlen, offset, ino, d_type, 1); |
| 1004 | } | 1005 | } |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index fea46368afb2..18aa9440df14 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
| @@ -1880,9 +1880,10 @@ nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr) | |||
| 1880 | } | 1880 | } |
| 1881 | 1881 | ||
| 1882 | static int | 1882 | static int |
| 1883 | nfsd4_encode_dirent(struct readdir_cd *ccd, const char *name, int namlen, | 1883 | nfsd4_encode_dirent(void *ccdv, const char *name, int namlen, |
| 1884 | loff_t offset, ino_t ino, unsigned int d_type) | 1884 | loff_t offset, u64 ino, unsigned int d_type) |
| 1885 | { | 1885 | { |
| 1886 | struct readdir_cd *ccd = ccdv; | ||
| 1886 | struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common); | 1887 | struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common); |
| 1887 | int buflen; | 1888 | int buflen; |
| 1888 | __be32 *p = cd->buffer; | 1889 | __be32 *p = cd->buffer; |
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 0aaccb03bf76..fbf5d51947ea 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
| @@ -72,7 +72,7 @@ static struct svc_program nfsd_acl_program = { | |||
| 72 | .pg_prog = NFS_ACL_PROGRAM, | 72 | .pg_prog = NFS_ACL_PROGRAM, |
| 73 | .pg_nvers = NFSD_ACL_NRVERS, | 73 | .pg_nvers = NFSD_ACL_NRVERS, |
| 74 | .pg_vers = nfsd_acl_versions, | 74 | .pg_vers = nfsd_acl_versions, |
| 75 | .pg_name = "nfsd", | 75 | .pg_name = "nfsacl", |
| 76 | .pg_class = "nfsd", | 76 | .pg_class = "nfsd", |
| 77 | .pg_stats = &nfsd_acl_svcstats, | 77 | .pg_stats = &nfsd_acl_svcstats, |
| 78 | .pg_authenticate = &svc_set_client, | 78 | .pg_authenticate = &svc_set_client, |
| @@ -118,16 +118,16 @@ int nfsd_vers(int vers, enum vers_op change) | |||
| 118 | switch(change) { | 118 | switch(change) { |
| 119 | case NFSD_SET: | 119 | case NFSD_SET: |
| 120 | nfsd_versions[vers] = nfsd_version[vers]; | 120 | nfsd_versions[vers] = nfsd_version[vers]; |
| 121 | break; | ||
| 122 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) | 121 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) |
| 123 | if (vers < NFSD_ACL_NRVERS) | 122 | if (vers < NFSD_ACL_NRVERS) |
| 124 | nfsd_acl_version[vers] = nfsd_acl_version[vers]; | 123 | nfsd_acl_versions[vers] = nfsd_acl_version[vers]; |
| 125 | #endif | 124 | #endif |
| 125 | break; | ||
| 126 | case NFSD_CLEAR: | 126 | case NFSD_CLEAR: |
| 127 | nfsd_versions[vers] = NULL; | 127 | nfsd_versions[vers] = NULL; |
| 128 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) | 128 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) |
| 129 | if (vers < NFSD_ACL_NRVERS) | 129 | if (vers < NFSD_ACL_NRVERS) |
| 130 | nfsd_acl_version[vers] = NULL; | 130 | nfsd_acl_versions[vers] = NULL; |
| 131 | #endif | 131 | #endif |
| 132 | break; | 132 | break; |
| 133 | case NFSD_TEST: | 133 | case NFSD_TEST: |
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index f5243f943996..6555c50d9006 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c | |||
| @@ -462,9 +462,10 @@ nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p, | |||
| 462 | } | 462 | } |
| 463 | 463 | ||
| 464 | int | 464 | int |
| 465 | nfssvc_encode_entry(struct readdir_cd *ccd, const char *name, | 465 | nfssvc_encode_entry(void *ccdv, const char *name, |
| 466 | int namlen, loff_t offset, ino_t ino, unsigned int d_type) | 466 | int namlen, loff_t offset, u64 ino, unsigned int d_type) |
| 467 | { | 467 | { |
| 468 | struct readdir_cd *ccd = ccdv; | ||
| 468 | struct nfsd_readdirres *cd = container_of(ccd, struct nfsd_readdirres, common); | 469 | struct nfsd_readdirres *cd = container_of(ccd, struct nfsd_readdirres, common); |
| 469 | __be32 *p = cd->buffer; | 470 | __be32 *p = cd->buffer; |
| 470 | int buflen, slen; | 471 | int buflen, slen; |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 7a79c23aa6d4..5d32e5fa697e 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -822,7 +822,8 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset | |||
| 822 | rqstp->rq_res.page_len = size; | 822 | rqstp->rq_res.page_len = size; |
| 823 | } else if (page != pp[-1]) { | 823 | } else if (page != pp[-1]) { |
| 824 | get_page(page); | 824 | get_page(page); |
| 825 | put_page(*pp); | 825 | if (*pp) |
| 826 | put_page(*pp); | ||
| 826 | *pp = page; | 827 | *pp = page; |
| 827 | rqstp->rq_resused++; | 828 | rqstp->rq_resused++; |
| 828 | rqstp->rq_res.page_len += size; | 829 | rqstp->rq_res.page_len += size; |
| @@ -1244,7 +1245,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1244 | __be32 err; | 1245 | __be32 err; |
| 1245 | int host_err; | 1246 | int host_err; |
| 1246 | __u32 v_mtime=0, v_atime=0; | 1247 | __u32 v_mtime=0, v_atime=0; |
| 1247 | int v_mode=0; | ||
| 1248 | 1248 | ||
| 1249 | err = nfserr_perm; | 1249 | err = nfserr_perm; |
| 1250 | if (!flen) | 1250 | if (!flen) |
| @@ -1281,16 +1281,11 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1281 | goto out; | 1281 | goto out; |
| 1282 | 1282 | ||
| 1283 | if (createmode == NFS3_CREATE_EXCLUSIVE) { | 1283 | if (createmode == NFS3_CREATE_EXCLUSIVE) { |
| 1284 | /* while the verifier would fit in mtime+atime, | 1284 | /* solaris7 gets confused (bugid 4218508) if these have |
| 1285 | * solaris7 gets confused (bugid 4218508) if these have | 1285 | * the high bit set, so just clear the high bits. |
| 1286 | * the high bit set, so we use the mode as well | ||
| 1287 | */ | 1286 | */ |
| 1288 | v_mtime = verifier[0]&0x7fffffff; | 1287 | v_mtime = verifier[0]&0x7fffffff; |
| 1289 | v_atime = verifier[1]&0x7fffffff; | 1288 | v_atime = verifier[1]&0x7fffffff; |
| 1290 | v_mode = S_IFREG | ||
| 1291 | | ((verifier[0]&0x80000000) >> (32-7)) /* u+x */ | ||
| 1292 | | ((verifier[1]&0x80000000) >> (32-9)) /* u+r */ | ||
| 1293 | ; | ||
| 1294 | } | 1289 | } |
| 1295 | 1290 | ||
| 1296 | if (dchild->d_inode) { | 1291 | if (dchild->d_inode) { |
| @@ -1318,7 +1313,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1318 | case NFS3_CREATE_EXCLUSIVE: | 1313 | case NFS3_CREATE_EXCLUSIVE: |
| 1319 | if ( dchild->d_inode->i_mtime.tv_sec == v_mtime | 1314 | if ( dchild->d_inode->i_mtime.tv_sec == v_mtime |
| 1320 | && dchild->d_inode->i_atime.tv_sec == v_atime | 1315 | && dchild->d_inode->i_atime.tv_sec == v_atime |
| 1321 | && dchild->d_inode->i_mode == v_mode | ||
| 1322 | && dchild->d_inode->i_size == 0 ) | 1316 | && dchild->d_inode->i_size == 0 ) |
| 1323 | break; | 1317 | break; |
| 1324 | /* fallthru */ | 1318 | /* fallthru */ |
| @@ -1340,26 +1334,22 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1340 | } | 1334 | } |
| 1341 | 1335 | ||
| 1342 | if (createmode == NFS3_CREATE_EXCLUSIVE) { | 1336 | if (createmode == NFS3_CREATE_EXCLUSIVE) { |
| 1343 | /* Cram the verifier into atime/mtime/mode */ | 1337 | /* Cram the verifier into atime/mtime */ |
| 1344 | iap->ia_valid = ATTR_MTIME|ATTR_ATIME | 1338 | iap->ia_valid = ATTR_MTIME|ATTR_ATIME |
| 1345 | | ATTR_MTIME_SET|ATTR_ATIME_SET | 1339 | | ATTR_MTIME_SET|ATTR_ATIME_SET; |
| 1346 | | ATTR_MODE; | ||
| 1347 | /* XXX someone who knows this better please fix it for nsec */ | 1340 | /* XXX someone who knows this better please fix it for nsec */ |
| 1348 | iap->ia_mtime.tv_sec = v_mtime; | 1341 | iap->ia_mtime.tv_sec = v_mtime; |
| 1349 | iap->ia_atime.tv_sec = v_atime; | 1342 | iap->ia_atime.tv_sec = v_atime; |
| 1350 | iap->ia_mtime.tv_nsec = 0; | 1343 | iap->ia_mtime.tv_nsec = 0; |
| 1351 | iap->ia_atime.tv_nsec = 0; | 1344 | iap->ia_atime.tv_nsec = 0; |
| 1352 | iap->ia_mode = v_mode; | ||
| 1353 | } | 1345 | } |
| 1354 | 1346 | ||
| 1355 | /* Set file attributes. | 1347 | /* Set file attributes. |
| 1356 | * Mode has already been set but we might need to reset it | ||
| 1357 | * for CREATE_EXCLUSIVE | ||
| 1358 | * Irix appears to send along the gid when it tries to | 1348 | * Irix appears to send along the gid when it tries to |
| 1359 | * implement setgid directories via NFS. Clear out all that cruft. | 1349 | * implement setgid directories via NFS. Clear out all that cruft. |
| 1360 | */ | 1350 | */ |
| 1361 | set_attr: | 1351 | set_attr: |
| 1362 | if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) { | 1352 | if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) { |
| 1363 | __be32 err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); | 1353 | __be32 err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); |
| 1364 | if (err2) | 1354 | if (err2) |
| 1365 | err = err2; | 1355 | err = err2; |
| @@ -1726,7 +1716,7 @@ out: | |||
| 1726 | */ | 1716 | */ |
| 1727 | __be32 | 1717 | __be32 |
| 1728 | nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, | 1718 | nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, |
| 1729 | struct readdir_cd *cdp, encode_dent_fn func) | 1719 | struct readdir_cd *cdp, filldir_t func) |
| 1730 | { | 1720 | { |
| 1731 | __be32 err; | 1721 | __be32 err; |
| 1732 | int host_err; | 1722 | int host_err; |
| @@ -1751,7 +1741,7 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, | |||
| 1751 | 1741 | ||
| 1752 | do { | 1742 | do { |
| 1753 | cdp->err = nfserr_eof; /* will be cleared on successful read */ | 1743 | cdp->err = nfserr_eof; /* will be cleared on successful read */ |
| 1754 | host_err = vfs_readdir(file, (filldir_t) func, cdp); | 1744 | host_err = vfs_readdir(file, func, cdp); |
| 1755 | } while (host_err >=0 && cdp->err == nfs_ok); | 1745 | } while (host_err >=0 && cdp->err == nfs_ok); |
| 1756 | if (host_err) | 1746 | if (host_err) |
| 1757 | err = nfserrno(host_err); | 1747 | err = nfserrno(host_err); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 77a57b5799c4..ff7a66850602 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -371,9 +371,11 @@ static int mounts_open(struct inode *inode, struct file *file) | |||
| 371 | 371 | ||
| 372 | if (task) { | 372 | if (task) { |
| 373 | task_lock(task); | 373 | task_lock(task); |
| 374 | ns = task->nsproxy->mnt_ns; | 374 | if (task->nsproxy) { |
| 375 | if (ns) | 375 | ns = task->nsproxy->mnt_ns; |
| 376 | get_mnt_ns(ns); | 376 | if (ns) |
| 377 | get_mnt_ns(ns); | ||
| 378 | } | ||
| 377 | task_unlock(task); | 379 | task_unlock(task); |
| 378 | put_task_struct(task); | 380 | put_task_struct(task); |
| 379 | } | 381 | } |
diff --git a/include/asm-i386/elf.h b/include/asm-i386/elf.h index 45d21a0c95bf..369035dfe4b6 100644 --- a/include/asm-i386/elf.h +++ b/include/asm-i386/elf.h | |||
| @@ -143,11 +143,8 @@ extern int dump_task_extended_fpu (struct task_struct *, struct user_fxsr_struct | |||
| 143 | # define VDSO_PRELINK 0 | 143 | # define VDSO_PRELINK 0 |
| 144 | #endif | 144 | #endif |
| 145 | 145 | ||
| 146 | #define VDSO_COMPAT_SYM(x) \ | ||
| 147 | (VDSO_COMPAT_BASE + (unsigned long)(x) - VDSO_PRELINK) | ||
| 148 | |||
| 149 | #define VDSO_SYM(x) \ | 146 | #define VDSO_SYM(x) \ |
| 150 | (VDSO_BASE + (unsigned long)(x) - VDSO_PRELINK) | 147 | (VDSO_COMPAT_BASE + (unsigned long)(x) - VDSO_PRELINK) |
| 151 | 148 | ||
| 152 | #define VDSO_HIGH_EHDR ((const struct elfhdr *) VDSO_HIGH_BASE) | 149 | #define VDSO_HIGH_EHDR ((const struct elfhdr *) VDSO_HIGH_BASE) |
| 153 | #define VDSO_EHDR ((const struct elfhdr *) VDSO_COMPAT_BASE) | 150 | #define VDSO_EHDR ((const struct elfhdr *) VDSO_COMPAT_BASE) |
| @@ -156,10 +153,12 @@ extern void __kernel_vsyscall; | |||
| 156 | 153 | ||
| 157 | #define VDSO_ENTRY VDSO_SYM(&__kernel_vsyscall) | 154 | #define VDSO_ENTRY VDSO_SYM(&__kernel_vsyscall) |
| 158 | 155 | ||
| 156 | #ifndef CONFIG_COMPAT_VDSO | ||
| 159 | #define ARCH_HAS_SETUP_ADDITIONAL_PAGES | 157 | #define ARCH_HAS_SETUP_ADDITIONAL_PAGES |
| 160 | struct linux_binprm; | 158 | struct linux_binprm; |
| 161 | extern int arch_setup_additional_pages(struct linux_binprm *bprm, | 159 | extern int arch_setup_additional_pages(struct linux_binprm *bprm, |
| 162 | int executable_stack); | 160 | int executable_stack); |
| 161 | #endif | ||
| 163 | 162 | ||
| 164 | extern unsigned int vdso_enabled; | 163 | extern unsigned int vdso_enabled; |
| 165 | 164 | ||
| @@ -169,50 +168,6 @@ do if (vdso_enabled) { \ | |||
| 169 | NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_COMPAT_BASE); \ | 168 | NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_COMPAT_BASE); \ |
| 170 | } while (0) | 169 | } while (0) |
| 171 | 170 | ||
| 172 | /* | ||
| 173 | * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out | ||
| 174 | * extra segments containing the vsyscall DSO contents. Dumping its | ||
| 175 | * contents makes post-mortem fully interpretable later without matching up | ||
| 176 | * the same kernel and hardware config to see what PC values meant. | ||
| 177 | * Dumping its extra ELF program headers includes all the other information | ||
| 178 | * a debugger needs to easily find how the vsyscall DSO was being used. | ||
| 179 | */ | ||
| 180 | #define ELF_CORE_EXTRA_PHDRS (VDSO_HIGH_EHDR->e_phnum) | ||
| 181 | #define ELF_CORE_WRITE_EXTRA_PHDRS \ | ||
| 182 | do { \ | ||
| 183 | const struct elf_phdr *const vsyscall_phdrs = \ | ||
| 184 | (const struct elf_phdr *) (VDSO_HIGH_BASE \ | ||
| 185 | + VDSO_HIGH_EHDR->e_phoff); \ | ||
| 186 | int i; \ | ||
| 187 | Elf32_Off ofs = 0; \ | ||
| 188 | for (i = 0; i < VDSO_HIGH_EHDR->e_phnum; ++i) { \ | ||
| 189 | struct elf_phdr phdr = vsyscall_phdrs[i]; \ | ||
| 190 | if (phdr.p_type == PT_LOAD) { \ | ||
| 191 | BUG_ON(ofs != 0); \ | ||
| 192 | ofs = phdr.p_offset = offset; \ | ||
| 193 | phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \ | ||
| 194 | phdr.p_filesz = phdr.p_memsz; \ | ||
| 195 | offset += phdr.p_filesz; \ | ||
| 196 | } \ | ||
| 197 | else \ | ||
| 198 | phdr.p_offset += ofs; \ | ||
| 199 | phdr.p_paddr = 0; /* match other core phdrs */ \ | ||
| 200 | DUMP_WRITE(&phdr, sizeof(phdr)); \ | ||
| 201 | } \ | ||
| 202 | } while (0) | ||
| 203 | #define ELF_CORE_WRITE_EXTRA_DATA \ | ||
| 204 | do { \ | ||
| 205 | const struct elf_phdr *const vsyscall_phdrs = \ | ||
| 206 | (const struct elf_phdr *) (VDSO_HIGH_BASE \ | ||
| 207 | + VDSO_HIGH_EHDR->e_phoff); \ | ||
| 208 | int i; \ | ||
| 209 | for (i = 0; i < VDSO_HIGH_EHDR->e_phnum; ++i) { \ | ||
| 210 | if (vsyscall_phdrs[i].p_type == PT_LOAD) \ | ||
| 211 | DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr, \ | ||
| 212 | PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \ | ||
| 213 | } \ | ||
| 214 | } while (0) | ||
| 215 | |||
| 216 | #endif | 171 | #endif |
| 217 | 172 | ||
| 218 | #endif | 173 | #endif |
diff --git a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h index 02428cb36621..3e9f610c35df 100644 --- a/include/asm-i386/fixmap.h +++ b/include/asm-i386/fixmap.h | |||
| @@ -23,6 +23,8 @@ | |||
| 23 | extern unsigned long __FIXADDR_TOP; | 23 | extern unsigned long __FIXADDR_TOP; |
| 24 | #else | 24 | #else |
| 25 | #define __FIXADDR_TOP 0xfffff000 | 25 | #define __FIXADDR_TOP 0xfffff000 |
| 26 | #define FIXADDR_USER_START __fix_to_virt(FIX_VDSO) | ||
| 27 | #define FIXADDR_USER_END __fix_to_virt(FIX_VDSO - 1) | ||
| 26 | #endif | 28 | #endif |
| 27 | 29 | ||
| 28 | #ifndef __ASSEMBLY__ | 30 | #ifndef __ASSEMBLY__ |
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h index fd3f64ace248..7b19f454761d 100644 --- a/include/asm-i386/page.h +++ b/include/asm-i386/page.h | |||
| @@ -143,7 +143,9 @@ extern int page_is_ram(unsigned long pagenr); | |||
| 143 | #include <asm-generic/memory_model.h> | 143 | #include <asm-generic/memory_model.h> |
| 144 | #include <asm-generic/page.h> | 144 | #include <asm-generic/page.h> |
| 145 | 145 | ||
| 146 | #ifndef CONFIG_COMPAT_VDSO | ||
| 146 | #define __HAVE_ARCH_GATE_AREA 1 | 147 | #define __HAVE_ARCH_GATE_AREA 1 |
| 148 | #endif | ||
| 147 | #endif /* __KERNEL__ */ | 149 | #endif /* __KERNEL__ */ |
| 148 | 150 | ||
| 149 | #endif /* _I386_PAGE_H */ | 151 | #endif /* _I386_PAGE_H */ |
diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h index d5dbc87274f8..c0eac519840b 100644 --- a/include/asm-x86_64/uaccess.h +++ b/include/asm-x86_64/uaccess.h | |||
| @@ -157,7 +157,7 @@ do { \ | |||
| 157 | case 1: __put_user_asm(x,ptr,retval,"b","b","iq",-EFAULT); break;\ | 157 | case 1: __put_user_asm(x,ptr,retval,"b","b","iq",-EFAULT); break;\ |
| 158 | case 2: __put_user_asm(x,ptr,retval,"w","w","ir",-EFAULT); break;\ | 158 | case 2: __put_user_asm(x,ptr,retval,"w","w","ir",-EFAULT); break;\ |
| 159 | case 4: __put_user_asm(x,ptr,retval,"l","k","ir",-EFAULT); break;\ | 159 | case 4: __put_user_asm(x,ptr,retval,"l","k","ir",-EFAULT); break;\ |
| 160 | case 8: __put_user_asm(x,ptr,retval,"q","","ir",-EFAULT); break;\ | 160 | case 8: __put_user_asm(x,ptr,retval,"q","","Zr",-EFAULT); break;\ |
| 161 | default: __put_user_bad(); \ | 161 | default: __put_user_bad(); \ |
| 162 | } \ | 162 | } \ |
| 163 | } while (0) | 163 | } while (0) |
diff --git a/include/linux/bitops.h b/include/linux/bitops.h index 5d1eabcde5d5..638165f571da 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h | |||
| @@ -31,9 +31,8 @@ static inline unsigned long hweight_long(unsigned long w) | |||
| 31 | return sizeof(w) == 4 ? hweight32(w) : hweight64(w); | 31 | return sizeof(w) == 4 ? hweight32(w) : hweight64(w); |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | /* | 34 | /** |
| 35 | * rol32 - rotate a 32-bit value left | 35 | * rol32 - rotate a 32-bit value left |
| 36 | * | ||
| 37 | * @word: value to rotate | 36 | * @word: value to rotate |
| 38 | * @shift: bits to roll | 37 | * @shift: bits to roll |
| 39 | */ | 38 | */ |
| @@ -42,9 +41,8 @@ static inline __u32 rol32(__u32 word, unsigned int shift) | |||
| 42 | return (word << shift) | (word >> (32 - shift)); | 41 | return (word << shift) | (word >> (32 - shift)); |
| 43 | } | 42 | } |
| 44 | 43 | ||
| 45 | /* | 44 | /** |
| 46 | * ror32 - rotate a 32-bit value right | 45 | * ror32 - rotate a 32-bit value right |
| 47 | * | ||
| 48 | * @word: value to rotate | 46 | * @word: value to rotate |
| 49 | * @shift: bits to roll | 47 | * @shift: bits to roll |
| 50 | */ | 48 | */ |
diff --git a/include/linux/kvm.h b/include/linux/kvm.h index bc8b4616bad7..1be148f0fce4 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h | |||
| @@ -46,6 +46,7 @@ enum kvm_exit_reason { | |||
| 46 | KVM_EXIT_HLT = 5, | 46 | KVM_EXIT_HLT = 5, |
| 47 | KVM_EXIT_MMIO = 6, | 47 | KVM_EXIT_MMIO = 6, |
| 48 | KVM_EXIT_IRQ_WINDOW_OPEN = 7, | 48 | KVM_EXIT_IRQ_WINDOW_OPEN = 7, |
| 49 | KVM_EXIT_SHUTDOWN = 8, | ||
| 49 | }; | 50 | }; |
| 50 | 51 | ||
| 51 | /* for KVM_RUN */ | 52 | /* for KVM_RUN */ |
diff --git a/include/linux/list.h b/include/linux/list.h index a9c90287c0ff..611059d633f4 100644 --- a/include/linux/list.h +++ b/include/linux/list.h | |||
| @@ -227,13 +227,13 @@ static inline void list_replace_init(struct list_head *old, | |||
| 227 | INIT_LIST_HEAD(old); | 227 | INIT_LIST_HEAD(old); |
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | /* | 230 | /** |
| 231 | * list_replace_rcu - replace old entry by new one | 231 | * list_replace_rcu - replace old entry by new one |
| 232 | * @old : the element to be replaced | 232 | * @old : the element to be replaced |
| 233 | * @new : the new element to insert | 233 | * @new : the new element to insert |
| 234 | * | 234 | * |
| 235 | * The old entry will be replaced with the new entry atomically. | 235 | * The @old entry will be replaced with the @new entry atomically. |
| 236 | * Note: 'old' should not be empty. | 236 | * Note: @old should not be empty. |
| 237 | */ | 237 | */ |
| 238 | static inline void list_replace_rcu(struct list_head *old, | 238 | static inline void list_replace_rcu(struct list_head *old, |
| 239 | struct list_head *new) | 239 | struct list_head *new) |
| @@ -680,12 +680,12 @@ static inline void hlist_del_init(struct hlist_node *n) | |||
| 680 | } | 680 | } |
| 681 | } | 681 | } |
| 682 | 682 | ||
| 683 | /* | 683 | /** |
| 684 | * hlist_replace_rcu - replace old entry by new one | 684 | * hlist_replace_rcu - replace old entry by new one |
| 685 | * @old : the element to be replaced | 685 | * @old : the element to be replaced |
| 686 | * @new : the new element to insert | 686 | * @new : the new element to insert |
| 687 | * | 687 | * |
| 688 | * The old entry will be replaced with the new entry atomically. | 688 | * The @old entry will be replaced with the @new entry atomically. |
| 689 | */ | 689 | */ |
| 690 | static inline void hlist_replace_rcu(struct hlist_node *old, | 690 | static inline void hlist_replace_rcu(struct hlist_node *old, |
| 691 | struct hlist_node *new) | 691 | struct hlist_node *new) |
diff --git a/include/linux/mm.h b/include/linux/mm.h index 76912231af41..2d2c08d5f473 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -168,6 +168,7 @@ extern unsigned int kobjsize(const void *objp); | |||
| 168 | #define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */ | 168 | #define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */ |
| 169 | #define VM_MAPPED_COPY 0x01000000 /* T if mapped copy of data (nommu mmap) */ | 169 | #define VM_MAPPED_COPY 0x01000000 /* T if mapped copy of data (nommu mmap) */ |
| 170 | #define VM_INSERTPAGE 0x02000000 /* The vma has had "vm_insert_page()" done on it */ | 170 | #define VM_INSERTPAGE 0x02000000 /* The vma has had "vm_insert_page()" done on it */ |
| 171 | #define VM_ALWAYSDUMP 0x04000000 /* Always include in core dumps */ | ||
| 171 | 172 | ||
| 172 | #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */ | 173 | #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */ |
| 173 | #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS | 174 | #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS |
diff --git a/include/linux/mutex.h b/include/linux/mutex.h index a7544afd7582..b81bc2adaeff 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h | |||
| @@ -105,7 +105,7 @@ do { \ | |||
| 105 | extern void __mutex_init(struct mutex *lock, const char *name, | 105 | extern void __mutex_init(struct mutex *lock, const char *name, |
| 106 | struct lock_class_key *key); | 106 | struct lock_class_key *key); |
| 107 | 107 | ||
| 108 | /*** | 108 | /** |
| 109 | * mutex_is_locked - is the mutex locked | 109 | * mutex_is_locked - is the mutex locked |
| 110 | * @lock: the mutex to be queried | 110 | * @lock: the mutex to be queried |
| 111 | * | 111 | * |
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index 0727774772ba..4b7c4b568f6d 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h | |||
| @@ -52,8 +52,6 @@ | |||
| 52 | struct readdir_cd { | 52 | struct readdir_cd { |
| 53 | __be32 err; /* 0, nfserr, or nfserr_eof */ | 53 | __be32 err; /* 0, nfserr, or nfserr_eof */ |
| 54 | }; | 54 | }; |
| 55 | typedef int (*encode_dent_fn)(struct readdir_cd *, const char *, | ||
| 56 | int, loff_t, ino_t, unsigned int); | ||
| 57 | typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int); | 55 | typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int); |
| 58 | 56 | ||
| 59 | extern struct svc_program nfsd_program; | 57 | extern struct svc_program nfsd_program; |
| @@ -117,7 +115,7 @@ __be32 nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type, | |||
| 117 | int nfsd_truncate(struct svc_rqst *, struct svc_fh *, | 115 | int nfsd_truncate(struct svc_rqst *, struct svc_fh *, |
| 118 | unsigned long size); | 116 | unsigned long size); |
| 119 | __be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *, | 117 | __be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *, |
| 120 | loff_t *, struct readdir_cd *, encode_dent_fn); | 118 | loff_t *, struct readdir_cd *, filldir_t); |
| 121 | __be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *, | 119 | __be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *, |
| 122 | struct kstatfs *); | 120 | struct kstatfs *); |
| 123 | 121 | ||
diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h index f3b51d62ec7d..d9c6c382165d 100644 --- a/include/linux/nfsd/nfsfh.h +++ b/include/linux/nfsd/nfsfh.h | |||
| @@ -217,11 +217,7 @@ void fh_put(struct svc_fh *); | |||
| 217 | static __inline__ struct svc_fh * | 217 | static __inline__ struct svc_fh * |
| 218 | fh_copy(struct svc_fh *dst, struct svc_fh *src) | 218 | fh_copy(struct svc_fh *dst, struct svc_fh *src) |
| 219 | { | 219 | { |
| 220 | if (src->fh_dentry || src->fh_locked) { | 220 | WARN_ON(src->fh_dentry || src->fh_locked); |
| 221 | struct dentry *dentry = src->fh_dentry; | ||
| 222 | printk(KERN_ERR "fh_copy: copying %s/%s, already verified!\n", | ||
| 223 | dentry->d_parent->d_name.name, dentry->d_name.name); | ||
| 224 | } | ||
| 225 | 221 | ||
| 226 | *dst = *src; | 222 | *dst = *src; |
| 227 | return dst; | 223 | return dst; |
| @@ -300,10 +296,8 @@ fh_lock_nested(struct svc_fh *fhp, unsigned int subclass) | |||
| 300 | dfprintk(FILEOP, "nfsd: fh_lock(%s) locked = %d\n", | 296 | dfprintk(FILEOP, "nfsd: fh_lock(%s) locked = %d\n", |
| 301 | SVCFH_fmt(fhp), fhp->fh_locked); | 297 | SVCFH_fmt(fhp), fhp->fh_locked); |
| 302 | 298 | ||
| 303 | if (!fhp->fh_dentry) { | 299 | BUG_ON(!dentry); |
| 304 | printk(KERN_ERR "fh_lock: fh not verified!\n"); | 300 | |
| 305 | return; | ||
| 306 | } | ||
| 307 | if (fhp->fh_locked) { | 301 | if (fhp->fh_locked) { |
| 308 | printk(KERN_WARNING "fh_lock: %s/%s already locked!\n", | 302 | printk(KERN_WARNING "fh_lock: %s/%s already locked!\n", |
| 309 | dentry->d_parent->d_name.name, dentry->d_name.name); | 303 | dentry->d_parent->d_name.name, dentry->d_name.name); |
| @@ -328,8 +322,7 @@ fh_lock(struct svc_fh *fhp) | |||
| 328 | static inline void | 322 | static inline void |
| 329 | fh_unlock(struct svc_fh *fhp) | 323 | fh_unlock(struct svc_fh *fhp) |
| 330 | { | 324 | { |
| 331 | if (!fhp->fh_dentry) | 325 | BUG_ON(!fhp->fh_dentry); |
| 332 | printk(KERN_ERR "fh_unlock: fh not verified!\n"); | ||
| 333 | 326 | ||
| 334 | if (fhp->fh_locked) { | 327 | if (fhp->fh_locked) { |
| 335 | fill_post_wcc(fhp); | 328 | fill_post_wcc(fhp); |
diff --git a/include/linux/nfsd/xdr.h b/include/linux/nfsd/xdr.h index 877192d3ae79..67885d5e6e50 100644 --- a/include/linux/nfsd/xdr.h +++ b/include/linux/nfsd/xdr.h | |||
| @@ -165,8 +165,8 @@ int nfssvc_encode_readres(struct svc_rqst *, __be32 *, struct nfsd_readres *); | |||
| 165 | int nfssvc_encode_statfsres(struct svc_rqst *, __be32 *, struct nfsd_statfsres *); | 165 | int nfssvc_encode_statfsres(struct svc_rqst *, __be32 *, struct nfsd_statfsres *); |
| 166 | int nfssvc_encode_readdirres(struct svc_rqst *, __be32 *, struct nfsd_readdirres *); | 166 | int nfssvc_encode_readdirres(struct svc_rqst *, __be32 *, struct nfsd_readdirres *); |
| 167 | 167 | ||
| 168 | int nfssvc_encode_entry(struct readdir_cd *, const char *name, | 168 | int nfssvc_encode_entry(void *, const char *name, |
| 169 | int namlen, loff_t offset, ino_t ino, unsigned int); | 169 | int namlen, loff_t offset, u64 ino, unsigned int); |
| 170 | 170 | ||
| 171 | int nfssvc_release_fhandle(struct svc_rqst *, __be32 *, struct nfsd_fhandle *); | 171 | int nfssvc_release_fhandle(struct svc_rqst *, __be32 *, struct nfsd_fhandle *); |
| 172 | 172 | ||
diff --git a/include/linux/nfsd/xdr3.h b/include/linux/nfsd/xdr3.h index 79963867b0d7..89d9d6061a62 100644 --- a/include/linux/nfsd/xdr3.h +++ b/include/linux/nfsd/xdr3.h | |||
| @@ -331,11 +331,11 @@ int nfs3svc_release_fhandle(struct svc_rqst *, __be32 *, | |||
| 331 | struct nfsd3_attrstat *); | 331 | struct nfsd3_attrstat *); |
| 332 | int nfs3svc_release_fhandle2(struct svc_rqst *, __be32 *, | 332 | int nfs3svc_release_fhandle2(struct svc_rqst *, __be32 *, |
| 333 | struct nfsd3_fhandle_pair *); | 333 | struct nfsd3_fhandle_pair *); |
| 334 | int nfs3svc_encode_entry(struct readdir_cd *, const char *name, | 334 | int nfs3svc_encode_entry(void *, const char *name, |
| 335 | int namlen, loff_t offset, ino_t ino, | 335 | int namlen, loff_t offset, u64 ino, |
| 336 | unsigned int); | 336 | unsigned int); |
| 337 | int nfs3svc_encode_entry_plus(struct readdir_cd *, const char *name, | 337 | int nfs3svc_encode_entry_plus(void *, const char *name, |
| 338 | int namlen, loff_t offset, ino_t ino, | 338 | int namlen, loff_t offset, u64 ino, |
| 339 | unsigned int); | 339 | unsigned int); |
| 340 | /* Helper functions for NFSv3 ACL code */ | 340 | /* Helper functions for NFSv3 ACL code */ |
| 341 | __be32 *nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, | 341 | __be32 *nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, |
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h index 866a1e2b0ce0..fbaeda79b2e9 100644 --- a/include/linux/raid/md.h +++ b/include/linux/raid/md.h | |||
| @@ -94,7 +94,7 @@ extern int sync_page_io(struct block_device *bdev, sector_t sector, int size, | |||
| 94 | struct page *page, int rw); | 94 | struct page *page, int rw); |
| 95 | extern void md_do_sync(mddev_t *mddev); | 95 | extern void md_do_sync(mddev_t *mddev); |
| 96 | extern void md_new_event(mddev_t *mddev); | 96 | extern void md_new_event(mddev_t *mddev); |
| 97 | 97 | extern void md_allow_write(mddev_t *mddev); | |
| 98 | 98 | ||
| 99 | #endif /* CONFIG_MD */ | 99 | #endif /* CONFIG_MD */ |
| 100 | #endif | 100 | #endif |
diff --git a/include/linux/rtmutex.h b/include/linux/rtmutex.h index b0090e9f7884..382bb7951166 100644 --- a/include/linux/rtmutex.h +++ b/include/linux/rtmutex.h | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | #include <linux/plist.h> | 16 | #include <linux/plist.h> |
| 17 | #include <linux/spinlock_types.h> | 17 | #include <linux/spinlock_types.h> |
| 18 | 18 | ||
| 19 | /* | 19 | /** |
| 20 | * The rt_mutex structure | 20 | * The rt_mutex structure |
| 21 | * | 21 | * |
| 22 | * @wait_lock: spinlock to protect the structure | 22 | * @wait_lock: spinlock to protect the structure |
| @@ -71,7 +71,7 @@ struct hrtimer_sleeper; | |||
| 71 | #define DEFINE_RT_MUTEX(mutexname) \ | 71 | #define DEFINE_RT_MUTEX(mutexname) \ |
| 72 | struct rt_mutex mutexname = __RT_MUTEX_INITIALIZER(mutexname) | 72 | struct rt_mutex mutexname = __RT_MUTEX_INITIALIZER(mutexname) |
| 73 | 73 | ||
| 74 | /*** | 74 | /** |
| 75 | * rt_mutex_is_locked - is the mutex locked | 75 | * rt_mutex_is_locked - is the mutex locked |
| 76 | * @lock: the mutex to be queried | 76 | * @lock: the mutex to be queried |
| 77 | * | 77 | * |
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 965d6c20086e..64f3d60c72af 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h | |||
| @@ -144,8 +144,11 @@ extern u32 svc_max_payload(const struct svc_rqst *rqstp); | |||
| 144 | * | 144 | * |
| 145 | * Each request/reply pair can have at most one "payload", plus two pages, | 145 | * Each request/reply pair can have at most one "payload", plus two pages, |
| 146 | * one for the request, and one for the reply. | 146 | * one for the request, and one for the reply. |
| 147 | * We using ->sendfile to return read data, we might need one extra page | ||
| 148 | * if the request is not page-aligned. So add another '1'. | ||
| 147 | */ | 149 | */ |
| 148 | #define RPCSVC_MAXPAGES ((RPCSVC_MAXPAYLOAD+PAGE_SIZE-1)/PAGE_SIZE + 2) | 150 | #define RPCSVC_MAXPAGES ((RPCSVC_MAXPAYLOAD+PAGE_SIZE-1)/PAGE_SIZE \ |
| 151 | + 2 + 1) | ||
| 149 | 152 | ||
| 150 | static inline u32 svc_getnl(struct kvec *iov) | 153 | static inline u32 svc_getnl(struct kvec *iov) |
| 151 | { | 154 | { |
diff --git a/include/linux/timer.h b/include/linux/timer.h index eeef6643d4c6..fb5edaaf0ebd 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h | |||
| @@ -41,7 +41,7 @@ static inline void setup_timer(struct timer_list * timer, | |||
| 41 | init_timer(timer); | 41 | init_timer(timer); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | /*** | 44 | /** |
| 45 | * timer_pending - is a timer pending? | 45 | * timer_pending - is a timer pending? |
| 46 | * @timer: the timer in question | 46 | * @timer: the timer in question |
| 47 | * | 47 | * |
| @@ -63,7 +63,7 @@ extern int mod_timer(struct timer_list *timer, unsigned long expires); | |||
| 63 | 63 | ||
| 64 | extern unsigned long next_timer_interrupt(void); | 64 | extern unsigned long next_timer_interrupt(void); |
| 65 | 65 | ||
| 66 | /*** | 66 | /** |
| 67 | * add_timer - start a timer | 67 | * add_timer - start a timer |
| 68 | * @timer: the timer to be added | 68 | * @timer: the timer to be added |
| 69 | * | 69 | * |
diff --git a/mm/memory.c b/mm/memory.c index af227d26e104..ef09f0acb1d8 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
| @@ -2606,8 +2606,15 @@ static int __init gate_vma_init(void) | |||
| 2606 | gate_vma.vm_mm = NULL; | 2606 | gate_vma.vm_mm = NULL; |
| 2607 | gate_vma.vm_start = FIXADDR_USER_START; | 2607 | gate_vma.vm_start = FIXADDR_USER_START; |
| 2608 | gate_vma.vm_end = FIXADDR_USER_END; | 2608 | gate_vma.vm_end = FIXADDR_USER_END; |
| 2609 | gate_vma.vm_page_prot = PAGE_READONLY; | 2609 | gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC; |
| 2610 | gate_vma.vm_flags = 0; | 2610 | gate_vma.vm_page_prot = __P101; |
| 2611 | /* | ||
| 2612 | * Make sure the vDSO gets into every core dump. | ||
| 2613 | * Dumping its contents makes post-mortem fully interpretable later | ||
| 2614 | * without matching up the same kernel and hardware config to see | ||
| 2615 | * what PC values meant. | ||
| 2616 | */ | ||
| 2617 | gate_vma.vm_flags |= VM_ALWAYSDUMP; | ||
| 2611 | return 0; | 2618 | return 0; |
| 2612 | } | 2619 | } |
| 2613 | __initcall(gate_vma_init); | 2620 | __initcall(gate_vma_init); |
diff --git a/mm/truncate.c b/mm/truncate.c index 6c79ca4a1ca7..5df947de7654 100644 --- a/mm/truncate.c +++ b/mm/truncate.c | |||
| @@ -51,15 +51,22 @@ static inline void truncate_partial_page(struct page *page, unsigned partial) | |||
| 51 | do_invalidatepage(page, partial); | 51 | do_invalidatepage(page, partial); |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | /* | ||
| 55 | * This cancels just the dirty bit on the kernel page itself, it | ||
| 56 | * does NOT actually remove dirty bits on any mmap's that may be | ||
| 57 | * around. It also leaves the page tagged dirty, so any sync | ||
| 58 | * activity will still find it on the dirty lists, and in particular, | ||
| 59 | * clear_page_dirty_for_io() will still look at the dirty bits in | ||
| 60 | * the VM. | ||
| 61 | * | ||
| 62 | * Doing this should *normally* only ever be done when a page | ||
| 63 | * is truncated, and is not actually mapped anywhere at all. However, | ||
| 64 | * fs/buffer.c does this when it notices that somebody has cleaned | ||
| 65 | * out all the buffers on a page without actually doing it through | ||
| 66 | * the VM. Can you say "ext3 is horribly ugly"? Tought you could. | ||
| 67 | */ | ||
| 54 | void cancel_dirty_page(struct page *page, unsigned int account_size) | 68 | void cancel_dirty_page(struct page *page, unsigned int account_size) |
| 55 | { | 69 | { |
| 56 | /* If we're cancelling the page, it had better not be mapped any more */ | ||
| 57 | if (page_mapped(page)) { | ||
| 58 | static unsigned int warncount; | ||
| 59 | |||
| 60 | WARN_ON(++warncount < 5); | ||
| 61 | } | ||
| 62 | |||
| 63 | if (TestClearPageDirty(page)) { | 70 | if (TestClearPageDirty(page)) { |
| 64 | struct address_space *mapping = page->mapping; | 71 | struct address_space *mapping = page->mapping; |
| 65 | if (mapping && mapping_cap_account_dirty(mapping)) { | 72 | if (mapping && mapping_cap_account_dirty(mapping)) { |
| @@ -422,7 +429,6 @@ int invalidate_inode_pages2_range(struct address_space *mapping, | |||
| 422 | pagevec_release(&pvec); | 429 | pagevec_release(&pvec); |
| 423 | cond_resched(); | 430 | cond_resched(); |
| 424 | } | 431 | } |
| 425 | WARN_ON_ONCE(ret); | ||
| 426 | return ret; | 432 | return ret; |
| 427 | } | 433 | } |
| 428 | EXPORT_SYMBOL_GPL(invalidate_inode_pages2_range); | 434 | EXPORT_SYMBOL_GPL(invalidate_inode_pages2_range); |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index f3001f3626f6..bf21a2047010 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
| @@ -910,7 +910,8 @@ err_bad_prog: | |||
| 910 | 910 | ||
| 911 | err_bad_vers: | 911 | err_bad_vers: |
| 912 | #ifdef RPC_PARANOIA | 912 | #ifdef RPC_PARANOIA |
| 913 | printk("svc: unknown version (%d)\n", vers); | 913 | printk("svc: unknown version (%d for prog %d, %s)\n", |
| 914 | vers, prog, progp->pg_name); | ||
| 914 | #endif | 915 | #endif |
| 915 | serv->sv_stats->rpcbadfmt++; | 916 | serv->sv_stats->rpcbadfmt++; |
| 916 | svc_putnl(resv, RPC_PROG_MISMATCH); | 917 | svc_putnl(resv, RPC_PROG_MISMATCH); |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 99f54fb6d669..45120f268d03 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
| @@ -1278,6 +1278,8 @@ svc_recv(struct svc_rqst *rqstp, long timeout) | |||
| 1278 | schedule_timeout_uninterruptible(msecs_to_jiffies(500)); | 1278 | schedule_timeout_uninterruptible(msecs_to_jiffies(500)); |
| 1279 | rqstp->rq_pages[i] = p; | 1279 | rqstp->rq_pages[i] = p; |
| 1280 | } | 1280 | } |
| 1281 | rqstp->rq_pages[i++] = NULL; /* this might be seen in nfs_read_actor */ | ||
| 1282 | BUG_ON(pages >= RPCSVC_MAXPAGES); | ||
| 1281 | 1283 | ||
| 1282 | /* Make arg->head point to first page and arg->pages point to rest */ | 1284 | /* Make arg->head point to first page and arg->pages point to rest */ |
| 1283 | arg = &rqstp->rq_arg; | 1285 | arg = &rqstp->rq_arg; |
