diff options
66 files changed, 1095 insertions, 884 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 09497ba15d5d..3d4179fbc526 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3164,7 +3164,7 @@ F: drivers/net/ioc3-eth.c | |||
3164 | 3164 | ||
3165 | IOC3 SERIAL DRIVER | 3165 | IOC3 SERIAL DRIVER |
3166 | M: Pat Gefre <pfg@sgi.com> | 3166 | M: Pat Gefre <pfg@sgi.com> |
3167 | L: linux-mips@linux-mips.org | 3167 | L: linux-serial@vger.kernel.org |
3168 | S: Maintained | 3168 | S: Maintained |
3169 | F: drivers/serial/ioc3_serial.c | 3169 | F: drivers/serial/ioc3_serial.c |
3170 | 3170 | ||
@@ -1,7 +1,7 @@ | |||
1 | VERSION = 2 | 1 | VERSION = 2 |
2 | PATCHLEVEL = 6 | 2 | PATCHLEVEL = 6 |
3 | SUBLEVEL = 36 | 3 | SUBLEVEL = 36 |
4 | EXTRAVERSION = -rc8 | 4 | EXTRAVERSION = |
5 | NAME = Flesh-Eating Bats with Fangs | 5 | NAME = Flesh-Eating Bats with Fangs |
6 | 6 | ||
7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/m32r/include/asm/elf.h b/arch/m32r/include/asm/elf.h index 2f85412ef730..b8da7d0574d2 100644 --- a/arch/m32r/include/asm/elf.h +++ b/arch/m32r/include/asm/elf.h | |||
@@ -82,9 +82,9 @@ typedef elf_fpreg_t elf_fpregset_t; | |||
82 | * These are used to set parameters in the core dumps. | 82 | * These are used to set parameters in the core dumps. |
83 | */ | 83 | */ |
84 | #define ELF_CLASS ELFCLASS32 | 84 | #define ELF_CLASS ELFCLASS32 |
85 | #if defined(__LITTLE_ENDIAN) | 85 | #if defined(__LITTLE_ENDIAN__) |
86 | #define ELF_DATA ELFDATA2LSB | 86 | #define ELF_DATA ELFDATA2LSB |
87 | #elif defined(__BIG_ENDIAN) | 87 | #elif defined(__BIG_ENDIAN__) |
88 | #define ELF_DATA ELFDATA2MSB | 88 | #define ELF_DATA ELFDATA2MSB |
89 | #else | 89 | #else |
90 | #error no endian defined | 90 | #error no endian defined |
diff --git a/arch/m32r/kernel/.gitignore b/arch/m32r/kernel/.gitignore new file mode 100644 index 000000000000..c5f676c3c224 --- /dev/null +++ b/arch/m32r/kernel/.gitignore | |||
@@ -0,0 +1 @@ | |||
vmlinux.lds | |||
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c index 7bbe38645ed5..a08697f0886d 100644 --- a/arch/m32r/kernel/signal.c +++ b/arch/m32r/kernel/signal.c | |||
@@ -28,6 +28,8 @@ | |||
28 | 28 | ||
29 | #define DEBUG_SIG 0 | 29 | #define DEBUG_SIG 0 |
30 | 30 | ||
31 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||
32 | |||
31 | asmlinkage int | 33 | asmlinkage int |
32 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 34 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, |
33 | unsigned long r2, unsigned long r3, unsigned long r4, | 35 | unsigned long r2, unsigned long r3, unsigned long r4, |
@@ -254,7 +256,7 @@ give_sigsegv: | |||
254 | static int prev_insn(struct pt_regs *regs) | 256 | static int prev_insn(struct pt_regs *regs) |
255 | { | 257 | { |
256 | u16 inst; | 258 | u16 inst; |
257 | if (get_user(&inst, (u16 __user *)(regs->bpc - 2))) | 259 | if (get_user(inst, (u16 __user *)(regs->bpc - 2))) |
258 | return -EFAULT; | 260 | return -EFAULT; |
259 | if ((inst & 0xfff0) == 0x10f0) /* trap ? */ | 261 | if ((inst & 0xfff0) == 0x10f0) /* trap ? */ |
260 | regs->bpc -= 2; | 262 | regs->bpc -= 2; |
diff --git a/arch/mips/Kbuild b/arch/mips/Kbuild index e322d65f33a4..7dd65cfae837 100644 --- a/arch/mips/Kbuild +++ b/arch/mips/Kbuild | |||
@@ -7,6 +7,10 @@ subdir-ccflags-y := -Werror | |||
7 | include arch/mips/Kbuild.platforms | 7 | include arch/mips/Kbuild.platforms |
8 | obj-y := $(platform-y) | 8 | obj-y := $(platform-y) |
9 | 9 | ||
10 | # make clean traverses $(obj-) without having included .config, so | ||
11 | # everything ends up here | ||
12 | obj- := $(platform-) | ||
13 | |||
10 | # mips object files | 14 | # mips object files |
11 | # The object files are linked as core-y files would be linked | 15 | # The object files are linked as core-y files would be linked |
12 | 16 | ||
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 5526faabfc21..4c9f402295dd 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -881,11 +881,15 @@ config NO_IOPORT | |||
881 | config GENERIC_ISA_DMA | 881 | config GENERIC_ISA_DMA |
882 | bool | 882 | bool |
883 | select ZONE_DMA if GENERIC_ISA_DMA_SUPPORT_BROKEN=n | 883 | select ZONE_DMA if GENERIC_ISA_DMA_SUPPORT_BROKEN=n |
884 | select ISA_DMA_API | ||
884 | 885 | ||
885 | config GENERIC_ISA_DMA_SUPPORT_BROKEN | 886 | config GENERIC_ISA_DMA_SUPPORT_BROKEN |
886 | bool | 887 | bool |
887 | select GENERIC_ISA_DMA | 888 | select GENERIC_ISA_DMA |
888 | 889 | ||
890 | config ISA_DMA_API | ||
891 | bool | ||
892 | |||
889 | config GENERIC_GPIO | 893 | config GENERIC_GPIO |
890 | bool | 894 | bool |
891 | 895 | ||
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile index 5fd7f7a58b7e..5042d51b0512 100644 --- a/arch/mips/boot/compressed/Makefile +++ b/arch/mips/boot/compressed/Makefile | |||
@@ -105,4 +105,4 @@ OBJCOPYFLAGS_vmlinuz.srec := $(OBJCOPYFLAGS) -S -O srec | |||
105 | vmlinuz.srec: vmlinuz | 105 | vmlinuz.srec: vmlinuz |
106 | $(call cmd,objcopy) | 106 | $(call cmd,objcopy) |
107 | 107 | ||
108 | clean-files := $(objtree)/vmlinuz.* | 108 | clean-files := $(objtree)/vmlinuz $(objtree)/vmlinuz.{32,ecoff,bin,srec} |
diff --git a/arch/mips/dec/Platform b/arch/mips/dec/Platform index 3adbcbd95db1..cf55a6f4e720 100644 --- a/arch/mips/dec/Platform +++ b/arch/mips/dec/Platform | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # DECstation family | 2 | # DECstation family |
3 | # | 3 | # |
4 | platform-$(CONFIG_MACH_DECSTATION) = dec/ | 4 | platform-$(CONFIG_MACH_DECSTATION) += dec/ |
5 | cflags-$(CONFIG_MACH_DECSTATION) += \ | 5 | cflags-$(CONFIG_MACH_DECSTATION) += \ |
6 | -I$(srctree)/arch/mips/include/asm/mach-dec | 6 | -I$(srctree)/arch/mips/include/asm/mach-dec |
7 | libs-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/prom/ | 7 | libs-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/prom/ |
diff --git a/arch/mips/include/asm/fcntl.h b/arch/mips/include/asm/fcntl.h index e482fe90fe88..75eddedcfc3e 100644 --- a/arch/mips/include/asm/fcntl.h +++ b/arch/mips/include/asm/fcntl.h | |||
@@ -56,6 +56,7 @@ | |||
56 | */ | 56 | */ |
57 | 57 | ||
58 | #ifdef CONFIG_32BIT | 58 | #ifdef CONFIG_32BIT |
59 | #include <linux/types.h> | ||
59 | 60 | ||
60 | struct flock { | 61 | struct flock { |
61 | short l_type; | 62 | short l_type; |
diff --git a/arch/mips/jz4740/Platform b/arch/mips/jz4740/Platform index 6a97230e3d05..ba91be9c21ef 100644 --- a/arch/mips/jz4740/Platform +++ b/arch/mips/jz4740/Platform | |||
@@ -1,3 +1,3 @@ | |||
1 | core-$(CONFIG_MACH_JZ4740) += arch/mips/jz4740/ | 1 | platform-$(CONFIG_MACH_JZ4740) += jz4740/ |
2 | cflags-$(CONFIG_MACH_JZ4740) += -I$(srctree)/arch/mips/include/asm/mach-jz4740 | 2 | cflags-$(CONFIG_MACH_JZ4740) += -I$(srctree)/arch/mips/include/asm/mach-jz4740 |
3 | load-$(CONFIG_MACH_JZ4740) += 0xffffffff80010000 | 3 | load-$(CONFIG_MACH_JZ4740) += 0xffffffff80010000 |
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index 0176ed015c89..32103cc2a257 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c | |||
@@ -40,7 +40,6 @@ int __compute_return_epc(struct pt_regs *regs) | |||
40 | return -EFAULT; | 40 | return -EFAULT; |
41 | } | 41 | } |
42 | 42 | ||
43 | regs->regs[0] = 0; | ||
44 | switch (insn.i_format.opcode) { | 43 | switch (insn.i_format.opcode) { |
45 | /* | 44 | /* |
46 | * jr and jalr are in r_format format. | 45 | * jr and jalr are in r_format format. |
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index c51b95ff8644..c8777333e198 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c | |||
@@ -536,7 +536,7 @@ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit) | |||
536 | { | 536 | { |
537 | /* do the secure computing check first */ | 537 | /* do the secure computing check first */ |
538 | if (!entryexit) | 538 | if (!entryexit) |
539 | secure_computing(regs->regs[0]); | 539 | secure_computing(regs->regs[2]); |
540 | 540 | ||
541 | if (unlikely(current->audit_context) && entryexit) | 541 | if (unlikely(current->audit_context) && entryexit) |
542 | audit_syscall_exit(AUDITSC_RESULT(regs->regs[2]), | 542 | audit_syscall_exit(AUDITSC_RESULT(regs->regs[2]), |
@@ -565,7 +565,7 @@ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit) | |||
565 | 565 | ||
566 | out: | 566 | out: |
567 | if (unlikely(current->audit_context) && !entryexit) | 567 | if (unlikely(current->audit_context) && !entryexit) |
568 | audit_syscall_entry(audit_arch(), regs->regs[0], | 568 | audit_syscall_entry(audit_arch(), regs->regs[2], |
569 | regs->regs[4], regs->regs[5], | 569 | regs->regs[4], regs->regs[5], |
570 | regs->regs[6], regs->regs[7]); | 570 | regs->regs[6], regs->regs[7]); |
571 | } | 571 | } |
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 584415eef8c9..fbaabad0e6e2 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S | |||
@@ -63,9 +63,9 @@ stack_done: | |||
63 | sw t0, PT_R7(sp) # set error flag | 63 | sw t0, PT_R7(sp) # set error flag |
64 | beqz t0, 1f | 64 | beqz t0, 1f |
65 | 65 | ||
66 | lw t1, PT_R2(sp) # syscall number | ||
66 | negu v0 # error | 67 | negu v0 # error |
67 | sw v0, PT_R0(sp) # set flag for syscall | 68 | sw t1, PT_R0(sp) # save it for syscall restarting |
68 | # restarting | ||
69 | 1: sw v0, PT_R2(sp) # result | 69 | 1: sw v0, PT_R2(sp) # result |
70 | 70 | ||
71 | o32_syscall_exit: | 71 | o32_syscall_exit: |
@@ -104,9 +104,9 @@ syscall_trace_entry: | |||
104 | sw t0, PT_R7(sp) # set error flag | 104 | sw t0, PT_R7(sp) # set error flag |
105 | beqz t0, 1f | 105 | beqz t0, 1f |
106 | 106 | ||
107 | lw t1, PT_R2(sp) # syscall number | ||
107 | negu v0 # error | 108 | negu v0 # error |
108 | sw v0, PT_R0(sp) # set flag for syscall | 109 | sw t1, PT_R0(sp) # save it for syscall restarting |
109 | # restarting | ||
110 | 1: sw v0, PT_R2(sp) # result | 110 | 1: sw v0, PT_R2(sp) # result |
111 | 111 | ||
112 | j syscall_exit | 112 | j syscall_exit |
@@ -169,8 +169,7 @@ stackargs: | |||
169 | * We probably should handle this case a bit more drastic. | 169 | * We probably should handle this case a bit more drastic. |
170 | */ | 170 | */ |
171 | bad_stack: | 171 | bad_stack: |
172 | negu v0 # error | 172 | li v0, EFAULT |
173 | sw v0, PT_R0(sp) | ||
174 | sw v0, PT_R2(sp) | 173 | sw v0, PT_R2(sp) |
175 | li t0, 1 # set error flag | 174 | li t0, 1 # set error flag |
176 | sw t0, PT_R7(sp) | 175 | sw t0, PT_R7(sp) |
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index 5573f8e4e326..3f4179283207 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S | |||
@@ -66,9 +66,9 @@ NESTED(handle_sys64, PT_SIZE, sp) | |||
66 | sd t0, PT_R7(sp) # set error flag | 66 | sd t0, PT_R7(sp) # set error flag |
67 | beqz t0, 1f | 67 | beqz t0, 1f |
68 | 68 | ||
69 | ld t1, PT_R2(sp) # syscall number | ||
69 | dnegu v0 # error | 70 | dnegu v0 # error |
70 | sd v0, PT_R0(sp) # set flag for syscall | 71 | sd t1, PT_R0(sp) # save it for syscall restarting |
71 | # restarting | ||
72 | 1: sd v0, PT_R2(sp) # result | 72 | 1: sd v0, PT_R2(sp) # result |
73 | 73 | ||
74 | n64_syscall_exit: | 74 | n64_syscall_exit: |
@@ -109,8 +109,9 @@ syscall_trace_entry: | |||
109 | sd t0, PT_R7(sp) # set error flag | 109 | sd t0, PT_R7(sp) # set error flag |
110 | beqz t0, 1f | 110 | beqz t0, 1f |
111 | 111 | ||
112 | ld t1, PT_R2(sp) # syscall number | ||
112 | dnegu v0 # error | 113 | dnegu v0 # error |
113 | sd v0, PT_R0(sp) # set flag for syscall restarting | 114 | sd t1, PT_R0(sp) # save it for syscall restarting |
114 | 1: sd v0, PT_R2(sp) # result | 115 | 1: sd v0, PT_R2(sp) # result |
115 | 116 | ||
116 | j syscall_exit | 117 | j syscall_exit |
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 1e38ec97672e..f08ece6d8acc 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S | |||
@@ -65,8 +65,9 @@ NESTED(handle_sysn32, PT_SIZE, sp) | |||
65 | sd t0, PT_R7(sp) # set error flag | 65 | sd t0, PT_R7(sp) # set error flag |
66 | beqz t0, 1f | 66 | beqz t0, 1f |
67 | 67 | ||
68 | ld t1, PT_R2(sp) # syscall number | ||
68 | dnegu v0 # error | 69 | dnegu v0 # error |
69 | sd v0, PT_R0(sp) # set flag for syscall restarting | 70 | sd t1, PT_R0(sp) # save it for syscall restarting |
70 | 1: sd v0, PT_R2(sp) # result | 71 | 1: sd v0, PT_R2(sp) # result |
71 | 72 | ||
72 | local_irq_disable # make sure need_resched and | 73 | local_irq_disable # make sure need_resched and |
@@ -106,8 +107,9 @@ n32_syscall_trace_entry: | |||
106 | sd t0, PT_R7(sp) # set error flag | 107 | sd t0, PT_R7(sp) # set error flag |
107 | beqz t0, 1f | 108 | beqz t0, 1f |
108 | 109 | ||
110 | ld t1, PT_R2(sp) # syscall number | ||
109 | dnegu v0 # error | 111 | dnegu v0 # error |
110 | sd v0, PT_R0(sp) # set flag for syscall restarting | 112 | sd t1, PT_R0(sp) # save it for syscall restarting |
111 | 1: sd v0, PT_R2(sp) # result | 113 | 1: sd v0, PT_R2(sp) # result |
112 | 114 | ||
113 | j syscall_exit | 115 | j syscall_exit |
@@ -320,10 +322,10 @@ EXPORT(sysn32_call_table) | |||
320 | PTR sys_cacheflush | 322 | PTR sys_cacheflush |
321 | PTR sys_cachectl | 323 | PTR sys_cachectl |
322 | PTR sys_sysmips | 324 | PTR sys_sysmips |
323 | PTR sys_io_setup /* 6200 */ | 325 | PTR compat_sys_io_setup /* 6200 */ |
324 | PTR sys_io_destroy | 326 | PTR sys_io_destroy |
325 | PTR sys_io_getevents | 327 | PTR compat_sys_io_getevents |
326 | PTR sys_io_submit | 328 | PTR compat_sys_io_submit |
327 | PTR sys_io_cancel | 329 | PTR sys_io_cancel |
328 | PTR sys_exit_group /* 6205 */ | 330 | PTR sys_exit_group /* 6205 */ |
329 | PTR sys_lookup_dcookie | 331 | PTR sys_lookup_dcookie |
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 171979fc98e5..78d768a3e19d 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S | |||
@@ -93,8 +93,9 @@ NESTED(handle_sys, PT_SIZE, sp) | |||
93 | sd t0, PT_R7(sp) # set error flag | 93 | sd t0, PT_R7(sp) # set error flag |
94 | beqz t0, 1f | 94 | beqz t0, 1f |
95 | 95 | ||
96 | ld t1, PT_R2(sp) # syscall number | ||
96 | dnegu v0 # error | 97 | dnegu v0 # error |
97 | sd v0, PT_R0(sp) # flag for syscall restarting | 98 | sd t1, PT_R0(sp) # save it for syscall restarting |
98 | 1: sd v0, PT_R2(sp) # result | 99 | 1: sd v0, PT_R2(sp) # result |
99 | 100 | ||
100 | o32_syscall_exit: | 101 | o32_syscall_exit: |
@@ -142,8 +143,9 @@ trace_a_syscall: | |||
142 | sd t0, PT_R7(sp) # set error flag | 143 | sd t0, PT_R7(sp) # set error flag |
143 | beqz t0, 1f | 144 | beqz t0, 1f |
144 | 145 | ||
146 | ld t1, PT_R2(sp) # syscall number | ||
145 | dnegu v0 # error | 147 | dnegu v0 # error |
146 | sd v0, PT_R0(sp) # set flag for syscall restarting | 148 | sd t1, PT_R0(sp) # save it for syscall restarting |
147 | 1: sd v0, PT_R2(sp) # result | 149 | 1: sd v0, PT_R2(sp) # result |
148 | 150 | ||
149 | j syscall_exit | 151 | j syscall_exit |
@@ -154,8 +156,7 @@ trace_a_syscall: | |||
154 | * The stackpointer for a call with more than 4 arguments is bad. | 156 | * The stackpointer for a call with more than 4 arguments is bad. |
155 | */ | 157 | */ |
156 | bad_stack: | 158 | bad_stack: |
157 | dnegu v0 # error | 159 | li v0, EFAULT |
158 | sd v0, PT_R0(sp) | ||
159 | sd v0, PT_R2(sp) | 160 | sd v0, PT_R2(sp) |
160 | li t0, 1 # set error flag | 161 | li t0, 1 # set error flag |
161 | sd t0, PT_R7(sp) | 162 | sd t0, PT_R7(sp) |
@@ -444,10 +445,10 @@ sys_call_table: | |||
444 | PTR compat_sys_futex | 445 | PTR compat_sys_futex |
445 | PTR compat_sys_sched_setaffinity | 446 | PTR compat_sys_sched_setaffinity |
446 | PTR compat_sys_sched_getaffinity /* 4240 */ | 447 | PTR compat_sys_sched_getaffinity /* 4240 */ |
447 | PTR sys_io_setup | 448 | PTR compat_sys_io_setup |
448 | PTR sys_io_destroy | 449 | PTR sys_io_destroy |
449 | PTR sys_io_getevents | 450 | PTR compat_sys_io_getevents |
450 | PTR sys_io_submit | 451 | PTR compat_sys_io_submit |
451 | PTR sys_io_cancel /* 4245 */ | 452 | PTR sys_io_cancel /* 4245 */ |
452 | PTR sys_exit_group | 453 | PTR sys_exit_group |
453 | PTR sys32_lookup_dcookie | 454 | PTR sys32_lookup_dcookie |
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 2099d5a4c4b7..5922342bca39 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
@@ -390,7 +390,6 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
390 | { | 390 | { |
391 | struct rt_sigframe __user *frame; | 391 | struct rt_sigframe __user *frame; |
392 | sigset_t set; | 392 | sigset_t set; |
393 | stack_t st; | ||
394 | int sig; | 393 | int sig; |
395 | 394 | ||
396 | frame = (struct rt_sigframe __user *) regs.regs[29]; | 395 | frame = (struct rt_sigframe __user *) regs.regs[29]; |
@@ -411,11 +410,9 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
411 | else if (sig) | 410 | else if (sig) |
412 | force_sig(sig, current); | 411 | force_sig(sig, current); |
413 | 412 | ||
414 | if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st))) | ||
415 | goto badframe; | ||
416 | /* It is more difficult to avoid calling this function than to | 413 | /* It is more difficult to avoid calling this function than to |
417 | call it and ignore errors. */ | 414 | call it and ignore errors. */ |
418 | do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]); | 415 | do_sigaltstack(&frame->rs_uc.uc_stack, NULL, regs.regs[29]); |
419 | 416 | ||
420 | /* | 417 | /* |
421 | * Don't let your children do this ... | 418 | * Don't let your children do this ... |
@@ -550,23 +547,26 @@ static int handle_signal(unsigned long sig, siginfo_t *info, | |||
550 | struct mips_abi *abi = current->thread.abi; | 547 | struct mips_abi *abi = current->thread.abi; |
551 | void *vdso = current->mm->context.vdso; | 548 | void *vdso = current->mm->context.vdso; |
552 | 549 | ||
553 | switch(regs->regs[0]) { | 550 | if (regs->regs[0]) { |
554 | case ERESTART_RESTARTBLOCK: | 551 | switch(regs->regs[2]) { |
555 | case ERESTARTNOHAND: | 552 | case ERESTART_RESTARTBLOCK: |
556 | regs->regs[2] = EINTR; | 553 | case ERESTARTNOHAND: |
557 | break; | ||
558 | case ERESTARTSYS: | ||
559 | if (!(ka->sa.sa_flags & SA_RESTART)) { | ||
560 | regs->regs[2] = EINTR; | 554 | regs->regs[2] = EINTR; |
561 | break; | 555 | break; |
556 | case ERESTARTSYS: | ||
557 | if (!(ka->sa.sa_flags & SA_RESTART)) { | ||
558 | regs->regs[2] = EINTR; | ||
559 | break; | ||
560 | } | ||
561 | /* fallthrough */ | ||
562 | case ERESTARTNOINTR: | ||
563 | regs->regs[7] = regs->regs[26]; | ||
564 | regs->regs[2] = regs->regs[0]; | ||
565 | regs->cp0_epc -= 4; | ||
562 | } | 566 | } |
563 | /* fallthrough */ | ||
564 | case ERESTARTNOINTR: /* Userland will reload $v0. */ | ||
565 | regs->regs[7] = regs->regs[26]; | ||
566 | regs->cp0_epc -= 8; | ||
567 | } | ||
568 | 567 | ||
569 | regs->regs[0] = 0; /* Don't deal with this again. */ | 568 | regs->regs[0] = 0; /* Don't deal with this again. */ |
569 | } | ||
570 | 570 | ||
571 | if (sig_uses_siginfo(ka)) | 571 | if (sig_uses_siginfo(ka)) |
572 | ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset, | 572 | ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset, |
@@ -575,6 +575,9 @@ static int handle_signal(unsigned long sig, siginfo_t *info, | |||
575 | ret = abi->setup_frame(vdso + abi->signal_return_offset, | 575 | ret = abi->setup_frame(vdso + abi->signal_return_offset, |
576 | ka, regs, sig, oldset); | 576 | ka, regs, sig, oldset); |
577 | 577 | ||
578 | if (ret) | ||
579 | return ret; | ||
580 | |||
578 | spin_lock_irq(¤t->sighand->siglock); | 581 | spin_lock_irq(¤t->sighand->siglock); |
579 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | 582 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); |
580 | if (!(ka->sa.sa_flags & SA_NODEFER)) | 583 | if (!(ka->sa.sa_flags & SA_NODEFER)) |
@@ -622,17 +625,13 @@ static void do_signal(struct pt_regs *regs) | |||
622 | return; | 625 | return; |
623 | } | 626 | } |
624 | 627 | ||
625 | /* | ||
626 | * Who's code doesn't conform to the restartable syscall convention | ||
627 | * dies here!!! The li instruction, a single machine instruction, | ||
628 | * must directly be followed by the syscall instruction. | ||
629 | */ | ||
630 | if (regs->regs[0]) { | 628 | if (regs->regs[0]) { |
631 | if (regs->regs[2] == ERESTARTNOHAND || | 629 | if (regs->regs[2] == ERESTARTNOHAND || |
632 | regs->regs[2] == ERESTARTSYS || | 630 | regs->regs[2] == ERESTARTSYS || |
633 | regs->regs[2] == ERESTARTNOINTR) { | 631 | regs->regs[2] == ERESTARTNOINTR) { |
632 | regs->regs[2] = regs->regs[0]; | ||
634 | regs->regs[7] = regs->regs[26]; | 633 | regs->regs[7] = regs->regs[26]; |
635 | regs->cp0_epc -= 8; | 634 | regs->cp0_epc -= 4; |
636 | } | 635 | } |
637 | if (regs->regs[2] == ERESTART_RESTARTBLOCK) { | 636 | if (regs->regs[2] == ERESTART_RESTARTBLOCK) { |
638 | regs->regs[2] = current->thread.abi->restart; | 637 | regs->regs[2] = current->thread.abi->restart; |
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index 2c5df818c65a..ee24d814d5b9 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c | |||
@@ -109,6 +109,7 @@ asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) | |||
109 | asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | 109 | asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) |
110 | { | 110 | { |
111 | struct rt_sigframe_n32 __user *frame; | 111 | struct rt_sigframe_n32 __user *frame; |
112 | mm_segment_t old_fs; | ||
112 | sigset_t set; | 113 | sigset_t set; |
113 | stack_t st; | 114 | stack_t st; |
114 | s32 sp; | 115 | s32 sp; |
@@ -143,7 +144,11 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
143 | 144 | ||
144 | /* It is more difficult to avoid calling this function than to | 145 | /* It is more difficult to avoid calling this function than to |
145 | call it and ignore errors. */ | 146 | call it and ignore errors. */ |
147 | old_fs = get_fs(); | ||
148 | set_fs(KERNEL_DS); | ||
146 | do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]); | 149 | do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]); |
150 | set_fs(old_fs); | ||
151 | |||
147 | 152 | ||
148 | /* | 153 | /* |
149 | * Don't let your children do this ... | 154 | * Don't let your children do this ... |
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 69b039ca8d83..33d5a5ce4a29 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c | |||
@@ -109,8 +109,6 @@ static void emulate_load_store_insn(struct pt_regs *regs, | |||
109 | unsigned long value; | 109 | unsigned long value; |
110 | unsigned int res; | 110 | unsigned int res; |
111 | 111 | ||
112 | regs->regs[0] = 0; | ||
113 | |||
114 | /* | 112 | /* |
115 | * This load never faults. | 113 | * This load never faults. |
116 | */ | 114 | */ |
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index 0c46e398cd8f..63c740a85b4c 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c | |||
@@ -40,6 +40,11 @@ static char *mixer = HOSTAUDIO_DEV_MIXER; | |||
40 | " This is used to specify the host mixer device to the hostaudio driver.\n"\ | 40 | " This is used to specify the host mixer device to the hostaudio driver.\n"\ |
41 | " The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n" | 41 | " The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n" |
42 | 42 | ||
43 | module_param(dsp, charp, 0644); | ||
44 | MODULE_PARM_DESC(dsp, DSP_HELP); | ||
45 | module_param(mixer, charp, 0644); | ||
46 | MODULE_PARM_DESC(mixer, MIXER_HELP); | ||
47 | |||
43 | #ifndef MODULE | 48 | #ifndef MODULE |
44 | static int set_dsp(char *name, int *add) | 49 | static int set_dsp(char *name, int *add) |
45 | { | 50 | { |
@@ -56,15 +61,6 @@ static int set_mixer(char *name, int *add) | |||
56 | } | 61 | } |
57 | 62 | ||
58 | __uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP); | 63 | __uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP); |
59 | |||
60 | #else /*MODULE*/ | ||
61 | |||
62 | module_param(dsp, charp, 0644); | ||
63 | MODULE_PARM_DESC(dsp, DSP_HELP); | ||
64 | |||
65 | module_param(mixer, charp, 0644); | ||
66 | MODULE_PARM_DESC(mixer, MIXER_HELP); | ||
67 | |||
68 | #endif | 64 | #endif |
69 | 65 | ||
70 | /* /dev/dsp file operations */ | 66 | /* /dev/dsp file operations */ |
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 1bcd208c459f..9734994cba1e 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c | |||
@@ -163,6 +163,7 @@ struct ubd { | |||
163 | struct scatterlist sg[MAX_SG]; | 163 | struct scatterlist sg[MAX_SG]; |
164 | struct request *request; | 164 | struct request *request; |
165 | int start_sg, end_sg; | 165 | int start_sg, end_sg; |
166 | sector_t rq_pos; | ||
166 | }; | 167 | }; |
167 | 168 | ||
168 | #define DEFAULT_COW { \ | 169 | #define DEFAULT_COW { \ |
@@ -187,6 +188,7 @@ struct ubd { | |||
187 | .request = NULL, \ | 188 | .request = NULL, \ |
188 | .start_sg = 0, \ | 189 | .start_sg = 0, \ |
189 | .end_sg = 0, \ | 190 | .end_sg = 0, \ |
191 | .rq_pos = 0, \ | ||
190 | } | 192 | } |
191 | 193 | ||
192 | /* Protected by ubd_lock */ | 194 | /* Protected by ubd_lock */ |
@@ -1228,7 +1230,6 @@ static void do_ubd_request(struct request_queue *q) | |||
1228 | { | 1230 | { |
1229 | struct io_thread_req *io_req; | 1231 | struct io_thread_req *io_req; |
1230 | struct request *req; | 1232 | struct request *req; |
1231 | sector_t sector; | ||
1232 | int n; | 1233 | int n; |
1233 | 1234 | ||
1234 | while(1){ | 1235 | while(1){ |
@@ -1239,12 +1240,12 @@ static void do_ubd_request(struct request_queue *q) | |||
1239 | return; | 1240 | return; |
1240 | 1241 | ||
1241 | dev->request = req; | 1242 | dev->request = req; |
1243 | dev->rq_pos = blk_rq_pos(req); | ||
1242 | dev->start_sg = 0; | 1244 | dev->start_sg = 0; |
1243 | dev->end_sg = blk_rq_map_sg(q, req, dev->sg); | 1245 | dev->end_sg = blk_rq_map_sg(q, req, dev->sg); |
1244 | } | 1246 | } |
1245 | 1247 | ||
1246 | req = dev->request; | 1248 | req = dev->request; |
1247 | sector = blk_rq_pos(req); | ||
1248 | while(dev->start_sg < dev->end_sg){ | 1249 | while(dev->start_sg < dev->end_sg){ |
1249 | struct scatterlist *sg = &dev->sg[dev->start_sg]; | 1250 | struct scatterlist *sg = &dev->sg[dev->start_sg]; |
1250 | 1251 | ||
@@ -1256,10 +1257,9 @@ static void do_ubd_request(struct request_queue *q) | |||
1256 | return; | 1257 | return; |
1257 | } | 1258 | } |
1258 | prepare_request(req, io_req, | 1259 | prepare_request(req, io_req, |
1259 | (unsigned long long)sector << 9, | 1260 | (unsigned long long)dev->rq_pos << 9, |
1260 | sg->offset, sg->length, sg_page(sg)); | 1261 | sg->offset, sg->length, sg_page(sg)); |
1261 | 1262 | ||
1262 | sector += sg->length >> 9; | ||
1263 | n = os_write_file(thread_fd, &io_req, | 1263 | n = os_write_file(thread_fd, &io_req, |
1264 | sizeof(struct io_thread_req *)); | 1264 | sizeof(struct io_thread_req *)); |
1265 | if(n != sizeof(struct io_thread_req *)){ | 1265 | if(n != sizeof(struct io_thread_req *)){ |
@@ -1272,6 +1272,7 @@ static void do_ubd_request(struct request_queue *q) | |||
1272 | return; | 1272 | return; |
1273 | } | 1273 | } |
1274 | 1274 | ||
1275 | dev->rq_pos += sg->length >> 9; | ||
1275 | dev->start_sg++; | 1276 | dev->start_sg++; |
1276 | } | 1277 | } |
1277 | dev->end_sg = 0; | 1278 | dev->end_sg = 0; |
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 502e53f999cf..c52e2eb40a1e 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
@@ -652,20 +652,6 @@ static inline struct kvm_mmu_page *page_header(hpa_t shadow_page) | |||
652 | return (struct kvm_mmu_page *)page_private(page); | 652 | return (struct kvm_mmu_page *)page_private(page); |
653 | } | 653 | } |
654 | 654 | ||
655 | static inline u16 kvm_read_fs(void) | ||
656 | { | ||
657 | u16 seg; | ||
658 | asm("mov %%fs, %0" : "=g"(seg)); | ||
659 | return seg; | ||
660 | } | ||
661 | |||
662 | static inline u16 kvm_read_gs(void) | ||
663 | { | ||
664 | u16 seg; | ||
665 | asm("mov %%gs, %0" : "=g"(seg)); | ||
666 | return seg; | ||
667 | } | ||
668 | |||
669 | static inline u16 kvm_read_ldt(void) | 655 | static inline u16 kvm_read_ldt(void) |
670 | { | 656 | { |
671 | u16 ldt; | 657 | u16 ldt; |
@@ -673,16 +659,6 @@ static inline u16 kvm_read_ldt(void) | |||
673 | return ldt; | 659 | return ldt; |
674 | } | 660 | } |
675 | 661 | ||
676 | static inline void kvm_load_fs(u16 sel) | ||
677 | { | ||
678 | asm("mov %0, %%fs" : : "rm"(sel)); | ||
679 | } | ||
680 | |||
681 | static inline void kvm_load_gs(u16 sel) | ||
682 | { | ||
683 | asm("mov %0, %%gs" : : "rm"(sel)); | ||
684 | } | ||
685 | |||
686 | static inline void kvm_load_ldt(u16 sel) | 662 | static inline void kvm_load_ldt(u16 sel) |
687 | { | 663 | { |
688 | asm("lldt %0" : : "rm"(sel)); | 664 | asm("lldt %0" : : "rm"(sel)); |
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 81ed28cb36e6..8a3f9f64f86f 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -3163,8 +3163,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) | |||
3163 | sync_lapic_to_cr8(vcpu); | 3163 | sync_lapic_to_cr8(vcpu); |
3164 | 3164 | ||
3165 | save_host_msrs(vcpu); | 3165 | save_host_msrs(vcpu); |
3166 | fs_selector = kvm_read_fs(); | 3166 | savesegment(fs, fs_selector); |
3167 | gs_selector = kvm_read_gs(); | 3167 | savesegment(gs, gs_selector); |
3168 | ldt_selector = kvm_read_ldt(); | 3168 | ldt_selector = kvm_read_ldt(); |
3169 | svm->vmcb->save.cr2 = vcpu->arch.cr2; | 3169 | svm->vmcb->save.cr2 = vcpu->arch.cr2; |
3170 | /* required for live migration with NPT */ | 3170 | /* required for live migration with NPT */ |
@@ -3251,10 +3251,15 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) | |||
3251 | vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp; | 3251 | vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp; |
3252 | vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip; | 3252 | vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip; |
3253 | 3253 | ||
3254 | kvm_load_fs(fs_selector); | ||
3255 | kvm_load_gs(gs_selector); | ||
3256 | kvm_load_ldt(ldt_selector); | ||
3257 | load_host_msrs(vcpu); | 3254 | load_host_msrs(vcpu); |
3255 | loadsegment(fs, fs_selector); | ||
3256 | #ifdef CONFIG_X86_64 | ||
3257 | load_gs_index(gs_selector); | ||
3258 | wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs); | ||
3259 | #else | ||
3260 | loadsegment(gs, gs_selector); | ||
3261 | #endif | ||
3262 | kvm_load_ldt(ldt_selector); | ||
3258 | 3263 | ||
3259 | reload_tss(vcpu); | 3264 | reload_tss(vcpu); |
3260 | 3265 | ||
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 49b25eee25ac..7bddfab12013 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -803,7 +803,7 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu) | |||
803 | */ | 803 | */ |
804 | vmx->host_state.ldt_sel = kvm_read_ldt(); | 804 | vmx->host_state.ldt_sel = kvm_read_ldt(); |
805 | vmx->host_state.gs_ldt_reload_needed = vmx->host_state.ldt_sel; | 805 | vmx->host_state.gs_ldt_reload_needed = vmx->host_state.ldt_sel; |
806 | vmx->host_state.fs_sel = kvm_read_fs(); | 806 | savesegment(fs, vmx->host_state.fs_sel); |
807 | if (!(vmx->host_state.fs_sel & 7)) { | 807 | if (!(vmx->host_state.fs_sel & 7)) { |
808 | vmcs_write16(HOST_FS_SELECTOR, vmx->host_state.fs_sel); | 808 | vmcs_write16(HOST_FS_SELECTOR, vmx->host_state.fs_sel); |
809 | vmx->host_state.fs_reload_needed = 0; | 809 | vmx->host_state.fs_reload_needed = 0; |
@@ -811,7 +811,7 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu) | |||
811 | vmcs_write16(HOST_FS_SELECTOR, 0); | 811 | vmcs_write16(HOST_FS_SELECTOR, 0); |
812 | vmx->host_state.fs_reload_needed = 1; | 812 | vmx->host_state.fs_reload_needed = 1; |
813 | } | 813 | } |
814 | vmx->host_state.gs_sel = kvm_read_gs(); | 814 | savesegment(gs, vmx->host_state.gs_sel); |
815 | if (!(vmx->host_state.gs_sel & 7)) | 815 | if (!(vmx->host_state.gs_sel & 7)) |
816 | vmcs_write16(HOST_GS_SELECTOR, vmx->host_state.gs_sel); | 816 | vmcs_write16(HOST_GS_SELECTOR, vmx->host_state.gs_sel); |
817 | else { | 817 | else { |
@@ -841,27 +841,21 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu) | |||
841 | 841 | ||
842 | static void __vmx_load_host_state(struct vcpu_vmx *vmx) | 842 | static void __vmx_load_host_state(struct vcpu_vmx *vmx) |
843 | { | 843 | { |
844 | unsigned long flags; | ||
845 | |||
846 | if (!vmx->host_state.loaded) | 844 | if (!vmx->host_state.loaded) |
847 | return; | 845 | return; |
848 | 846 | ||
849 | ++vmx->vcpu.stat.host_state_reload; | 847 | ++vmx->vcpu.stat.host_state_reload; |
850 | vmx->host_state.loaded = 0; | 848 | vmx->host_state.loaded = 0; |
851 | if (vmx->host_state.fs_reload_needed) | 849 | if (vmx->host_state.fs_reload_needed) |
852 | kvm_load_fs(vmx->host_state.fs_sel); | 850 | loadsegment(fs, vmx->host_state.fs_sel); |
853 | if (vmx->host_state.gs_ldt_reload_needed) { | 851 | if (vmx->host_state.gs_ldt_reload_needed) { |
854 | kvm_load_ldt(vmx->host_state.ldt_sel); | 852 | kvm_load_ldt(vmx->host_state.ldt_sel); |
855 | /* | ||
856 | * If we have to reload gs, we must take care to | ||
857 | * preserve our gs base. | ||
858 | */ | ||
859 | local_irq_save(flags); | ||
860 | kvm_load_gs(vmx->host_state.gs_sel); | ||
861 | #ifdef CONFIG_X86_64 | 853 | #ifdef CONFIG_X86_64 |
862 | wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE)); | 854 | load_gs_index(vmx->host_state.gs_sel); |
855 | wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs); | ||
856 | #else | ||
857 | loadsegment(gs, vmx->host_state.gs_sel); | ||
863 | #endif | 858 | #endif |
864 | local_irq_restore(flags); | ||
865 | } | 859 | } |
866 | reload_tss(); | 860 | reload_tss(); |
867 | #ifdef CONFIG_X86_64 | 861 | #ifdef CONFIG_X86_64 |
@@ -2589,8 +2583,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) | |||
2589 | vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */ | 2583 | vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */ |
2590 | vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */ | 2584 | vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */ |
2591 | vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */ | 2585 | vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */ |
2592 | vmcs_write16(HOST_FS_SELECTOR, kvm_read_fs()); /* 22.2.4 */ | 2586 | vmcs_write16(HOST_FS_SELECTOR, 0); /* 22.2.4 */ |
2593 | vmcs_write16(HOST_GS_SELECTOR, kvm_read_gs()); /* 22.2.4 */ | 2587 | vmcs_write16(HOST_GS_SELECTOR, 0); /* 22.2.4 */ |
2594 | vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS); /* 22.2.4 */ | 2588 | vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS); /* 22.2.4 */ |
2595 | #ifdef CONFIG_X86_64 | 2589 | #ifdef CONFIG_X86_64 |
2596 | rdmsrl(MSR_FS_BASE, a); | 2590 | rdmsrl(MSR_FS_BASE, a); |
diff --git a/block/bsg.c b/block/bsg.c index 82d58829ba59..0c00870553a3 100644 --- a/block/bsg.c +++ b/block/bsg.c | |||
@@ -426,7 +426,7 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr, | |||
426 | /* | 426 | /* |
427 | * fill in all the output members | 427 | * fill in all the output members |
428 | */ | 428 | */ |
429 | hdr->device_status = status_byte(rq->errors); | 429 | hdr->device_status = rq->errors & 0xff; |
430 | hdr->transport_status = host_byte(rq->errors); | 430 | hdr->transport_status = host_byte(rq->errors); |
431 | hdr->driver_status = driver_byte(rq->errors); | 431 | hdr->driver_status = driver_byte(rq->errors); |
432 | hdr->info = 0; | 432 | hdr->info = 0; |
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index e9da874d0419..03688c2da319 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c | |||
@@ -113,7 +113,7 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev, | |||
113 | memcpy(buf, dev->bounce_buf+offset, size); | 113 | memcpy(buf, dev->bounce_buf+offset, size); |
114 | offset += size; | 114 | offset += size; |
115 | flush_kernel_dcache_page(bvec->bv_page); | 115 | flush_kernel_dcache_page(bvec->bv_page); |
116 | bvec_kunmap_irq(bvec, &flags); | 116 | bvec_kunmap_irq(buf, &flags); |
117 | i++; | 117 | i++; |
118 | } | 118 | } |
119 | } | 119 | } |
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index c810481a5bc2..0f69c5ec0ecd 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -459,9 +459,12 @@ static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count, | |||
459 | 459 | ||
460 | /* | 460 | /* |
461 | * Wait till the host acknowledges it pushed out the data we | 461 | * Wait till the host acknowledges it pushed out the data we |
462 | * sent. This is done for ports in blocking mode or for data | 462 | * sent. This is done for data from the hvc_console; the tty |
463 | * from the hvc_console; the tty operations are performed with | 463 | * operations are performed with spinlocks held so we can't |
464 | * spinlocks held so we can't sleep here. | 464 | * sleep here. An alternative would be to copy the data to a |
465 | * buffer and relax the spinning requirement. The downside is | ||
466 | * we need to kmalloc a GFP_ATOMIC buffer each time the | ||
467 | * console driver writes something out. | ||
465 | */ | 468 | */ |
466 | while (!virtqueue_get_buf(out_vq, &len)) | 469 | while (!virtqueue_get_buf(out_vq, &len)) |
467 | cpu_relax(); | 470 | cpu_relax(); |
@@ -626,6 +629,14 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, | |||
626 | goto free_buf; | 629 | goto free_buf; |
627 | } | 630 | } |
628 | 631 | ||
632 | /* | ||
633 | * We now ask send_buf() to not spin for generic ports -- we | ||
634 | * can re-use the same code path that non-blocking file | ||
635 | * descriptors take for blocking file descriptors since the | ||
636 | * wait is already done and we're certain the write will go | ||
637 | * through to the host. | ||
638 | */ | ||
639 | nonblock = true; | ||
629 | ret = send_buf(port, buf, count, nonblock); | 640 | ret = send_buf(port, buf, count, nonblock); |
630 | 641 | ||
631 | if (nonblock && ret > 0) | 642 | if (nonblock && ret > 0) |
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 1b05896648bc..9dcb17d51aee 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c | |||
@@ -2840,7 +2840,7 @@ static int __devinit pci_probe(struct pci_dev *dev, | |||
2840 | const struct pci_device_id *ent) | 2840 | const struct pci_device_id *ent) |
2841 | { | 2841 | { |
2842 | struct fw_ohci *ohci; | 2842 | struct fw_ohci *ohci; |
2843 | u32 bus_options, max_receive, link_speed, version, link_enh; | 2843 | u32 bus_options, max_receive, link_speed, version; |
2844 | u64 guid; | 2844 | u64 guid; |
2845 | int i, err, n_ir, n_it; | 2845 | int i, err, n_ir, n_it; |
2846 | size_t size; | 2846 | size_t size; |
@@ -2894,23 +2894,6 @@ static int __devinit pci_probe(struct pci_dev *dev, | |||
2894 | if (param_quirks) | 2894 | if (param_quirks) |
2895 | ohci->quirks = param_quirks; | 2895 | ohci->quirks = param_quirks; |
2896 | 2896 | ||
2897 | /* TI OHCI-Lynx and compatible: set recommended configuration bits. */ | ||
2898 | if (dev->vendor == PCI_VENDOR_ID_TI) { | ||
2899 | pci_read_config_dword(dev, PCI_CFG_TI_LinkEnh, &link_enh); | ||
2900 | |||
2901 | /* adjust latency of ATx FIFO: use 1.7 KB threshold */ | ||
2902 | link_enh &= ~TI_LinkEnh_atx_thresh_mask; | ||
2903 | link_enh |= TI_LinkEnh_atx_thresh_1_7K; | ||
2904 | |||
2905 | /* use priority arbitration for asynchronous responses */ | ||
2906 | link_enh |= TI_LinkEnh_enab_unfair; | ||
2907 | |||
2908 | /* required for aPhyEnhanceEnable to work */ | ||
2909 | link_enh |= TI_LinkEnh_enab_accel; | ||
2910 | |||
2911 | pci_write_config_dword(dev, PCI_CFG_TI_LinkEnh, link_enh); | ||
2912 | } | ||
2913 | |||
2914 | ar_context_init(&ohci->ar_request_ctx, ohci, | 2897 | ar_context_init(&ohci->ar_request_ctx, ohci, |
2915 | OHCI1394_AsReqRcvContextControlSet); | 2898 | OHCI1394_AsReqRcvContextControlSet); |
2916 | 2899 | ||
diff --git a/drivers/firewire/ohci.h b/drivers/firewire/ohci.h index 0e6c5a466908..ef5e7336da68 100644 --- a/drivers/firewire/ohci.h +++ b/drivers/firewire/ohci.h | |||
@@ -155,12 +155,4 @@ | |||
155 | 155 | ||
156 | #define OHCI1394_phy_tcode 0xe | 156 | #define OHCI1394_phy_tcode 0xe |
157 | 157 | ||
158 | /* TI extensions */ | ||
159 | |||
160 | #define PCI_CFG_TI_LinkEnh 0xf4 | ||
161 | #define TI_LinkEnh_enab_accel 0x00000002 | ||
162 | #define TI_LinkEnh_enab_unfair 0x00000080 | ||
163 | #define TI_LinkEnh_atx_thresh_mask 0x00003000 | ||
164 | #define TI_LinkEnh_atx_thresh_1_7K 0x00001000 | ||
165 | |||
166 | #endif /* _FIREWIRE_OHCI_H */ | 158 | #endif /* _FIREWIRE_OHCI_H */ |
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 5731fc9b1ae3..3eef567b0421 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c | |||
@@ -203,6 +203,7 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, | |||
203 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 203 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
204 | struct radeon_device *rdev = crtc->dev->dev_private; | 204 | struct radeon_device *rdev = crtc->dev->dev_private; |
205 | int xorigin = 0, yorigin = 0; | 205 | int xorigin = 0, yorigin = 0; |
206 | int w = radeon_crtc->cursor_width; | ||
206 | 207 | ||
207 | if (x < 0) | 208 | if (x < 0) |
208 | xorigin = -x + 1; | 209 | xorigin = -x + 1; |
@@ -213,22 +214,7 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, | |||
213 | if (yorigin >= CURSOR_HEIGHT) | 214 | if (yorigin >= CURSOR_HEIGHT) |
214 | yorigin = CURSOR_HEIGHT - 1; | 215 | yorigin = CURSOR_HEIGHT - 1; |
215 | 216 | ||
216 | radeon_lock_cursor(crtc, true); | 217 | if (ASIC_IS_AVIVO(rdev)) { |
217 | if (ASIC_IS_DCE4(rdev)) { | ||
218 | /* cursors are offset into the total surface */ | ||
219 | x += crtc->x; | ||
220 | y += crtc->y; | ||
221 | DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y); | ||
222 | |||
223 | /* XXX: check if evergreen has the same issues as avivo chips */ | ||
224 | WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, | ||
225 | ((xorigin ? 0 : x) << 16) | | ||
226 | (yorigin ? 0 : y)); | ||
227 | WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); | ||
228 | WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset, | ||
229 | ((radeon_crtc->cursor_width - 1) << 16) | (radeon_crtc->cursor_height - 1)); | ||
230 | } else if (ASIC_IS_AVIVO(rdev)) { | ||
231 | int w = radeon_crtc->cursor_width; | ||
232 | int i = 0; | 218 | int i = 0; |
233 | struct drm_crtc *crtc_p; | 219 | struct drm_crtc *crtc_p; |
234 | 220 | ||
@@ -260,7 +246,17 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, | |||
260 | if (w <= 0) | 246 | if (w <= 0) |
261 | w = 1; | 247 | w = 1; |
262 | } | 248 | } |
249 | } | ||
263 | 250 | ||
251 | radeon_lock_cursor(crtc, true); | ||
252 | if (ASIC_IS_DCE4(rdev)) { | ||
253 | WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, | ||
254 | ((xorigin ? 0 : x) << 16) | | ||
255 | (yorigin ? 0 : y)); | ||
256 | WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); | ||
257 | WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset, | ||
258 | ((w - 1) << 16) | (radeon_crtc->cursor_height - 1)); | ||
259 | } else if (ASIC_IS_AVIVO(rdev)) { | ||
264 | WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, | 260 | WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, |
265 | ((xorigin ? 0 : x) << 16) | | 261 | ((xorigin ? 0 : x) << 16) | |
266 | (yorigin ? 0 : y)); | 262 | (yorigin ? 0 : y)); |
diff --git a/drivers/hid/hid-cando.c b/drivers/hid/hid-cando.c index 4267a6fdc277..5925bdcd417d 100644 --- a/drivers/hid/hid-cando.c +++ b/drivers/hid/hid-cando.c | |||
@@ -237,6 +237,8 @@ static const struct hid_device_id cando_devices[] = { | |||
237 | USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, | 237 | USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, |
238 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | 238 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, |
239 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, | 239 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, |
240 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | ||
241 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, | ||
240 | { } | 242 | { } |
241 | }; | 243 | }; |
242 | MODULE_DEVICE_TABLE(hid, cando_devices); | 244 | MODULE_DEVICE_TABLE(hid, cando_devices); |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 3f7292486024..a0dea3d1296e 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1292,6 +1292,7 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1292 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, | 1292 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, |
1293 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, | 1293 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, |
1294 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, | 1294 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, |
1295 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, | ||
1295 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, | 1296 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, |
1296 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, | 1297 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, |
1297 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, | 1298 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 765a4f53eb5c..c5ae5f1545bd 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -134,6 +134,7 @@ | |||
134 | #define USB_VENDOR_ID_CANDO 0x2087 | 134 | #define USB_VENDOR_ID_CANDO 0x2087 |
135 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 | 135 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 |
136 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03 | 136 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03 |
137 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01 | ||
137 | 138 | ||
138 | #define USB_VENDOR_ID_CH 0x068e | 139 | #define USB_VENDOR_ID_CH 0x068e |
139 | #define USB_DEVICE_ID_CH_PRO_PEDALS 0x00f2 | 140 | #define USB_DEVICE_ID_CH_PRO_PEDALS 0x00f2 |
@@ -503,6 +504,7 @@ | |||
503 | 504 | ||
504 | #define USB_VENDOR_ID_TURBOX 0x062a | 505 | #define USB_VENDOR_ID_TURBOX 0x062a |
505 | #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 | 506 | #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 |
507 | #define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART 0x7100 | ||
506 | 508 | ||
507 | #define USB_VENDOR_ID_TWINHAN 0x6253 | 509 | #define USB_VENDOR_ID_TWINHAN 0x6253 |
508 | #define USB_DEVICE_ID_TWINHAN_IR_REMOTE 0x0100 | 510 | #define USB_DEVICE_ID_TWINHAN_IR_REMOTE 0x0100 |
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 47d70c523d93..a3866b5c0c43 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
@@ -109,6 +109,12 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t | |||
109 | int ret = 0; | 109 | int ret = 0; |
110 | 110 | ||
111 | mutex_lock(&minors_lock); | 111 | mutex_lock(&minors_lock); |
112 | |||
113 | if (!hidraw_table[minor]) { | ||
114 | ret = -ENODEV; | ||
115 | goto out; | ||
116 | } | ||
117 | |||
112 | dev = hidraw_table[minor]->hid; | 118 | dev = hidraw_table[minor]->hid; |
113 | 119 | ||
114 | if (!dev->hid_output_raw_report) { | 120 | if (!dev->hid_output_raw_report) { |
@@ -244,6 +250,10 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, | |||
244 | 250 | ||
245 | mutex_lock(&minors_lock); | 251 | mutex_lock(&minors_lock); |
246 | dev = hidraw_table[minor]; | 252 | dev = hidraw_table[minor]; |
253 | if (!dev) { | ||
254 | ret = -ENODEV; | ||
255 | goto out; | ||
256 | } | ||
247 | 257 | ||
248 | switch (cmd) { | 258 | switch (cmd) { |
249 | case HIDIOCGRDESCSIZE: | 259 | case HIDIOCGRDESCSIZE: |
@@ -317,6 +327,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, | |||
317 | 327 | ||
318 | ret = -ENOTTY; | 328 | ret = -ENOTTY; |
319 | } | 329 | } |
330 | out: | ||
320 | mutex_unlock(&minors_lock); | 331 | mutex_unlock(&minors_lock); |
321 | return ret; | 332 | return ret; |
322 | } | 333 | } |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 70da3181c8a0..f0260c699adb 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -36,6 +36,7 @@ static const struct hid_blacklist { | |||
36 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, | 36 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, |
37 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, | 37 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, |
38 | { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, | 38 | { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, |
39 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART, HID_QUIRK_MULTI_INPUT }, | ||
39 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 40 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
40 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 41 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
41 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 42 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index b8feac5f2ef4..5795c8398c7c 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c | |||
@@ -331,21 +331,16 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) | |||
331 | INIT_COMPLETION(dev->cmd_complete); | 331 | INIT_COMPLETION(dev->cmd_complete); |
332 | dev->cmd_err = 0; | 332 | dev->cmd_err = 0; |
333 | 333 | ||
334 | /* Take I2C out of reset, configure it as master and set the | 334 | /* Take I2C out of reset and configure it as master */ |
335 | * start bit */ | 335 | flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST; |
336 | flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT; | ||
337 | 336 | ||
338 | /* if the slave address is ten bit address, enable XA bit */ | 337 | /* if the slave address is ten bit address, enable XA bit */ |
339 | if (msg->flags & I2C_M_TEN) | 338 | if (msg->flags & I2C_M_TEN) |
340 | flag |= DAVINCI_I2C_MDR_XA; | 339 | flag |= DAVINCI_I2C_MDR_XA; |
341 | if (!(msg->flags & I2C_M_RD)) | 340 | if (!(msg->flags & I2C_M_RD)) |
342 | flag |= DAVINCI_I2C_MDR_TRX; | 341 | flag |= DAVINCI_I2C_MDR_TRX; |
343 | if (stop) | 342 | if (msg->len == 0) |
344 | flag |= DAVINCI_I2C_MDR_STP; | ||
345 | if (msg->len == 0) { | ||
346 | flag |= DAVINCI_I2C_MDR_RM; | 343 | flag |= DAVINCI_I2C_MDR_RM; |
347 | flag &= ~DAVINCI_I2C_MDR_STP; | ||
348 | } | ||
349 | 344 | ||
350 | /* Enable receive or transmit interrupts */ | 345 | /* Enable receive or transmit interrupts */ |
351 | w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); | 346 | w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); |
@@ -358,17 +353,28 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) | |||
358 | dev->terminate = 0; | 353 | dev->terminate = 0; |
359 | 354 | ||
360 | /* | 355 | /* |
356 | * Write mode register first as needed for correct behaviour | ||
357 | * on OMAP-L138, but don't set STT yet to avoid a race with XRDY | ||
358 | * occuring before we have loaded DXR | ||
359 | */ | ||
360 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); | ||
361 | |||
362 | /* | ||
361 | * First byte should be set here, not after interrupt, | 363 | * First byte should be set here, not after interrupt, |
362 | * because transmit-data-ready interrupt can come before | 364 | * because transmit-data-ready interrupt can come before |
363 | * NACK-interrupt during sending of previous message and | 365 | * NACK-interrupt during sending of previous message and |
364 | * ICDXR may have wrong data | 366 | * ICDXR may have wrong data |
367 | * It also saves us one interrupt, slightly faster | ||
365 | */ | 368 | */ |
366 | if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { | 369 | if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { |
367 | davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); | 370 | davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); |
368 | dev->buf_len--; | 371 | dev->buf_len--; |
369 | } | 372 | } |
370 | 373 | ||
371 | /* write the data into mode register; start transmitting */ | 374 | /* Set STT to begin transmit now DXR is loaded */ |
375 | flag |= DAVINCI_I2C_MDR_STT; | ||
376 | if (stop && msg->len != 0) | ||
377 | flag |= DAVINCI_I2C_MDR_STP; | ||
372 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); | 378 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); |
373 | 379 | ||
374 | r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, | 380 | r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, |
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index d1ff9408dc1f..4c2a62b75b5c 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c | |||
@@ -159,15 +159,9 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) | |||
159 | 159 | ||
160 | static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx) | 160 | static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx) |
161 | { | 161 | { |
162 | int result; | 162 | wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10); |
163 | |||
164 | result = wait_event_interruptible_timeout(i2c_imx->queue, | ||
165 | i2c_imx->i2csr & I2SR_IIF, HZ / 10); | ||
166 | 163 | ||
167 | if (unlikely(result < 0)) { | 164 | if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) { |
168 | dev_dbg(&i2c_imx->adapter.dev, "<%s> result < 0\n", __func__); | ||
169 | return result; | ||
170 | } else if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) { | ||
171 | dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__); | 165 | dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__); |
172 | return -ETIMEDOUT; | 166 | return -ETIMEDOUT; |
173 | } | 167 | } |
@@ -295,7 +289,7 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id) | |||
295 | i2c_imx->i2csr = temp; | 289 | i2c_imx->i2csr = temp; |
296 | temp &= ~I2SR_IIF; | 290 | temp &= ~I2SR_IIF; |
297 | writeb(temp, i2c_imx->base + IMX_I2C_I2SR); | 291 | writeb(temp, i2c_imx->base + IMX_I2C_I2SR); |
298 | wake_up_interruptible(&i2c_imx->queue); | 292 | wake_up(&i2c_imx->queue); |
299 | return IRQ_HANDLED; | 293 | return IRQ_HANDLED; |
300 | } | 294 | } |
301 | 295 | ||
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index c908c5f83645..9ddafc30f432 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -669,6 +669,9 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
669 | 669 | ||
670 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | 670 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { |
671 | 671 | ||
672 | if (!dev->absinfo) | ||
673 | return -EINVAL; | ||
674 | |||
672 | t = _IOC_NR(cmd) & ABS_MAX; | 675 | t = _IOC_NR(cmd) & ABS_MAX; |
673 | abs = dev->absinfo[t]; | 676 | abs = dev->absinfo[t]; |
674 | 677 | ||
@@ -680,10 +683,13 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
680 | } | 683 | } |
681 | } | 684 | } |
682 | 685 | ||
683 | if (_IOC_DIR(cmd) == _IOC_READ) { | 686 | if (_IOC_DIR(cmd) == _IOC_WRITE) { |
684 | 687 | ||
685 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | 688 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { |
686 | 689 | ||
690 | if (!dev->absinfo) | ||
691 | return -EINVAL; | ||
692 | |||
687 | t = _IOC_NR(cmd) & ABS_MAX; | 693 | t = _IOC_NR(cmd) & ABS_MAX; |
688 | 694 | ||
689 | if (copy_from_user(&abs, p, min_t(size_t, | 695 | if (copy_from_user(&abs, p, min_t(size_t, |
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index 073f01390cdd..86294ed35c9b 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c | |||
@@ -193,17 +193,24 @@ static int put_video_window32(struct video_window *kp, struct video_window32 __u | |||
193 | struct video_code32 { | 193 | struct video_code32 { |
194 | char loadwhat[16]; /* name or tag of file being passed */ | 194 | char loadwhat[16]; /* name or tag of file being passed */ |
195 | compat_int_t datasize; | 195 | compat_int_t datasize; |
196 | unsigned char *data; | 196 | compat_uptr_t data; |
197 | }; | 197 | }; |
198 | 198 | ||
199 | static int get_microcode32(struct video_code *kp, struct video_code32 __user *up) | 199 | static struct video_code __user *get_microcode32(struct video_code32 *kp) |
200 | { | 200 | { |
201 | if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) || | 201 | struct video_code __user *up; |
202 | copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) || | 202 | |
203 | get_user(kp->datasize, &up->datasize) || | 203 | up = compat_alloc_user_space(sizeof(*up)); |
204 | copy_from_user(kp->data, up->data, up->datasize)) | 204 | |
205 | return -EFAULT; | 205 | /* |
206 | return 0; | 206 | * NOTE! We don't actually care if these fail. If the |
207 | * user address is invalid, the native ioctl will do | ||
208 | * the error handling for us | ||
209 | */ | ||
210 | (void) copy_to_user(up->loadwhat, kp->loadwhat, sizeof(up->loadwhat)); | ||
211 | (void) put_user(kp->datasize, &up->datasize); | ||
212 | (void) put_user(compat_ptr(kp->data), &up->data); | ||
213 | return up; | ||
207 | } | 214 | } |
208 | 215 | ||
209 | #define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32) | 216 | #define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32) |
@@ -739,7 +746,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar | |||
739 | struct video_tuner vt; | 746 | struct video_tuner vt; |
740 | struct video_buffer vb; | 747 | struct video_buffer vb; |
741 | struct video_window vw; | 748 | struct video_window vw; |
742 | struct video_code vc; | 749 | struct video_code32 vc; |
743 | struct video_audio va; | 750 | struct video_audio va; |
744 | #endif | 751 | #endif |
745 | struct v4l2_format v2f; | 752 | struct v4l2_format v2f; |
@@ -818,8 +825,11 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar | |||
818 | break; | 825 | break; |
819 | 826 | ||
820 | case VIDIOCSMICROCODE: | 827 | case VIDIOCSMICROCODE: |
821 | err = get_microcode32(&karg.vc, up); | 828 | /* Copy the 32-bit "video_code32" to kernel space */ |
822 | compatible_arg = 0; | 829 | if (copy_from_user(&karg.vc, up, sizeof(karg.vc))) |
830 | return -EFAULT; | ||
831 | /* Convert the 32-bit version to a 64-bit version in user space */ | ||
832 | up = get_microcode32(&karg.vc); | ||
823 | break; | 833 | break; |
824 | 834 | ||
825 | case VIDIOCSFREQ: | 835 | case VIDIOCSFREQ: |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 5db49b124ffa..09eee6df0653 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -1631,6 +1631,19 @@ int mmc_suspend_host(struct mmc_host *host) | |||
1631 | if (host->bus_ops && !host->bus_dead) { | 1631 | if (host->bus_ops && !host->bus_dead) { |
1632 | if (host->bus_ops->suspend) | 1632 | if (host->bus_ops->suspend) |
1633 | err = host->bus_ops->suspend(host); | 1633 | err = host->bus_ops->suspend(host); |
1634 | if (err == -ENOSYS || !host->bus_ops->resume) { | ||
1635 | /* | ||
1636 | * We simply "remove" the card in this case. | ||
1637 | * It will be redetected on resume. | ||
1638 | */ | ||
1639 | if (host->bus_ops->remove) | ||
1640 | host->bus_ops->remove(host); | ||
1641 | mmc_claim_host(host); | ||
1642 | mmc_detach_bus(host); | ||
1643 | mmc_release_host(host); | ||
1644 | host->pm_flags = 0; | ||
1645 | err = 0; | ||
1646 | } | ||
1634 | } | 1647 | } |
1635 | mmc_bus_put(host); | 1648 | mmc_bus_put(host); |
1636 | 1649 | ||
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index b2828e84d243..214b03afdd48 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
31 | #include <linux/err.h> | 31 | #include <linux/err.h> |
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | #include <linux/irq.h> | ||
34 | #include <linux/completion.h> | ||
33 | 35 | ||
34 | #include <asm/mach/flash.h> | 36 | #include <asm/mach/flash.h> |
35 | #include <mach/mxc_nand.h> | 37 | #include <mach/mxc_nand.h> |
@@ -151,7 +153,7 @@ struct mxc_nand_host { | |||
151 | int irq; | 153 | int irq; |
152 | int eccsize; | 154 | int eccsize; |
153 | 155 | ||
154 | wait_queue_head_t irq_waitq; | 156 | struct completion op_completion; |
155 | 157 | ||
156 | uint8_t *data_buf; | 158 | uint8_t *data_buf; |
157 | unsigned int buf_start; | 159 | unsigned int buf_start; |
@@ -164,6 +166,7 @@ struct mxc_nand_host { | |||
164 | void (*send_read_id)(struct mxc_nand_host *); | 166 | void (*send_read_id)(struct mxc_nand_host *); |
165 | uint16_t (*get_dev_status)(struct mxc_nand_host *); | 167 | uint16_t (*get_dev_status)(struct mxc_nand_host *); |
166 | int (*check_int)(struct mxc_nand_host *); | 168 | int (*check_int)(struct mxc_nand_host *); |
169 | void (*irq_control)(struct mxc_nand_host *, int); | ||
167 | }; | 170 | }; |
168 | 171 | ||
169 | /* OOB placement block for use with hardware ecc generation */ | 172 | /* OOB placement block for use with hardware ecc generation */ |
@@ -216,9 +219,12 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) | |||
216 | { | 219 | { |
217 | struct mxc_nand_host *host = dev_id; | 220 | struct mxc_nand_host *host = dev_id; |
218 | 221 | ||
219 | disable_irq_nosync(irq); | 222 | if (!host->check_int(host)) |
223 | return IRQ_NONE; | ||
220 | 224 | ||
221 | wake_up(&host->irq_waitq); | 225 | host->irq_control(host, 0); |
226 | |||
227 | complete(&host->op_completion); | ||
222 | 228 | ||
223 | return IRQ_HANDLED; | 229 | return IRQ_HANDLED; |
224 | } | 230 | } |
@@ -245,11 +251,54 @@ static int check_int_v1_v2(struct mxc_nand_host *host) | |||
245 | if (!(tmp & NFC_V1_V2_CONFIG2_INT)) | 251 | if (!(tmp & NFC_V1_V2_CONFIG2_INT)) |
246 | return 0; | 252 | return 0; |
247 | 253 | ||
248 | writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2); | 254 | if (!cpu_is_mx21()) |
255 | writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2); | ||
249 | 256 | ||
250 | return 1; | 257 | return 1; |
251 | } | 258 | } |
252 | 259 | ||
260 | /* | ||
261 | * It has been observed that the i.MX21 cannot read the CONFIG2:INT bit | ||
262 | * if interrupts are masked (CONFIG1:INT_MSK is set). To handle this, the | ||
263 | * driver can enable/disable the irq line rather than simply masking the | ||
264 | * interrupts. | ||
265 | */ | ||
266 | static void irq_control_mx21(struct mxc_nand_host *host, int activate) | ||
267 | { | ||
268 | if (activate) | ||
269 | enable_irq(host->irq); | ||
270 | else | ||
271 | disable_irq_nosync(host->irq); | ||
272 | } | ||
273 | |||
274 | static void irq_control_v1_v2(struct mxc_nand_host *host, int activate) | ||
275 | { | ||
276 | uint16_t tmp; | ||
277 | |||
278 | tmp = readw(NFC_V1_V2_CONFIG1); | ||
279 | |||
280 | if (activate) | ||
281 | tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK; | ||
282 | else | ||
283 | tmp |= NFC_V1_V2_CONFIG1_INT_MSK; | ||
284 | |||
285 | writew(tmp, NFC_V1_V2_CONFIG1); | ||
286 | } | ||
287 | |||
288 | static void irq_control_v3(struct mxc_nand_host *host, int activate) | ||
289 | { | ||
290 | uint32_t tmp; | ||
291 | |||
292 | tmp = readl(NFC_V3_CONFIG2); | ||
293 | |||
294 | if (activate) | ||
295 | tmp &= ~NFC_V3_CONFIG2_INT_MSK; | ||
296 | else | ||
297 | tmp |= NFC_V3_CONFIG2_INT_MSK; | ||
298 | |||
299 | writel(tmp, NFC_V3_CONFIG2); | ||
300 | } | ||
301 | |||
253 | /* This function polls the NANDFC to wait for the basic operation to | 302 | /* This function polls the NANDFC to wait for the basic operation to |
254 | * complete by checking the INT bit of config2 register. | 303 | * complete by checking the INT bit of config2 register. |
255 | */ | 304 | */ |
@@ -259,10 +308,9 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq) | |||
259 | 308 | ||
260 | if (useirq) { | 309 | if (useirq) { |
261 | if (!host->check_int(host)) { | 310 | if (!host->check_int(host)) { |
262 | 311 | INIT_COMPLETION(host->op_completion); | |
263 | enable_irq(host->irq); | 312 | host->irq_control(host, 1); |
264 | 313 | wait_for_completion(&host->op_completion); | |
265 | wait_event(host->irq_waitq, host->check_int(host)); | ||
266 | } | 314 | } |
267 | } else { | 315 | } else { |
268 | while (max_retries-- > 0) { | 316 | while (max_retries-- > 0) { |
@@ -799,6 +847,7 @@ static void preset_v3(struct mtd_info *mtd) | |||
799 | NFC_V3_CONFIG2_2CMD_PHASES | | 847 | NFC_V3_CONFIG2_2CMD_PHASES | |
800 | NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) | | 848 | NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) | |
801 | NFC_V3_CONFIG2_ST_CMD(0x70) | | 849 | NFC_V3_CONFIG2_ST_CMD(0x70) | |
850 | NFC_V3_CONFIG2_INT_MSK | | ||
802 | NFC_V3_CONFIG2_NUM_ADDR_PHASE0; | 851 | NFC_V3_CONFIG2_NUM_ADDR_PHASE0; |
803 | 852 | ||
804 | if (chip->ecc.mode == NAND_ECC_HW) | 853 | if (chip->ecc.mode == NAND_ECC_HW) |
@@ -1024,6 +1073,10 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1024 | host->send_read_id = send_read_id_v1_v2; | 1073 | host->send_read_id = send_read_id_v1_v2; |
1025 | host->get_dev_status = get_dev_status_v1_v2; | 1074 | host->get_dev_status = get_dev_status_v1_v2; |
1026 | host->check_int = check_int_v1_v2; | 1075 | host->check_int = check_int_v1_v2; |
1076 | if (cpu_is_mx21()) | ||
1077 | host->irq_control = irq_control_mx21; | ||
1078 | else | ||
1079 | host->irq_control = irq_control_v1_v2; | ||
1027 | } | 1080 | } |
1028 | 1081 | ||
1029 | if (nfc_is_v21()) { | 1082 | if (nfc_is_v21()) { |
@@ -1062,6 +1115,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1062 | host->send_read_id = send_read_id_v3; | 1115 | host->send_read_id = send_read_id_v3; |
1063 | host->check_int = check_int_v3; | 1116 | host->check_int = check_int_v3; |
1064 | host->get_dev_status = get_dev_status_v3; | 1117 | host->get_dev_status = get_dev_status_v3; |
1118 | host->irq_control = irq_control_v3; | ||
1065 | oob_smallpage = &nandv2_hw_eccoob_smallpage; | 1119 | oob_smallpage = &nandv2_hw_eccoob_smallpage; |
1066 | oob_largepage = &nandv2_hw_eccoob_largepage; | 1120 | oob_largepage = &nandv2_hw_eccoob_largepage; |
1067 | } else | 1121 | } else |
@@ -1093,14 +1147,34 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
1093 | this->options |= NAND_USE_FLASH_BBT; | 1147 | this->options |= NAND_USE_FLASH_BBT; |
1094 | } | 1148 | } |
1095 | 1149 | ||
1096 | init_waitqueue_head(&host->irq_waitq); | 1150 | init_completion(&host->op_completion); |
1097 | 1151 | ||
1098 | host->irq = platform_get_irq(pdev, 0); | 1152 | host->irq = platform_get_irq(pdev, 0); |
1099 | 1153 | ||
1154 | /* | ||
1155 | * mask the interrupt. For i.MX21 explicitely call | ||
1156 | * irq_control_v1_v2 to use the mask bit. We can't call | ||
1157 | * disable_irq_nosync() for an interrupt we do not own yet. | ||
1158 | */ | ||
1159 | if (cpu_is_mx21()) | ||
1160 | irq_control_v1_v2(host, 0); | ||
1161 | else | ||
1162 | host->irq_control(host, 0); | ||
1163 | |||
1100 | err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host); | 1164 | err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host); |
1101 | if (err) | 1165 | if (err) |
1102 | goto eirq; | 1166 | goto eirq; |
1103 | 1167 | ||
1168 | host->irq_control(host, 0); | ||
1169 | |||
1170 | /* | ||
1171 | * Now that the interrupt is disabled make sure the interrupt | ||
1172 | * mask bit is cleared on i.MX21. Otherwise we can't read | ||
1173 | * the interrupt status bit on this machine. | ||
1174 | */ | ||
1175 | if (cpu_is_mx21()) | ||
1176 | irq_control_v1_v2(host, 1); | ||
1177 | |||
1104 | /* first scan to find the device and get the page size */ | 1178 | /* first scan to find the device and get the page size */ |
1105 | if (nand_scan_ident(mtd, 1, NULL)) { | 1179 | if (nand_scan_ident(mtd, 1, NULL)) { |
1106 | err = -ENXIO; | 1180 | err = -ENXIO; |
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index ad0ed212db4a..348fba0a8976 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -1046,13 +1046,13 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf, | |||
1046 | 1046 | ||
1047 | /* If the user actually wanted this page, we can skip the rest */ | 1047 | /* If the user actually wanted this page, we can skip the rest */ |
1048 | if (page == 0) | 1048 | if (page == 0) |
1049 | return -EINVAL; | 1049 | return 0; |
1050 | 1050 | ||
1051 | for (i = 0; i < min((int)buf[3], buf_len - 4); i++) | 1051 | for (i = 0; i < min((int)buf[3], buf_len - 4); i++) |
1052 | if (buf[i + 4] == page) | 1052 | if (buf[i + 4] == page) |
1053 | goto found; | 1053 | goto found; |
1054 | 1054 | ||
1055 | if (i < buf[3] && i > buf_len) | 1055 | if (i < buf[3] && i >= buf_len - 4) |
1056 | /* ran off the end of the buffer, give us benefit of doubt */ | 1056 | /* ran off the end of the buffer, give us benefit of doubt */ |
1057 | goto found; | 1057 | goto found; |
1058 | /* The device claims it doesn't support the requested page */ | 1058 | /* The device claims it doesn't support the requested page */ |
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c index 93de907b1208..800c54602339 100644 --- a/drivers/serial/ioc3_serial.c +++ b/drivers/serial/ioc3_serial.c | |||
@@ -2044,6 +2044,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd) | |||
2044 | if (!port) { | 2044 | if (!port) { |
2045 | printk(KERN_WARNING | 2045 | printk(KERN_WARNING |
2046 | "IOC3 serial memory not available for port\n"); | 2046 | "IOC3 serial memory not available for port\n"); |
2047 | ret = -ENOMEM; | ||
2047 | goto out4; | 2048 | goto out4; |
2048 | } | 2049 | } |
2049 | spin_lock_init(&port->ip_lock); | 2050 | spin_lock_init(&port->ip_lock); |
@@ -2024,6 +2024,7 @@ int dump_write(struct file *file, const void *addr, int nr) | |||
2024 | { | 2024 | { |
2025 | return access_ok(VERIFY_READ, addr, nr) && file->f_op->write(file, addr, nr, &file->f_pos) == nr; | 2025 | return access_ok(VERIFY_READ, addr, nr) && file->f_op->write(file, addr, nr, &file->f_pos) == nr; |
2026 | } | 2026 | } |
2027 | EXPORT_SYMBOL(dump_write); | ||
2027 | 2028 | ||
2028 | int dump_seek(struct file *file, loff_t off) | 2029 | int dump_seek(struct file *file, loff_t off) |
2029 | { | 2030 | { |
@@ -2052,3 +2053,4 @@ int dump_seek(struct file *file, loff_t off) | |||
2052 | } | 2053 | } |
2053 | return ret; | 2054 | return ret; |
2054 | } | 2055 | } |
2056 | EXPORT_SYMBOL(dump_seek); | ||
diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c index 5007a41f1be9..d182438c7ae4 100644 --- a/fs/hfsplus/bfind.c +++ b/fs/hfsplus/bfind.c | |||
@@ -23,7 +23,7 @@ int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd) | |||
23 | fd->search_key = ptr; | 23 | fd->search_key = ptr; |
24 | fd->key = ptr + tree->max_key_len + 2; | 24 | fd->key = ptr + tree->max_key_len + 2; |
25 | dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n", tree->cnid, __builtin_return_address(0)); | 25 | dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n", tree->cnid, __builtin_return_address(0)); |
26 | down(&tree->tree_lock); | 26 | mutex_lock(&tree->tree_lock); |
27 | return 0; | 27 | return 0; |
28 | } | 28 | } |
29 | 29 | ||
@@ -32,7 +32,7 @@ void hfs_find_exit(struct hfs_find_data *fd) | |||
32 | hfs_bnode_put(fd->bnode); | 32 | hfs_bnode_put(fd->bnode); |
33 | kfree(fd->search_key); | 33 | kfree(fd->search_key); |
34 | dprint(DBG_BNODE_REFS, "find_exit: %d (%p)\n", fd->tree->cnid, __builtin_return_address(0)); | 34 | dprint(DBG_BNODE_REFS, "find_exit: %d (%p)\n", fd->tree->cnid, __builtin_return_address(0)); |
35 | up(&fd->tree->tree_lock); | 35 | mutex_unlock(&fd->tree->tree_lock); |
36 | fd->tree = NULL; | 36 | fd->tree = NULL; |
37 | } | 37 | } |
38 | 38 | ||
@@ -52,6 +52,10 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd) | |||
52 | rec = (e + b) / 2; | 52 | rec = (e + b) / 2; |
53 | len = hfs_brec_lenoff(bnode, rec, &off); | 53 | len = hfs_brec_lenoff(bnode, rec, &off); |
54 | keylen = hfs_brec_keylen(bnode, rec); | 54 | keylen = hfs_brec_keylen(bnode, rec); |
55 | if (keylen == 0) { | ||
56 | res = -EINVAL; | ||
57 | goto fail; | ||
58 | } | ||
55 | hfs_bnode_read(bnode, fd->key, off, keylen); | 59 | hfs_bnode_read(bnode, fd->key, off, keylen); |
56 | cmpval = bnode->tree->keycmp(fd->key, fd->search_key); | 60 | cmpval = bnode->tree->keycmp(fd->key, fd->search_key); |
57 | if (!cmpval) { | 61 | if (!cmpval) { |
@@ -67,6 +71,10 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd) | |||
67 | if (rec != e && e >= 0) { | 71 | if (rec != e && e >= 0) { |
68 | len = hfs_brec_lenoff(bnode, e, &off); | 72 | len = hfs_brec_lenoff(bnode, e, &off); |
69 | keylen = hfs_brec_keylen(bnode, e); | 73 | keylen = hfs_brec_keylen(bnode, e); |
74 | if (keylen == 0) { | ||
75 | res = -EINVAL; | ||
76 | goto fail; | ||
77 | } | ||
70 | hfs_bnode_read(bnode, fd->key, off, keylen); | 78 | hfs_bnode_read(bnode, fd->key, off, keylen); |
71 | } | 79 | } |
72 | done: | 80 | done: |
@@ -75,6 +83,7 @@ done: | |||
75 | fd->keylength = keylen; | 83 | fd->keylength = keylen; |
76 | fd->entryoffset = off + keylen; | 84 | fd->entryoffset = off + keylen; |
77 | fd->entrylength = len - keylen; | 85 | fd->entrylength = len - keylen; |
86 | fail: | ||
78 | return res; | 87 | return res; |
79 | } | 88 | } |
80 | 89 | ||
@@ -198,6 +207,10 @@ int hfs_brec_goto(struct hfs_find_data *fd, int cnt) | |||
198 | 207 | ||
199 | len = hfs_brec_lenoff(bnode, fd->record, &off); | 208 | len = hfs_brec_lenoff(bnode, fd->record, &off); |
200 | keylen = hfs_brec_keylen(bnode, fd->record); | 209 | keylen = hfs_brec_keylen(bnode, fd->record); |
210 | if (keylen == 0) { | ||
211 | res = -EINVAL; | ||
212 | goto out; | ||
213 | } | ||
201 | fd->keyoffset = off; | 214 | fd->keyoffset = off; |
202 | fd->keylength = keylen; | 215 | fd->keylength = keylen; |
203 | fd->entryoffset = off + keylen; | 216 | fd->entryoffset = off + keylen; |
diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c index ea30afc2a03c..ad57f5991eb1 100644 --- a/fs/hfsplus/bitmap.c +++ b/fs/hfsplus/bitmap.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *max) | 18 | int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *max) |
19 | { | 19 | { |
20 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
20 | struct page *page; | 21 | struct page *page; |
21 | struct address_space *mapping; | 22 | struct address_space *mapping; |
22 | __be32 *pptr, *curr, *end; | 23 | __be32 *pptr, *curr, *end; |
@@ -29,8 +30,8 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma | |||
29 | return size; | 30 | return size; |
30 | 31 | ||
31 | dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len); | 32 | dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len); |
32 | mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); | 33 | mutex_lock(&sbi->alloc_mutex); |
33 | mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; | 34 | mapping = sbi->alloc_file->i_mapping; |
34 | page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL); | 35 | page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL); |
35 | if (IS_ERR(page)) { | 36 | if (IS_ERR(page)) { |
36 | start = size; | 37 | start = size; |
@@ -150,16 +151,17 @@ done: | |||
150 | set_page_dirty(page); | 151 | set_page_dirty(page); |
151 | kunmap(page); | 152 | kunmap(page); |
152 | *max = offset + (curr - pptr) * 32 + i - start; | 153 | *max = offset + (curr - pptr) * 32 + i - start; |
153 | HFSPLUS_SB(sb).free_blocks -= *max; | 154 | sbi->free_blocks -= *max; |
154 | sb->s_dirt = 1; | 155 | sb->s_dirt = 1; |
155 | dprint(DBG_BITMAP, "-> %u,%u\n", start, *max); | 156 | dprint(DBG_BITMAP, "-> %u,%u\n", start, *max); |
156 | out: | 157 | out: |
157 | mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex); | 158 | mutex_unlock(&sbi->alloc_mutex); |
158 | return start; | 159 | return start; |
159 | } | 160 | } |
160 | 161 | ||
161 | int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count) | 162 | int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count) |
162 | { | 163 | { |
164 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
163 | struct page *page; | 165 | struct page *page; |
164 | struct address_space *mapping; | 166 | struct address_space *mapping; |
165 | __be32 *pptr, *curr, *end; | 167 | __be32 *pptr, *curr, *end; |
@@ -172,11 +174,11 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count) | |||
172 | 174 | ||
173 | dprint(DBG_BITMAP, "block_free: %u,%u\n", offset, count); | 175 | dprint(DBG_BITMAP, "block_free: %u,%u\n", offset, count); |
174 | /* are all of the bits in range? */ | 176 | /* are all of the bits in range? */ |
175 | if ((offset + count) > HFSPLUS_SB(sb).total_blocks) | 177 | if ((offset + count) > sbi->total_blocks) |
176 | return -2; | 178 | return -2; |
177 | 179 | ||
178 | mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); | 180 | mutex_lock(&sbi->alloc_mutex); |
179 | mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; | 181 | mapping = sbi->alloc_file->i_mapping; |
180 | pnr = offset / PAGE_CACHE_BITS; | 182 | pnr = offset / PAGE_CACHE_BITS; |
181 | page = read_mapping_page(mapping, pnr, NULL); | 183 | page = read_mapping_page(mapping, pnr, NULL); |
182 | pptr = kmap(page); | 184 | pptr = kmap(page); |
@@ -224,9 +226,9 @@ done: | |||
224 | out: | 226 | out: |
225 | set_page_dirty(page); | 227 | set_page_dirty(page); |
226 | kunmap(page); | 228 | kunmap(page); |
227 | HFSPLUS_SB(sb).free_blocks += len; | 229 | sbi->free_blocks += len; |
228 | sb->s_dirt = 1; | 230 | sb->s_dirt = 1; |
229 | mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex); | 231 | mutex_unlock(&sbi->alloc_mutex); |
230 | 232 | ||
231 | return 0; | 233 | return 0; |
232 | } | 234 | } |
diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c index c88e5d72a402..2f39d05443e1 100644 --- a/fs/hfsplus/brec.c +++ b/fs/hfsplus/brec.c | |||
@@ -42,10 +42,13 @@ u16 hfs_brec_keylen(struct hfs_bnode *node, u16 rec) | |||
42 | recoff = hfs_bnode_read_u16(node, node->tree->node_size - (rec + 1) * 2); | 42 | recoff = hfs_bnode_read_u16(node, node->tree->node_size - (rec + 1) * 2); |
43 | if (!recoff) | 43 | if (!recoff) |
44 | return 0; | 44 | return 0; |
45 | if (node->tree->attributes & HFS_TREE_BIGKEYS) | 45 | |
46 | retval = hfs_bnode_read_u16(node, recoff) + 2; | 46 | retval = hfs_bnode_read_u16(node, recoff) + 2; |
47 | else | 47 | if (retval > node->tree->max_key_len + 2) { |
48 | retval = (hfs_bnode_read_u8(node, recoff) | 1) + 1; | 48 | printk(KERN_ERR "hfs: keylen %d too large\n", |
49 | retval); | ||
50 | retval = 0; | ||
51 | } | ||
49 | } | 52 | } |
50 | return retval; | 53 | return retval; |
51 | } | 54 | } |
@@ -216,7 +219,7 @@ skip: | |||
216 | static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) | 219 | static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) |
217 | { | 220 | { |
218 | struct hfs_btree *tree; | 221 | struct hfs_btree *tree; |
219 | struct hfs_bnode *node, *new_node; | 222 | struct hfs_bnode *node, *new_node, *next_node; |
220 | struct hfs_bnode_desc node_desc; | 223 | struct hfs_bnode_desc node_desc; |
221 | int num_recs, new_rec_off, new_off, old_rec_off; | 224 | int num_recs, new_rec_off, new_off, old_rec_off; |
222 | int data_start, data_end, size; | 225 | int data_start, data_end, size; |
@@ -235,6 +238,17 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) | |||
235 | new_node->type = node->type; | 238 | new_node->type = node->type; |
236 | new_node->height = node->height; | 239 | new_node->height = node->height; |
237 | 240 | ||
241 | if (node->next) | ||
242 | next_node = hfs_bnode_find(tree, node->next); | ||
243 | else | ||
244 | next_node = NULL; | ||
245 | |||
246 | if (IS_ERR(next_node)) { | ||
247 | hfs_bnode_put(node); | ||
248 | hfs_bnode_put(new_node); | ||
249 | return next_node; | ||
250 | } | ||
251 | |||
238 | size = tree->node_size / 2 - node->num_recs * 2 - 14; | 252 | size = tree->node_size / 2 - node->num_recs * 2 - 14; |
239 | old_rec_off = tree->node_size - 4; | 253 | old_rec_off = tree->node_size - 4; |
240 | num_recs = 1; | 254 | num_recs = 1; |
@@ -248,6 +262,8 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) | |||
248 | /* panic? */ | 262 | /* panic? */ |
249 | hfs_bnode_put(node); | 263 | hfs_bnode_put(node); |
250 | hfs_bnode_put(new_node); | 264 | hfs_bnode_put(new_node); |
265 | if (next_node) | ||
266 | hfs_bnode_put(next_node); | ||
251 | return ERR_PTR(-ENOSPC); | 267 | return ERR_PTR(-ENOSPC); |
252 | } | 268 | } |
253 | 269 | ||
@@ -302,8 +318,7 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) | |||
302 | hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc)); | 318 | hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc)); |
303 | 319 | ||
304 | /* update next bnode header */ | 320 | /* update next bnode header */ |
305 | if (new_node->next) { | 321 | if (next_node) { |
306 | struct hfs_bnode *next_node = hfs_bnode_find(tree, new_node->next); | ||
307 | next_node->prev = new_node->this; | 322 | next_node->prev = new_node->this; |
308 | hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc)); | 323 | hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc)); |
309 | node_desc.prev = cpu_to_be32(next_node->prev); | 324 | node_desc.prev = cpu_to_be32(next_node->prev); |
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c index e49fcee1e293..22e4d4e32999 100644 --- a/fs/hfsplus/btree.c +++ b/fs/hfsplus/btree.c | |||
@@ -30,7 +30,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) | |||
30 | if (!tree) | 30 | if (!tree) |
31 | return NULL; | 31 | return NULL; |
32 | 32 | ||
33 | init_MUTEX(&tree->tree_lock); | 33 | mutex_init(&tree->tree_lock); |
34 | spin_lock_init(&tree->hash_lock); | 34 | spin_lock_init(&tree->hash_lock); |
35 | tree->sb = sb; | 35 | tree->sb = sb; |
36 | tree->cnid = id; | 36 | tree->cnid = id; |
@@ -39,10 +39,16 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) | |||
39 | goto free_tree; | 39 | goto free_tree; |
40 | tree->inode = inode; | 40 | tree->inode = inode; |
41 | 41 | ||
42 | if (!HFSPLUS_I(tree->inode)->first_blocks) { | ||
43 | printk(KERN_ERR | ||
44 | "hfs: invalid btree extent records (0 size).\n"); | ||
45 | goto free_inode; | ||
46 | } | ||
47 | |||
42 | mapping = tree->inode->i_mapping; | 48 | mapping = tree->inode->i_mapping; |
43 | page = read_mapping_page(mapping, 0, NULL); | 49 | page = read_mapping_page(mapping, 0, NULL); |
44 | if (IS_ERR(page)) | 50 | if (IS_ERR(page)) |
45 | goto free_tree; | 51 | goto free_inode; |
46 | 52 | ||
47 | /* Load the header */ | 53 | /* Load the header */ |
48 | head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc)); | 54 | head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc)); |
@@ -57,27 +63,56 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) | |||
57 | tree->max_key_len = be16_to_cpu(head->max_key_len); | 63 | tree->max_key_len = be16_to_cpu(head->max_key_len); |
58 | tree->depth = be16_to_cpu(head->depth); | 64 | tree->depth = be16_to_cpu(head->depth); |
59 | 65 | ||
60 | /* Set the correct compare function */ | 66 | /* Verify the tree and set the correct compare function */ |
61 | if (id == HFSPLUS_EXT_CNID) { | 67 | switch (id) { |
68 | case HFSPLUS_EXT_CNID: | ||
69 | if (tree->max_key_len != HFSPLUS_EXT_KEYLEN - sizeof(u16)) { | ||
70 | printk(KERN_ERR "hfs: invalid extent max_key_len %d\n", | ||
71 | tree->max_key_len); | ||
72 | goto fail_page; | ||
73 | } | ||
74 | if (tree->attributes & HFS_TREE_VARIDXKEYS) { | ||
75 | printk(KERN_ERR "hfs: invalid extent btree flag\n"); | ||
76 | goto fail_page; | ||
77 | } | ||
78 | |||
62 | tree->keycmp = hfsplus_ext_cmp_key; | 79 | tree->keycmp = hfsplus_ext_cmp_key; |
63 | } else if (id == HFSPLUS_CAT_CNID) { | 80 | break; |
64 | if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) && | 81 | case HFSPLUS_CAT_CNID: |
82 | if (tree->max_key_len != HFSPLUS_CAT_KEYLEN - sizeof(u16)) { | ||
83 | printk(KERN_ERR "hfs: invalid catalog max_key_len %d\n", | ||
84 | tree->max_key_len); | ||
85 | goto fail_page; | ||
86 | } | ||
87 | if (!(tree->attributes & HFS_TREE_VARIDXKEYS)) { | ||
88 | printk(KERN_ERR "hfs: invalid catalog btree flag\n"); | ||
89 | goto fail_page; | ||
90 | } | ||
91 | |||
92 | if (test_bit(HFSPLUS_SB_HFSX, &HFSPLUS_SB(sb)->flags) && | ||
65 | (head->key_type == HFSPLUS_KEY_BINARY)) | 93 | (head->key_type == HFSPLUS_KEY_BINARY)) |
66 | tree->keycmp = hfsplus_cat_bin_cmp_key; | 94 | tree->keycmp = hfsplus_cat_bin_cmp_key; |
67 | else { | 95 | else { |
68 | tree->keycmp = hfsplus_cat_case_cmp_key; | 96 | tree->keycmp = hfsplus_cat_case_cmp_key; |
69 | HFSPLUS_SB(sb).flags |= HFSPLUS_SB_CASEFOLD; | 97 | set_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags); |
70 | } | 98 | } |
71 | } else { | 99 | break; |
100 | default: | ||
72 | printk(KERN_ERR "hfs: unknown B*Tree requested\n"); | 101 | printk(KERN_ERR "hfs: unknown B*Tree requested\n"); |
73 | goto fail_page; | 102 | goto fail_page; |
74 | } | 103 | } |
75 | 104 | ||
105 | if (!(tree->attributes & HFS_TREE_BIGKEYS)) { | ||
106 | printk(KERN_ERR "hfs: invalid btree flag\n"); | ||
107 | goto fail_page; | ||
108 | } | ||
109 | |||
76 | size = tree->node_size; | 110 | size = tree->node_size; |
77 | if (!is_power_of_2(size)) | 111 | if (!is_power_of_2(size)) |
78 | goto fail_page; | 112 | goto fail_page; |
79 | if (!tree->node_count) | 113 | if (!tree->node_count) |
80 | goto fail_page; | 114 | goto fail_page; |
115 | |||
81 | tree->node_size_shift = ffs(size) - 1; | 116 | tree->node_size_shift = ffs(size) - 1; |
82 | 117 | ||
83 | tree->pages_per_bnode = (tree->node_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 118 | tree->pages_per_bnode = (tree->node_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
@@ -87,10 +122,11 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) | |||
87 | return tree; | 122 | return tree; |
88 | 123 | ||
89 | fail_page: | 124 | fail_page: |
90 | tree->inode->i_mapping->a_ops = &hfsplus_aops; | ||
91 | page_cache_release(page); | 125 | page_cache_release(page); |
92 | free_tree: | 126 | free_inode: |
127 | tree->inode->i_mapping->a_ops = &hfsplus_aops; | ||
93 | iput(tree->inode); | 128 | iput(tree->inode); |
129 | free_tree: | ||
94 | kfree(tree); | 130 | kfree(tree); |
95 | return NULL; | 131 | return NULL; |
96 | } | 132 | } |
@@ -192,17 +228,18 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) | |||
192 | 228 | ||
193 | while (!tree->free_nodes) { | 229 | while (!tree->free_nodes) { |
194 | struct inode *inode = tree->inode; | 230 | struct inode *inode = tree->inode; |
231 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
195 | u32 count; | 232 | u32 count; |
196 | int res; | 233 | int res; |
197 | 234 | ||
198 | res = hfsplus_file_extend(inode); | 235 | res = hfsplus_file_extend(inode); |
199 | if (res) | 236 | if (res) |
200 | return ERR_PTR(res); | 237 | return ERR_PTR(res); |
201 | HFSPLUS_I(inode).phys_size = inode->i_size = | 238 | hip->phys_size = inode->i_size = |
202 | (loff_t)HFSPLUS_I(inode).alloc_blocks << | 239 | (loff_t)hip->alloc_blocks << |
203 | HFSPLUS_SB(tree->sb).alloc_blksz_shift; | 240 | HFSPLUS_SB(tree->sb)->alloc_blksz_shift; |
204 | HFSPLUS_I(inode).fs_blocks = HFSPLUS_I(inode).alloc_blocks << | 241 | hip->fs_blocks = |
205 | HFSPLUS_SB(tree->sb).fs_shift; | 242 | hip->alloc_blocks << HFSPLUS_SB(tree->sb)->fs_shift; |
206 | inode_set_bytes(inode, inode->i_size); | 243 | inode_set_bytes(inode, inode->i_size); |
207 | count = inode->i_size >> tree->node_size_shift; | 244 | count = inode->i_size >> tree->node_size_shift; |
208 | tree->free_nodes = count - tree->node_count; | 245 | tree->free_nodes = count - tree->node_count; |
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c index f6874acb2cf2..8af45fc5b051 100644 --- a/fs/hfsplus/catalog.c +++ b/fs/hfsplus/catalog.c | |||
@@ -67,7 +67,7 @@ static void hfsplus_cat_build_key_uni(hfsplus_btree_key *key, u32 parent, | |||
67 | key->key_len = cpu_to_be16(6 + ustrlen); | 67 | key->key_len = cpu_to_be16(6 + ustrlen); |
68 | } | 68 | } |
69 | 69 | ||
70 | static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms) | 70 | void hfsplus_cat_set_perms(struct inode *inode, struct hfsplus_perm *perms) |
71 | { | 71 | { |
72 | if (inode->i_flags & S_IMMUTABLE) | 72 | if (inode->i_flags & S_IMMUTABLE) |
73 | perms->rootflags |= HFSPLUS_FLG_IMMUTABLE; | 73 | perms->rootflags |= HFSPLUS_FLG_IMMUTABLE; |
@@ -77,15 +77,24 @@ static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms) | |||
77 | perms->rootflags |= HFSPLUS_FLG_APPEND; | 77 | perms->rootflags |= HFSPLUS_FLG_APPEND; |
78 | else | 78 | else |
79 | perms->rootflags &= ~HFSPLUS_FLG_APPEND; | 79 | perms->rootflags &= ~HFSPLUS_FLG_APPEND; |
80 | HFSPLUS_I(inode).rootflags = perms->rootflags; | 80 | |
81 | HFSPLUS_I(inode).userflags = perms->userflags; | 81 | perms->userflags = HFSPLUS_I(inode)->userflags; |
82 | perms->mode = cpu_to_be16(inode->i_mode); | 82 | perms->mode = cpu_to_be16(inode->i_mode); |
83 | perms->owner = cpu_to_be32(inode->i_uid); | 83 | perms->owner = cpu_to_be32(inode->i_uid); |
84 | perms->group = cpu_to_be32(inode->i_gid); | 84 | perms->group = cpu_to_be32(inode->i_gid); |
85 | |||
86 | if (S_ISREG(inode->i_mode)) | ||
87 | perms->dev = cpu_to_be32(inode->i_nlink); | ||
88 | else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) | ||
89 | perms->dev = cpu_to_be32(inode->i_rdev); | ||
90 | else | ||
91 | perms->dev = 0; | ||
85 | } | 92 | } |
86 | 93 | ||
87 | static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct inode *inode) | 94 | static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct inode *inode) |
88 | { | 95 | { |
96 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); | ||
97 | |||
89 | if (S_ISDIR(inode->i_mode)) { | 98 | if (S_ISDIR(inode->i_mode)) { |
90 | struct hfsplus_cat_folder *folder; | 99 | struct hfsplus_cat_folder *folder; |
91 | 100 | ||
@@ -93,13 +102,13 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i | |||
93 | memset(folder, 0, sizeof(*folder)); | 102 | memset(folder, 0, sizeof(*folder)); |
94 | folder->type = cpu_to_be16(HFSPLUS_FOLDER); | 103 | folder->type = cpu_to_be16(HFSPLUS_FOLDER); |
95 | folder->id = cpu_to_be32(inode->i_ino); | 104 | folder->id = cpu_to_be32(inode->i_ino); |
96 | HFSPLUS_I(inode).create_date = | 105 | HFSPLUS_I(inode)->create_date = |
97 | folder->create_date = | 106 | folder->create_date = |
98 | folder->content_mod_date = | 107 | folder->content_mod_date = |
99 | folder->attribute_mod_date = | 108 | folder->attribute_mod_date = |
100 | folder->access_date = hfsp_now2mt(); | 109 | folder->access_date = hfsp_now2mt(); |
101 | hfsplus_set_perms(inode, &folder->permissions); | 110 | hfsplus_cat_set_perms(inode, &folder->permissions); |
102 | if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir) | 111 | if (inode == sbi->hidden_dir) |
103 | /* invisible and namelocked */ | 112 | /* invisible and namelocked */ |
104 | folder->user_info.frFlags = cpu_to_be16(0x5000); | 113 | folder->user_info.frFlags = cpu_to_be16(0x5000); |
105 | return sizeof(*folder); | 114 | return sizeof(*folder); |
@@ -111,19 +120,19 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i | |||
111 | file->type = cpu_to_be16(HFSPLUS_FILE); | 120 | file->type = cpu_to_be16(HFSPLUS_FILE); |
112 | file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS); | 121 | file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS); |
113 | file->id = cpu_to_be32(cnid); | 122 | file->id = cpu_to_be32(cnid); |
114 | HFSPLUS_I(inode).create_date = | 123 | HFSPLUS_I(inode)->create_date = |
115 | file->create_date = | 124 | file->create_date = |
116 | file->content_mod_date = | 125 | file->content_mod_date = |
117 | file->attribute_mod_date = | 126 | file->attribute_mod_date = |
118 | file->access_date = hfsp_now2mt(); | 127 | file->access_date = hfsp_now2mt(); |
119 | if (cnid == inode->i_ino) { | 128 | if (cnid == inode->i_ino) { |
120 | hfsplus_set_perms(inode, &file->permissions); | 129 | hfsplus_cat_set_perms(inode, &file->permissions); |
121 | if (S_ISLNK(inode->i_mode)) { | 130 | if (S_ISLNK(inode->i_mode)) { |
122 | file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE); | 131 | file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE); |
123 | file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR); | 132 | file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR); |
124 | } else { | 133 | } else { |
125 | file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type); | 134 | file->user_info.fdType = cpu_to_be32(sbi->type); |
126 | file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator); | 135 | file->user_info.fdCreator = cpu_to_be32(sbi->creator); |
127 | } | 136 | } |
128 | if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) | 137 | if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) |
129 | file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); | 138 | file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); |
@@ -131,8 +140,8 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i | |||
131 | file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE); | 140 | file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE); |
132 | file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR); | 141 | file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR); |
133 | file->user_info.fdFlags = cpu_to_be16(0x100); | 142 | file->user_info.fdFlags = cpu_to_be16(0x100); |
134 | file->create_date = HFSPLUS_I(HFSPLUS_SB(inode->i_sb).hidden_dir).create_date; | 143 | file->create_date = HFSPLUS_I(sbi->hidden_dir)->create_date; |
135 | file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev); | 144 | file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode)->linkid); |
136 | } | 145 | } |
137 | return sizeof(*file); | 146 | return sizeof(*file); |
138 | } | 147 | } |
@@ -180,15 +189,14 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid, | |||
180 | 189 | ||
181 | int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str, struct inode *inode) | 190 | int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str, struct inode *inode) |
182 | { | 191 | { |
192 | struct super_block *sb = dir->i_sb; | ||
183 | struct hfs_find_data fd; | 193 | struct hfs_find_data fd; |
184 | struct super_block *sb; | ||
185 | hfsplus_cat_entry entry; | 194 | hfsplus_cat_entry entry; |
186 | int entry_size; | 195 | int entry_size; |
187 | int err; | 196 | int err; |
188 | 197 | ||
189 | dprint(DBG_CAT_MOD, "create_cat: %s,%u(%d)\n", str->name, cnid, inode->i_nlink); | 198 | dprint(DBG_CAT_MOD, "create_cat: %s,%u(%d)\n", str->name, cnid, inode->i_nlink); |
190 | sb = dir->i_sb; | 199 | hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); |
191 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | ||
192 | 200 | ||
193 | hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL); | 201 | hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL); |
194 | entry_size = hfsplus_fill_cat_thread(sb, &entry, S_ISDIR(inode->i_mode) ? | 202 | entry_size = hfsplus_fill_cat_thread(sb, &entry, S_ISDIR(inode->i_mode) ? |
@@ -234,7 +242,7 @@ err2: | |||
234 | 242 | ||
235 | int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) | 243 | int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) |
236 | { | 244 | { |
237 | struct super_block *sb; | 245 | struct super_block *sb = dir->i_sb; |
238 | struct hfs_find_data fd; | 246 | struct hfs_find_data fd; |
239 | struct hfsplus_fork_raw fork; | 247 | struct hfsplus_fork_raw fork; |
240 | struct list_head *pos; | 248 | struct list_head *pos; |
@@ -242,8 +250,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) | |||
242 | u16 type; | 250 | u16 type; |
243 | 251 | ||
244 | dprint(DBG_CAT_MOD, "delete_cat: %s,%u\n", str ? str->name : NULL, cnid); | 252 | dprint(DBG_CAT_MOD, "delete_cat: %s,%u\n", str ? str->name : NULL, cnid); |
245 | sb = dir->i_sb; | 253 | hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); |
246 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | ||
247 | 254 | ||
248 | if (!str) { | 255 | if (!str) { |
249 | int len; | 256 | int len; |
@@ -279,7 +286,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) | |||
279 | hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_RSRC); | 286 | hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_RSRC); |
280 | } | 287 | } |
281 | 288 | ||
282 | list_for_each(pos, &HFSPLUS_I(dir).open_dir_list) { | 289 | list_for_each(pos, &HFSPLUS_I(dir)->open_dir_list) { |
283 | struct hfsplus_readdir_data *rd = | 290 | struct hfsplus_readdir_data *rd = |
284 | list_entry(pos, struct hfsplus_readdir_data, list); | 291 | list_entry(pos, struct hfsplus_readdir_data, list); |
285 | if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0) | 292 | if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0) |
@@ -312,7 +319,7 @@ int hfsplus_rename_cat(u32 cnid, | |||
312 | struct inode *src_dir, struct qstr *src_name, | 319 | struct inode *src_dir, struct qstr *src_name, |
313 | struct inode *dst_dir, struct qstr *dst_name) | 320 | struct inode *dst_dir, struct qstr *dst_name) |
314 | { | 321 | { |
315 | struct super_block *sb; | 322 | struct super_block *sb = src_dir->i_sb; |
316 | struct hfs_find_data src_fd, dst_fd; | 323 | struct hfs_find_data src_fd, dst_fd; |
317 | hfsplus_cat_entry entry; | 324 | hfsplus_cat_entry entry; |
318 | int entry_size, type; | 325 | int entry_size, type; |
@@ -320,8 +327,7 @@ int hfsplus_rename_cat(u32 cnid, | |||
320 | 327 | ||
321 | dprint(DBG_CAT_MOD, "rename_cat: %u - %lu,%s - %lu,%s\n", cnid, src_dir->i_ino, src_name->name, | 328 | dprint(DBG_CAT_MOD, "rename_cat: %u - %lu,%s - %lu,%s\n", cnid, src_dir->i_ino, src_name->name, |
322 | dst_dir->i_ino, dst_name->name); | 329 | dst_dir->i_ino, dst_name->name); |
323 | sb = src_dir->i_sb; | 330 | hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &src_fd); |
324 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &src_fd); | ||
325 | dst_fd = src_fd; | 331 | dst_fd = src_fd; |
326 | 332 | ||
327 | /* find the old dir entry and read the data */ | 333 | /* find the old dir entry and read the data */ |
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 764fd1bdca88..d236d85ec9d7 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c | |||
@@ -39,7 +39,7 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry, | |||
39 | 39 | ||
40 | dentry->d_op = &hfsplus_dentry_operations; | 40 | dentry->d_op = &hfsplus_dentry_operations; |
41 | dentry->d_fsdata = NULL; | 41 | dentry->d_fsdata = NULL; |
42 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | 42 | hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); |
43 | hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name); | 43 | hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name); |
44 | again: | 44 | again: |
45 | err = hfs_brec_read(&fd, &entry, sizeof(entry)); | 45 | err = hfs_brec_read(&fd, &entry, sizeof(entry)); |
@@ -68,9 +68,9 @@ again: | |||
68 | cnid = be32_to_cpu(entry.file.id); | 68 | cnid = be32_to_cpu(entry.file.id); |
69 | if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) && | 69 | if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) && |
70 | entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) && | 70 | entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) && |
71 | (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb).hidden_dir).create_date || | 71 | (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb)->hidden_dir)->create_date || |
72 | entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode).create_date) && | 72 | entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode)->create_date) && |
73 | HFSPLUS_SB(sb).hidden_dir) { | 73 | HFSPLUS_SB(sb)->hidden_dir) { |
74 | struct qstr str; | 74 | struct qstr str; |
75 | char name[32]; | 75 | char name[32]; |
76 | 76 | ||
@@ -86,7 +86,8 @@ again: | |||
86 | linkid = be32_to_cpu(entry.file.permissions.dev); | 86 | linkid = be32_to_cpu(entry.file.permissions.dev); |
87 | str.len = sprintf(name, "iNode%d", linkid); | 87 | str.len = sprintf(name, "iNode%d", linkid); |
88 | str.name = name; | 88 | str.name = name; |
89 | hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str); | 89 | hfsplus_cat_build_key(sb, fd.search_key, |
90 | HFSPLUS_SB(sb)->hidden_dir->i_ino, &str); | ||
90 | goto again; | 91 | goto again; |
91 | } | 92 | } |
92 | } else if (!dentry->d_fsdata) | 93 | } else if (!dentry->d_fsdata) |
@@ -101,7 +102,7 @@ again: | |||
101 | if (IS_ERR(inode)) | 102 | if (IS_ERR(inode)) |
102 | return ERR_CAST(inode); | 103 | return ERR_CAST(inode); |
103 | if (S_ISREG(inode->i_mode)) | 104 | if (S_ISREG(inode->i_mode)) |
104 | HFSPLUS_I(inode).dev = linkid; | 105 | HFSPLUS_I(inode)->linkid = linkid; |
105 | out: | 106 | out: |
106 | d_add(dentry, inode); | 107 | d_add(dentry, inode); |
107 | return NULL; | 108 | return NULL; |
@@ -124,7 +125,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
124 | if (filp->f_pos >= inode->i_size) | 125 | if (filp->f_pos >= inode->i_size) |
125 | return 0; | 126 | return 0; |
126 | 127 | ||
127 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | 128 | hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); |
128 | hfsplus_cat_build_key(sb, fd.search_key, inode->i_ino, NULL); | 129 | hfsplus_cat_build_key(sb, fd.search_key, inode->i_ino, NULL); |
129 | err = hfs_brec_find(&fd); | 130 | err = hfs_brec_find(&fd); |
130 | if (err) | 131 | if (err) |
@@ -180,8 +181,9 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
180 | err = -EIO; | 181 | err = -EIO; |
181 | goto out; | 182 | goto out; |
182 | } | 183 | } |
183 | if (HFSPLUS_SB(sb).hidden_dir && | 184 | if (HFSPLUS_SB(sb)->hidden_dir && |
184 | HFSPLUS_SB(sb).hidden_dir->i_ino == be32_to_cpu(entry.folder.id)) | 185 | HFSPLUS_SB(sb)->hidden_dir->i_ino == |
186 | be32_to_cpu(entry.folder.id)) | ||
185 | goto next; | 187 | goto next; |
186 | if (filldir(dirent, strbuf, len, filp->f_pos, | 188 | if (filldir(dirent, strbuf, len, filp->f_pos, |
187 | be32_to_cpu(entry.folder.id), DT_DIR)) | 189 | be32_to_cpu(entry.folder.id), DT_DIR)) |
@@ -217,7 +219,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
217 | } | 219 | } |
218 | filp->private_data = rd; | 220 | filp->private_data = rd; |
219 | rd->file = filp; | 221 | rd->file = filp; |
220 | list_add(&rd->list, &HFSPLUS_I(inode).open_dir_list); | 222 | list_add(&rd->list, &HFSPLUS_I(inode)->open_dir_list); |
221 | } | 223 | } |
222 | memcpy(&rd->key, fd.key, sizeof(struct hfsplus_cat_key)); | 224 | memcpy(&rd->key, fd.key, sizeof(struct hfsplus_cat_key)); |
223 | out: | 225 | out: |
@@ -229,38 +231,18 @@ static int hfsplus_dir_release(struct inode *inode, struct file *file) | |||
229 | { | 231 | { |
230 | struct hfsplus_readdir_data *rd = file->private_data; | 232 | struct hfsplus_readdir_data *rd = file->private_data; |
231 | if (rd) { | 233 | if (rd) { |
234 | mutex_lock(&inode->i_mutex); | ||
232 | list_del(&rd->list); | 235 | list_del(&rd->list); |
236 | mutex_unlock(&inode->i_mutex); | ||
233 | kfree(rd); | 237 | kfree(rd); |
234 | } | 238 | } |
235 | return 0; | 239 | return 0; |
236 | } | 240 | } |
237 | 241 | ||
238 | static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode, | ||
239 | struct nameidata *nd) | ||
240 | { | ||
241 | struct inode *inode; | ||
242 | int res; | ||
243 | |||
244 | inode = hfsplus_new_inode(dir->i_sb, mode); | ||
245 | if (!inode) | ||
246 | return -ENOSPC; | ||
247 | |||
248 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); | ||
249 | if (res) { | ||
250 | inode->i_nlink = 0; | ||
251 | hfsplus_delete_inode(inode); | ||
252 | iput(inode); | ||
253 | return res; | ||
254 | } | ||
255 | hfsplus_instantiate(dentry, inode, inode->i_ino); | ||
256 | mark_inode_dirty(inode); | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, | 242 | static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, |
261 | struct dentry *dst_dentry) | 243 | struct dentry *dst_dentry) |
262 | { | 244 | { |
263 | struct super_block *sb = dst_dir->i_sb; | 245 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(dst_dir->i_sb); |
264 | struct inode *inode = src_dentry->d_inode; | 246 | struct inode *inode = src_dentry->d_inode; |
265 | struct inode *src_dir = src_dentry->d_parent->d_inode; | 247 | struct inode *src_dir = src_dentry->d_parent->d_inode; |
266 | struct qstr str; | 248 | struct qstr str; |
@@ -270,7 +252,10 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, | |||
270 | 252 | ||
271 | if (HFSPLUS_IS_RSRC(inode)) | 253 | if (HFSPLUS_IS_RSRC(inode)) |
272 | return -EPERM; | 254 | return -EPERM; |
255 | if (!S_ISREG(inode->i_mode)) | ||
256 | return -EPERM; | ||
273 | 257 | ||
258 | mutex_lock(&sbi->vh_mutex); | ||
274 | if (inode->i_ino == (u32)(unsigned long)src_dentry->d_fsdata) { | 259 | if (inode->i_ino == (u32)(unsigned long)src_dentry->d_fsdata) { |
275 | for (;;) { | 260 | for (;;) { |
276 | get_random_bytes(&id, sizeof(cnid)); | 261 | get_random_bytes(&id, sizeof(cnid)); |
@@ -279,40 +264,41 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, | |||
279 | str.len = sprintf(name, "iNode%d", id); | 264 | str.len = sprintf(name, "iNode%d", id); |
280 | res = hfsplus_rename_cat(inode->i_ino, | 265 | res = hfsplus_rename_cat(inode->i_ino, |
281 | src_dir, &src_dentry->d_name, | 266 | src_dir, &src_dentry->d_name, |
282 | HFSPLUS_SB(sb).hidden_dir, &str); | 267 | sbi->hidden_dir, &str); |
283 | if (!res) | 268 | if (!res) |
284 | break; | 269 | break; |
285 | if (res != -EEXIST) | 270 | if (res != -EEXIST) |
286 | return res; | 271 | goto out; |
287 | } | 272 | } |
288 | HFSPLUS_I(inode).dev = id; | 273 | HFSPLUS_I(inode)->linkid = id; |
289 | cnid = HFSPLUS_SB(sb).next_cnid++; | 274 | cnid = sbi->next_cnid++; |
290 | src_dentry->d_fsdata = (void *)(unsigned long)cnid; | 275 | src_dentry->d_fsdata = (void *)(unsigned long)cnid; |
291 | res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode); | 276 | res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode); |
292 | if (res) | 277 | if (res) |
293 | /* panic? */ | 278 | /* panic? */ |
294 | return res; | 279 | goto out; |
295 | HFSPLUS_SB(sb).file_count++; | 280 | sbi->file_count++; |
296 | } | 281 | } |
297 | cnid = HFSPLUS_SB(sb).next_cnid++; | 282 | cnid = sbi->next_cnid++; |
298 | res = hfsplus_create_cat(cnid, dst_dir, &dst_dentry->d_name, inode); | 283 | res = hfsplus_create_cat(cnid, dst_dir, &dst_dentry->d_name, inode); |
299 | if (res) | 284 | if (res) |
300 | return res; | 285 | goto out; |
301 | 286 | ||
302 | inc_nlink(inode); | 287 | inc_nlink(inode); |
303 | hfsplus_instantiate(dst_dentry, inode, cnid); | 288 | hfsplus_instantiate(dst_dentry, inode, cnid); |
304 | atomic_inc(&inode->i_count); | 289 | atomic_inc(&inode->i_count); |
305 | inode->i_ctime = CURRENT_TIME_SEC; | 290 | inode->i_ctime = CURRENT_TIME_SEC; |
306 | mark_inode_dirty(inode); | 291 | mark_inode_dirty(inode); |
307 | HFSPLUS_SB(sb).file_count++; | 292 | sbi->file_count++; |
308 | sb->s_dirt = 1; | 293 | dst_dir->i_sb->s_dirt = 1; |
309 | 294 | out: | |
310 | return 0; | 295 | mutex_unlock(&sbi->vh_mutex); |
296 | return res; | ||
311 | } | 297 | } |
312 | 298 | ||
313 | static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) | 299 | static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) |
314 | { | 300 | { |
315 | struct super_block *sb = dir->i_sb; | 301 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); |
316 | struct inode *inode = dentry->d_inode; | 302 | struct inode *inode = dentry->d_inode; |
317 | struct qstr str; | 303 | struct qstr str; |
318 | char name[32]; | 304 | char name[32]; |
@@ -322,21 +308,22 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) | |||
322 | if (HFSPLUS_IS_RSRC(inode)) | 308 | if (HFSPLUS_IS_RSRC(inode)) |
323 | return -EPERM; | 309 | return -EPERM; |
324 | 310 | ||
311 | mutex_lock(&sbi->vh_mutex); | ||
325 | cnid = (u32)(unsigned long)dentry->d_fsdata; | 312 | cnid = (u32)(unsigned long)dentry->d_fsdata; |
326 | if (inode->i_ino == cnid && | 313 | if (inode->i_ino == cnid && |
327 | atomic_read(&HFSPLUS_I(inode).opencnt)) { | 314 | atomic_read(&HFSPLUS_I(inode)->opencnt)) { |
328 | str.name = name; | 315 | str.name = name; |
329 | str.len = sprintf(name, "temp%lu", inode->i_ino); | 316 | str.len = sprintf(name, "temp%lu", inode->i_ino); |
330 | res = hfsplus_rename_cat(inode->i_ino, | 317 | res = hfsplus_rename_cat(inode->i_ino, |
331 | dir, &dentry->d_name, | 318 | dir, &dentry->d_name, |
332 | HFSPLUS_SB(sb).hidden_dir, &str); | 319 | sbi->hidden_dir, &str); |
333 | if (!res) | 320 | if (!res) |
334 | inode->i_flags |= S_DEAD; | 321 | inode->i_flags |= S_DEAD; |
335 | return res; | 322 | goto out; |
336 | } | 323 | } |
337 | res = hfsplus_delete_cat(cnid, dir, &dentry->d_name); | 324 | res = hfsplus_delete_cat(cnid, dir, &dentry->d_name); |
338 | if (res) | 325 | if (res) |
339 | return res; | 326 | goto out; |
340 | 327 | ||
341 | if (inode->i_nlink > 0) | 328 | if (inode->i_nlink > 0) |
342 | drop_nlink(inode); | 329 | drop_nlink(inode); |
@@ -344,10 +331,10 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) | |||
344 | clear_nlink(inode); | 331 | clear_nlink(inode); |
345 | if (!inode->i_nlink) { | 332 | if (!inode->i_nlink) { |
346 | if (inode->i_ino != cnid) { | 333 | if (inode->i_ino != cnid) { |
347 | HFSPLUS_SB(sb).file_count--; | 334 | sbi->file_count--; |
348 | if (!atomic_read(&HFSPLUS_I(inode).opencnt)) { | 335 | if (!atomic_read(&HFSPLUS_I(inode)->opencnt)) { |
349 | res = hfsplus_delete_cat(inode->i_ino, | 336 | res = hfsplus_delete_cat(inode->i_ino, |
350 | HFSPLUS_SB(sb).hidden_dir, | 337 | sbi->hidden_dir, |
351 | NULL); | 338 | NULL); |
352 | if (!res) | 339 | if (!res) |
353 | hfsplus_delete_inode(inode); | 340 | hfsplus_delete_inode(inode); |
@@ -356,107 +343,108 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) | |||
356 | } else | 343 | } else |
357 | hfsplus_delete_inode(inode); | 344 | hfsplus_delete_inode(inode); |
358 | } else | 345 | } else |
359 | HFSPLUS_SB(sb).file_count--; | 346 | sbi->file_count--; |
360 | inode->i_ctime = CURRENT_TIME_SEC; | 347 | inode->i_ctime = CURRENT_TIME_SEC; |
361 | mark_inode_dirty(inode); | 348 | mark_inode_dirty(inode); |
362 | 349 | out: | |
350 | mutex_unlock(&sbi->vh_mutex); | ||
363 | return res; | 351 | return res; |
364 | } | 352 | } |
365 | 353 | ||
366 | static int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode) | ||
367 | { | ||
368 | struct inode *inode; | ||
369 | int res; | ||
370 | |||
371 | inode = hfsplus_new_inode(dir->i_sb, S_IFDIR | mode); | ||
372 | if (!inode) | ||
373 | return -ENOSPC; | ||
374 | |||
375 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); | ||
376 | if (res) { | ||
377 | inode->i_nlink = 0; | ||
378 | hfsplus_delete_inode(inode); | ||
379 | iput(inode); | ||
380 | return res; | ||
381 | } | ||
382 | hfsplus_instantiate(dentry, inode, inode->i_ino); | ||
383 | mark_inode_dirty(inode); | ||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry) | 354 | static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry) |
388 | { | 355 | { |
389 | struct inode *inode; | 356 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); |
357 | struct inode *inode = dentry->d_inode; | ||
390 | int res; | 358 | int res; |
391 | 359 | ||
392 | inode = dentry->d_inode; | ||
393 | if (inode->i_size != 2) | 360 | if (inode->i_size != 2) |
394 | return -ENOTEMPTY; | 361 | return -ENOTEMPTY; |
362 | |||
363 | mutex_lock(&sbi->vh_mutex); | ||
395 | res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name); | 364 | res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name); |
396 | if (res) | 365 | if (res) |
397 | return res; | 366 | goto out; |
398 | clear_nlink(inode); | 367 | clear_nlink(inode); |
399 | inode->i_ctime = CURRENT_TIME_SEC; | 368 | inode->i_ctime = CURRENT_TIME_SEC; |
400 | hfsplus_delete_inode(inode); | 369 | hfsplus_delete_inode(inode); |
401 | mark_inode_dirty(inode); | 370 | mark_inode_dirty(inode); |
402 | return 0; | 371 | out: |
372 | mutex_unlock(&sbi->vh_mutex); | ||
373 | return res; | ||
403 | } | 374 | } |
404 | 375 | ||
405 | static int hfsplus_symlink(struct inode *dir, struct dentry *dentry, | 376 | static int hfsplus_symlink(struct inode *dir, struct dentry *dentry, |
406 | const char *symname) | 377 | const char *symname) |
407 | { | 378 | { |
408 | struct super_block *sb; | 379 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); |
409 | struct inode *inode; | 380 | struct inode *inode; |
410 | int res; | 381 | int res = -ENOSPC; |
411 | 382 | ||
412 | sb = dir->i_sb; | 383 | mutex_lock(&sbi->vh_mutex); |
413 | inode = hfsplus_new_inode(sb, S_IFLNK | S_IRWXUGO); | 384 | inode = hfsplus_new_inode(dir->i_sb, S_IFLNK | S_IRWXUGO); |
414 | if (!inode) | 385 | if (!inode) |
415 | return -ENOSPC; | 386 | goto out; |
416 | 387 | ||
417 | res = page_symlink(inode, symname, strlen(symname) + 1); | 388 | res = page_symlink(inode, symname, strlen(symname) + 1); |
418 | if (res) { | 389 | if (res) |
419 | inode->i_nlink = 0; | 390 | goto out_err; |
420 | hfsplus_delete_inode(inode); | ||
421 | iput(inode); | ||
422 | return res; | ||
423 | } | ||
424 | 391 | ||
425 | mark_inode_dirty(inode); | ||
426 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); | 392 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); |
393 | if (res) | ||
394 | goto out_err; | ||
427 | 395 | ||
428 | if (!res) { | 396 | hfsplus_instantiate(dentry, inode, inode->i_ino); |
429 | hfsplus_instantiate(dentry, inode, inode->i_ino); | 397 | mark_inode_dirty(inode); |
430 | mark_inode_dirty(inode); | 398 | goto out; |
431 | } | ||
432 | 399 | ||
400 | out_err: | ||
401 | inode->i_nlink = 0; | ||
402 | hfsplus_delete_inode(inode); | ||
403 | iput(inode); | ||
404 | out: | ||
405 | mutex_unlock(&sbi->vh_mutex); | ||
433 | return res; | 406 | return res; |
434 | } | 407 | } |
435 | 408 | ||
436 | static int hfsplus_mknod(struct inode *dir, struct dentry *dentry, | 409 | static int hfsplus_mknod(struct inode *dir, struct dentry *dentry, |
437 | int mode, dev_t rdev) | 410 | int mode, dev_t rdev) |
438 | { | 411 | { |
439 | struct super_block *sb; | 412 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); |
440 | struct inode *inode; | 413 | struct inode *inode; |
441 | int res; | 414 | int res = -ENOSPC; |
442 | 415 | ||
443 | sb = dir->i_sb; | 416 | mutex_lock(&sbi->vh_mutex); |
444 | inode = hfsplus_new_inode(sb, mode); | 417 | inode = hfsplus_new_inode(dir->i_sb, mode); |
445 | if (!inode) | 418 | if (!inode) |
446 | return -ENOSPC; | 419 | goto out; |
420 | |||
421 | if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) | ||
422 | init_special_inode(inode, mode, rdev); | ||
447 | 423 | ||
448 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); | 424 | res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); |
449 | if (res) { | 425 | if (res) { |
450 | inode->i_nlink = 0; | 426 | inode->i_nlink = 0; |
451 | hfsplus_delete_inode(inode); | 427 | hfsplus_delete_inode(inode); |
452 | iput(inode); | 428 | iput(inode); |
453 | return res; | 429 | goto out; |
454 | } | 430 | } |
455 | init_special_inode(inode, mode, rdev); | 431 | |
456 | hfsplus_instantiate(dentry, inode, inode->i_ino); | 432 | hfsplus_instantiate(dentry, inode, inode->i_ino); |
457 | mark_inode_dirty(inode); | 433 | mark_inode_dirty(inode); |
434 | out: | ||
435 | mutex_unlock(&sbi->vh_mutex); | ||
436 | return res; | ||
437 | } | ||
458 | 438 | ||
459 | return 0; | 439 | static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode, |
440 | struct nameidata *nd) | ||
441 | { | ||
442 | return hfsplus_mknod(dir, dentry, mode, 0); | ||
443 | } | ||
444 | |||
445 | static int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode) | ||
446 | { | ||
447 | return hfsplus_mknod(dir, dentry, mode | S_IFDIR, 0); | ||
460 | } | 448 | } |
461 | 449 | ||
462 | static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, | 450 | static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, |
@@ -466,7 +454,10 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
466 | 454 | ||
467 | /* Unlink destination if it already exists */ | 455 | /* Unlink destination if it already exists */ |
468 | if (new_dentry->d_inode) { | 456 | if (new_dentry->d_inode) { |
469 | res = hfsplus_unlink(new_dir, new_dentry); | 457 | if (S_ISDIR(new_dentry->d_inode->i_mode)) |
458 | res = hfsplus_rmdir(new_dir, new_dentry); | ||
459 | else | ||
460 | res = hfsplus_unlink(new_dir, new_dentry); | ||
470 | if (res) | 461 | if (res) |
471 | return res; | 462 | return res; |
472 | } | 463 | } |
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c index 0022eec63cda..0c9cb1820a52 100644 --- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c | |||
@@ -85,35 +85,49 @@ static u32 hfsplus_ext_lastblock(struct hfsplus_extent *ext) | |||
85 | 85 | ||
86 | static void __hfsplus_ext_write_extent(struct inode *inode, struct hfs_find_data *fd) | 86 | static void __hfsplus_ext_write_extent(struct inode *inode, struct hfs_find_data *fd) |
87 | { | 87 | { |
88 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
88 | int res; | 89 | int res; |
89 | 90 | ||
90 | hfsplus_ext_build_key(fd->search_key, inode->i_ino, HFSPLUS_I(inode).cached_start, | 91 | WARN_ON(!mutex_is_locked(&hip->extents_lock)); |
91 | HFSPLUS_IS_RSRC(inode) ? HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA); | 92 | |
93 | hfsplus_ext_build_key(fd->search_key, inode->i_ino, hip->cached_start, | ||
94 | HFSPLUS_IS_RSRC(inode) ? | ||
95 | HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA); | ||
96 | |||
92 | res = hfs_brec_find(fd); | 97 | res = hfs_brec_find(fd); |
93 | if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_NEW) { | 98 | if (hip->flags & HFSPLUS_FLG_EXT_NEW) { |
94 | if (res != -ENOENT) | 99 | if (res != -ENOENT) |
95 | return; | 100 | return; |
96 | hfs_brec_insert(fd, HFSPLUS_I(inode).cached_extents, sizeof(hfsplus_extent_rec)); | 101 | hfs_brec_insert(fd, hip->cached_extents, |
97 | HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); | 102 | sizeof(hfsplus_extent_rec)); |
103 | hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); | ||
98 | } else { | 104 | } else { |
99 | if (res) | 105 | if (res) |
100 | return; | 106 | return; |
101 | hfs_bnode_write(fd->bnode, HFSPLUS_I(inode).cached_extents, fd->entryoffset, fd->entrylength); | 107 | hfs_bnode_write(fd->bnode, hip->cached_extents, |
102 | HFSPLUS_I(inode).flags &= ~HFSPLUS_FLG_EXT_DIRTY; | 108 | fd->entryoffset, fd->entrylength); |
109 | hip->flags &= ~HFSPLUS_FLG_EXT_DIRTY; | ||
103 | } | 110 | } |
104 | } | 111 | } |
105 | 112 | ||
106 | void hfsplus_ext_write_extent(struct inode *inode) | 113 | static void hfsplus_ext_write_extent_locked(struct inode *inode) |
107 | { | 114 | { |
108 | if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_DIRTY) { | 115 | if (HFSPLUS_I(inode)->flags & HFSPLUS_FLG_EXT_DIRTY) { |
109 | struct hfs_find_data fd; | 116 | struct hfs_find_data fd; |
110 | 117 | ||
111 | hfs_find_init(HFSPLUS_SB(inode->i_sb).ext_tree, &fd); | 118 | hfs_find_init(HFSPLUS_SB(inode->i_sb)->ext_tree, &fd); |
112 | __hfsplus_ext_write_extent(inode, &fd); | 119 | __hfsplus_ext_write_extent(inode, &fd); |
113 | hfs_find_exit(&fd); | 120 | hfs_find_exit(&fd); |
114 | } | 121 | } |
115 | } | 122 | } |
116 | 123 | ||
124 | void hfsplus_ext_write_extent(struct inode *inode) | ||
125 | { | ||
126 | mutex_lock(&HFSPLUS_I(inode)->extents_lock); | ||
127 | hfsplus_ext_write_extent_locked(inode); | ||
128 | mutex_unlock(&HFSPLUS_I(inode)->extents_lock); | ||
129 | } | ||
130 | |||
117 | static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd, | 131 | static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd, |
118 | struct hfsplus_extent *extent, | 132 | struct hfsplus_extent *extent, |
119 | u32 cnid, u32 block, u8 type) | 133 | u32 cnid, u32 block, u8 type) |
@@ -136,33 +150,39 @@ static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd, | |||
136 | 150 | ||
137 | static inline int __hfsplus_ext_cache_extent(struct hfs_find_data *fd, struct inode *inode, u32 block) | 151 | static inline int __hfsplus_ext_cache_extent(struct hfs_find_data *fd, struct inode *inode, u32 block) |
138 | { | 152 | { |
153 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
139 | int res; | 154 | int res; |
140 | 155 | ||
141 | if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_DIRTY) | 156 | WARN_ON(!mutex_is_locked(&hip->extents_lock)); |
157 | |||
158 | if (hip->flags & HFSPLUS_FLG_EXT_DIRTY) | ||
142 | __hfsplus_ext_write_extent(inode, fd); | 159 | __hfsplus_ext_write_extent(inode, fd); |
143 | 160 | ||
144 | res = __hfsplus_ext_read_extent(fd, HFSPLUS_I(inode).cached_extents, inode->i_ino, | 161 | res = __hfsplus_ext_read_extent(fd, hip->cached_extents, inode->i_ino, |
145 | block, HFSPLUS_IS_RSRC(inode) ? HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA); | 162 | block, HFSPLUS_IS_RSRC(inode) ? |
163 | HFSPLUS_TYPE_RSRC : | ||
164 | HFSPLUS_TYPE_DATA); | ||
146 | if (!res) { | 165 | if (!res) { |
147 | HFSPLUS_I(inode).cached_start = be32_to_cpu(fd->key->ext.start_block); | 166 | hip->cached_start = be32_to_cpu(fd->key->ext.start_block); |
148 | HFSPLUS_I(inode).cached_blocks = hfsplus_ext_block_count(HFSPLUS_I(inode).cached_extents); | 167 | hip->cached_blocks = hfsplus_ext_block_count(hip->cached_extents); |
149 | } else { | 168 | } else { |
150 | HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).cached_blocks = 0; | 169 | hip->cached_start = hip->cached_blocks = 0; |
151 | HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); | 170 | hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); |
152 | } | 171 | } |
153 | return res; | 172 | return res; |
154 | } | 173 | } |
155 | 174 | ||
156 | static int hfsplus_ext_read_extent(struct inode *inode, u32 block) | 175 | static int hfsplus_ext_read_extent(struct inode *inode, u32 block) |
157 | { | 176 | { |
177 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
158 | struct hfs_find_data fd; | 178 | struct hfs_find_data fd; |
159 | int res; | 179 | int res; |
160 | 180 | ||
161 | if (block >= HFSPLUS_I(inode).cached_start && | 181 | if (block >= hip->cached_start && |
162 | block < HFSPLUS_I(inode).cached_start + HFSPLUS_I(inode).cached_blocks) | 182 | block < hip->cached_start + hip->cached_blocks) |
163 | return 0; | 183 | return 0; |
164 | 184 | ||
165 | hfs_find_init(HFSPLUS_SB(inode->i_sb).ext_tree, &fd); | 185 | hfs_find_init(HFSPLUS_SB(inode->i_sb)->ext_tree, &fd); |
166 | res = __hfsplus_ext_cache_extent(&fd, inode, block); | 186 | res = __hfsplus_ext_cache_extent(&fd, inode, block); |
167 | hfs_find_exit(&fd); | 187 | hfs_find_exit(&fd); |
168 | return res; | 188 | return res; |
@@ -172,21 +192,21 @@ static int hfsplus_ext_read_extent(struct inode *inode, u32 block) | |||
172 | int hfsplus_get_block(struct inode *inode, sector_t iblock, | 192 | int hfsplus_get_block(struct inode *inode, sector_t iblock, |
173 | struct buffer_head *bh_result, int create) | 193 | struct buffer_head *bh_result, int create) |
174 | { | 194 | { |
175 | struct super_block *sb; | 195 | struct super_block *sb = inode->i_sb; |
196 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
197 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
176 | int res = -EIO; | 198 | int res = -EIO; |
177 | u32 ablock, dblock, mask; | 199 | u32 ablock, dblock, mask; |
178 | int shift; | 200 | int shift; |
179 | 201 | ||
180 | sb = inode->i_sb; | ||
181 | |||
182 | /* Convert inode block to disk allocation block */ | 202 | /* Convert inode block to disk allocation block */ |
183 | shift = HFSPLUS_SB(sb).alloc_blksz_shift - sb->s_blocksize_bits; | 203 | shift = sbi->alloc_blksz_shift - sb->s_blocksize_bits; |
184 | ablock = iblock >> HFSPLUS_SB(sb).fs_shift; | 204 | ablock = iblock >> sbi->fs_shift; |
185 | 205 | ||
186 | if (iblock >= HFSPLUS_I(inode).fs_blocks) { | 206 | if (iblock >= hip->fs_blocks) { |
187 | if (iblock > HFSPLUS_I(inode).fs_blocks || !create) | 207 | if (iblock > hip->fs_blocks || !create) |
188 | return -EIO; | 208 | return -EIO; |
189 | if (ablock >= HFSPLUS_I(inode).alloc_blocks) { | 209 | if (ablock >= hip->alloc_blocks) { |
190 | res = hfsplus_file_extend(inode); | 210 | res = hfsplus_file_extend(inode); |
191 | if (res) | 211 | if (res) |
192 | return res; | 212 | return res; |
@@ -194,33 +214,33 @@ int hfsplus_get_block(struct inode *inode, sector_t iblock, | |||
194 | } else | 214 | } else |
195 | create = 0; | 215 | create = 0; |
196 | 216 | ||
197 | if (ablock < HFSPLUS_I(inode).first_blocks) { | 217 | if (ablock < hip->first_blocks) { |
198 | dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).first_extents, ablock); | 218 | dblock = hfsplus_ext_find_block(hip->first_extents, ablock); |
199 | goto done; | 219 | goto done; |
200 | } | 220 | } |
201 | 221 | ||
202 | if (inode->i_ino == HFSPLUS_EXT_CNID) | 222 | if (inode->i_ino == HFSPLUS_EXT_CNID) |
203 | return -EIO; | 223 | return -EIO; |
204 | 224 | ||
205 | mutex_lock(&HFSPLUS_I(inode).extents_lock); | 225 | mutex_lock(&hip->extents_lock); |
206 | res = hfsplus_ext_read_extent(inode, ablock); | 226 | res = hfsplus_ext_read_extent(inode, ablock); |
207 | if (!res) { | 227 | if (!res) { |
208 | dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).cached_extents, ablock - | 228 | dblock = hfsplus_ext_find_block(hip->cached_extents, |
209 | HFSPLUS_I(inode).cached_start); | 229 | ablock - hip->cached_start); |
210 | } else { | 230 | } else { |
211 | mutex_unlock(&HFSPLUS_I(inode).extents_lock); | 231 | mutex_unlock(&hip->extents_lock); |
212 | return -EIO; | 232 | return -EIO; |
213 | } | 233 | } |
214 | mutex_unlock(&HFSPLUS_I(inode).extents_lock); | 234 | mutex_unlock(&hip->extents_lock); |
215 | 235 | ||
216 | done: | 236 | done: |
217 | dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock); | 237 | dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock); |
218 | mask = (1 << HFSPLUS_SB(sb).fs_shift) - 1; | 238 | mask = (1 << sbi->fs_shift) - 1; |
219 | map_bh(bh_result, sb, (dblock << HFSPLUS_SB(sb).fs_shift) + HFSPLUS_SB(sb).blockoffset + (iblock & mask)); | 239 | map_bh(bh_result, sb, (dblock << sbi->fs_shift) + sbi->blockoffset + (iblock & mask)); |
220 | if (create) { | 240 | if (create) { |
221 | set_buffer_new(bh_result); | 241 | set_buffer_new(bh_result); |
222 | HFSPLUS_I(inode).phys_size += sb->s_blocksize; | 242 | hip->phys_size += sb->s_blocksize; |
223 | HFSPLUS_I(inode).fs_blocks++; | 243 | hip->fs_blocks++; |
224 | inode_add_bytes(inode, sb->s_blocksize); | 244 | inode_add_bytes(inode, sb->s_blocksize); |
225 | mark_inode_dirty(inode); | 245 | mark_inode_dirty(inode); |
226 | } | 246 | } |
@@ -327,7 +347,7 @@ int hfsplus_free_fork(struct super_block *sb, u32 cnid, struct hfsplus_fork_raw | |||
327 | if (total_blocks == blocks) | 347 | if (total_blocks == blocks) |
328 | return 0; | 348 | return 0; |
329 | 349 | ||
330 | hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd); | 350 | hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd); |
331 | do { | 351 | do { |
332 | res = __hfsplus_ext_read_extent(&fd, ext_entry, cnid, | 352 | res = __hfsplus_ext_read_extent(&fd, ext_entry, cnid, |
333 | total_blocks, type); | 353 | total_blocks, type); |
@@ -348,29 +368,33 @@ int hfsplus_free_fork(struct super_block *sb, u32 cnid, struct hfsplus_fork_raw | |||
348 | int hfsplus_file_extend(struct inode *inode) | 368 | int hfsplus_file_extend(struct inode *inode) |
349 | { | 369 | { |
350 | struct super_block *sb = inode->i_sb; | 370 | struct super_block *sb = inode->i_sb; |
371 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
372 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
351 | u32 start, len, goal; | 373 | u32 start, len, goal; |
352 | int res; | 374 | int res; |
353 | 375 | ||
354 | if (HFSPLUS_SB(sb).alloc_file->i_size * 8 < HFSPLUS_SB(sb).total_blocks - HFSPLUS_SB(sb).free_blocks + 8) { | 376 | if (sbi->alloc_file->i_size * 8 < |
377 | sbi->total_blocks - sbi->free_blocks + 8) { | ||
355 | // extend alloc file | 378 | // extend alloc file |
356 | printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8, | 379 | printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n", |
357 | HFSPLUS_SB(sb).total_blocks, HFSPLUS_SB(sb).free_blocks); | 380 | sbi->alloc_file->i_size * 8, |
381 | sbi->total_blocks, sbi->free_blocks); | ||
358 | return -ENOSPC; | 382 | return -ENOSPC; |
359 | } | 383 | } |
360 | 384 | ||
361 | mutex_lock(&HFSPLUS_I(inode).extents_lock); | 385 | mutex_lock(&hip->extents_lock); |
362 | if (HFSPLUS_I(inode).alloc_blocks == HFSPLUS_I(inode).first_blocks) | 386 | if (hip->alloc_blocks == hip->first_blocks) |
363 | goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).first_extents); | 387 | goal = hfsplus_ext_lastblock(hip->first_extents); |
364 | else { | 388 | else { |
365 | res = hfsplus_ext_read_extent(inode, HFSPLUS_I(inode).alloc_blocks); | 389 | res = hfsplus_ext_read_extent(inode, hip->alloc_blocks); |
366 | if (res) | 390 | if (res) |
367 | goto out; | 391 | goto out; |
368 | goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).cached_extents); | 392 | goal = hfsplus_ext_lastblock(hip->cached_extents); |
369 | } | 393 | } |
370 | 394 | ||
371 | len = HFSPLUS_I(inode).clump_blocks; | 395 | len = hip->clump_blocks; |
372 | start = hfsplus_block_allocate(sb, HFSPLUS_SB(sb).total_blocks, goal, &len); | 396 | start = hfsplus_block_allocate(sb, sbi->total_blocks, goal, &len); |
373 | if (start >= HFSPLUS_SB(sb).total_blocks) { | 397 | if (start >= sbi->total_blocks) { |
374 | start = hfsplus_block_allocate(sb, goal, 0, &len); | 398 | start = hfsplus_block_allocate(sb, goal, 0, &len); |
375 | if (start >= goal) { | 399 | if (start >= goal) { |
376 | res = -ENOSPC; | 400 | res = -ENOSPC; |
@@ -379,56 +403,56 @@ int hfsplus_file_extend(struct inode *inode) | |||
379 | } | 403 | } |
380 | 404 | ||
381 | dprint(DBG_EXTENT, "extend %lu: %u,%u\n", inode->i_ino, start, len); | 405 | dprint(DBG_EXTENT, "extend %lu: %u,%u\n", inode->i_ino, start, len); |
382 | if (HFSPLUS_I(inode).alloc_blocks <= HFSPLUS_I(inode).first_blocks) { | 406 | |
383 | if (!HFSPLUS_I(inode).first_blocks) { | 407 | if (hip->alloc_blocks <= hip->first_blocks) { |
408 | if (!hip->first_blocks) { | ||
384 | dprint(DBG_EXTENT, "first extents\n"); | 409 | dprint(DBG_EXTENT, "first extents\n"); |
385 | /* no extents yet */ | 410 | /* no extents yet */ |
386 | HFSPLUS_I(inode).first_extents[0].start_block = cpu_to_be32(start); | 411 | hip->first_extents[0].start_block = cpu_to_be32(start); |
387 | HFSPLUS_I(inode).first_extents[0].block_count = cpu_to_be32(len); | 412 | hip->first_extents[0].block_count = cpu_to_be32(len); |
388 | res = 0; | 413 | res = 0; |
389 | } else { | 414 | } else { |
390 | /* try to append to extents in inode */ | 415 | /* try to append to extents in inode */ |
391 | res = hfsplus_add_extent(HFSPLUS_I(inode).first_extents, | 416 | res = hfsplus_add_extent(hip->first_extents, |
392 | HFSPLUS_I(inode).alloc_blocks, | 417 | hip->alloc_blocks, |
393 | start, len); | 418 | start, len); |
394 | if (res == -ENOSPC) | 419 | if (res == -ENOSPC) |
395 | goto insert_extent; | 420 | goto insert_extent; |
396 | } | 421 | } |
397 | if (!res) { | 422 | if (!res) { |
398 | hfsplus_dump_extent(HFSPLUS_I(inode).first_extents); | 423 | hfsplus_dump_extent(hip->first_extents); |
399 | HFSPLUS_I(inode).first_blocks += len; | 424 | hip->first_blocks += len; |
400 | } | 425 | } |
401 | } else { | 426 | } else { |
402 | res = hfsplus_add_extent(HFSPLUS_I(inode).cached_extents, | 427 | res = hfsplus_add_extent(hip->cached_extents, |
403 | HFSPLUS_I(inode).alloc_blocks - | 428 | hip->alloc_blocks - hip->cached_start, |
404 | HFSPLUS_I(inode).cached_start, | ||
405 | start, len); | 429 | start, len); |
406 | if (!res) { | 430 | if (!res) { |
407 | hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents); | 431 | hfsplus_dump_extent(hip->cached_extents); |
408 | HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY; | 432 | hip->flags |= HFSPLUS_FLG_EXT_DIRTY; |
409 | HFSPLUS_I(inode).cached_blocks += len; | 433 | hip->cached_blocks += len; |
410 | } else if (res == -ENOSPC) | 434 | } else if (res == -ENOSPC) |
411 | goto insert_extent; | 435 | goto insert_extent; |
412 | } | 436 | } |
413 | out: | 437 | out: |
414 | mutex_unlock(&HFSPLUS_I(inode).extents_lock); | 438 | mutex_unlock(&hip->extents_lock); |
415 | if (!res) { | 439 | if (!res) { |
416 | HFSPLUS_I(inode).alloc_blocks += len; | 440 | hip->alloc_blocks += len; |
417 | mark_inode_dirty(inode); | 441 | mark_inode_dirty(inode); |
418 | } | 442 | } |
419 | return res; | 443 | return res; |
420 | 444 | ||
421 | insert_extent: | 445 | insert_extent: |
422 | dprint(DBG_EXTENT, "insert new extent\n"); | 446 | dprint(DBG_EXTENT, "insert new extent\n"); |
423 | hfsplus_ext_write_extent(inode); | 447 | hfsplus_ext_write_extent_locked(inode); |
424 | 448 | ||
425 | memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec)); | 449 | memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec)); |
426 | HFSPLUS_I(inode).cached_extents[0].start_block = cpu_to_be32(start); | 450 | hip->cached_extents[0].start_block = cpu_to_be32(start); |
427 | HFSPLUS_I(inode).cached_extents[0].block_count = cpu_to_be32(len); | 451 | hip->cached_extents[0].block_count = cpu_to_be32(len); |
428 | hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents); | 452 | hfsplus_dump_extent(hip->cached_extents); |
429 | HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW; | 453 | hip->flags |= HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW; |
430 | HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).alloc_blocks; | 454 | hip->cached_start = hip->alloc_blocks; |
431 | HFSPLUS_I(inode).cached_blocks = len; | 455 | hip->cached_blocks = len; |
432 | 456 | ||
433 | res = 0; | 457 | res = 0; |
434 | goto out; | 458 | goto out; |
@@ -437,13 +461,15 @@ insert_extent: | |||
437 | void hfsplus_file_truncate(struct inode *inode) | 461 | void hfsplus_file_truncate(struct inode *inode) |
438 | { | 462 | { |
439 | struct super_block *sb = inode->i_sb; | 463 | struct super_block *sb = inode->i_sb; |
464 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
440 | struct hfs_find_data fd; | 465 | struct hfs_find_data fd; |
441 | u32 alloc_cnt, blk_cnt, start; | 466 | u32 alloc_cnt, blk_cnt, start; |
442 | int res; | 467 | int res; |
443 | 468 | ||
444 | dprint(DBG_INODE, "truncate: %lu, %Lu -> %Lu\n", inode->i_ino, | 469 | dprint(DBG_INODE, "truncate: %lu, %Lu -> %Lu\n", |
445 | (long long)HFSPLUS_I(inode).phys_size, inode->i_size); | 470 | inode->i_ino, (long long)hip->phys_size, inode->i_size); |
446 | if (inode->i_size > HFSPLUS_I(inode).phys_size) { | 471 | |
472 | if (inode->i_size > hip->phys_size) { | ||
447 | struct address_space *mapping = inode->i_mapping; | 473 | struct address_space *mapping = inode->i_mapping; |
448 | struct page *page; | 474 | struct page *page; |
449 | void *fsdata; | 475 | void *fsdata; |
@@ -460,47 +486,48 @@ void hfsplus_file_truncate(struct inode *inode) | |||
460 | return; | 486 | return; |
461 | mark_inode_dirty(inode); | 487 | mark_inode_dirty(inode); |
462 | return; | 488 | return; |
463 | } else if (inode->i_size == HFSPLUS_I(inode).phys_size) | 489 | } else if (inode->i_size == hip->phys_size) |
464 | return; | 490 | return; |
465 | 491 | ||
466 | blk_cnt = (inode->i_size + HFSPLUS_SB(sb).alloc_blksz - 1) >> HFSPLUS_SB(sb).alloc_blksz_shift; | 492 | blk_cnt = (inode->i_size + HFSPLUS_SB(sb)->alloc_blksz - 1) >> |
467 | alloc_cnt = HFSPLUS_I(inode).alloc_blocks; | 493 | HFSPLUS_SB(sb)->alloc_blksz_shift; |
494 | alloc_cnt = hip->alloc_blocks; | ||
468 | if (blk_cnt == alloc_cnt) | 495 | if (blk_cnt == alloc_cnt) |
469 | goto out; | 496 | goto out; |
470 | 497 | ||
471 | mutex_lock(&HFSPLUS_I(inode).extents_lock); | 498 | mutex_lock(&hip->extents_lock); |
472 | hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd); | 499 | hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd); |
473 | while (1) { | 500 | while (1) { |
474 | if (alloc_cnt == HFSPLUS_I(inode).first_blocks) { | 501 | if (alloc_cnt == hip->first_blocks) { |
475 | hfsplus_free_extents(sb, HFSPLUS_I(inode).first_extents, | 502 | hfsplus_free_extents(sb, hip->first_extents, |
476 | alloc_cnt, alloc_cnt - blk_cnt); | 503 | alloc_cnt, alloc_cnt - blk_cnt); |
477 | hfsplus_dump_extent(HFSPLUS_I(inode).first_extents); | 504 | hfsplus_dump_extent(hip->first_extents); |
478 | HFSPLUS_I(inode).first_blocks = blk_cnt; | 505 | hip->first_blocks = blk_cnt; |
479 | break; | 506 | break; |
480 | } | 507 | } |
481 | res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt); | 508 | res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt); |
482 | if (res) | 509 | if (res) |
483 | break; | 510 | break; |
484 | start = HFSPLUS_I(inode).cached_start; | 511 | start = hip->cached_start; |
485 | hfsplus_free_extents(sb, HFSPLUS_I(inode).cached_extents, | 512 | hfsplus_free_extents(sb, hip->cached_extents, |
486 | alloc_cnt - start, alloc_cnt - blk_cnt); | 513 | alloc_cnt - start, alloc_cnt - blk_cnt); |
487 | hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents); | 514 | hfsplus_dump_extent(hip->cached_extents); |
488 | if (blk_cnt > start) { | 515 | if (blk_cnt > start) { |
489 | HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY; | 516 | hip->flags |= HFSPLUS_FLG_EXT_DIRTY; |
490 | break; | 517 | break; |
491 | } | 518 | } |
492 | alloc_cnt = start; | 519 | alloc_cnt = start; |
493 | HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).cached_blocks = 0; | 520 | hip->cached_start = hip->cached_blocks = 0; |
494 | HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); | 521 | hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); |
495 | hfs_brec_remove(&fd); | 522 | hfs_brec_remove(&fd); |
496 | } | 523 | } |
497 | hfs_find_exit(&fd); | 524 | hfs_find_exit(&fd); |
498 | mutex_unlock(&HFSPLUS_I(inode).extents_lock); | 525 | mutex_unlock(&hip->extents_lock); |
499 | 526 | ||
500 | HFSPLUS_I(inode).alloc_blocks = blk_cnt; | 527 | hip->alloc_blocks = blk_cnt; |
501 | out: | 528 | out: |
502 | HFSPLUS_I(inode).phys_size = inode->i_size; | 529 | hip->phys_size = inode->i_size; |
503 | HFSPLUS_I(inode).fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; | 530 | hip->fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; |
504 | inode_set_bytes(inode, HFSPLUS_I(inode).fs_blocks << sb->s_blocksize_bits); | 531 | inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits); |
505 | mark_inode_dirty(inode); | 532 | mark_inode_dirty(inode); |
506 | } | 533 | } |
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index dc856be3c2b0..cb3653efb57a 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h | |||
@@ -62,7 +62,7 @@ struct hfs_btree { | |||
62 | unsigned int depth; | 62 | unsigned int depth; |
63 | 63 | ||
64 | //unsigned int map1_size, map_size; | 64 | //unsigned int map1_size, map_size; |
65 | struct semaphore tree_lock; | 65 | struct mutex tree_lock; |
66 | 66 | ||
67 | unsigned int pages_per_bnode; | 67 | unsigned int pages_per_bnode; |
68 | spinlock_t hash_lock; | 68 | spinlock_t hash_lock; |
@@ -121,16 +121,21 @@ struct hfsplus_sb_info { | |||
121 | u32 sect_count; | 121 | u32 sect_count; |
122 | int fs_shift; | 122 | int fs_shift; |
123 | 123 | ||
124 | /* Stuff in host order from Vol Header */ | 124 | /* immutable data from the volume header */ |
125 | u32 alloc_blksz; | 125 | u32 alloc_blksz; |
126 | int alloc_blksz_shift; | 126 | int alloc_blksz_shift; |
127 | u32 total_blocks; | 127 | u32 total_blocks; |
128 | u32 data_clump_blocks, rsrc_clump_blocks; | ||
129 | |||
130 | /* mutable data from the volume header, protected by alloc_mutex */ | ||
128 | u32 free_blocks; | 131 | u32 free_blocks; |
129 | u32 next_alloc; | 132 | struct mutex alloc_mutex; |
133 | |||
134 | /* mutable data from the volume header, protected by vh_mutex */ | ||
130 | u32 next_cnid; | 135 | u32 next_cnid; |
131 | u32 file_count; | 136 | u32 file_count; |
132 | u32 folder_count; | 137 | u32 folder_count; |
133 | u32 data_clump_blocks, rsrc_clump_blocks; | 138 | struct mutex vh_mutex; |
134 | 139 | ||
135 | /* Config options */ | 140 | /* Config options */ |
136 | u32 creator; | 141 | u32 creator; |
@@ -143,40 +148,50 @@ struct hfsplus_sb_info { | |||
143 | int part, session; | 148 | int part, session; |
144 | 149 | ||
145 | unsigned long flags; | 150 | unsigned long flags; |
146 | |||
147 | struct hlist_head rsrc_inodes; | ||
148 | }; | 151 | }; |
149 | 152 | ||
150 | #define HFSPLUS_SB_WRITEBACKUP 0x0001 | 153 | #define HFSPLUS_SB_WRITEBACKUP 0 |
151 | #define HFSPLUS_SB_NODECOMPOSE 0x0002 | 154 | #define HFSPLUS_SB_NODECOMPOSE 1 |
152 | #define HFSPLUS_SB_FORCE 0x0004 | 155 | #define HFSPLUS_SB_FORCE 2 |
153 | #define HFSPLUS_SB_HFSX 0x0008 | 156 | #define HFSPLUS_SB_HFSX 3 |
154 | #define HFSPLUS_SB_CASEFOLD 0x0010 | 157 | #define HFSPLUS_SB_CASEFOLD 4 |
155 | 158 | ||
156 | 159 | ||
157 | struct hfsplus_inode_info { | 160 | struct hfsplus_inode_info { |
158 | struct mutex extents_lock; | ||
159 | u32 clump_blocks, alloc_blocks; | ||
160 | sector_t fs_blocks; | ||
161 | /* Allocation extents from catalog record or volume header */ | ||
162 | hfsplus_extent_rec first_extents; | ||
163 | u32 first_blocks; | ||
164 | hfsplus_extent_rec cached_extents; | ||
165 | u32 cached_start, cached_blocks; | ||
166 | atomic_t opencnt; | 161 | atomic_t opencnt; |
167 | 162 | ||
168 | struct inode *rsrc_inode; | 163 | /* |
164 | * Extent allocation information, protected by extents_lock. | ||
165 | */ | ||
166 | u32 first_blocks; | ||
167 | u32 clump_blocks; | ||
168 | u32 alloc_blocks; | ||
169 | u32 cached_start; | ||
170 | u32 cached_blocks; | ||
171 | hfsplus_extent_rec first_extents; | ||
172 | hfsplus_extent_rec cached_extents; | ||
169 | unsigned long flags; | 173 | unsigned long flags; |
174 | struct mutex extents_lock; | ||
170 | 175 | ||
176 | /* | ||
177 | * Immutable data. | ||
178 | */ | ||
179 | struct inode *rsrc_inode; | ||
171 | __be32 create_date; | 180 | __be32 create_date; |
172 | /* Device number in hfsplus_permissions in catalog */ | ||
173 | u32 dev; | ||
174 | /* BSD system and user file flags */ | ||
175 | u8 rootflags; | ||
176 | u8 userflags; | ||
177 | 181 | ||
182 | /* | ||
183 | * Protected by sbi->vh_mutex. | ||
184 | */ | ||
185 | u32 linkid; | ||
186 | |||
187 | /* | ||
188 | * Protected by i_mutex. | ||
189 | */ | ||
190 | sector_t fs_blocks; | ||
191 | u8 userflags; /* BSD user file flags */ | ||
178 | struct list_head open_dir_list; | 192 | struct list_head open_dir_list; |
179 | loff_t phys_size; | 193 | loff_t phys_size; |
194 | |||
180 | struct inode vfs_inode; | 195 | struct inode vfs_inode; |
181 | }; | 196 | }; |
182 | 197 | ||
@@ -184,8 +199,8 @@ struct hfsplus_inode_info { | |||
184 | #define HFSPLUS_FLG_EXT_DIRTY 0x0002 | 199 | #define HFSPLUS_FLG_EXT_DIRTY 0x0002 |
185 | #define HFSPLUS_FLG_EXT_NEW 0x0004 | 200 | #define HFSPLUS_FLG_EXT_NEW 0x0004 |
186 | 201 | ||
187 | #define HFSPLUS_IS_DATA(inode) (!(HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC)) | 202 | #define HFSPLUS_IS_DATA(inode) (!(HFSPLUS_I(inode)->flags & HFSPLUS_FLG_RSRC)) |
188 | #define HFSPLUS_IS_RSRC(inode) (HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC) | 203 | #define HFSPLUS_IS_RSRC(inode) (HFSPLUS_I(inode)->flags & HFSPLUS_FLG_RSRC) |
189 | 204 | ||
190 | struct hfs_find_data { | 205 | struct hfs_find_data { |
191 | /* filled by caller */ | 206 | /* filled by caller */ |
@@ -311,6 +326,7 @@ int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *); | |||
311 | int hfsplus_delete_cat(u32, struct inode *, struct qstr *); | 326 | int hfsplus_delete_cat(u32, struct inode *, struct qstr *); |
312 | int hfsplus_rename_cat(u32, struct inode *, struct qstr *, | 327 | int hfsplus_rename_cat(u32, struct inode *, struct qstr *, |
313 | struct inode *, struct qstr *); | 328 | struct inode *, struct qstr *); |
329 | void hfsplus_cat_set_perms(struct inode *inode, struct hfsplus_perm *perms); | ||
314 | 330 | ||
315 | /* dir.c */ | 331 | /* dir.c */ |
316 | extern const struct inode_operations hfsplus_dir_inode_operations; | 332 | extern const struct inode_operations hfsplus_dir_inode_operations; |
@@ -372,26 +388,15 @@ int hfsplus_read_wrapper(struct super_block *); | |||
372 | int hfs_part_find(struct super_block *, sector_t *, sector_t *); | 388 | int hfs_part_find(struct super_block *, sector_t *, sector_t *); |
373 | 389 | ||
374 | /* access macros */ | 390 | /* access macros */ |
375 | /* | ||
376 | static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb) | 391 | static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb) |
377 | { | 392 | { |
378 | return sb->s_fs_info; | 393 | return sb->s_fs_info; |
379 | } | 394 | } |
395 | |||
380 | static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode) | 396 | static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode) |
381 | { | 397 | { |
382 | return list_entry(inode, struct hfsplus_inode_info, vfs_inode); | 398 | return list_entry(inode, struct hfsplus_inode_info, vfs_inode); |
383 | } | 399 | } |
384 | */ | ||
385 | #define HFSPLUS_SB(super) (*(struct hfsplus_sb_info *)(super)->s_fs_info) | ||
386 | #define HFSPLUS_I(inode) (*list_entry(inode, struct hfsplus_inode_info, vfs_inode)) | ||
387 | |||
388 | #if 1 | ||
389 | #define hfsplus_kmap(p) ({ struct page *__p = (p); kmap(__p); }) | ||
390 | #define hfsplus_kunmap(p) ({ struct page *__p = (p); kunmap(__p); __p; }) | ||
391 | #else | ||
392 | #define hfsplus_kmap(p) kmap(p) | ||
393 | #define hfsplus_kunmap(p) kunmap(p) | ||
394 | #endif | ||
395 | 400 | ||
396 | #define sb_bread512(sb, sec, data) ({ \ | 401 | #define sb_bread512(sb, sec, data) ({ \ |
397 | struct buffer_head *__bh; \ | 402 | struct buffer_head *__bh; \ |
@@ -419,6 +424,4 @@ static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode) | |||
419 | #define hfsp_ut2mt(t) __hfsp_ut2mt((t).tv_sec) | 424 | #define hfsp_ut2mt(t) __hfsp_ut2mt((t).tv_sec) |
420 | #define hfsp_now2mt() __hfsp_ut2mt(get_seconds()) | 425 | #define hfsp_now2mt() __hfsp_ut2mt(get_seconds()) |
421 | 426 | ||
422 | #define kdev_t_to_nr(x) (x) | ||
423 | |||
424 | #endif | 427 | #endif |
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h index fe99fe8db61a..6892899fd6fb 100644 --- a/fs/hfsplus/hfsplus_raw.h +++ b/fs/hfsplus/hfsplus_raw.h | |||
@@ -200,6 +200,7 @@ struct hfsplus_cat_key { | |||
200 | struct hfsplus_unistr name; | 200 | struct hfsplus_unistr name; |
201 | } __packed; | 201 | } __packed; |
202 | 202 | ||
203 | #define HFSPLUS_CAT_KEYLEN (sizeof(struct hfsplus_cat_key)) | ||
203 | 204 | ||
204 | /* Structs from hfs.h */ | 205 | /* Structs from hfs.h */ |
205 | struct hfsp_point { | 206 | struct hfsp_point { |
@@ -323,7 +324,7 @@ struct hfsplus_ext_key { | |||
323 | __be32 start_block; | 324 | __be32 start_block; |
324 | } __packed; | 325 | } __packed; |
325 | 326 | ||
326 | #define HFSPLUS_EXT_KEYLEN 12 | 327 | #define HFSPLUS_EXT_KEYLEN sizeof(struct hfsplus_ext_key) |
327 | 328 | ||
328 | /* HFS+ generic BTree key */ | 329 | /* HFS+ generic BTree key */ |
329 | typedef union { | 330 | typedef union { |
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index c5a979d62c65..78449280dae0 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c | |||
@@ -36,7 +36,7 @@ static int hfsplus_write_begin(struct file *file, struct address_space *mapping, | |||
36 | *pagep = NULL; | 36 | *pagep = NULL; |
37 | ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 37 | ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, |
38 | hfsplus_get_block, | 38 | hfsplus_get_block, |
39 | &HFSPLUS_I(mapping->host).phys_size); | 39 | &HFSPLUS_I(mapping->host)->phys_size); |
40 | if (unlikely(ret)) { | 40 | if (unlikely(ret)) { |
41 | loff_t isize = mapping->host->i_size; | 41 | loff_t isize = mapping->host->i_size; |
42 | if (pos + len > isize) | 42 | if (pos + len > isize) |
@@ -62,13 +62,13 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask) | |||
62 | 62 | ||
63 | switch (inode->i_ino) { | 63 | switch (inode->i_ino) { |
64 | case HFSPLUS_EXT_CNID: | 64 | case HFSPLUS_EXT_CNID: |
65 | tree = HFSPLUS_SB(sb).ext_tree; | 65 | tree = HFSPLUS_SB(sb)->ext_tree; |
66 | break; | 66 | break; |
67 | case HFSPLUS_CAT_CNID: | 67 | case HFSPLUS_CAT_CNID: |
68 | tree = HFSPLUS_SB(sb).cat_tree; | 68 | tree = HFSPLUS_SB(sb)->cat_tree; |
69 | break; | 69 | break; |
70 | case HFSPLUS_ATTR_CNID: | 70 | case HFSPLUS_ATTR_CNID: |
71 | tree = HFSPLUS_SB(sb).attr_tree; | 71 | tree = HFSPLUS_SB(sb)->attr_tree; |
72 | break; | 72 | break; |
73 | default: | 73 | default: |
74 | BUG(); | 74 | BUG(); |
@@ -172,12 +172,13 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent | |||
172 | struct hfs_find_data fd; | 172 | struct hfs_find_data fd; |
173 | struct super_block *sb = dir->i_sb; | 173 | struct super_block *sb = dir->i_sb; |
174 | struct inode *inode = NULL; | 174 | struct inode *inode = NULL; |
175 | struct hfsplus_inode_info *hip; | ||
175 | int err; | 176 | int err; |
176 | 177 | ||
177 | if (HFSPLUS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc")) | 178 | if (HFSPLUS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc")) |
178 | goto out; | 179 | goto out; |
179 | 180 | ||
180 | inode = HFSPLUS_I(dir).rsrc_inode; | 181 | inode = HFSPLUS_I(dir)->rsrc_inode; |
181 | if (inode) | 182 | if (inode) |
182 | goto out; | 183 | goto out; |
183 | 184 | ||
@@ -185,12 +186,13 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent | |||
185 | if (!inode) | 186 | if (!inode) |
186 | return ERR_PTR(-ENOMEM); | 187 | return ERR_PTR(-ENOMEM); |
187 | 188 | ||
189 | hip = HFSPLUS_I(inode); | ||
188 | inode->i_ino = dir->i_ino; | 190 | inode->i_ino = dir->i_ino; |
189 | INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); | 191 | INIT_LIST_HEAD(&hip->open_dir_list); |
190 | mutex_init(&HFSPLUS_I(inode).extents_lock); | 192 | mutex_init(&hip->extents_lock); |
191 | HFSPLUS_I(inode).flags = HFSPLUS_FLG_RSRC; | 193 | hip->flags = HFSPLUS_FLG_RSRC; |
192 | 194 | ||
193 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | 195 | hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); |
194 | err = hfsplus_find_cat(sb, dir->i_ino, &fd); | 196 | err = hfsplus_find_cat(sb, dir->i_ino, &fd); |
195 | if (!err) | 197 | if (!err) |
196 | err = hfsplus_cat_read_inode(inode, &fd); | 198 | err = hfsplus_cat_read_inode(inode, &fd); |
@@ -199,10 +201,18 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent | |||
199 | iput(inode); | 201 | iput(inode); |
200 | return ERR_PTR(err); | 202 | return ERR_PTR(err); |
201 | } | 203 | } |
202 | HFSPLUS_I(inode).rsrc_inode = dir; | 204 | hip->rsrc_inode = dir; |
203 | HFSPLUS_I(dir).rsrc_inode = inode; | 205 | HFSPLUS_I(dir)->rsrc_inode = inode; |
204 | igrab(dir); | 206 | igrab(dir); |
205 | hlist_add_head(&inode->i_hash, &HFSPLUS_SB(sb).rsrc_inodes); | 207 | |
208 | /* | ||
209 | * __mark_inode_dirty expects inodes to be hashed. Since we don't | ||
210 | * want resource fork inodes in the regular inode space, we make them | ||
211 | * appear hashed, but do not put on any lists. hlist_del() | ||
212 | * will work fine and require no locking. | ||
213 | */ | ||
214 | inode->i_hash.pprev = &inode->i_hash.next; | ||
215 | |||
206 | mark_inode_dirty(inode); | 216 | mark_inode_dirty(inode); |
207 | out: | 217 | out: |
208 | d_add(dentry, inode); | 218 | d_add(dentry, inode); |
@@ -211,30 +221,27 @@ out: | |||
211 | 221 | ||
212 | static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, int dir) | 222 | static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, int dir) |
213 | { | 223 | { |
214 | struct super_block *sb = inode->i_sb; | 224 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); |
215 | u16 mode; | 225 | u16 mode; |
216 | 226 | ||
217 | mode = be16_to_cpu(perms->mode); | 227 | mode = be16_to_cpu(perms->mode); |
218 | 228 | ||
219 | inode->i_uid = be32_to_cpu(perms->owner); | 229 | inode->i_uid = be32_to_cpu(perms->owner); |
220 | if (!inode->i_uid && !mode) | 230 | if (!inode->i_uid && !mode) |
221 | inode->i_uid = HFSPLUS_SB(sb).uid; | 231 | inode->i_uid = sbi->uid; |
222 | 232 | ||
223 | inode->i_gid = be32_to_cpu(perms->group); | 233 | inode->i_gid = be32_to_cpu(perms->group); |
224 | if (!inode->i_gid && !mode) | 234 | if (!inode->i_gid && !mode) |
225 | inode->i_gid = HFSPLUS_SB(sb).gid; | 235 | inode->i_gid = sbi->gid; |
226 | 236 | ||
227 | if (dir) { | 237 | if (dir) { |
228 | mode = mode ? (mode & S_IALLUGO) : | 238 | mode = mode ? (mode & S_IALLUGO) : (S_IRWXUGO & ~(sbi->umask)); |
229 | (S_IRWXUGO & ~(HFSPLUS_SB(sb).umask)); | ||
230 | mode |= S_IFDIR; | 239 | mode |= S_IFDIR; |
231 | } else if (!mode) | 240 | } else if (!mode) |
232 | mode = S_IFREG | ((S_IRUGO|S_IWUGO) & | 241 | mode = S_IFREG | ((S_IRUGO|S_IWUGO) & ~(sbi->umask)); |
233 | ~(HFSPLUS_SB(sb).umask)); | ||
234 | inode->i_mode = mode; | 242 | inode->i_mode = mode; |
235 | 243 | ||
236 | HFSPLUS_I(inode).rootflags = perms->rootflags; | 244 | HFSPLUS_I(inode)->userflags = perms->userflags; |
237 | HFSPLUS_I(inode).userflags = perms->userflags; | ||
238 | if (perms->rootflags & HFSPLUS_FLG_IMMUTABLE) | 245 | if (perms->rootflags & HFSPLUS_FLG_IMMUTABLE) |
239 | inode->i_flags |= S_IMMUTABLE; | 246 | inode->i_flags |= S_IMMUTABLE; |
240 | else | 247 | else |
@@ -245,30 +252,13 @@ static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, i | |||
245 | inode->i_flags &= ~S_APPEND; | 252 | inode->i_flags &= ~S_APPEND; |
246 | } | 253 | } |
247 | 254 | ||
248 | static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms) | ||
249 | { | ||
250 | if (inode->i_flags & S_IMMUTABLE) | ||
251 | perms->rootflags |= HFSPLUS_FLG_IMMUTABLE; | ||
252 | else | ||
253 | perms->rootflags &= ~HFSPLUS_FLG_IMMUTABLE; | ||
254 | if (inode->i_flags & S_APPEND) | ||
255 | perms->rootflags |= HFSPLUS_FLG_APPEND; | ||
256 | else | ||
257 | perms->rootflags &= ~HFSPLUS_FLG_APPEND; | ||
258 | perms->userflags = HFSPLUS_I(inode).userflags; | ||
259 | perms->mode = cpu_to_be16(inode->i_mode); | ||
260 | perms->owner = cpu_to_be32(inode->i_uid); | ||
261 | perms->group = cpu_to_be32(inode->i_gid); | ||
262 | perms->dev = cpu_to_be32(HFSPLUS_I(inode).dev); | ||
263 | } | ||
264 | |||
265 | static int hfsplus_file_open(struct inode *inode, struct file *file) | 255 | static int hfsplus_file_open(struct inode *inode, struct file *file) |
266 | { | 256 | { |
267 | if (HFSPLUS_IS_RSRC(inode)) | 257 | if (HFSPLUS_IS_RSRC(inode)) |
268 | inode = HFSPLUS_I(inode).rsrc_inode; | 258 | inode = HFSPLUS_I(inode)->rsrc_inode; |
269 | if (!(file->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) | 259 | if (!(file->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) |
270 | return -EOVERFLOW; | 260 | return -EOVERFLOW; |
271 | atomic_inc(&HFSPLUS_I(inode).opencnt); | 261 | atomic_inc(&HFSPLUS_I(inode)->opencnt); |
272 | return 0; | 262 | return 0; |
273 | } | 263 | } |
274 | 264 | ||
@@ -277,12 +267,13 @@ static int hfsplus_file_release(struct inode *inode, struct file *file) | |||
277 | struct super_block *sb = inode->i_sb; | 267 | struct super_block *sb = inode->i_sb; |
278 | 268 | ||
279 | if (HFSPLUS_IS_RSRC(inode)) | 269 | if (HFSPLUS_IS_RSRC(inode)) |
280 | inode = HFSPLUS_I(inode).rsrc_inode; | 270 | inode = HFSPLUS_I(inode)->rsrc_inode; |
281 | if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) { | 271 | if (atomic_dec_and_test(&HFSPLUS_I(inode)->opencnt)) { |
282 | mutex_lock(&inode->i_mutex); | 272 | mutex_lock(&inode->i_mutex); |
283 | hfsplus_file_truncate(inode); | 273 | hfsplus_file_truncate(inode); |
284 | if (inode->i_flags & S_DEAD) { | 274 | if (inode->i_flags & S_DEAD) { |
285 | hfsplus_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL); | 275 | hfsplus_delete_cat(inode->i_ino, |
276 | HFSPLUS_SB(sb)->hidden_dir, NULL); | ||
286 | hfsplus_delete_inode(inode); | 277 | hfsplus_delete_inode(inode); |
287 | } | 278 | } |
288 | mutex_unlock(&inode->i_mutex); | 279 | mutex_unlock(&inode->i_mutex); |
@@ -361,47 +352,52 @@ static const struct file_operations hfsplus_file_operations = { | |||
361 | 352 | ||
362 | struct inode *hfsplus_new_inode(struct super_block *sb, int mode) | 353 | struct inode *hfsplus_new_inode(struct super_block *sb, int mode) |
363 | { | 354 | { |
355 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
364 | struct inode *inode = new_inode(sb); | 356 | struct inode *inode = new_inode(sb); |
357 | struct hfsplus_inode_info *hip; | ||
358 | |||
365 | if (!inode) | 359 | if (!inode) |
366 | return NULL; | 360 | return NULL; |
367 | 361 | ||
368 | inode->i_ino = HFSPLUS_SB(sb).next_cnid++; | 362 | inode->i_ino = sbi->next_cnid++; |
369 | inode->i_mode = mode; | 363 | inode->i_mode = mode; |
370 | inode->i_uid = current_fsuid(); | 364 | inode->i_uid = current_fsuid(); |
371 | inode->i_gid = current_fsgid(); | 365 | inode->i_gid = current_fsgid(); |
372 | inode->i_nlink = 1; | 366 | inode->i_nlink = 1; |
373 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; | 367 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; |
374 | INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); | 368 | |
375 | mutex_init(&HFSPLUS_I(inode).extents_lock); | 369 | hip = HFSPLUS_I(inode); |
376 | atomic_set(&HFSPLUS_I(inode).opencnt, 0); | 370 | INIT_LIST_HEAD(&hip->open_dir_list); |
377 | HFSPLUS_I(inode).flags = 0; | 371 | mutex_init(&hip->extents_lock); |
378 | memset(HFSPLUS_I(inode).first_extents, 0, sizeof(hfsplus_extent_rec)); | 372 | atomic_set(&hip->opencnt, 0); |
379 | memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec)); | 373 | hip->flags = 0; |
380 | HFSPLUS_I(inode).alloc_blocks = 0; | 374 | memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec)); |
381 | HFSPLUS_I(inode).first_blocks = 0; | 375 | memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec)); |
382 | HFSPLUS_I(inode).cached_start = 0; | 376 | hip->alloc_blocks = 0; |
383 | HFSPLUS_I(inode).cached_blocks = 0; | 377 | hip->first_blocks = 0; |
384 | HFSPLUS_I(inode).phys_size = 0; | 378 | hip->cached_start = 0; |
385 | HFSPLUS_I(inode).fs_blocks = 0; | 379 | hip->cached_blocks = 0; |
386 | HFSPLUS_I(inode).rsrc_inode = NULL; | 380 | hip->phys_size = 0; |
381 | hip->fs_blocks = 0; | ||
382 | hip->rsrc_inode = NULL; | ||
387 | if (S_ISDIR(inode->i_mode)) { | 383 | if (S_ISDIR(inode->i_mode)) { |
388 | inode->i_size = 2; | 384 | inode->i_size = 2; |
389 | HFSPLUS_SB(sb).folder_count++; | 385 | sbi->folder_count++; |
390 | inode->i_op = &hfsplus_dir_inode_operations; | 386 | inode->i_op = &hfsplus_dir_inode_operations; |
391 | inode->i_fop = &hfsplus_dir_operations; | 387 | inode->i_fop = &hfsplus_dir_operations; |
392 | } else if (S_ISREG(inode->i_mode)) { | 388 | } else if (S_ISREG(inode->i_mode)) { |
393 | HFSPLUS_SB(sb).file_count++; | 389 | sbi->file_count++; |
394 | inode->i_op = &hfsplus_file_inode_operations; | 390 | inode->i_op = &hfsplus_file_inode_operations; |
395 | inode->i_fop = &hfsplus_file_operations; | 391 | inode->i_fop = &hfsplus_file_operations; |
396 | inode->i_mapping->a_ops = &hfsplus_aops; | 392 | inode->i_mapping->a_ops = &hfsplus_aops; |
397 | HFSPLUS_I(inode).clump_blocks = HFSPLUS_SB(sb).data_clump_blocks; | 393 | hip->clump_blocks = sbi->data_clump_blocks; |
398 | } else if (S_ISLNK(inode->i_mode)) { | 394 | } else if (S_ISLNK(inode->i_mode)) { |
399 | HFSPLUS_SB(sb).file_count++; | 395 | sbi->file_count++; |
400 | inode->i_op = &page_symlink_inode_operations; | 396 | inode->i_op = &page_symlink_inode_operations; |
401 | inode->i_mapping->a_ops = &hfsplus_aops; | 397 | inode->i_mapping->a_ops = &hfsplus_aops; |
402 | HFSPLUS_I(inode).clump_blocks = 1; | 398 | hip->clump_blocks = 1; |
403 | } else | 399 | } else |
404 | HFSPLUS_SB(sb).file_count++; | 400 | sbi->file_count++; |
405 | insert_inode_hash(inode); | 401 | insert_inode_hash(inode); |
406 | mark_inode_dirty(inode); | 402 | mark_inode_dirty(inode); |
407 | sb->s_dirt = 1; | 403 | sb->s_dirt = 1; |
@@ -414,11 +410,11 @@ void hfsplus_delete_inode(struct inode *inode) | |||
414 | struct super_block *sb = inode->i_sb; | 410 | struct super_block *sb = inode->i_sb; |
415 | 411 | ||
416 | if (S_ISDIR(inode->i_mode)) { | 412 | if (S_ISDIR(inode->i_mode)) { |
417 | HFSPLUS_SB(sb).folder_count--; | 413 | HFSPLUS_SB(sb)->folder_count--; |
418 | sb->s_dirt = 1; | 414 | sb->s_dirt = 1; |
419 | return; | 415 | return; |
420 | } | 416 | } |
421 | HFSPLUS_SB(sb).file_count--; | 417 | HFSPLUS_SB(sb)->file_count--; |
422 | if (S_ISREG(inode->i_mode)) { | 418 | if (S_ISREG(inode->i_mode)) { |
423 | if (!inode->i_nlink) { | 419 | if (!inode->i_nlink) { |
424 | inode->i_size = 0; | 420 | inode->i_size = 0; |
@@ -434,34 +430,39 @@ void hfsplus_delete_inode(struct inode *inode) | |||
434 | void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork) | 430 | void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork) |
435 | { | 431 | { |
436 | struct super_block *sb = inode->i_sb; | 432 | struct super_block *sb = inode->i_sb; |
433 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
434 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
437 | u32 count; | 435 | u32 count; |
438 | int i; | 436 | int i; |
439 | 437 | ||
440 | memcpy(&HFSPLUS_I(inode).first_extents, &fork->extents, | 438 | memcpy(&hip->first_extents, &fork->extents, sizeof(hfsplus_extent_rec)); |
441 | sizeof(hfsplus_extent_rec)); | ||
442 | for (count = 0, i = 0; i < 8; i++) | 439 | for (count = 0, i = 0; i < 8; i++) |
443 | count += be32_to_cpu(fork->extents[i].block_count); | 440 | count += be32_to_cpu(fork->extents[i].block_count); |
444 | HFSPLUS_I(inode).first_blocks = count; | 441 | hip->first_blocks = count; |
445 | memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec)); | 442 | memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec)); |
446 | HFSPLUS_I(inode).cached_start = 0; | 443 | hip->cached_start = 0; |
447 | HFSPLUS_I(inode).cached_blocks = 0; | 444 | hip->cached_blocks = 0; |
448 | 445 | ||
449 | HFSPLUS_I(inode).alloc_blocks = be32_to_cpu(fork->total_blocks); | 446 | hip->alloc_blocks = be32_to_cpu(fork->total_blocks); |
450 | inode->i_size = HFSPLUS_I(inode).phys_size = be64_to_cpu(fork->total_size); | 447 | hip->phys_size = inode->i_size = be64_to_cpu(fork->total_size); |
451 | HFSPLUS_I(inode).fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; | 448 | hip->fs_blocks = |
452 | inode_set_bytes(inode, HFSPLUS_I(inode).fs_blocks << sb->s_blocksize_bits); | 449 | (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; |
453 | HFSPLUS_I(inode).clump_blocks = be32_to_cpu(fork->clump_size) >> HFSPLUS_SB(sb).alloc_blksz_shift; | 450 | inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits); |
454 | if (!HFSPLUS_I(inode).clump_blocks) | 451 | hip->clump_blocks = |
455 | HFSPLUS_I(inode).clump_blocks = HFSPLUS_IS_RSRC(inode) ? HFSPLUS_SB(sb).rsrc_clump_blocks : | 452 | be32_to_cpu(fork->clump_size) >> sbi->alloc_blksz_shift; |
456 | HFSPLUS_SB(sb).data_clump_blocks; | 453 | if (!hip->clump_blocks) { |
454 | hip->clump_blocks = HFSPLUS_IS_RSRC(inode) ? | ||
455 | sbi->rsrc_clump_blocks : | ||
456 | sbi->data_clump_blocks; | ||
457 | } | ||
457 | } | 458 | } |
458 | 459 | ||
459 | void hfsplus_inode_write_fork(struct inode *inode, struct hfsplus_fork_raw *fork) | 460 | void hfsplus_inode_write_fork(struct inode *inode, struct hfsplus_fork_raw *fork) |
460 | { | 461 | { |
461 | memcpy(&fork->extents, &HFSPLUS_I(inode).first_extents, | 462 | memcpy(&fork->extents, &HFSPLUS_I(inode)->first_extents, |
462 | sizeof(hfsplus_extent_rec)); | 463 | sizeof(hfsplus_extent_rec)); |
463 | fork->total_size = cpu_to_be64(inode->i_size); | 464 | fork->total_size = cpu_to_be64(inode->i_size); |
464 | fork->total_blocks = cpu_to_be32(HFSPLUS_I(inode).alloc_blocks); | 465 | fork->total_blocks = cpu_to_be32(HFSPLUS_I(inode)->alloc_blocks); |
465 | } | 466 | } |
466 | 467 | ||
467 | int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) | 468 | int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) |
@@ -472,7 +473,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) | |||
472 | 473 | ||
473 | type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset); | 474 | type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset); |
474 | 475 | ||
475 | HFSPLUS_I(inode).dev = 0; | 476 | HFSPLUS_I(inode)->linkid = 0; |
476 | if (type == HFSPLUS_FOLDER) { | 477 | if (type == HFSPLUS_FOLDER) { |
477 | struct hfsplus_cat_folder *folder = &entry.folder; | 478 | struct hfsplus_cat_folder *folder = &entry.folder; |
478 | 479 | ||
@@ -486,8 +487,8 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) | |||
486 | inode->i_atime = hfsp_mt2ut(folder->access_date); | 487 | inode->i_atime = hfsp_mt2ut(folder->access_date); |
487 | inode->i_mtime = hfsp_mt2ut(folder->content_mod_date); | 488 | inode->i_mtime = hfsp_mt2ut(folder->content_mod_date); |
488 | inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date); | 489 | inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date); |
489 | HFSPLUS_I(inode).create_date = folder->create_date; | 490 | HFSPLUS_I(inode)->create_date = folder->create_date; |
490 | HFSPLUS_I(inode).fs_blocks = 0; | 491 | HFSPLUS_I(inode)->fs_blocks = 0; |
491 | inode->i_op = &hfsplus_dir_inode_operations; | 492 | inode->i_op = &hfsplus_dir_inode_operations; |
492 | inode->i_fop = &hfsplus_dir_operations; | 493 | inode->i_fop = &hfsplus_dir_operations; |
493 | } else if (type == HFSPLUS_FILE) { | 494 | } else if (type == HFSPLUS_FILE) { |
@@ -518,7 +519,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) | |||
518 | inode->i_atime = hfsp_mt2ut(file->access_date); | 519 | inode->i_atime = hfsp_mt2ut(file->access_date); |
519 | inode->i_mtime = hfsp_mt2ut(file->content_mod_date); | 520 | inode->i_mtime = hfsp_mt2ut(file->content_mod_date); |
520 | inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date); | 521 | inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date); |
521 | HFSPLUS_I(inode).create_date = file->create_date; | 522 | HFSPLUS_I(inode)->create_date = file->create_date; |
522 | } else { | 523 | } else { |
523 | printk(KERN_ERR "hfs: bad catalog entry used to create inode\n"); | 524 | printk(KERN_ERR "hfs: bad catalog entry used to create inode\n"); |
524 | res = -EIO; | 525 | res = -EIO; |
@@ -533,12 +534,12 @@ int hfsplus_cat_write_inode(struct inode *inode) | |||
533 | hfsplus_cat_entry entry; | 534 | hfsplus_cat_entry entry; |
534 | 535 | ||
535 | if (HFSPLUS_IS_RSRC(inode)) | 536 | if (HFSPLUS_IS_RSRC(inode)) |
536 | main_inode = HFSPLUS_I(inode).rsrc_inode; | 537 | main_inode = HFSPLUS_I(inode)->rsrc_inode; |
537 | 538 | ||
538 | if (!main_inode->i_nlink) | 539 | if (!main_inode->i_nlink) |
539 | return 0; | 540 | return 0; |
540 | 541 | ||
541 | if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb).cat_tree, &fd)) | 542 | if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb)->cat_tree, &fd)) |
542 | /* panic? */ | 543 | /* panic? */ |
543 | return -EIO; | 544 | return -EIO; |
544 | 545 | ||
@@ -554,7 +555,7 @@ int hfsplus_cat_write_inode(struct inode *inode) | |||
554 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, | 555 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, |
555 | sizeof(struct hfsplus_cat_folder)); | 556 | sizeof(struct hfsplus_cat_folder)); |
556 | /* simple node checks? */ | 557 | /* simple node checks? */ |
557 | hfsplus_set_perms(inode, &folder->permissions); | 558 | hfsplus_cat_set_perms(inode, &folder->permissions); |
558 | folder->access_date = hfsp_ut2mt(inode->i_atime); | 559 | folder->access_date = hfsp_ut2mt(inode->i_atime); |
559 | folder->content_mod_date = hfsp_ut2mt(inode->i_mtime); | 560 | folder->content_mod_date = hfsp_ut2mt(inode->i_mtime); |
560 | folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime); | 561 | folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime); |
@@ -576,11 +577,7 @@ int hfsplus_cat_write_inode(struct inode *inode) | |||
576 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, | 577 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, |
577 | sizeof(struct hfsplus_cat_file)); | 578 | sizeof(struct hfsplus_cat_file)); |
578 | hfsplus_inode_write_fork(inode, &file->data_fork); | 579 | hfsplus_inode_write_fork(inode, &file->data_fork); |
579 | if (S_ISREG(inode->i_mode)) | 580 | hfsplus_cat_set_perms(inode, &file->permissions); |
580 | HFSPLUS_I(inode).dev = inode->i_nlink; | ||
581 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) | ||
582 | HFSPLUS_I(inode).dev = kdev_t_to_nr(inode->i_rdev); | ||
583 | hfsplus_set_perms(inode, &file->permissions); | ||
584 | if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) | 581 | if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) |
585 | file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); | 582 | file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); |
586 | else | 583 | else |
diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c index ac405f099026..5b4667e08ef7 100644 --- a/fs/hfsplus/ioctl.c +++ b/fs/hfsplus/ioctl.c | |||
@@ -17,83 +17,98 @@ | |||
17 | #include <linux/mount.h> | 17 | #include <linux/mount.h> |
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | #include <linux/xattr.h> | 19 | #include <linux/xattr.h> |
20 | #include <linux/smp_lock.h> | ||
21 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
22 | #include "hfsplus_fs.h" | 21 | #include "hfsplus_fs.h" |
23 | 22 | ||
24 | long hfsplus_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 23 | static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags) |
25 | { | 24 | { |
26 | struct inode *inode = filp->f_path.dentry->d_inode; | 25 | struct inode *inode = file->f_path.dentry->d_inode; |
26 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
27 | unsigned int flags = 0; | ||
28 | |||
29 | if (inode->i_flags & S_IMMUTABLE) | ||
30 | flags |= FS_IMMUTABLE_FL; | ||
31 | if (inode->i_flags |= S_APPEND) | ||
32 | flags |= FS_APPEND_FL; | ||
33 | if (hip->userflags & HFSPLUS_FLG_NODUMP) | ||
34 | flags |= FS_NODUMP_FL; | ||
35 | |||
36 | return put_user(flags, user_flags); | ||
37 | } | ||
38 | |||
39 | static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags) | ||
40 | { | ||
41 | struct inode *inode = file->f_path.dentry->d_inode; | ||
42 | struct hfsplus_inode_info *hip = HFSPLUS_I(inode); | ||
27 | unsigned int flags; | 43 | unsigned int flags; |
44 | int err = 0; | ||
28 | 45 | ||
29 | lock_kernel(); | 46 | err = mnt_want_write(file->f_path.mnt); |
30 | switch (cmd) { | 47 | if (err) |
31 | case HFSPLUS_IOC_EXT2_GETFLAGS: | 48 | goto out; |
32 | flags = 0; | ||
33 | if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_IMMUTABLE) | ||
34 | flags |= FS_IMMUTABLE_FL; /* EXT2_IMMUTABLE_FL */ | ||
35 | if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_APPEND) | ||
36 | flags |= FS_APPEND_FL; /* EXT2_APPEND_FL */ | ||
37 | if (HFSPLUS_I(inode).userflags & HFSPLUS_FLG_NODUMP) | ||
38 | flags |= FS_NODUMP_FL; /* EXT2_NODUMP_FL */ | ||
39 | return put_user(flags, (int __user *)arg); | ||
40 | case HFSPLUS_IOC_EXT2_SETFLAGS: { | ||
41 | int err = 0; | ||
42 | err = mnt_want_write(filp->f_path.mnt); | ||
43 | if (err) { | ||
44 | unlock_kernel(); | ||
45 | return err; | ||
46 | } | ||
47 | 49 | ||
48 | if (!is_owner_or_cap(inode)) { | 50 | if (!is_owner_or_cap(inode)) { |
49 | err = -EACCES; | 51 | err = -EACCES; |
50 | goto setflags_out; | 52 | goto out_drop_write; |
51 | } | 53 | } |
52 | if (get_user(flags, (int __user *)arg)) { | ||
53 | err = -EFAULT; | ||
54 | goto setflags_out; | ||
55 | } | ||
56 | if (flags & (FS_IMMUTABLE_FL|FS_APPEND_FL) || | ||
57 | HFSPLUS_I(inode).rootflags & (HFSPLUS_FLG_IMMUTABLE|HFSPLUS_FLG_APPEND)) { | ||
58 | if (!capable(CAP_LINUX_IMMUTABLE)) { | ||
59 | err = -EPERM; | ||
60 | goto setflags_out; | ||
61 | } | ||
62 | } | ||
63 | 54 | ||
64 | /* don't silently ignore unsupported ext2 flags */ | 55 | if (get_user(flags, user_flags)) { |
65 | if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) { | 56 | err = -EFAULT; |
66 | err = -EOPNOTSUPP; | 57 | goto out_drop_write; |
67 | goto setflags_out; | 58 | } |
68 | } | 59 | |
69 | if (flags & FS_IMMUTABLE_FL) { /* EXT2_IMMUTABLE_FL */ | 60 | mutex_lock(&inode->i_mutex); |
70 | inode->i_flags |= S_IMMUTABLE; | 61 | |
71 | HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_IMMUTABLE; | 62 | if ((flags & (FS_IMMUTABLE_FL|FS_APPEND_FL)) || |
72 | } else { | 63 | inode->i_flags & (S_IMMUTABLE|S_APPEND)) { |
73 | inode->i_flags &= ~S_IMMUTABLE; | 64 | if (!capable(CAP_LINUX_IMMUTABLE)) { |
74 | HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_IMMUTABLE; | 65 | err = -EPERM; |
75 | } | 66 | goto out_unlock_inode; |
76 | if (flags & FS_APPEND_FL) { /* EXT2_APPEND_FL */ | ||
77 | inode->i_flags |= S_APPEND; | ||
78 | HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_APPEND; | ||
79 | } else { | ||
80 | inode->i_flags &= ~S_APPEND; | ||
81 | HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_APPEND; | ||
82 | } | 67 | } |
83 | if (flags & FS_NODUMP_FL) /* EXT2_NODUMP_FL */ | ||
84 | HFSPLUS_I(inode).userflags |= HFSPLUS_FLG_NODUMP; | ||
85 | else | ||
86 | HFSPLUS_I(inode).userflags &= ~HFSPLUS_FLG_NODUMP; | ||
87 | |||
88 | inode->i_ctime = CURRENT_TIME_SEC; | ||
89 | mark_inode_dirty(inode); | ||
90 | setflags_out: | ||
91 | mnt_drop_write(filp->f_path.mnt); | ||
92 | unlock_kernel(); | ||
93 | return err; | ||
94 | } | 68 | } |
69 | |||
70 | /* don't silently ignore unsupported ext2 flags */ | ||
71 | if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) { | ||
72 | err = -EOPNOTSUPP; | ||
73 | goto out_unlock_inode; | ||
74 | } | ||
75 | |||
76 | if (flags & FS_IMMUTABLE_FL) | ||
77 | inode->i_flags |= S_IMMUTABLE; | ||
78 | else | ||
79 | inode->i_flags &= ~S_IMMUTABLE; | ||
80 | |||
81 | if (flags & FS_APPEND_FL) | ||
82 | inode->i_flags |= S_APPEND; | ||
83 | else | ||
84 | inode->i_flags &= ~S_APPEND; | ||
85 | |||
86 | if (flags & FS_NODUMP_FL) | ||
87 | hip->userflags |= HFSPLUS_FLG_NODUMP; | ||
88 | else | ||
89 | hip->userflags &= ~HFSPLUS_FLG_NODUMP; | ||
90 | |||
91 | inode->i_ctime = CURRENT_TIME_SEC; | ||
92 | mark_inode_dirty(inode); | ||
93 | |||
94 | out_unlock_inode: | ||
95 | mutex_lock(&inode->i_mutex); | ||
96 | out_drop_write: | ||
97 | mnt_drop_write(file->f_path.mnt); | ||
98 | out: | ||
99 | return err; | ||
100 | } | ||
101 | |||
102 | long hfsplus_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
103 | { | ||
104 | void __user *argp = (void __user *)arg; | ||
105 | |||
106 | switch (cmd) { | ||
107 | case HFSPLUS_IOC_EXT2_GETFLAGS: | ||
108 | return hfsplus_ioctl_getflags(file, argp); | ||
109 | case HFSPLUS_IOC_EXT2_SETFLAGS: | ||
110 | return hfsplus_ioctl_setflags(file, argp); | ||
95 | default: | 111 | default: |
96 | unlock_kernel(); | ||
97 | return -ENOTTY; | 112 | return -ENOTTY; |
98 | } | 113 | } |
99 | } | 114 | } |
@@ -110,7 +125,7 @@ int hfsplus_setxattr(struct dentry *dentry, const char *name, | |||
110 | if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode)) | 125 | if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode)) |
111 | return -EOPNOTSUPP; | 126 | return -EOPNOTSUPP; |
112 | 127 | ||
113 | res = hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd); | 128 | res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd); |
114 | if (res) | 129 | if (res) |
115 | return res; | 130 | return res; |
116 | res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); | 131 | res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); |
@@ -153,7 +168,7 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, | |||
153 | return -EOPNOTSUPP; | 168 | return -EOPNOTSUPP; |
154 | 169 | ||
155 | if (size) { | 170 | if (size) { |
156 | res = hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd); | 171 | res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd); |
157 | if (res) | 172 | if (res) |
158 | return res; | 173 | return res; |
159 | res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); | 174 | res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); |
@@ -177,7 +192,7 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, | |||
177 | } else | 192 | } else |
178 | res = size ? -ERANGE : 4; | 193 | res = size ? -ERANGE : 4; |
179 | } else | 194 | } else |
180 | res = -ENODATA; | 195 | res = -EOPNOTSUPP; |
181 | out: | 196 | out: |
182 | if (size) | 197 | if (size) |
183 | hfs_find_exit(&fd); | 198 | hfs_find_exit(&fd); |
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c index 572628b4b07d..f9ab276a4d8d 100644 --- a/fs/hfsplus/options.c +++ b/fs/hfsplus/options.c | |||
@@ -143,13 +143,13 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi) | |||
143 | kfree(p); | 143 | kfree(p); |
144 | break; | 144 | break; |
145 | case opt_decompose: | 145 | case opt_decompose: |
146 | sbi->flags &= ~HFSPLUS_SB_NODECOMPOSE; | 146 | clear_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags); |
147 | break; | 147 | break; |
148 | case opt_nodecompose: | 148 | case opt_nodecompose: |
149 | sbi->flags |= HFSPLUS_SB_NODECOMPOSE; | 149 | set_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags); |
150 | break; | 150 | break; |
151 | case opt_force: | 151 | case opt_force: |
152 | sbi->flags |= HFSPLUS_SB_FORCE; | 152 | set_bit(HFSPLUS_SB_FORCE, &sbi->flags); |
153 | break; | 153 | break; |
154 | default: | 154 | default: |
155 | return 0; | 155 | return 0; |
@@ -171,7 +171,7 @@ done: | |||
171 | 171 | ||
172 | int hfsplus_show_options(struct seq_file *seq, struct vfsmount *mnt) | 172 | int hfsplus_show_options(struct seq_file *seq, struct vfsmount *mnt) |
173 | { | 173 | { |
174 | struct hfsplus_sb_info *sbi = &HFSPLUS_SB(mnt->mnt_sb); | 174 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(mnt->mnt_sb); |
175 | 175 | ||
176 | if (sbi->creator != HFSPLUS_DEF_CR_TYPE) | 176 | if (sbi->creator != HFSPLUS_DEF_CR_TYPE) |
177 | seq_printf(seq, ",creator=%.4s", (char *)&sbi->creator); | 177 | seq_printf(seq, ",creator=%.4s", (char *)&sbi->creator); |
@@ -184,7 +184,7 @@ int hfsplus_show_options(struct seq_file *seq, struct vfsmount *mnt) | |||
184 | seq_printf(seq, ",session=%u", sbi->session); | 184 | seq_printf(seq, ",session=%u", sbi->session); |
185 | if (sbi->nls) | 185 | if (sbi->nls) |
186 | seq_printf(seq, ",nls=%s", sbi->nls->charset); | 186 | seq_printf(seq, ",nls=%s", sbi->nls->charset); |
187 | if (sbi->flags & HFSPLUS_SB_NODECOMPOSE) | 187 | if (test_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags)) |
188 | seq_printf(seq, ",nodecompose"); | 188 | seq_printf(seq, ",nodecompose"); |
189 | return 0; | 189 | return 0; |
190 | } | 190 | } |
diff --git a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c index 1528a6fd0299..208b16c645cc 100644 --- a/fs/hfsplus/part_tbl.c +++ b/fs/hfsplus/part_tbl.c | |||
@@ -74,6 +74,7 @@ struct old_pmap { | |||
74 | int hfs_part_find(struct super_block *sb, | 74 | int hfs_part_find(struct super_block *sb, |
75 | sector_t *part_start, sector_t *part_size) | 75 | sector_t *part_start, sector_t *part_size) |
76 | { | 76 | { |
77 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
77 | struct buffer_head *bh; | 78 | struct buffer_head *bh; |
78 | __be16 *data; | 79 | __be16 *data; |
79 | int i, size, res; | 80 | int i, size, res; |
@@ -95,7 +96,7 @@ int hfs_part_find(struct super_block *sb, | |||
95 | for (i = 0; i < size; p++, i++) { | 96 | for (i = 0; i < size; p++, i++) { |
96 | if (p->pdStart && p->pdSize && | 97 | if (p->pdStart && p->pdSize && |
97 | p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ && | 98 | p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ && |
98 | (HFSPLUS_SB(sb).part < 0 || HFSPLUS_SB(sb).part == i)) { | 99 | (sbi->part < 0 || sbi->part == i)) { |
99 | *part_start += be32_to_cpu(p->pdStart); | 100 | *part_start += be32_to_cpu(p->pdStart); |
100 | *part_size = be32_to_cpu(p->pdSize); | 101 | *part_size = be32_to_cpu(p->pdSize); |
101 | res = 0; | 102 | res = 0; |
@@ -111,7 +112,7 @@ int hfs_part_find(struct super_block *sb, | |||
111 | size = be32_to_cpu(pm->pmMapBlkCnt); | 112 | size = be32_to_cpu(pm->pmMapBlkCnt); |
112 | for (i = 0; i < size;) { | 113 | for (i = 0; i < size;) { |
113 | if (!memcmp(pm->pmPartType,"Apple_HFS", 9) && | 114 | if (!memcmp(pm->pmPartType,"Apple_HFS", 9) && |
114 | (HFSPLUS_SB(sb).part < 0 || HFSPLUS_SB(sb).part == i)) { | 115 | (sbi->part < 0 || sbi->part == i)) { |
115 | *part_start += be32_to_cpu(pm->pmPyPartStart); | 116 | *part_start += be32_to_cpu(pm->pmPyPartStart); |
116 | *part_size = be32_to_cpu(pm->pmPartBlkCnt); | 117 | *part_size = be32_to_cpu(pm->pmPartBlkCnt); |
117 | res = 0; | 118 | res = 0; |
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 3b55c050c742..9a88d7536103 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/pagemap.h> | 12 | #include <linux/pagemap.h> |
13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/smp_lock.h> | ||
16 | #include <linux/vfs.h> | 15 | #include <linux/vfs.h> |
17 | #include <linux/nls.h> | 16 | #include <linux/nls.h> |
18 | 17 | ||
@@ -21,40 +20,11 @@ static void hfsplus_destroy_inode(struct inode *inode); | |||
21 | 20 | ||
22 | #include "hfsplus_fs.h" | 21 | #include "hfsplus_fs.h" |
23 | 22 | ||
24 | struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino) | 23 | static int hfsplus_system_read_inode(struct inode *inode) |
25 | { | 24 | { |
26 | struct hfs_find_data fd; | 25 | struct hfsplus_vh *vhdr = HFSPLUS_SB(inode->i_sb)->s_vhdr; |
27 | struct hfsplus_vh *vhdr; | ||
28 | struct inode *inode; | ||
29 | long err = -EIO; | ||
30 | |||
31 | inode = iget_locked(sb, ino); | ||
32 | if (!inode) | ||
33 | return ERR_PTR(-ENOMEM); | ||
34 | if (!(inode->i_state & I_NEW)) | ||
35 | return inode; | ||
36 | 26 | ||
37 | INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); | 27 | switch (inode->i_ino) { |
38 | mutex_init(&HFSPLUS_I(inode).extents_lock); | ||
39 | HFSPLUS_I(inode).flags = 0; | ||
40 | HFSPLUS_I(inode).rsrc_inode = NULL; | ||
41 | atomic_set(&HFSPLUS_I(inode).opencnt, 0); | ||
42 | |||
43 | if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) { | ||
44 | read_inode: | ||
45 | hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd); | ||
46 | err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); | ||
47 | if (!err) | ||
48 | err = hfsplus_cat_read_inode(inode, &fd); | ||
49 | hfs_find_exit(&fd); | ||
50 | if (err) | ||
51 | goto bad_inode; | ||
52 | goto done; | ||
53 | } | ||
54 | vhdr = HFSPLUS_SB(inode->i_sb).s_vhdr; | ||
55 | switch(inode->i_ino) { | ||
56 | case HFSPLUS_ROOT_CNID: | ||
57 | goto read_inode; | ||
58 | case HFSPLUS_EXT_CNID: | 28 | case HFSPLUS_EXT_CNID: |
59 | hfsplus_inode_read_fork(inode, &vhdr->ext_file); | 29 | hfsplus_inode_read_fork(inode, &vhdr->ext_file); |
60 | inode->i_mapping->a_ops = &hfsplus_btree_aops; | 30 | inode->i_mapping->a_ops = &hfsplus_btree_aops; |
@@ -75,74 +45,101 @@ struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino) | |||
75 | inode->i_mapping->a_ops = &hfsplus_btree_aops; | 45 | inode->i_mapping->a_ops = &hfsplus_btree_aops; |
76 | break; | 46 | break; |
77 | default: | 47 | default: |
78 | goto bad_inode; | 48 | return -EIO; |
49 | } | ||
50 | |||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino) | ||
55 | { | ||
56 | struct hfs_find_data fd; | ||
57 | struct inode *inode; | ||
58 | int err; | ||
59 | |||
60 | inode = iget_locked(sb, ino); | ||
61 | if (!inode) | ||
62 | return ERR_PTR(-ENOMEM); | ||
63 | if (!(inode->i_state & I_NEW)) | ||
64 | return inode; | ||
65 | |||
66 | INIT_LIST_HEAD(&HFSPLUS_I(inode)->open_dir_list); | ||
67 | mutex_init(&HFSPLUS_I(inode)->extents_lock); | ||
68 | HFSPLUS_I(inode)->flags = 0; | ||
69 | HFSPLUS_I(inode)->rsrc_inode = NULL; | ||
70 | atomic_set(&HFSPLUS_I(inode)->opencnt, 0); | ||
71 | |||
72 | if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID || | ||
73 | inode->i_ino == HFSPLUS_ROOT_CNID) { | ||
74 | hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd); | ||
75 | err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); | ||
76 | if (!err) | ||
77 | err = hfsplus_cat_read_inode(inode, &fd); | ||
78 | hfs_find_exit(&fd); | ||
79 | } else { | ||
80 | err = hfsplus_system_read_inode(inode); | ||
81 | } | ||
82 | |||
83 | if (err) { | ||
84 | iget_failed(inode); | ||
85 | return ERR_PTR(err); | ||
79 | } | 86 | } |
80 | 87 | ||
81 | done: | ||
82 | unlock_new_inode(inode); | 88 | unlock_new_inode(inode); |
83 | return inode; | 89 | return inode; |
84 | |||
85 | bad_inode: | ||
86 | iget_failed(inode); | ||
87 | return ERR_PTR(err); | ||
88 | } | 90 | } |
89 | 91 | ||
90 | static int hfsplus_write_inode(struct inode *inode, | 92 | static int hfsplus_system_write_inode(struct inode *inode) |
91 | struct writeback_control *wbc) | ||
92 | { | 93 | { |
93 | struct hfsplus_vh *vhdr; | 94 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); |
94 | int ret = 0; | 95 | struct hfsplus_vh *vhdr = sbi->s_vhdr; |
96 | struct hfsplus_fork_raw *fork; | ||
97 | struct hfs_btree *tree = NULL; | ||
95 | 98 | ||
96 | dprint(DBG_INODE, "hfsplus_write_inode: %lu\n", inode->i_ino); | ||
97 | hfsplus_ext_write_extent(inode); | ||
98 | if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) { | ||
99 | return hfsplus_cat_write_inode(inode); | ||
100 | } | ||
101 | vhdr = HFSPLUS_SB(inode->i_sb).s_vhdr; | ||
102 | switch (inode->i_ino) { | 99 | switch (inode->i_ino) { |
103 | case HFSPLUS_ROOT_CNID: | ||
104 | ret = hfsplus_cat_write_inode(inode); | ||
105 | break; | ||
106 | case HFSPLUS_EXT_CNID: | 100 | case HFSPLUS_EXT_CNID: |
107 | if (vhdr->ext_file.total_size != cpu_to_be64(inode->i_size)) { | 101 | fork = &vhdr->ext_file; |
108 | HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; | 102 | tree = sbi->ext_tree; |
109 | inode->i_sb->s_dirt = 1; | ||
110 | } | ||
111 | hfsplus_inode_write_fork(inode, &vhdr->ext_file); | ||
112 | hfs_btree_write(HFSPLUS_SB(inode->i_sb).ext_tree); | ||
113 | break; | 103 | break; |
114 | case HFSPLUS_CAT_CNID: | 104 | case HFSPLUS_CAT_CNID: |
115 | if (vhdr->cat_file.total_size != cpu_to_be64(inode->i_size)) { | 105 | fork = &vhdr->cat_file; |
116 | HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; | 106 | tree = sbi->cat_tree; |
117 | inode->i_sb->s_dirt = 1; | ||
118 | } | ||
119 | hfsplus_inode_write_fork(inode, &vhdr->cat_file); | ||
120 | hfs_btree_write(HFSPLUS_SB(inode->i_sb).cat_tree); | ||
121 | break; | 107 | break; |
122 | case HFSPLUS_ALLOC_CNID: | 108 | case HFSPLUS_ALLOC_CNID: |
123 | if (vhdr->alloc_file.total_size != cpu_to_be64(inode->i_size)) { | 109 | fork = &vhdr->alloc_file; |
124 | HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; | ||
125 | inode->i_sb->s_dirt = 1; | ||
126 | } | ||
127 | hfsplus_inode_write_fork(inode, &vhdr->alloc_file); | ||
128 | break; | 110 | break; |
129 | case HFSPLUS_START_CNID: | 111 | case HFSPLUS_START_CNID: |
130 | if (vhdr->start_file.total_size != cpu_to_be64(inode->i_size)) { | 112 | fork = &vhdr->start_file; |
131 | HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; | ||
132 | inode->i_sb->s_dirt = 1; | ||
133 | } | ||
134 | hfsplus_inode_write_fork(inode, &vhdr->start_file); | ||
135 | break; | 113 | break; |
136 | case HFSPLUS_ATTR_CNID: | 114 | case HFSPLUS_ATTR_CNID: |
137 | if (vhdr->attr_file.total_size != cpu_to_be64(inode->i_size)) { | 115 | fork = &vhdr->attr_file; |
138 | HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; | 116 | tree = sbi->attr_tree; |
139 | inode->i_sb->s_dirt = 1; | 117 | default: |
140 | } | 118 | return -EIO; |
141 | hfsplus_inode_write_fork(inode, &vhdr->attr_file); | 119 | } |
142 | hfs_btree_write(HFSPLUS_SB(inode->i_sb).attr_tree); | 120 | |
143 | break; | 121 | if (fork->total_size != cpu_to_be64(inode->i_size)) { |
122 | set_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags); | ||
123 | inode->i_sb->s_dirt = 1; | ||
144 | } | 124 | } |
145 | return ret; | 125 | hfsplus_inode_write_fork(inode, fork); |
126 | if (tree) | ||
127 | hfs_btree_write(tree); | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static int hfsplus_write_inode(struct inode *inode, | ||
132 | struct writeback_control *wbc) | ||
133 | { | ||
134 | dprint(DBG_INODE, "hfsplus_write_inode: %lu\n", inode->i_ino); | ||
135 | |||
136 | hfsplus_ext_write_extent(inode); | ||
137 | |||
138 | if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID || | ||
139 | inode->i_ino == HFSPLUS_ROOT_CNID) | ||
140 | return hfsplus_cat_write_inode(inode); | ||
141 | else | ||
142 | return hfsplus_system_write_inode(inode); | ||
146 | } | 143 | } |
147 | 144 | ||
148 | static void hfsplus_evict_inode(struct inode *inode) | 145 | static void hfsplus_evict_inode(struct inode *inode) |
@@ -151,51 +148,53 @@ static void hfsplus_evict_inode(struct inode *inode) | |||
151 | truncate_inode_pages(&inode->i_data, 0); | 148 | truncate_inode_pages(&inode->i_data, 0); |
152 | end_writeback(inode); | 149 | end_writeback(inode); |
153 | if (HFSPLUS_IS_RSRC(inode)) { | 150 | if (HFSPLUS_IS_RSRC(inode)) { |
154 | HFSPLUS_I(HFSPLUS_I(inode).rsrc_inode).rsrc_inode = NULL; | 151 | HFSPLUS_I(HFSPLUS_I(inode)->rsrc_inode)->rsrc_inode = NULL; |
155 | iput(HFSPLUS_I(inode).rsrc_inode); | 152 | iput(HFSPLUS_I(inode)->rsrc_inode); |
156 | } | 153 | } |
157 | } | 154 | } |
158 | 155 | ||
159 | int hfsplus_sync_fs(struct super_block *sb, int wait) | 156 | int hfsplus_sync_fs(struct super_block *sb, int wait) |
160 | { | 157 | { |
161 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; | 158 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); |
159 | struct hfsplus_vh *vhdr = sbi->s_vhdr; | ||
162 | 160 | ||
163 | dprint(DBG_SUPER, "hfsplus_write_super\n"); | 161 | dprint(DBG_SUPER, "hfsplus_write_super\n"); |
164 | 162 | ||
165 | lock_super(sb); | 163 | mutex_lock(&sbi->vh_mutex); |
164 | mutex_lock(&sbi->alloc_mutex); | ||
166 | sb->s_dirt = 0; | 165 | sb->s_dirt = 0; |
167 | 166 | ||
168 | vhdr->free_blocks = cpu_to_be32(HFSPLUS_SB(sb).free_blocks); | 167 | vhdr->free_blocks = cpu_to_be32(sbi->free_blocks); |
169 | vhdr->next_alloc = cpu_to_be32(HFSPLUS_SB(sb).next_alloc); | 168 | vhdr->next_cnid = cpu_to_be32(sbi->next_cnid); |
170 | vhdr->next_cnid = cpu_to_be32(HFSPLUS_SB(sb).next_cnid); | 169 | vhdr->folder_count = cpu_to_be32(sbi->folder_count); |
171 | vhdr->folder_count = cpu_to_be32(HFSPLUS_SB(sb).folder_count); | 170 | vhdr->file_count = cpu_to_be32(sbi->file_count); |
172 | vhdr->file_count = cpu_to_be32(HFSPLUS_SB(sb).file_count); | ||
173 | 171 | ||
174 | mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh); | 172 | mark_buffer_dirty(sbi->s_vhbh); |
175 | if (HFSPLUS_SB(sb).flags & HFSPLUS_SB_WRITEBACKUP) { | 173 | if (test_and_clear_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags)) { |
176 | if (HFSPLUS_SB(sb).sect_count) { | 174 | if (sbi->sect_count) { |
177 | struct buffer_head *bh; | 175 | struct buffer_head *bh; |
178 | u32 block, offset; | 176 | u32 block, offset; |
179 | 177 | ||
180 | block = HFSPLUS_SB(sb).blockoffset; | 178 | block = sbi->blockoffset; |
181 | block += (HFSPLUS_SB(sb).sect_count - 2) >> (sb->s_blocksize_bits - 9); | 179 | block += (sbi->sect_count - 2) >> (sb->s_blocksize_bits - 9); |
182 | offset = ((HFSPLUS_SB(sb).sect_count - 2) << 9) & (sb->s_blocksize - 1); | 180 | offset = ((sbi->sect_count - 2) << 9) & (sb->s_blocksize - 1); |
183 | printk(KERN_DEBUG "hfs: backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset, | 181 | printk(KERN_DEBUG "hfs: backup: %u,%u,%u,%u\n", |
184 | HFSPLUS_SB(sb).sect_count, block, offset); | 182 | sbi->blockoffset, sbi->sect_count, |
183 | block, offset); | ||
185 | bh = sb_bread(sb, block); | 184 | bh = sb_bread(sb, block); |
186 | if (bh) { | 185 | if (bh) { |
187 | vhdr = (struct hfsplus_vh *)(bh->b_data + offset); | 186 | vhdr = (struct hfsplus_vh *)(bh->b_data + offset); |
188 | if (be16_to_cpu(vhdr->signature) == HFSPLUS_VOLHEAD_SIG) { | 187 | if (be16_to_cpu(vhdr->signature) == HFSPLUS_VOLHEAD_SIG) { |
189 | memcpy(vhdr, HFSPLUS_SB(sb).s_vhdr, sizeof(*vhdr)); | 188 | memcpy(vhdr, sbi->s_vhdr, sizeof(*vhdr)); |
190 | mark_buffer_dirty(bh); | 189 | mark_buffer_dirty(bh); |
191 | brelse(bh); | 190 | brelse(bh); |
192 | } else | 191 | } else |
193 | printk(KERN_WARNING "hfs: backup not found!\n"); | 192 | printk(KERN_WARNING "hfs: backup not found!\n"); |
194 | } | 193 | } |
195 | } | 194 | } |
196 | HFSPLUS_SB(sb).flags &= ~HFSPLUS_SB_WRITEBACKUP; | ||
197 | } | 195 | } |
198 | unlock_super(sb); | 196 | mutex_unlock(&sbi->alloc_mutex); |
197 | mutex_unlock(&sbi->vh_mutex); | ||
199 | return 0; | 198 | return 0; |
200 | } | 199 | } |
201 | 200 | ||
@@ -209,48 +208,48 @@ static void hfsplus_write_super(struct super_block *sb) | |||
209 | 208 | ||
210 | static void hfsplus_put_super(struct super_block *sb) | 209 | static void hfsplus_put_super(struct super_block *sb) |
211 | { | 210 | { |
211 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
212 | |||
212 | dprint(DBG_SUPER, "hfsplus_put_super\n"); | 213 | dprint(DBG_SUPER, "hfsplus_put_super\n"); |
214 | |||
213 | if (!sb->s_fs_info) | 215 | if (!sb->s_fs_info) |
214 | return; | 216 | return; |
215 | 217 | ||
216 | lock_kernel(); | ||
217 | |||
218 | if (sb->s_dirt) | 218 | if (sb->s_dirt) |
219 | hfsplus_write_super(sb); | 219 | hfsplus_write_super(sb); |
220 | if (!(sb->s_flags & MS_RDONLY) && HFSPLUS_SB(sb).s_vhdr) { | 220 | if (!(sb->s_flags & MS_RDONLY) && sbi->s_vhdr) { |
221 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; | 221 | struct hfsplus_vh *vhdr = sbi->s_vhdr; |
222 | 222 | ||
223 | vhdr->modify_date = hfsp_now2mt(); | 223 | vhdr->modify_date = hfsp_now2mt(); |
224 | vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_UNMNT); | 224 | vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_UNMNT); |
225 | vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_INCNSTNT); | 225 | vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_INCNSTNT); |
226 | mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh); | 226 | mark_buffer_dirty(sbi->s_vhbh); |
227 | sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh); | 227 | sync_dirty_buffer(sbi->s_vhbh); |
228 | } | 228 | } |
229 | 229 | ||
230 | hfs_btree_close(HFSPLUS_SB(sb).cat_tree); | 230 | hfs_btree_close(sbi->cat_tree); |
231 | hfs_btree_close(HFSPLUS_SB(sb).ext_tree); | 231 | hfs_btree_close(sbi->ext_tree); |
232 | iput(HFSPLUS_SB(sb).alloc_file); | 232 | iput(sbi->alloc_file); |
233 | iput(HFSPLUS_SB(sb).hidden_dir); | 233 | iput(sbi->hidden_dir); |
234 | brelse(HFSPLUS_SB(sb).s_vhbh); | 234 | brelse(sbi->s_vhbh); |
235 | unload_nls(HFSPLUS_SB(sb).nls); | 235 | unload_nls(sbi->nls); |
236 | kfree(sb->s_fs_info); | 236 | kfree(sb->s_fs_info); |
237 | sb->s_fs_info = NULL; | 237 | sb->s_fs_info = NULL; |
238 | |||
239 | unlock_kernel(); | ||
240 | } | 238 | } |
241 | 239 | ||
242 | static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf) | 240 | static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf) |
243 | { | 241 | { |
244 | struct super_block *sb = dentry->d_sb; | 242 | struct super_block *sb = dentry->d_sb; |
243 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
245 | u64 id = huge_encode_dev(sb->s_bdev->bd_dev); | 244 | u64 id = huge_encode_dev(sb->s_bdev->bd_dev); |
246 | 245 | ||
247 | buf->f_type = HFSPLUS_SUPER_MAGIC; | 246 | buf->f_type = HFSPLUS_SUPER_MAGIC; |
248 | buf->f_bsize = sb->s_blocksize; | 247 | buf->f_bsize = sb->s_blocksize; |
249 | buf->f_blocks = HFSPLUS_SB(sb).total_blocks << HFSPLUS_SB(sb).fs_shift; | 248 | buf->f_blocks = sbi->total_blocks << sbi->fs_shift; |
250 | buf->f_bfree = HFSPLUS_SB(sb).free_blocks << HFSPLUS_SB(sb).fs_shift; | 249 | buf->f_bfree = sbi->free_blocks << sbi->fs_shift; |
251 | buf->f_bavail = buf->f_bfree; | 250 | buf->f_bavail = buf->f_bfree; |
252 | buf->f_files = 0xFFFFFFFF; | 251 | buf->f_files = 0xFFFFFFFF; |
253 | buf->f_ffree = 0xFFFFFFFF - HFSPLUS_SB(sb).next_cnid; | 252 | buf->f_ffree = 0xFFFFFFFF - sbi->next_cnid; |
254 | buf->f_fsid.val[0] = (u32)id; | 253 | buf->f_fsid.val[0] = (u32)id; |
255 | buf->f_fsid.val[1] = (u32)(id >> 32); | 254 | buf->f_fsid.val[1] = (u32)(id >> 32); |
256 | buf->f_namelen = HFSPLUS_MAX_STRLEN; | 255 | buf->f_namelen = HFSPLUS_MAX_STRLEN; |
@@ -263,11 +262,11 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data) | |||
263 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) | 262 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) |
264 | return 0; | 263 | return 0; |
265 | if (!(*flags & MS_RDONLY)) { | 264 | if (!(*flags & MS_RDONLY)) { |
266 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; | 265 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb)->s_vhdr; |
267 | struct hfsplus_sb_info sbi; | 266 | struct hfsplus_sb_info sbi; |
268 | 267 | ||
269 | memset(&sbi, 0, sizeof(struct hfsplus_sb_info)); | 268 | memset(&sbi, 0, sizeof(struct hfsplus_sb_info)); |
270 | sbi.nls = HFSPLUS_SB(sb).nls; | 269 | sbi.nls = HFSPLUS_SB(sb)->nls; |
271 | if (!hfsplus_parse_options(data, &sbi)) | 270 | if (!hfsplus_parse_options(data, &sbi)) |
272 | return -EINVAL; | 271 | return -EINVAL; |
273 | 272 | ||
@@ -276,7 +275,7 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data) | |||
276 | "running fsck.hfsplus is recommended. leaving read-only.\n"); | 275 | "running fsck.hfsplus is recommended. leaving read-only.\n"); |
277 | sb->s_flags |= MS_RDONLY; | 276 | sb->s_flags |= MS_RDONLY; |
278 | *flags |= MS_RDONLY; | 277 | *flags |= MS_RDONLY; |
279 | } else if (sbi.flags & HFSPLUS_SB_FORCE) { | 278 | } else if (test_bit(HFSPLUS_SB_FORCE, &sbi.flags)) { |
280 | /* nothing */ | 279 | /* nothing */ |
281 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { | 280 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { |
282 | printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n"); | 281 | printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n"); |
@@ -320,7 +319,8 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
320 | return -ENOMEM; | 319 | return -ENOMEM; |
321 | 320 | ||
322 | sb->s_fs_info = sbi; | 321 | sb->s_fs_info = sbi; |
323 | INIT_HLIST_HEAD(&sbi->rsrc_inodes); | 322 | mutex_init(&sbi->alloc_mutex); |
323 | mutex_init(&sbi->vh_mutex); | ||
324 | hfsplus_fill_defaults(sbi); | 324 | hfsplus_fill_defaults(sbi); |
325 | if (!hfsplus_parse_options(data, sbi)) { | 325 | if (!hfsplus_parse_options(data, sbi)) { |
326 | printk(KERN_ERR "hfs: unable to parse mount options\n"); | 326 | printk(KERN_ERR "hfs: unable to parse mount options\n"); |
@@ -344,7 +344,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
344 | err = -EINVAL; | 344 | err = -EINVAL; |
345 | goto cleanup; | 345 | goto cleanup; |
346 | } | 346 | } |
347 | vhdr = HFSPLUS_SB(sb).s_vhdr; | 347 | vhdr = sbi->s_vhdr; |
348 | 348 | ||
349 | /* Copy parts of the volume header into the superblock */ | 349 | /* Copy parts of the volume header into the superblock */ |
350 | sb->s_magic = HFSPLUS_VOLHEAD_SIG; | 350 | sb->s_magic = HFSPLUS_VOLHEAD_SIG; |
@@ -353,18 +353,19 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
353 | printk(KERN_ERR "hfs: wrong filesystem version\n"); | 353 | printk(KERN_ERR "hfs: wrong filesystem version\n"); |
354 | goto cleanup; | 354 | goto cleanup; |
355 | } | 355 | } |
356 | HFSPLUS_SB(sb).total_blocks = be32_to_cpu(vhdr->total_blocks); | 356 | sbi->total_blocks = be32_to_cpu(vhdr->total_blocks); |
357 | HFSPLUS_SB(sb).free_blocks = be32_to_cpu(vhdr->free_blocks); | 357 | sbi->free_blocks = be32_to_cpu(vhdr->free_blocks); |
358 | HFSPLUS_SB(sb).next_alloc = be32_to_cpu(vhdr->next_alloc); | 358 | sbi->next_cnid = be32_to_cpu(vhdr->next_cnid); |
359 | HFSPLUS_SB(sb).next_cnid = be32_to_cpu(vhdr->next_cnid); | 359 | sbi->file_count = be32_to_cpu(vhdr->file_count); |
360 | HFSPLUS_SB(sb).file_count = be32_to_cpu(vhdr->file_count); | 360 | sbi->folder_count = be32_to_cpu(vhdr->folder_count); |
361 | HFSPLUS_SB(sb).folder_count = be32_to_cpu(vhdr->folder_count); | 361 | sbi->data_clump_blocks = |
362 | HFSPLUS_SB(sb).data_clump_blocks = be32_to_cpu(vhdr->data_clump_sz) >> HFSPLUS_SB(sb).alloc_blksz_shift; | 362 | be32_to_cpu(vhdr->data_clump_sz) >> sbi->alloc_blksz_shift; |
363 | if (!HFSPLUS_SB(sb).data_clump_blocks) | 363 | if (!sbi->data_clump_blocks) |
364 | HFSPLUS_SB(sb).data_clump_blocks = 1; | 364 | sbi->data_clump_blocks = 1; |
365 | HFSPLUS_SB(sb).rsrc_clump_blocks = be32_to_cpu(vhdr->rsrc_clump_sz) >> HFSPLUS_SB(sb).alloc_blksz_shift; | 365 | sbi->rsrc_clump_blocks = |
366 | if (!HFSPLUS_SB(sb).rsrc_clump_blocks) | 366 | be32_to_cpu(vhdr->rsrc_clump_sz) >> sbi->alloc_blksz_shift; |
367 | HFSPLUS_SB(sb).rsrc_clump_blocks = 1; | 367 | if (!sbi->rsrc_clump_blocks) |
368 | sbi->rsrc_clump_blocks = 1; | ||
368 | 369 | ||
369 | /* Set up operations so we can load metadata */ | 370 | /* Set up operations so we can load metadata */ |
370 | sb->s_op = &hfsplus_sops; | 371 | sb->s_op = &hfsplus_sops; |
@@ -374,7 +375,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
374 | printk(KERN_WARNING "hfs: Filesystem was not cleanly unmounted, " | 375 | printk(KERN_WARNING "hfs: Filesystem was not cleanly unmounted, " |
375 | "running fsck.hfsplus is recommended. mounting read-only.\n"); | 376 | "running fsck.hfsplus is recommended. mounting read-only.\n"); |
376 | sb->s_flags |= MS_RDONLY; | 377 | sb->s_flags |= MS_RDONLY; |
377 | } else if (sbi->flags & HFSPLUS_SB_FORCE) { | 378 | } else if (test_and_clear_bit(HFSPLUS_SB_FORCE, &sbi->flags)) { |
378 | /* nothing */ | 379 | /* nothing */ |
379 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { | 380 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { |
380 | printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only.\n"); | 381 | printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only.\n"); |
@@ -384,16 +385,15 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
384 | "use the force option at your own risk, mounting read-only.\n"); | 385 | "use the force option at your own risk, mounting read-only.\n"); |
385 | sb->s_flags |= MS_RDONLY; | 386 | sb->s_flags |= MS_RDONLY; |
386 | } | 387 | } |
387 | sbi->flags &= ~HFSPLUS_SB_FORCE; | ||
388 | 388 | ||
389 | /* Load metadata objects (B*Trees) */ | 389 | /* Load metadata objects (B*Trees) */ |
390 | HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); | 390 | sbi->ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); |
391 | if (!HFSPLUS_SB(sb).ext_tree) { | 391 | if (!sbi->ext_tree) { |
392 | printk(KERN_ERR "hfs: failed to load extents file\n"); | 392 | printk(KERN_ERR "hfs: failed to load extents file\n"); |
393 | goto cleanup; | 393 | goto cleanup; |
394 | } | 394 | } |
395 | HFSPLUS_SB(sb).cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID); | 395 | sbi->cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID); |
396 | if (!HFSPLUS_SB(sb).cat_tree) { | 396 | if (!sbi->cat_tree) { |
397 | printk(KERN_ERR "hfs: failed to load catalog file\n"); | 397 | printk(KERN_ERR "hfs: failed to load catalog file\n"); |
398 | goto cleanup; | 398 | goto cleanup; |
399 | } | 399 | } |
@@ -404,7 +404,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
404 | err = PTR_ERR(inode); | 404 | err = PTR_ERR(inode); |
405 | goto cleanup; | 405 | goto cleanup; |
406 | } | 406 | } |
407 | HFSPLUS_SB(sb).alloc_file = inode; | 407 | sbi->alloc_file = inode; |
408 | 408 | ||
409 | /* Load the root directory */ | 409 | /* Load the root directory */ |
410 | root = hfsplus_iget(sb, HFSPLUS_ROOT_CNID); | 410 | root = hfsplus_iget(sb, HFSPLUS_ROOT_CNID); |
@@ -423,7 +423,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
423 | 423 | ||
424 | str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1; | 424 | str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1; |
425 | str.name = HFSP_HIDDENDIR_NAME; | 425 | str.name = HFSP_HIDDENDIR_NAME; |
426 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | 426 | hfs_find_init(sbi->cat_tree, &fd); |
427 | hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str); | 427 | hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str); |
428 | if (!hfs_brec_read(&fd, &entry, sizeof(entry))) { | 428 | if (!hfs_brec_read(&fd, &entry, sizeof(entry))) { |
429 | hfs_find_exit(&fd); | 429 | hfs_find_exit(&fd); |
@@ -434,7 +434,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
434 | err = PTR_ERR(inode); | 434 | err = PTR_ERR(inode); |
435 | goto cleanup; | 435 | goto cleanup; |
436 | } | 436 | } |
437 | HFSPLUS_SB(sb).hidden_dir = inode; | 437 | sbi->hidden_dir = inode; |
438 | } else | 438 | } else |
439 | hfs_find_exit(&fd); | 439 | hfs_find_exit(&fd); |
440 | 440 | ||
@@ -449,15 +449,19 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
449 | be32_add_cpu(&vhdr->write_count, 1); | 449 | be32_add_cpu(&vhdr->write_count, 1); |
450 | vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT); | 450 | vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT); |
451 | vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT); | 451 | vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT); |
452 | mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh); | 452 | mark_buffer_dirty(sbi->s_vhbh); |
453 | sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh); | 453 | sync_dirty_buffer(sbi->s_vhbh); |
454 | 454 | ||
455 | if (!HFSPLUS_SB(sb).hidden_dir) { | 455 | if (!sbi->hidden_dir) { |
456 | printk(KERN_DEBUG "hfs: create hidden dir...\n"); | 456 | printk(KERN_DEBUG "hfs: create hidden dir...\n"); |
457 | HFSPLUS_SB(sb).hidden_dir = hfsplus_new_inode(sb, S_IFDIR); | 457 | |
458 | hfsplus_create_cat(HFSPLUS_SB(sb).hidden_dir->i_ino, sb->s_root->d_inode, | 458 | mutex_lock(&sbi->vh_mutex); |
459 | &str, HFSPLUS_SB(sb).hidden_dir); | 459 | sbi->hidden_dir = hfsplus_new_inode(sb, S_IFDIR); |
460 | mark_inode_dirty(HFSPLUS_SB(sb).hidden_dir); | 460 | hfsplus_create_cat(sbi->hidden_dir->i_ino, sb->s_root->d_inode, |
461 | &str, sbi->hidden_dir); | ||
462 | mutex_unlock(&sbi->vh_mutex); | ||
463 | |||
464 | mark_inode_dirty(sbi->hidden_dir); | ||
461 | } | 465 | } |
462 | out: | 466 | out: |
463 | unload_nls(sbi->nls); | 467 | unload_nls(sbi->nls); |
@@ -486,7 +490,7 @@ static struct inode *hfsplus_alloc_inode(struct super_block *sb) | |||
486 | 490 | ||
487 | static void hfsplus_destroy_inode(struct inode *inode) | 491 | static void hfsplus_destroy_inode(struct inode *inode) |
488 | { | 492 | { |
489 | kmem_cache_free(hfsplus_inode_cachep, &HFSPLUS_I(inode)); | 493 | kmem_cache_free(hfsplus_inode_cachep, HFSPLUS_I(inode)); |
490 | } | 494 | } |
491 | 495 | ||
492 | #define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info) | 496 | #define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info) |
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c index 628ccf6fa402..b66d67de882c 100644 --- a/fs/hfsplus/unicode.c +++ b/fs/hfsplus/unicode.c | |||
@@ -121,7 +121,7 @@ static u16 *hfsplus_compose_lookup(u16 *p, u16 cc) | |||
121 | int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, char *astr, int *len_p) | 121 | int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, char *astr, int *len_p) |
122 | { | 122 | { |
123 | const hfsplus_unichr *ip; | 123 | const hfsplus_unichr *ip; |
124 | struct nls_table *nls = HFSPLUS_SB(sb).nls; | 124 | struct nls_table *nls = HFSPLUS_SB(sb)->nls; |
125 | u8 *op; | 125 | u8 *op; |
126 | u16 cc, c0, c1; | 126 | u16 cc, c0, c1; |
127 | u16 *ce1, *ce2; | 127 | u16 *ce1, *ce2; |
@@ -132,7 +132,7 @@ int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, c | |||
132 | ustrlen = be16_to_cpu(ustr->length); | 132 | ustrlen = be16_to_cpu(ustr->length); |
133 | len = *len_p; | 133 | len = *len_p; |
134 | ce1 = NULL; | 134 | ce1 = NULL; |
135 | compose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); | 135 | compose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags); |
136 | 136 | ||
137 | while (ustrlen > 0) { | 137 | while (ustrlen > 0) { |
138 | c0 = be16_to_cpu(*ip++); | 138 | c0 = be16_to_cpu(*ip++); |
@@ -246,7 +246,7 @@ out: | |||
246 | static inline int asc2unichar(struct super_block *sb, const char *astr, int len, | 246 | static inline int asc2unichar(struct super_block *sb, const char *astr, int len, |
247 | wchar_t *uc) | 247 | wchar_t *uc) |
248 | { | 248 | { |
249 | int size = HFSPLUS_SB(sb).nls->char2uni(astr, len, uc); | 249 | int size = HFSPLUS_SB(sb)->nls->char2uni(astr, len, uc); |
250 | if (size <= 0) { | 250 | if (size <= 0) { |
251 | *uc = '?'; | 251 | *uc = '?'; |
252 | size = 1; | 252 | size = 1; |
@@ -293,7 +293,7 @@ int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr, | |||
293 | u16 *dstr, outlen = 0; | 293 | u16 *dstr, outlen = 0; |
294 | wchar_t c; | 294 | wchar_t c; |
295 | 295 | ||
296 | decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); | 296 | decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags); |
297 | while (outlen < HFSPLUS_MAX_STRLEN && len > 0) { | 297 | while (outlen < HFSPLUS_MAX_STRLEN && len > 0) { |
298 | size = asc2unichar(sb, astr, len, &c); | 298 | size = asc2unichar(sb, astr, len, &c); |
299 | 299 | ||
@@ -330,8 +330,8 @@ int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str) | |||
330 | wchar_t c; | 330 | wchar_t c; |
331 | u16 c2; | 331 | u16 c2; |
332 | 332 | ||
333 | casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD); | 333 | casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags); |
334 | decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); | 334 | decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags); |
335 | hash = init_name_hash(); | 335 | hash = init_name_hash(); |
336 | astr = str->name; | 336 | astr = str->name; |
337 | len = str->len; | 337 | len = str->len; |
@@ -373,8 +373,8 @@ int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr * | |||
373 | u16 c1, c2; | 373 | u16 c1, c2; |
374 | wchar_t c; | 374 | wchar_t c; |
375 | 375 | ||
376 | casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD); | 376 | casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags); |
377 | decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); | 377 | decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags); |
378 | astr1 = s1->name; | 378 | astr1 = s1->name; |
379 | len1 = s1->len; | 379 | len1 = s1->len; |
380 | astr2 = s2->name; | 380 | astr2 = s2->name; |
diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c index bed78ac8f6d1..8972c20b3216 100644 --- a/fs/hfsplus/wrapper.c +++ b/fs/hfsplus/wrapper.c | |||
@@ -65,8 +65,8 @@ static int hfsplus_get_last_session(struct super_block *sb, | |||
65 | *start = 0; | 65 | *start = 0; |
66 | *size = sb->s_bdev->bd_inode->i_size >> 9; | 66 | *size = sb->s_bdev->bd_inode->i_size >> 9; |
67 | 67 | ||
68 | if (HFSPLUS_SB(sb).session >= 0) { | 68 | if (HFSPLUS_SB(sb)->session >= 0) { |
69 | te.cdte_track = HFSPLUS_SB(sb).session; | 69 | te.cdte_track = HFSPLUS_SB(sb)->session; |
70 | te.cdte_format = CDROM_LBA; | 70 | te.cdte_format = CDROM_LBA; |
71 | res = ioctl_by_bdev(sb->s_bdev, CDROMREADTOCENTRY, (unsigned long)&te); | 71 | res = ioctl_by_bdev(sb->s_bdev, CDROMREADTOCENTRY, (unsigned long)&te); |
72 | if (!res && (te.cdte_ctrl & CDROM_DATA_TRACK) == 4) { | 72 | if (!res && (te.cdte_ctrl & CDROM_DATA_TRACK) == 4) { |
@@ -87,6 +87,7 @@ static int hfsplus_get_last_session(struct super_block *sb, | |||
87 | /* Takes in super block, returns true if good data read */ | 87 | /* Takes in super block, returns true if good data read */ |
88 | int hfsplus_read_wrapper(struct super_block *sb) | 88 | int hfsplus_read_wrapper(struct super_block *sb) |
89 | { | 89 | { |
90 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
90 | struct buffer_head *bh; | 91 | struct buffer_head *bh; |
91 | struct hfsplus_vh *vhdr; | 92 | struct hfsplus_vh *vhdr; |
92 | struct hfsplus_wd wd; | 93 | struct hfsplus_wd wd; |
@@ -122,7 +123,7 @@ int hfsplus_read_wrapper(struct super_block *sb) | |||
122 | if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG)) | 123 | if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG)) |
123 | break; | 124 | break; |
124 | if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) { | 125 | if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) { |
125 | HFSPLUS_SB(sb).flags |= HFSPLUS_SB_HFSX; | 126 | set_bit(HFSPLUS_SB_HFSX, &sbi->flags); |
126 | break; | 127 | break; |
127 | } | 128 | } |
128 | brelse(bh); | 129 | brelse(bh); |
@@ -143,11 +144,11 @@ int hfsplus_read_wrapper(struct super_block *sb) | |||
143 | if (blocksize < HFSPLUS_SECTOR_SIZE || | 144 | if (blocksize < HFSPLUS_SECTOR_SIZE || |
144 | ((blocksize - 1) & blocksize)) | 145 | ((blocksize - 1) & blocksize)) |
145 | return -EINVAL; | 146 | return -EINVAL; |
146 | HFSPLUS_SB(sb).alloc_blksz = blocksize; | 147 | sbi->alloc_blksz = blocksize; |
147 | HFSPLUS_SB(sb).alloc_blksz_shift = 0; | 148 | sbi->alloc_blksz_shift = 0; |
148 | while ((blocksize >>= 1) != 0) | 149 | while ((blocksize >>= 1) != 0) |
149 | HFSPLUS_SB(sb).alloc_blksz_shift++; | 150 | sbi->alloc_blksz_shift++; |
150 | blocksize = min(HFSPLUS_SB(sb).alloc_blksz, (u32)PAGE_SIZE); | 151 | blocksize = min(sbi->alloc_blksz, (u32)PAGE_SIZE); |
151 | 152 | ||
152 | /* align block size to block offset */ | 153 | /* align block size to block offset */ |
153 | while (part_start & ((blocksize >> HFSPLUS_SECTOR_SHIFT) - 1)) | 154 | while (part_start & ((blocksize >> HFSPLUS_SECTOR_SHIFT) - 1)) |
@@ -158,23 +159,26 @@ int hfsplus_read_wrapper(struct super_block *sb) | |||
158 | return -EINVAL; | 159 | return -EINVAL; |
159 | } | 160 | } |
160 | 161 | ||
161 | HFSPLUS_SB(sb).blockoffset = part_start >> | 162 | sbi->blockoffset = |
162 | (sb->s_blocksize_bits - HFSPLUS_SECTOR_SHIFT); | 163 | part_start >> (sb->s_blocksize_bits - HFSPLUS_SECTOR_SHIFT); |
163 | HFSPLUS_SB(sb).sect_count = part_size; | 164 | sbi->sect_count = part_size; |
164 | HFSPLUS_SB(sb).fs_shift = HFSPLUS_SB(sb).alloc_blksz_shift - | 165 | sbi->fs_shift = sbi->alloc_blksz_shift - sb->s_blocksize_bits; |
165 | sb->s_blocksize_bits; | ||
166 | 166 | ||
167 | bh = sb_bread512(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, vhdr); | 167 | bh = sb_bread512(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, vhdr); |
168 | if (!bh) | 168 | if (!bh) |
169 | return -EIO; | 169 | return -EIO; |
170 | 170 | ||
171 | /* should still be the same... */ | 171 | /* should still be the same... */ |
172 | if (vhdr->signature != (HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX ? | 172 | if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags)) { |
173 | cpu_to_be16(HFSPLUS_VOLHEAD_SIGX) : | 173 | if (vhdr->signature != cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) |
174 | cpu_to_be16(HFSPLUS_VOLHEAD_SIG))) | 174 | goto error; |
175 | goto error; | 175 | } else { |
176 | HFSPLUS_SB(sb).s_vhbh = bh; | 176 | if (vhdr->signature != cpu_to_be16(HFSPLUS_VOLHEAD_SIG)) |
177 | HFSPLUS_SB(sb).s_vhdr = vhdr; | 177 | goto error; |
178 | } | ||
179 | |||
180 | sbi->s_vhbh = bh; | ||
181 | sbi->s_vhdr = vhdr; | ||
178 | 182 | ||
179 | return 0; | 183 | return 0; |
180 | error: | 184 | error: |
diff --git a/include/linux/types.h b/include/linux/types.h index 01a082f56ef4..357dbc19606f 100644 --- a/include/linux/types.h +++ b/include/linux/types.h | |||
@@ -121,7 +121,15 @@ typedef __u64 u_int64_t; | |||
121 | typedef __s64 int64_t; | 121 | typedef __s64 int64_t; |
122 | #endif | 122 | #endif |
123 | 123 | ||
124 | /* this is a special 64bit data type that is 8-byte aligned */ | 124 | /* |
125 | * aligned_u64 should be used in defining kernel<->userspace ABIs to avoid | ||
126 | * common 32/64-bit compat problems. | ||
127 | * 64-bit values align to 4-byte boundaries on x86_32 (and possibly other | ||
128 | * architectures) and to 8-byte boundaries on 64-bit architetures. The new | ||
129 | * aligned_64 type enforces 8-byte alignment so that structs containing | ||
130 | * aligned_64 values have the same alignment on 32-bit and 64-bit architectures. | ||
131 | * No conversions are necessary between 32-bit user-space and a 64-bit kernel. | ||
132 | */ | ||
125 | #define aligned_u64 __u64 __attribute__((aligned(8))) | 133 | #define aligned_u64 __u64 __attribute__((aligned(8))) |
126 | #define aligned_be64 __be64 __attribute__((aligned(8))) | 134 | #define aligned_be64 __be64 __attribute__((aligned(8))) |
127 | #define aligned_le64 __le64 __attribute__((aligned(8))) | 135 | #define aligned_le64 __le64 __attribute__((aligned(8))) |
@@ -178,6 +186,11 @@ typedef __u64 __bitwise __be64; | |||
178 | typedef __u16 __bitwise __sum16; | 186 | typedef __u16 __bitwise __sum16; |
179 | typedef __u32 __bitwise __wsum; | 187 | typedef __u32 __bitwise __wsum; |
180 | 188 | ||
189 | /* this is a special 64bit data type that is 8-byte aligned */ | ||
190 | #define __aligned_u64 __u64 __attribute__((aligned(8))) | ||
191 | #define __aligned_be64 __be64 __attribute__((aligned(8))) | ||
192 | #define __aligned_le64 __le64 __attribute__((aligned(8))) | ||
193 | |||
181 | #ifdef __KERNEL__ | 194 | #ifdef __KERNEL__ |
182 | typedef unsigned __bitwise__ gfp_t; | 195 | typedef unsigned __bitwise__ gfp_t; |
183 | typedef unsigned __bitwise__ fmode_t; | 196 | typedef unsigned __bitwise__ fmode_t; |
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 1decafbb6b1a..72206cf5c6cf 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -931,6 +931,7 @@ static inline int | |||
931 | remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base) | 931 | remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base) |
932 | { | 932 | { |
933 | if (hrtimer_is_queued(timer)) { | 933 | if (hrtimer_is_queued(timer)) { |
934 | unsigned long state; | ||
934 | int reprogram; | 935 | int reprogram; |
935 | 936 | ||
936 | /* | 937 | /* |
@@ -944,8 +945,13 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base) | |||
944 | debug_deactivate(timer); | 945 | debug_deactivate(timer); |
945 | timer_stats_hrtimer_clear_start_info(timer); | 946 | timer_stats_hrtimer_clear_start_info(timer); |
946 | reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases); | 947 | reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases); |
947 | __remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE, | 948 | /* |
948 | reprogram); | 949 | * We must preserve the CALLBACK state flag here, |
950 | * otherwise we could move the timer base in | ||
951 | * switch_hrtimer_base. | ||
952 | */ | ||
953 | state = timer->state & HRTIMER_STATE_CALLBACK; | ||
954 | __remove_hrtimer(timer, base, state, reprogram); | ||
949 | return 1; | 955 | return 1; |
950 | } | 956 | } |
951 | return 0; | 957 | return 0; |
@@ -1231,6 +1237,9 @@ static void __run_hrtimer(struct hrtimer *timer, ktime_t *now) | |||
1231 | BUG_ON(timer->state != HRTIMER_STATE_CALLBACK); | 1237 | BUG_ON(timer->state != HRTIMER_STATE_CALLBACK); |
1232 | enqueue_hrtimer(timer, base); | 1238 | enqueue_hrtimer(timer, base); |
1233 | } | 1239 | } |
1240 | |||
1241 | WARN_ON_ONCE(!(timer->state & HRTIMER_STATE_CALLBACK)); | ||
1242 | |||
1234 | timer->state &= ~HRTIMER_STATE_CALLBACK; | 1243 | timer->state &= ~HRTIMER_STATE_CALLBACK; |
1235 | } | 1244 | } |
1236 | 1245 | ||
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c index 04cdcf72c827..10b90d8a03c4 100644 --- a/kernel/sysctl_check.c +++ b/kernel/sysctl_check.c | |||
@@ -143,15 +143,6 @@ int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table) | |||
143 | if (!table->maxlen) | 143 | if (!table->maxlen) |
144 | set_fail(&fail, table, "No maxlen"); | 144 | set_fail(&fail, table, "No maxlen"); |
145 | } | 145 | } |
146 | if ((table->proc_handler == proc_doulongvec_minmax) || | ||
147 | (table->proc_handler == proc_doulongvec_ms_jiffies_minmax)) { | ||
148 | if (table->maxlen > sizeof (unsigned long)) { | ||
149 | if (!table->extra1) | ||
150 | set_fail(&fail, table, "No min"); | ||
151 | if (!table->extra2) | ||
152 | set_fail(&fail, table, "No max"); | ||
153 | } | ||
154 | } | ||
155 | #ifdef CONFIG_PROC_SYSCTL | 146 | #ifdef CONFIG_PROC_SYSCTL |
156 | if (table->procname && !table->proc_handler) | 147 | if (table->procname && !table->proc_handler) |
157 | set_fail(&fail, table, "No proc_handler"); | 148 | set_fail(&fail, table, "No proc_handler"); |
diff --git a/net/rds/page.c b/net/rds/page.c index 595a952d4b17..1dfbfea12e9b 100644 --- a/net/rds/page.c +++ b/net/rds/page.c | |||
@@ -57,30 +57,17 @@ int rds_page_copy_user(struct page *page, unsigned long offset, | |||
57 | unsigned long ret; | 57 | unsigned long ret; |
58 | void *addr; | 58 | void *addr; |
59 | 59 | ||
60 | if (to_user) | 60 | addr = kmap(page); |
61 | if (to_user) { | ||
61 | rds_stats_add(s_copy_to_user, bytes); | 62 | rds_stats_add(s_copy_to_user, bytes); |
62 | else | 63 | ret = copy_to_user(ptr, addr + offset, bytes); |
64 | } else { | ||
63 | rds_stats_add(s_copy_from_user, bytes); | 65 | rds_stats_add(s_copy_from_user, bytes); |
64 | 66 | ret = copy_from_user(addr + offset, ptr, bytes); | |
65 | addr = kmap_atomic(page, KM_USER0); | ||
66 | if (to_user) | ||
67 | ret = __copy_to_user_inatomic(ptr, addr + offset, bytes); | ||
68 | else | ||
69 | ret = __copy_from_user_inatomic(addr + offset, ptr, bytes); | ||
70 | kunmap_atomic(addr, KM_USER0); | ||
71 | |||
72 | if (ret) { | ||
73 | addr = kmap(page); | ||
74 | if (to_user) | ||
75 | ret = copy_to_user(ptr, addr + offset, bytes); | ||
76 | else | ||
77 | ret = copy_from_user(addr + offset, ptr, bytes); | ||
78 | kunmap(page); | ||
79 | if (ret) | ||
80 | return -EFAULT; | ||
81 | } | 67 | } |
68 | kunmap(page); | ||
82 | 69 | ||
83 | return 0; | 70 | return ret ? -EFAULT : 0; |
84 | } | 71 | } |
85 | EXPORT_SYMBOL_GPL(rds_page_copy_user); | 72 | EXPORT_SYMBOL_GPL(rds_page_copy_user); |
86 | 73 | ||
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index a7868ad4d530..cbbed0db9e56 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c | |||
@@ -535,13 +535,15 @@ static int snd_rawmidi_release(struct inode *inode, struct file *file) | |||
535 | { | 535 | { |
536 | struct snd_rawmidi_file *rfile; | 536 | struct snd_rawmidi_file *rfile; |
537 | struct snd_rawmidi *rmidi; | 537 | struct snd_rawmidi *rmidi; |
538 | struct module *module; | ||
538 | 539 | ||
539 | rfile = file->private_data; | 540 | rfile = file->private_data; |
540 | rmidi = rfile->rmidi; | 541 | rmidi = rfile->rmidi; |
541 | rawmidi_release_priv(rfile); | 542 | rawmidi_release_priv(rfile); |
542 | kfree(rfile); | 543 | kfree(rfile); |
544 | module = rmidi->card->module; | ||
543 | snd_card_file_remove(rmidi->card, file); | 545 | snd_card_file_remove(rmidi->card, file); |
544 | module_put(rmidi->card->module); | 546 | module_put(module); |
545 | return 0; | 547 | return 0; |
546 | } | 548 | } |
547 | 549 | ||