diff --git a/[refs] b/[refs] index aa3045bdaad7..41daa1acc8f3 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9f1ad09493451c19d00c004da479acf699eeedd6 +refs/heads/master: 7669a2c95e502a77f93f27e5449fc93a00d588b6 diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index f2a2b8e647c5..7679bf32f7bb 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -3162,7 +3162,7 @@ F: drivers/net/ioc3-eth.c IOC3 SERIAL DRIVER M: Pat Gefre -L: linux-serial@vger.kernel.org +L: linux-mips@linux-mips.org S: Maintained F: drivers/serial/ioc3_serial.c diff --git a/trunk/Makefile b/trunk/Makefile index 860c26af52c3..7583116e5d9a 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 36 -EXTRAVERSION = +EXTRAVERSION = -rc8 NAME = Flesh-Eating Bats with Fangs # *DOCUMENTATION* diff --git a/trunk/arch/m32r/include/asm/elf.h b/trunk/arch/m32r/include/asm/elf.h index b8da7d0574d2..2f85412ef730 100644 --- a/trunk/arch/m32r/include/asm/elf.h +++ b/trunk/arch/m32r/include/asm/elf.h @@ -82,9 +82,9 @@ typedef elf_fpreg_t elf_fpregset_t; * These are used to set parameters in the core dumps. */ #define ELF_CLASS ELFCLASS32 -#if defined(__LITTLE_ENDIAN__) +#if defined(__LITTLE_ENDIAN) #define ELF_DATA ELFDATA2LSB -#elif defined(__BIG_ENDIAN__) +#elif defined(__BIG_ENDIAN) #define ELF_DATA ELFDATA2MSB #else #error no endian defined diff --git a/trunk/arch/m32r/kernel/.gitignore b/trunk/arch/m32r/kernel/.gitignore deleted file mode 100644 index c5f676c3c224..000000000000 --- a/trunk/arch/m32r/kernel/.gitignore +++ /dev/null @@ -1 +0,0 @@ -vmlinux.lds diff --git a/trunk/arch/m32r/kernel/signal.c b/trunk/arch/m32r/kernel/signal.c index a08697f0886d..7bbe38645ed5 100644 --- a/trunk/arch/m32r/kernel/signal.c +++ b/trunk/arch/m32r/kernel/signal.c @@ -28,8 +28,6 @@ #define DEBUG_SIG 0 -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r2, unsigned long r3, unsigned long r4, @@ -256,7 +254,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static int prev_insn(struct pt_regs *regs) { u16 inst; - if (get_user(inst, (u16 __user *)(regs->bpc - 2))) + if (get_user(&inst, (u16 __user *)(regs->bpc - 2))) return -EFAULT; if ((inst & 0xfff0) == 0x10f0) /* trap ? */ regs->bpc -= 2; diff --git a/trunk/arch/mips/Kbuild b/trunk/arch/mips/Kbuild index 7dd65cfae837..e322d65f33a4 100644 --- a/trunk/arch/mips/Kbuild +++ b/trunk/arch/mips/Kbuild @@ -7,10 +7,6 @@ subdir-ccflags-y := -Werror include arch/mips/Kbuild.platforms obj-y := $(platform-y) -# make clean traverses $(obj-) without having included .config, so -# everything ends up here -obj- := $(platform-) - # mips object files # The object files are linked as core-y files would be linked diff --git a/trunk/arch/mips/Kconfig b/trunk/arch/mips/Kconfig index 4c9f402295dd..5526faabfc21 100644 --- a/trunk/arch/mips/Kconfig +++ b/trunk/arch/mips/Kconfig @@ -881,15 +881,11 @@ config NO_IOPORT config GENERIC_ISA_DMA bool select ZONE_DMA if GENERIC_ISA_DMA_SUPPORT_BROKEN=n - select ISA_DMA_API config GENERIC_ISA_DMA_SUPPORT_BROKEN bool select GENERIC_ISA_DMA -config ISA_DMA_API - bool - config GENERIC_GPIO bool diff --git a/trunk/arch/mips/boot/compressed/Makefile b/trunk/arch/mips/boot/compressed/Makefile index 5042d51b0512..5fd7f7a58b7e 100644 --- a/trunk/arch/mips/boot/compressed/Makefile +++ b/trunk/arch/mips/boot/compressed/Makefile @@ -105,4 +105,4 @@ OBJCOPYFLAGS_vmlinuz.srec := $(OBJCOPYFLAGS) -S -O srec vmlinuz.srec: vmlinuz $(call cmd,objcopy) -clean-files := $(objtree)/vmlinuz $(objtree)/vmlinuz.{32,ecoff,bin,srec} +clean-files := $(objtree)/vmlinuz.* diff --git a/trunk/arch/mips/dec/Platform b/trunk/arch/mips/dec/Platform index cf55a6f4e720..3adbcbd95db1 100644 --- a/trunk/arch/mips/dec/Platform +++ b/trunk/arch/mips/dec/Platform @@ -1,7 +1,7 @@ # # DECstation family # -platform-$(CONFIG_MACH_DECSTATION) += dec/ +platform-$(CONFIG_MACH_DECSTATION) = dec/ cflags-$(CONFIG_MACH_DECSTATION) += \ -I$(srctree)/arch/mips/include/asm/mach-dec libs-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/prom/ diff --git a/trunk/arch/mips/include/asm/fcntl.h b/trunk/arch/mips/include/asm/fcntl.h index 75eddedcfc3e..e482fe90fe88 100644 --- a/trunk/arch/mips/include/asm/fcntl.h +++ b/trunk/arch/mips/include/asm/fcntl.h @@ -56,7 +56,6 @@ */ #ifdef CONFIG_32BIT -#include struct flock { short l_type; diff --git a/trunk/arch/mips/jz4740/Platform b/trunk/arch/mips/jz4740/Platform index ba91be9c21ef..6a97230e3d05 100644 --- a/trunk/arch/mips/jz4740/Platform +++ b/trunk/arch/mips/jz4740/Platform @@ -1,3 +1,3 @@ -platform-$(CONFIG_MACH_JZ4740) += jz4740/ +core-$(CONFIG_MACH_JZ4740) += arch/mips/jz4740/ cflags-$(CONFIG_MACH_JZ4740) += -I$(srctree)/arch/mips/include/asm/mach-jz4740 load-$(CONFIG_MACH_JZ4740) += 0xffffffff80010000 diff --git a/trunk/arch/mips/kernel/branch.c b/trunk/arch/mips/kernel/branch.c index 32103cc2a257..0176ed015c89 100644 --- a/trunk/arch/mips/kernel/branch.c +++ b/trunk/arch/mips/kernel/branch.c @@ -40,6 +40,7 @@ int __compute_return_epc(struct pt_regs *regs) return -EFAULT; } + regs->regs[0] = 0; switch (insn.i_format.opcode) { /* * jr and jalr are in r_format format. diff --git a/trunk/arch/mips/kernel/ptrace.c b/trunk/arch/mips/kernel/ptrace.c index c8777333e198..c51b95ff8644 100644 --- a/trunk/arch/mips/kernel/ptrace.c +++ b/trunk/arch/mips/kernel/ptrace.c @@ -536,7 +536,7 @@ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit) { /* do the secure computing check first */ if (!entryexit) - secure_computing(regs->regs[2]); + secure_computing(regs->regs[0]); if (unlikely(current->audit_context) && entryexit) audit_syscall_exit(AUDITSC_RESULT(regs->regs[2]), @@ -565,7 +565,7 @@ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit) out: if (unlikely(current->audit_context) && !entryexit) - audit_syscall_entry(audit_arch(), regs->regs[2], + audit_syscall_entry(audit_arch(), regs->regs[0], regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); } diff --git a/trunk/arch/mips/kernel/scall32-o32.S b/trunk/arch/mips/kernel/scall32-o32.S index fbaabad0e6e2..584415eef8c9 100644 --- a/trunk/arch/mips/kernel/scall32-o32.S +++ b/trunk/arch/mips/kernel/scall32-o32.S @@ -63,9 +63,9 @@ stack_done: sw t0, PT_R7(sp) # set error flag beqz t0, 1f - lw t1, PT_R2(sp) # syscall number negu v0 # error - sw t1, PT_R0(sp) # save it for syscall restarting + sw v0, PT_R0(sp) # set flag for syscall + # restarting 1: sw v0, PT_R2(sp) # result o32_syscall_exit: @@ -104,9 +104,9 @@ syscall_trace_entry: sw t0, PT_R7(sp) # set error flag beqz t0, 1f - lw t1, PT_R2(sp) # syscall number negu v0 # error - sw t1, PT_R0(sp) # save it for syscall restarting + sw v0, PT_R0(sp) # set flag for syscall + # restarting 1: sw v0, PT_R2(sp) # result j syscall_exit @@ -169,7 +169,8 @@ stackargs: * We probably should handle this case a bit more drastic. */ bad_stack: - li v0, EFAULT + negu v0 # error + sw v0, PT_R0(sp) sw v0, PT_R2(sp) li t0, 1 # set error flag sw t0, PT_R7(sp) diff --git a/trunk/arch/mips/kernel/scall64-64.S b/trunk/arch/mips/kernel/scall64-64.S index 3f4179283207..5573f8e4e326 100644 --- a/trunk/arch/mips/kernel/scall64-64.S +++ b/trunk/arch/mips/kernel/scall64-64.S @@ -66,9 +66,9 @@ NESTED(handle_sys64, PT_SIZE, sp) sd t0, PT_R7(sp) # set error flag beqz t0, 1f - ld t1, PT_R2(sp) # syscall number dnegu v0 # error - sd t1, PT_R0(sp) # save it for syscall restarting + sd v0, PT_R0(sp) # set flag for syscall + # restarting 1: sd v0, PT_R2(sp) # result n64_syscall_exit: @@ -109,9 +109,8 @@ syscall_trace_entry: sd t0, PT_R7(sp) # set error flag beqz t0, 1f - ld t1, PT_R2(sp) # syscall number dnegu v0 # error - sd t1, PT_R0(sp) # save it for syscall restarting + sd v0, PT_R0(sp) # set flag for syscall restarting 1: sd v0, PT_R2(sp) # result j syscall_exit diff --git a/trunk/arch/mips/kernel/scall64-n32.S b/trunk/arch/mips/kernel/scall64-n32.S index f08ece6d8acc..1e38ec97672e 100644 --- a/trunk/arch/mips/kernel/scall64-n32.S +++ b/trunk/arch/mips/kernel/scall64-n32.S @@ -65,9 +65,8 @@ NESTED(handle_sysn32, PT_SIZE, sp) sd t0, PT_R7(sp) # set error flag beqz t0, 1f - ld t1, PT_R2(sp) # syscall number dnegu v0 # error - sd t1, PT_R0(sp) # save it for syscall restarting + sd v0, PT_R0(sp) # set flag for syscall restarting 1: sd v0, PT_R2(sp) # result local_irq_disable # make sure need_resched and @@ -107,9 +106,8 @@ n32_syscall_trace_entry: sd t0, PT_R7(sp) # set error flag beqz t0, 1f - ld t1, PT_R2(sp) # syscall number dnegu v0 # error - sd t1, PT_R0(sp) # save it for syscall restarting + sd v0, PT_R0(sp) # set flag for syscall restarting 1: sd v0, PT_R2(sp) # result j syscall_exit @@ -322,10 +320,10 @@ EXPORT(sysn32_call_table) PTR sys_cacheflush PTR sys_cachectl PTR sys_sysmips - PTR compat_sys_io_setup /* 6200 */ + PTR sys_io_setup /* 6200 */ PTR sys_io_destroy - PTR compat_sys_io_getevents - PTR compat_sys_io_submit + PTR sys_io_getevents + PTR sys_io_submit PTR sys_io_cancel PTR sys_exit_group /* 6205 */ PTR sys_lookup_dcookie diff --git a/trunk/arch/mips/kernel/scall64-o32.S b/trunk/arch/mips/kernel/scall64-o32.S index 78d768a3e19d..171979fc98e5 100644 --- a/trunk/arch/mips/kernel/scall64-o32.S +++ b/trunk/arch/mips/kernel/scall64-o32.S @@ -93,9 +93,8 @@ NESTED(handle_sys, PT_SIZE, sp) sd t0, PT_R7(sp) # set error flag beqz t0, 1f - ld t1, PT_R2(sp) # syscall number dnegu v0 # error - sd t1, PT_R0(sp) # save it for syscall restarting + sd v0, PT_R0(sp) # flag for syscall restarting 1: sd v0, PT_R2(sp) # result o32_syscall_exit: @@ -143,9 +142,8 @@ trace_a_syscall: sd t0, PT_R7(sp) # set error flag beqz t0, 1f - ld t1, PT_R2(sp) # syscall number dnegu v0 # error - sd t1, PT_R0(sp) # save it for syscall restarting + sd v0, PT_R0(sp) # set flag for syscall restarting 1: sd v0, PT_R2(sp) # result j syscall_exit @@ -156,7 +154,8 @@ trace_a_syscall: * The stackpointer for a call with more than 4 arguments is bad. */ bad_stack: - li v0, EFAULT + dnegu v0 # error + sd v0, PT_R0(sp) sd v0, PT_R2(sp) li t0, 1 # set error flag sd t0, PT_R7(sp) @@ -445,10 +444,10 @@ sys_call_table: PTR compat_sys_futex PTR compat_sys_sched_setaffinity PTR compat_sys_sched_getaffinity /* 4240 */ - PTR compat_sys_io_setup + PTR sys_io_setup PTR sys_io_destroy - PTR compat_sys_io_getevents - PTR compat_sys_io_submit + PTR sys_io_getevents + PTR sys_io_submit PTR sys_io_cancel /* 4245 */ PTR sys_exit_group PTR sys32_lookup_dcookie diff --git a/trunk/arch/mips/kernel/signal.c b/trunk/arch/mips/kernel/signal.c index 5922342bca39..2099d5a4c4b7 100644 --- a/trunk/arch/mips/kernel/signal.c +++ b/trunk/arch/mips/kernel/signal.c @@ -390,6 +390,7 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) { struct rt_sigframe __user *frame; sigset_t set; + stack_t st; int sig; frame = (struct rt_sigframe __user *) regs.regs[29]; @@ -410,9 +411,11 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) else if (sig) force_sig(sig, current); + if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st))) + goto badframe; /* It is more difficult to avoid calling this function than to call it and ignore errors. */ - do_sigaltstack(&frame->rs_uc.uc_stack, NULL, regs.regs[29]); + do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]); /* * Don't let your children do this ... @@ -547,27 +550,24 @@ static int handle_signal(unsigned long sig, siginfo_t *info, struct mips_abi *abi = current->thread.abi; void *vdso = current->mm->context.vdso; - if (regs->regs[0]) { - switch(regs->regs[2]) { - case ERESTART_RESTARTBLOCK: - case ERESTARTNOHAND: + switch(regs->regs[0]) { + case ERESTART_RESTARTBLOCK: + case ERESTARTNOHAND: + regs->regs[2] = EINTR; + break; + case ERESTARTSYS: + if (!(ka->sa.sa_flags & SA_RESTART)) { regs->regs[2] = EINTR; break; - case ERESTARTSYS: - if (!(ka->sa.sa_flags & SA_RESTART)) { - regs->regs[2] = EINTR; - break; - } - /* fallthrough */ - case ERESTARTNOINTR: - regs->regs[7] = regs->regs[26]; - regs->regs[2] = regs->regs[0]; - regs->cp0_epc -= 4; } - - regs->regs[0] = 0; /* Don't deal with this again. */ + /* fallthrough */ + case ERESTARTNOINTR: /* Userland will reload $v0. */ + regs->regs[7] = regs->regs[26]; + regs->cp0_epc -= 8; } + regs->regs[0] = 0; /* Don't deal with this again. */ + if (sig_uses_siginfo(ka)) ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset, ka, regs, sig, oldset, info); @@ -575,9 +575,6 @@ static int handle_signal(unsigned long sig, siginfo_t *info, ret = abi->setup_frame(vdso + abi->signal_return_offset, ka, regs, sig, oldset); - if (ret) - return ret; - spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NODEFER)) @@ -625,13 +622,17 @@ static void do_signal(struct pt_regs *regs) return; } + /* + * Who's code doesn't conform to the restartable syscall convention + * dies here!!! The li instruction, a single machine instruction, + * must directly be followed by the syscall instruction. + */ if (regs->regs[0]) { if (regs->regs[2] == ERESTARTNOHAND || regs->regs[2] == ERESTARTSYS || regs->regs[2] == ERESTARTNOINTR) { - regs->regs[2] = regs->regs[0]; regs->regs[7] = regs->regs[26]; - regs->cp0_epc -= 4; + regs->cp0_epc -= 8; } if (regs->regs[2] == ERESTART_RESTARTBLOCK) { regs->regs[2] = current->thread.abi->restart; diff --git a/trunk/arch/mips/kernel/signal_n32.c b/trunk/arch/mips/kernel/signal_n32.c index ee24d814d5b9..2c5df818c65a 100644 --- a/trunk/arch/mips/kernel/signal_n32.c +++ b/trunk/arch/mips/kernel/signal_n32.c @@ -109,7 +109,6 @@ asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) { struct rt_sigframe_n32 __user *frame; - mm_segment_t old_fs; sigset_t set; stack_t st; s32 sp; @@ -144,11 +143,7 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) /* It is more difficult to avoid calling this function than to call it and ignore errors. */ - old_fs = get_fs(); - set_fs(KERNEL_DS); do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]); - set_fs(old_fs); - /* * Don't let your children do this ... diff --git a/trunk/arch/mips/kernel/unaligned.c b/trunk/arch/mips/kernel/unaligned.c index 33d5a5ce4a29..69b039ca8d83 100644 --- a/trunk/arch/mips/kernel/unaligned.c +++ b/trunk/arch/mips/kernel/unaligned.c @@ -109,6 +109,8 @@ static void emulate_load_store_insn(struct pt_regs *regs, unsigned long value; unsigned int res; + regs->regs[0] = 0; + /* * This load never faults. */ diff --git a/trunk/arch/um/drivers/hostaudio_kern.c b/trunk/arch/um/drivers/hostaudio_kern.c index 63c740a85b4c..0c46e398cd8f 100644 --- a/trunk/arch/um/drivers/hostaudio_kern.c +++ b/trunk/arch/um/drivers/hostaudio_kern.c @@ -40,11 +40,6 @@ static char *mixer = HOSTAUDIO_DEV_MIXER; " This is used to specify the host mixer device to the hostaudio driver.\n"\ " The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n" -module_param(dsp, charp, 0644); -MODULE_PARM_DESC(dsp, DSP_HELP); -module_param(mixer, charp, 0644); -MODULE_PARM_DESC(mixer, MIXER_HELP); - #ifndef MODULE static int set_dsp(char *name, int *add) { @@ -61,6 +56,15 @@ static int set_mixer(char *name, int *add) } __uml_setup("mixer=", set_mixer, "mixer=\n" MIXER_HELP); + +#else /*MODULE*/ + +module_param(dsp, charp, 0644); +MODULE_PARM_DESC(dsp, DSP_HELP); + +module_param(mixer, charp, 0644); +MODULE_PARM_DESC(mixer, MIXER_HELP); + #endif /* /dev/dsp file operations */ diff --git a/trunk/arch/um/drivers/ubd_kern.c b/trunk/arch/um/drivers/ubd_kern.c index 9734994cba1e..1bcd208c459f 100644 --- a/trunk/arch/um/drivers/ubd_kern.c +++ b/trunk/arch/um/drivers/ubd_kern.c @@ -163,7 +163,6 @@ struct ubd { struct scatterlist sg[MAX_SG]; struct request *request; int start_sg, end_sg; - sector_t rq_pos; }; #define DEFAULT_COW { \ @@ -188,7 +187,6 @@ struct ubd { .request = NULL, \ .start_sg = 0, \ .end_sg = 0, \ - .rq_pos = 0, \ } /* Protected by ubd_lock */ @@ -1230,6 +1228,7 @@ static void do_ubd_request(struct request_queue *q) { struct io_thread_req *io_req; struct request *req; + sector_t sector; int n; while(1){ @@ -1240,12 +1239,12 @@ static void do_ubd_request(struct request_queue *q) return; dev->request = req; - dev->rq_pos = blk_rq_pos(req); dev->start_sg = 0; dev->end_sg = blk_rq_map_sg(q, req, dev->sg); } req = dev->request; + sector = blk_rq_pos(req); while(dev->start_sg < dev->end_sg){ struct scatterlist *sg = &dev->sg[dev->start_sg]; @@ -1257,9 +1256,10 @@ static void do_ubd_request(struct request_queue *q) return; } prepare_request(req, io_req, - (unsigned long long)dev->rq_pos << 9, + (unsigned long long)sector << 9, sg->offset, sg->length, sg_page(sg)); + sector += sg->length >> 9; n = os_write_file(thread_fd, &io_req, sizeof(struct io_thread_req *)); if(n != sizeof(struct io_thread_req *)){ @@ -1272,7 +1272,6 @@ static void do_ubd_request(struct request_queue *q) return; } - dev->rq_pos += sg->length >> 9; dev->start_sg++; } dev->end_sg = 0; diff --git a/trunk/arch/x86/include/asm/kvm_host.h b/trunk/arch/x86/include/asm/kvm_host.h index c52e2eb40a1e..502e53f999cf 100644 --- a/trunk/arch/x86/include/asm/kvm_host.h +++ b/trunk/arch/x86/include/asm/kvm_host.h @@ -652,6 +652,20 @@ static inline struct kvm_mmu_page *page_header(hpa_t shadow_page) return (struct kvm_mmu_page *)page_private(page); } +static inline u16 kvm_read_fs(void) +{ + u16 seg; + asm("mov %%fs, %0" : "=g"(seg)); + return seg; +} + +static inline u16 kvm_read_gs(void) +{ + u16 seg; + asm("mov %%gs, %0" : "=g"(seg)); + return seg; +} + static inline u16 kvm_read_ldt(void) { u16 ldt; @@ -659,6 +673,16 @@ static inline u16 kvm_read_ldt(void) return ldt; } +static inline void kvm_load_fs(u16 sel) +{ + asm("mov %0, %%fs" : : "rm"(sel)); +} + +static inline void kvm_load_gs(u16 sel) +{ + asm("mov %0, %%gs" : : "rm"(sel)); +} + static inline void kvm_load_ldt(u16 sel) { asm("lldt %0" : : "rm"(sel)); diff --git a/trunk/arch/x86/kvm/svm.c b/trunk/arch/x86/kvm/svm.c index 8a3f9f64f86f..81ed28cb36e6 100644 --- a/trunk/arch/x86/kvm/svm.c +++ b/trunk/arch/x86/kvm/svm.c @@ -3163,8 +3163,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) sync_lapic_to_cr8(vcpu); save_host_msrs(vcpu); - savesegment(fs, fs_selector); - savesegment(gs, gs_selector); + fs_selector = kvm_read_fs(); + gs_selector = kvm_read_gs(); ldt_selector = kvm_read_ldt(); svm->vmcb->save.cr2 = vcpu->arch.cr2; /* required for live migration with NPT */ @@ -3251,15 +3251,10 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu) vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp; vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip; - load_host_msrs(vcpu); - loadsegment(fs, fs_selector); -#ifdef CONFIG_X86_64 - load_gs_index(gs_selector); - wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs); -#else - loadsegment(gs, gs_selector); -#endif + kvm_load_fs(fs_selector); + kvm_load_gs(gs_selector); kvm_load_ldt(ldt_selector); + load_host_msrs(vcpu); reload_tss(vcpu); diff --git a/trunk/arch/x86/kvm/vmx.c b/trunk/arch/x86/kvm/vmx.c index 7bddfab12013..49b25eee25ac 100644 --- a/trunk/arch/x86/kvm/vmx.c +++ b/trunk/arch/x86/kvm/vmx.c @@ -803,7 +803,7 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu) */ vmx->host_state.ldt_sel = kvm_read_ldt(); vmx->host_state.gs_ldt_reload_needed = vmx->host_state.ldt_sel; - savesegment(fs, vmx->host_state.fs_sel); + vmx->host_state.fs_sel = kvm_read_fs(); if (!(vmx->host_state.fs_sel & 7)) { vmcs_write16(HOST_FS_SELECTOR, vmx->host_state.fs_sel); vmx->host_state.fs_reload_needed = 0; @@ -811,7 +811,7 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu) vmcs_write16(HOST_FS_SELECTOR, 0); vmx->host_state.fs_reload_needed = 1; } - savesegment(gs, vmx->host_state.gs_sel); + vmx->host_state.gs_sel = kvm_read_gs(); if (!(vmx->host_state.gs_sel & 7)) vmcs_write16(HOST_GS_SELECTOR, vmx->host_state.gs_sel); else { @@ -841,21 +841,27 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu) static void __vmx_load_host_state(struct vcpu_vmx *vmx) { + unsigned long flags; + if (!vmx->host_state.loaded) return; ++vmx->vcpu.stat.host_state_reload; vmx->host_state.loaded = 0; if (vmx->host_state.fs_reload_needed) - loadsegment(fs, vmx->host_state.fs_sel); + kvm_load_fs(vmx->host_state.fs_sel); if (vmx->host_state.gs_ldt_reload_needed) { kvm_load_ldt(vmx->host_state.ldt_sel); + /* + * If we have to reload gs, we must take care to + * preserve our gs base. + */ + local_irq_save(flags); + kvm_load_gs(vmx->host_state.gs_sel); #ifdef CONFIG_X86_64 - load_gs_index(vmx->host_state.gs_sel); - wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs); -#else - loadsegment(gs, vmx->host_state.gs_sel); + wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE)); #endif + local_irq_restore(flags); } reload_tss(); #ifdef CONFIG_X86_64 @@ -2583,8 +2589,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */ vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */ vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */ - vmcs_write16(HOST_FS_SELECTOR, 0); /* 22.2.4 */ - vmcs_write16(HOST_GS_SELECTOR, 0); /* 22.2.4 */ + vmcs_write16(HOST_FS_SELECTOR, kvm_read_fs()); /* 22.2.4 */ + vmcs_write16(HOST_GS_SELECTOR, kvm_read_gs()); /* 22.2.4 */ vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS); /* 22.2.4 */ #ifdef CONFIG_X86_64 rdmsrl(MSR_FS_BASE, a); diff --git a/trunk/block/bsg.c b/trunk/block/bsg.c index 0c00870553a3..82d58829ba59 100644 --- a/trunk/block/bsg.c +++ b/trunk/block/bsg.c @@ -426,7 +426,7 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr, /* * fill in all the output members */ - hdr->device_status = rq->errors & 0xff; + hdr->device_status = status_byte(rq->errors); hdr->transport_status = host_byte(rq->errors); hdr->driver_status = driver_byte(rq->errors); hdr->info = 0; diff --git a/trunk/drivers/block/ps3disk.c b/trunk/drivers/block/ps3disk.c index 03688c2da319..e9da874d0419 100644 --- a/trunk/drivers/block/ps3disk.c +++ b/trunk/drivers/block/ps3disk.c @@ -113,7 +113,7 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev, memcpy(buf, dev->bounce_buf+offset, size); offset += size; flush_kernel_dcache_page(bvec->bv_page); - bvec_kunmap_irq(buf, &flags); + bvec_kunmap_irq(bvec, &flags); i++; } } diff --git a/trunk/drivers/char/virtio_console.c b/trunk/drivers/char/virtio_console.c index 0f69c5ec0ecd..c810481a5bc2 100644 --- a/trunk/drivers/char/virtio_console.c +++ b/trunk/drivers/char/virtio_console.c @@ -459,12 +459,9 @@ static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count, /* * Wait till the host acknowledges it pushed out the data we - * sent. This is done for data from the hvc_console; the tty - * operations are performed with spinlocks held so we can't - * sleep here. An alternative would be to copy the data to a - * buffer and relax the spinning requirement. The downside is - * we need to kmalloc a GFP_ATOMIC buffer each time the - * console driver writes something out. + * sent. This is done for ports in blocking mode or for data + * from the hvc_console; the tty operations are performed with + * spinlocks held so we can't sleep here. */ while (!virtqueue_get_buf(out_vq, &len)) cpu_relax(); @@ -629,14 +626,6 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, goto free_buf; } - /* - * We now ask send_buf() to not spin for generic ports -- we - * can re-use the same code path that non-blocking file - * descriptors take for blocking file descriptors since the - * wait is already done and we're certain the write will go - * through to the host. - */ - nonblock = true; ret = send_buf(port, buf, count, nonblock); if (nonblock && ret > 0) diff --git a/trunk/drivers/firewire/ohci.c b/trunk/drivers/firewire/ohci.c index 9dcb17d51aee..1b05896648bc 100644 --- a/trunk/drivers/firewire/ohci.c +++ b/trunk/drivers/firewire/ohci.c @@ -2840,7 +2840,7 @@ static int __devinit pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) { struct fw_ohci *ohci; - u32 bus_options, max_receive, link_speed, version; + u32 bus_options, max_receive, link_speed, version, link_enh; u64 guid; int i, err, n_ir, n_it; size_t size; @@ -2894,6 +2894,23 @@ static int __devinit pci_probe(struct pci_dev *dev, if (param_quirks) ohci->quirks = param_quirks; + /* TI OHCI-Lynx and compatible: set recommended configuration bits. */ + if (dev->vendor == PCI_VENDOR_ID_TI) { + pci_read_config_dword(dev, PCI_CFG_TI_LinkEnh, &link_enh); + + /* adjust latency of ATx FIFO: use 1.7 KB threshold */ + link_enh &= ~TI_LinkEnh_atx_thresh_mask; + link_enh |= TI_LinkEnh_atx_thresh_1_7K; + + /* use priority arbitration for asynchronous responses */ + link_enh |= TI_LinkEnh_enab_unfair; + + /* required for aPhyEnhanceEnable to work */ + link_enh |= TI_LinkEnh_enab_accel; + + pci_write_config_dword(dev, PCI_CFG_TI_LinkEnh, link_enh); + } + ar_context_init(&ohci->ar_request_ctx, ohci, OHCI1394_AsReqRcvContextControlSet); diff --git a/trunk/drivers/firewire/ohci.h b/trunk/drivers/firewire/ohci.h index ef5e7336da68..0e6c5a466908 100644 --- a/trunk/drivers/firewire/ohci.h +++ b/trunk/drivers/firewire/ohci.h @@ -155,4 +155,12 @@ #define OHCI1394_phy_tcode 0xe +/* TI extensions */ + +#define PCI_CFG_TI_LinkEnh 0xf4 +#define TI_LinkEnh_enab_accel 0x00000002 +#define TI_LinkEnh_enab_unfair 0x00000080 +#define TI_LinkEnh_atx_thresh_mask 0x00003000 +#define TI_LinkEnh_atx_thresh_1_7K 0x00001000 + #endif /* _FIREWIRE_OHCI_H */ diff --git a/trunk/drivers/gpu/drm/radeon/radeon_cursor.c b/trunk/drivers/gpu/drm/radeon/radeon_cursor.c index 3eef567b0421..5731fc9b1ae3 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_cursor.c @@ -203,7 +203,6 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct radeon_device *rdev = crtc->dev->dev_private; int xorigin = 0, yorigin = 0; - int w = radeon_crtc->cursor_width; if (x < 0) xorigin = -x + 1; @@ -214,7 +213,22 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, if (yorigin >= CURSOR_HEIGHT) yorigin = CURSOR_HEIGHT - 1; - if (ASIC_IS_AVIVO(rdev)) { + radeon_lock_cursor(crtc, true); + if (ASIC_IS_DCE4(rdev)) { + /* cursors are offset into the total surface */ + x += crtc->x; + y += crtc->y; + DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y); + + /* XXX: check if evergreen has the same issues as avivo chips */ + WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, + ((xorigin ? 0 : x) << 16) | + (yorigin ? 0 : y)); + WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); + WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset, + ((radeon_crtc->cursor_width - 1) << 16) | (radeon_crtc->cursor_height - 1)); + } else if (ASIC_IS_AVIVO(rdev)) { + int w = radeon_crtc->cursor_width; int i = 0; struct drm_crtc *crtc_p; @@ -246,17 +260,7 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, if (w <= 0) w = 1; } - } - radeon_lock_cursor(crtc, true); - if (ASIC_IS_DCE4(rdev)) { - WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, - ((xorigin ? 0 : x) << 16) | - (yorigin ? 0 : y)); - WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); - WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset, - ((w - 1) << 16) | (radeon_crtc->cursor_height - 1)); - } else if (ASIC_IS_AVIVO(rdev)) { WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y)); diff --git a/trunk/drivers/hid/hid-cando.c b/trunk/drivers/hid/hid-cando.c index 5925bdcd417d..4267a6fdc277 100644 --- a/trunk/drivers/hid/hid-cando.c +++ b/trunk/drivers/hid/hid-cando.c @@ -237,8 +237,6 @@ static const struct hid_device_id cando_devices[] = { USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, - USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, { } }; MODULE_DEVICE_TABLE(hid, cando_devices); diff --git a/trunk/drivers/hid/hid-core.c b/trunk/drivers/hid/hid-core.c index a0dea3d1296e..3f7292486024 100644 --- a/trunk/drivers/hid/hid-core.c +++ b/trunk/drivers/hid/hid-core.c @@ -1292,7 +1292,6 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, diff --git a/trunk/drivers/hid/hid-ids.h b/trunk/drivers/hid/hid-ids.h index c5ae5f1545bd..765a4f53eb5c 100644 --- a/trunk/drivers/hid/hid-ids.h +++ b/trunk/drivers/hid/hid-ids.h @@ -134,7 +134,6 @@ #define USB_VENDOR_ID_CANDO 0x2087 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03 -#define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01 #define USB_VENDOR_ID_CH 0x068e #define USB_DEVICE_ID_CH_PRO_PEDALS 0x00f2 @@ -504,7 +503,6 @@ #define USB_VENDOR_ID_TURBOX 0x062a #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 -#define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART 0x7100 #define USB_VENDOR_ID_TWINHAN 0x6253 #define USB_DEVICE_ID_TWINHAN_IR_REMOTE 0x0100 diff --git a/trunk/drivers/hid/hidraw.c b/trunk/drivers/hid/hidraw.c index a3866b5c0c43..47d70c523d93 100644 --- a/trunk/drivers/hid/hidraw.c +++ b/trunk/drivers/hid/hidraw.c @@ -109,12 +109,6 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t int ret = 0; mutex_lock(&minors_lock); - - if (!hidraw_table[minor]) { - ret = -ENODEV; - goto out; - } - dev = hidraw_table[minor]->hid; if (!dev->hid_output_raw_report) { @@ -250,10 +244,6 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, mutex_lock(&minors_lock); dev = hidraw_table[minor]; - if (!dev) { - ret = -ENODEV; - goto out; - } switch (cmd) { case HIDIOCGRDESCSIZE: @@ -327,7 +317,6 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, ret = -ENOTTY; } -out: mutex_unlock(&minors_lock); return ret; } diff --git a/trunk/drivers/hid/usbhid/hid-quirks.c b/trunk/drivers/hid/usbhid/hid-quirks.c index f0260c699adb..70da3181c8a0 100644 --- a/trunk/drivers/hid/usbhid/hid-quirks.c +++ b/trunk/drivers/hid/usbhid/hid-quirks.c @@ -36,7 +36,6 @@ static const struct hid_blacklist { { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, diff --git a/trunk/drivers/i2c/busses/i2c-davinci.c b/trunk/drivers/i2c/busses/i2c-davinci.c index 5795c8398c7c..b8feac5f2ef4 100644 --- a/trunk/drivers/i2c/busses/i2c-davinci.c +++ b/trunk/drivers/i2c/busses/i2c-davinci.c @@ -331,16 +331,21 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) INIT_COMPLETION(dev->cmd_complete); dev->cmd_err = 0; - /* Take I2C out of reset and configure it as master */ - flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST; + /* Take I2C out of reset, configure it as master and set the + * start bit */ + flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT; /* if the slave address is ten bit address, enable XA bit */ if (msg->flags & I2C_M_TEN) flag |= DAVINCI_I2C_MDR_XA; if (!(msg->flags & I2C_M_RD)) flag |= DAVINCI_I2C_MDR_TRX; - if (msg->len == 0) + if (stop) + flag |= DAVINCI_I2C_MDR_STP; + if (msg->len == 0) { flag |= DAVINCI_I2C_MDR_RM; + flag &= ~DAVINCI_I2C_MDR_STP; + } /* Enable receive or transmit interrupts */ w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); @@ -352,29 +357,18 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) dev->terminate = 0; - /* - * Write mode register first as needed for correct behaviour - * on OMAP-L138, but don't set STT yet to avoid a race with XRDY - * occuring before we have loaded DXR - */ - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); - /* * First byte should be set here, not after interrupt, * because transmit-data-ready interrupt can come before * NACK-interrupt during sending of previous message and * ICDXR may have wrong data - * It also saves us one interrupt, slightly faster */ if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); dev->buf_len--; } - /* Set STT to begin transmit now DXR is loaded */ - flag |= DAVINCI_I2C_MDR_STT; - if (stop && msg->len != 0) - flag |= DAVINCI_I2C_MDR_STP; + /* write the data into mode register; start transmitting */ davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, diff --git a/trunk/drivers/i2c/busses/i2c-imx.c b/trunk/drivers/i2c/busses/i2c-imx.c index 4c2a62b75b5c..d1ff9408dc1f 100644 --- a/trunk/drivers/i2c/busses/i2c-imx.c +++ b/trunk/drivers/i2c/busses/i2c-imx.c @@ -159,9 +159,15 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx) { - wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10); + int result; + + result = wait_event_interruptible_timeout(i2c_imx->queue, + i2c_imx->i2csr & I2SR_IIF, HZ / 10); - if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) { + if (unlikely(result < 0)) { + dev_dbg(&i2c_imx->adapter.dev, "<%s> result < 0\n", __func__); + return result; + } else if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) { dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__); return -ETIMEDOUT; } @@ -289,7 +295,7 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id) i2c_imx->i2csr = temp; temp &= ~I2SR_IIF; writeb(temp, i2c_imx->base + IMX_I2C_I2SR); - wake_up(&i2c_imx->queue); + wake_up_interruptible(&i2c_imx->queue); return IRQ_HANDLED; } diff --git a/trunk/drivers/input/evdev.c b/trunk/drivers/input/evdev.c index 9ddafc30f432..c908c5f83645 100644 --- a/trunk/drivers/input/evdev.c +++ b/trunk/drivers/input/evdev.c @@ -669,9 +669,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { - if (!dev->absinfo) - return -EINVAL; - t = _IOC_NR(cmd) & ABS_MAX; abs = dev->absinfo[t]; @@ -683,13 +680,10 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, } } - if (_IOC_DIR(cmd) == _IOC_WRITE) { + if (_IOC_DIR(cmd) == _IOC_READ) { if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { - if (!dev->absinfo) - return -EINVAL; - t = _IOC_NR(cmd) & ABS_MAX; if (copy_from_user(&abs, p, min_t(size_t, diff --git a/trunk/drivers/media/video/v4l2-compat-ioctl32.c b/trunk/drivers/media/video/v4l2-compat-ioctl32.c index 86294ed35c9b..073f01390cdd 100644 --- a/trunk/drivers/media/video/v4l2-compat-ioctl32.c +++ b/trunk/drivers/media/video/v4l2-compat-ioctl32.c @@ -193,24 +193,17 @@ static int put_video_window32(struct video_window *kp, struct video_window32 __u struct video_code32 { char loadwhat[16]; /* name or tag of file being passed */ compat_int_t datasize; - compat_uptr_t data; + unsigned char *data; }; -static struct video_code __user *get_microcode32(struct video_code32 *kp) +static int get_microcode32(struct video_code *kp, struct video_code32 __user *up) { - struct video_code __user *up; - - up = compat_alloc_user_space(sizeof(*up)); - - /* - * NOTE! We don't actually care if these fail. If the - * user address is invalid, the native ioctl will do - * the error handling for us - */ - (void) copy_to_user(up->loadwhat, kp->loadwhat, sizeof(up->loadwhat)); - (void) put_user(kp->datasize, &up->datasize); - (void) put_user(compat_ptr(kp->data), &up->data); - return up; + if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) || + copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) || + get_user(kp->datasize, &up->datasize) || + copy_from_user(kp->data, up->data, up->datasize)) + return -EFAULT; + return 0; } #define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32) @@ -746,7 +739,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar struct video_tuner vt; struct video_buffer vb; struct video_window vw; - struct video_code32 vc; + struct video_code vc; struct video_audio va; #endif struct v4l2_format v2f; @@ -825,11 +818,8 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar break; case VIDIOCSMICROCODE: - /* Copy the 32-bit "video_code32" to kernel space */ - if (copy_from_user(&karg.vc, up, sizeof(karg.vc))) - return -EFAULT; - /* Convert the 32-bit version to a 64-bit version in user space */ - up = get_microcode32(&karg.vc); + err = get_microcode32(&karg.vc, up); + compatible_arg = 0; break; case VIDIOCSFREQ: diff --git a/trunk/drivers/mmc/core/core.c b/trunk/drivers/mmc/core/core.c index 09eee6df0653..5db49b124ffa 100644 --- a/trunk/drivers/mmc/core/core.c +++ b/trunk/drivers/mmc/core/core.c @@ -1631,19 +1631,6 @@ int mmc_suspend_host(struct mmc_host *host) if (host->bus_ops && !host->bus_dead) { if (host->bus_ops->suspend) err = host->bus_ops->suspend(host); - if (err == -ENOSYS || !host->bus_ops->resume) { - /* - * We simply "remove" the card in this case. - * It will be redetected on resume. - */ - if (host->bus_ops->remove) - host->bus_ops->remove(host); - mmc_claim_host(host); - mmc_detach_bus(host); - mmc_release_host(host); - host->pm_flags = 0; - err = 0; - } } mmc_bus_put(host); diff --git a/trunk/drivers/mtd/nand/mxc_nand.c b/trunk/drivers/mtd/nand/mxc_nand.c index 214b03afdd48..b2828e84d243 100644 --- a/trunk/drivers/mtd/nand/mxc_nand.c +++ b/trunk/drivers/mtd/nand/mxc_nand.c @@ -30,8 +30,6 @@ #include #include #include -#include -#include #include #include @@ -153,7 +151,7 @@ struct mxc_nand_host { int irq; int eccsize; - struct completion op_completion; + wait_queue_head_t irq_waitq; uint8_t *data_buf; unsigned int buf_start; @@ -166,7 +164,6 @@ struct mxc_nand_host { void (*send_read_id)(struct mxc_nand_host *); uint16_t (*get_dev_status)(struct mxc_nand_host *); int (*check_int)(struct mxc_nand_host *); - void (*irq_control)(struct mxc_nand_host *, int); }; /* OOB placement block for use with hardware ecc generation */ @@ -219,12 +216,9 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) { struct mxc_nand_host *host = dev_id; - if (!host->check_int(host)) - return IRQ_NONE; + disable_irq_nosync(irq); - host->irq_control(host, 0); - - complete(&host->op_completion); + wake_up(&host->irq_waitq); return IRQ_HANDLED; } @@ -251,54 +245,11 @@ static int check_int_v1_v2(struct mxc_nand_host *host) if (!(tmp & NFC_V1_V2_CONFIG2_INT)) return 0; - if (!cpu_is_mx21()) - writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2); + writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2); return 1; } -/* - * It has been observed that the i.MX21 cannot read the CONFIG2:INT bit - * if interrupts are masked (CONFIG1:INT_MSK is set). To handle this, the - * driver can enable/disable the irq line rather than simply masking the - * interrupts. - */ -static void irq_control_mx21(struct mxc_nand_host *host, int activate) -{ - if (activate) - enable_irq(host->irq); - else - disable_irq_nosync(host->irq); -} - -static void irq_control_v1_v2(struct mxc_nand_host *host, int activate) -{ - uint16_t tmp; - - tmp = readw(NFC_V1_V2_CONFIG1); - - if (activate) - tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK; - else - tmp |= NFC_V1_V2_CONFIG1_INT_MSK; - - writew(tmp, NFC_V1_V2_CONFIG1); -} - -static void irq_control_v3(struct mxc_nand_host *host, int activate) -{ - uint32_t tmp; - - tmp = readl(NFC_V3_CONFIG2); - - if (activate) - tmp &= ~NFC_V3_CONFIG2_INT_MSK; - else - tmp |= NFC_V3_CONFIG2_INT_MSK; - - writel(tmp, NFC_V3_CONFIG2); -} - /* This function polls the NANDFC to wait for the basic operation to * complete by checking the INT bit of config2 register. */ @@ -308,9 +259,10 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq) if (useirq) { if (!host->check_int(host)) { - INIT_COMPLETION(host->op_completion); - host->irq_control(host, 1); - wait_for_completion(&host->op_completion); + + enable_irq(host->irq); + + wait_event(host->irq_waitq, host->check_int(host)); } } else { while (max_retries-- > 0) { @@ -847,7 +799,6 @@ static void preset_v3(struct mtd_info *mtd) NFC_V3_CONFIG2_2CMD_PHASES | NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) | NFC_V3_CONFIG2_ST_CMD(0x70) | - NFC_V3_CONFIG2_INT_MSK | NFC_V3_CONFIG2_NUM_ADDR_PHASE0; if (chip->ecc.mode == NAND_ECC_HW) @@ -1073,10 +1024,6 @@ static int __init mxcnd_probe(struct platform_device *pdev) host->send_read_id = send_read_id_v1_v2; host->get_dev_status = get_dev_status_v1_v2; host->check_int = check_int_v1_v2; - if (cpu_is_mx21()) - host->irq_control = irq_control_mx21; - else - host->irq_control = irq_control_v1_v2; } if (nfc_is_v21()) { @@ -1115,7 +1062,6 @@ static int __init mxcnd_probe(struct platform_device *pdev) host->send_read_id = send_read_id_v3; host->check_int = check_int_v3; host->get_dev_status = get_dev_status_v3; - host->irq_control = irq_control_v3; oob_smallpage = &nandv2_hw_eccoob_smallpage; oob_largepage = &nandv2_hw_eccoob_largepage; } else @@ -1147,34 +1093,14 @@ static int __init mxcnd_probe(struct platform_device *pdev) this->options |= NAND_USE_FLASH_BBT; } - init_completion(&host->op_completion); + init_waitqueue_head(&host->irq_waitq); host->irq = platform_get_irq(pdev, 0); - /* - * mask the interrupt. For i.MX21 explicitely call - * irq_control_v1_v2 to use the mask bit. We can't call - * disable_irq_nosync() for an interrupt we do not own yet. - */ - if (cpu_is_mx21()) - irq_control_v1_v2(host, 0); - else - host->irq_control(host, 0); - err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host); if (err) goto eirq; - host->irq_control(host, 0); - - /* - * Now that the interrupt is disabled make sure the interrupt - * mask bit is cleared on i.MX21. Otherwise we can't read - * the interrupt status bit on this machine. - */ - if (cpu_is_mx21()) - irq_control_v1_v2(host, 1); - /* first scan to find the device and get the page size */ if (nand_scan_ident(mtd, 1, NULL)) { err = -ENXIO; diff --git a/trunk/drivers/scsi/scsi.c b/trunk/drivers/scsi/scsi.c index 348fba0a8976..ad0ed212db4a 100644 --- a/trunk/drivers/scsi/scsi.c +++ b/trunk/drivers/scsi/scsi.c @@ -1046,13 +1046,13 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf, /* If the user actually wanted this page, we can skip the rest */ if (page == 0) - return 0; + return -EINVAL; for (i = 0; i < min((int)buf[3], buf_len - 4); i++) if (buf[i + 4] == page) goto found; - if (i < buf[3] && i >= buf_len - 4) + if (i < buf[3] && i > buf_len) /* ran off the end of the buffer, give us benefit of doubt */ goto found; /* The device claims it doesn't support the requested page */ diff --git a/trunk/drivers/serial/ioc3_serial.c b/trunk/drivers/serial/ioc3_serial.c index 800c54602339..93de907b1208 100644 --- a/trunk/drivers/serial/ioc3_serial.c +++ b/trunk/drivers/serial/ioc3_serial.c @@ -2044,7 +2044,6 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd) if (!port) { printk(KERN_WARNING "IOC3 serial memory not available for port\n"); - ret = -ENOMEM; goto out4; } spin_lock_init(&port->ip_lock); diff --git a/trunk/fs/ceph/osdmap.c b/trunk/fs/ceph/osdmap.c index e31f118f1392..3ccd11761cb6 100644 --- a/trunk/fs/ceph/osdmap.c +++ b/trunk/fs/ceph/osdmap.c @@ -417,6 +417,19 @@ static struct ceph_pg_pool_info *__lookup_pg_pool(struct rb_root *root, int id) return NULL; } +int ceph_pg_poolid_by_name(struct ceph_osdmap *map, const char *name) +{ + struct rb_node *rbp; + + for (rbp = rb_first(&map->pg_pools); rbp; rbp = rb_next(rbp)) { + struct ceph_pg_pool_info *pi = + rb_entry(rbp, struct ceph_pg_pool_info, node); + if (pi->name && strcmp(pi->name, name) == 0) + return pi->id; + } + return -ENOENT; +} + static void __remove_pg_pool(struct rb_root *root, struct ceph_pg_pool_info *pi) { rb_erase(&pi->node, root); diff --git a/trunk/fs/ceph/osdmap.h b/trunk/fs/ceph/osdmap.h index 970b547e510d..a592b211be39 100644 --- a/trunk/fs/ceph/osdmap.h +++ b/trunk/fs/ceph/osdmap.h @@ -125,4 +125,6 @@ extern int ceph_calc_pg_acting(struct ceph_osdmap *osdmap, struct ceph_pg pgid, extern int ceph_calc_pg_primary(struct ceph_osdmap *osdmap, struct ceph_pg pgid); +extern int ceph_pg_poolid_by_name(struct ceph_osdmap *map, const char *name); + #endif diff --git a/trunk/fs/exec.c b/trunk/fs/exec.c index 6d2b6f936858..03278c984ba0 100644 --- a/trunk/fs/exec.c +++ b/trunk/fs/exec.c @@ -2024,7 +2024,6 @@ int dump_write(struct file *file, const void *addr, int nr) { return access_ok(VERIFY_READ, addr, nr) && file->f_op->write(file, addr, nr, &file->f_pos) == nr; } -EXPORT_SYMBOL(dump_write); int dump_seek(struct file *file, loff_t off) { @@ -2053,4 +2052,3 @@ int dump_seek(struct file *file, loff_t off) } return ret; } -EXPORT_SYMBOL(dump_seek); diff --git a/trunk/fs/hfsplus/bfind.c b/trunk/fs/hfsplus/bfind.c index d182438c7ae4..5007a41f1be9 100644 --- a/trunk/fs/hfsplus/bfind.c +++ b/trunk/fs/hfsplus/bfind.c @@ -23,7 +23,7 @@ int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd) fd->search_key = ptr; fd->key = ptr + tree->max_key_len + 2; dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n", tree->cnid, __builtin_return_address(0)); - mutex_lock(&tree->tree_lock); + down(&tree->tree_lock); return 0; } @@ -32,7 +32,7 @@ void hfs_find_exit(struct hfs_find_data *fd) hfs_bnode_put(fd->bnode); kfree(fd->search_key); dprint(DBG_BNODE_REFS, "find_exit: %d (%p)\n", fd->tree->cnid, __builtin_return_address(0)); - mutex_unlock(&fd->tree->tree_lock); + up(&fd->tree->tree_lock); fd->tree = NULL; } @@ -52,10 +52,6 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd) rec = (e + b) / 2; len = hfs_brec_lenoff(bnode, rec, &off); keylen = hfs_brec_keylen(bnode, rec); - if (keylen == 0) { - res = -EINVAL; - goto fail; - } hfs_bnode_read(bnode, fd->key, off, keylen); cmpval = bnode->tree->keycmp(fd->key, fd->search_key); if (!cmpval) { @@ -71,10 +67,6 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd) if (rec != e && e >= 0) { len = hfs_brec_lenoff(bnode, e, &off); keylen = hfs_brec_keylen(bnode, e); - if (keylen == 0) { - res = -EINVAL; - goto fail; - } hfs_bnode_read(bnode, fd->key, off, keylen); } done: @@ -83,7 +75,6 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd) fd->keylength = keylen; fd->entryoffset = off + keylen; fd->entrylength = len - keylen; -fail: return res; } @@ -207,10 +198,6 @@ int hfs_brec_goto(struct hfs_find_data *fd, int cnt) len = hfs_brec_lenoff(bnode, fd->record, &off); keylen = hfs_brec_keylen(bnode, fd->record); - if (keylen == 0) { - res = -EINVAL; - goto out; - } fd->keyoffset = off; fd->keylength = keylen; fd->entryoffset = off + keylen; diff --git a/trunk/fs/hfsplus/bitmap.c b/trunk/fs/hfsplus/bitmap.c index ad57f5991eb1..ea30afc2a03c 100644 --- a/trunk/fs/hfsplus/bitmap.c +++ b/trunk/fs/hfsplus/bitmap.c @@ -17,7 +17,6 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *max) { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); struct page *page; struct address_space *mapping; __be32 *pptr, *curr, *end; @@ -30,8 +29,8 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma return size; dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len); - mutex_lock(&sbi->alloc_mutex); - mapping = sbi->alloc_file->i_mapping; + mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); + mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL); if (IS_ERR(page)) { start = size; @@ -151,17 +150,16 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma set_page_dirty(page); kunmap(page); *max = offset + (curr - pptr) * 32 + i - start; - sbi->free_blocks -= *max; + HFSPLUS_SB(sb).free_blocks -= *max; sb->s_dirt = 1; dprint(DBG_BITMAP, "-> %u,%u\n", start, *max); out: - mutex_unlock(&sbi->alloc_mutex); + mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex); return start; } int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count) { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); struct page *page; struct address_space *mapping; __be32 *pptr, *curr, *end; @@ -174,11 +172,11 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count) dprint(DBG_BITMAP, "block_free: %u,%u\n", offset, count); /* are all of the bits in range? */ - if ((offset + count) > sbi->total_blocks) + if ((offset + count) > HFSPLUS_SB(sb).total_blocks) return -2; - mutex_lock(&sbi->alloc_mutex); - mapping = sbi->alloc_file->i_mapping; + mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); + mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; pnr = offset / PAGE_CACHE_BITS; page = read_mapping_page(mapping, pnr, NULL); pptr = kmap(page); @@ -226,9 +224,9 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count) out: set_page_dirty(page); kunmap(page); - sbi->free_blocks += len; + HFSPLUS_SB(sb).free_blocks += len; sb->s_dirt = 1; - mutex_unlock(&sbi->alloc_mutex); + mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex); return 0; } diff --git a/trunk/fs/hfsplus/brec.c b/trunk/fs/hfsplus/brec.c index 2f39d05443e1..c88e5d72a402 100644 --- a/trunk/fs/hfsplus/brec.c +++ b/trunk/fs/hfsplus/brec.c @@ -42,13 +42,10 @@ u16 hfs_brec_keylen(struct hfs_bnode *node, u16 rec) recoff = hfs_bnode_read_u16(node, node->tree->node_size - (rec + 1) * 2); if (!recoff) return 0; - - retval = hfs_bnode_read_u16(node, recoff) + 2; - if (retval > node->tree->max_key_len + 2) { - printk(KERN_ERR "hfs: keylen %d too large\n", - retval); - retval = 0; - } + if (node->tree->attributes & HFS_TREE_BIGKEYS) + retval = hfs_bnode_read_u16(node, recoff) + 2; + else + retval = (hfs_bnode_read_u8(node, recoff) | 1) + 1; } return retval; } @@ -219,7 +216,7 @@ int hfs_brec_remove(struct hfs_find_data *fd) static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) { struct hfs_btree *tree; - struct hfs_bnode *node, *new_node, *next_node; + struct hfs_bnode *node, *new_node; struct hfs_bnode_desc node_desc; int num_recs, new_rec_off, new_off, old_rec_off; int data_start, data_end, size; @@ -238,17 +235,6 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) new_node->type = node->type; new_node->height = node->height; - if (node->next) - next_node = hfs_bnode_find(tree, node->next); - else - next_node = NULL; - - if (IS_ERR(next_node)) { - hfs_bnode_put(node); - hfs_bnode_put(new_node); - return next_node; - } - size = tree->node_size / 2 - node->num_recs * 2 - 14; old_rec_off = tree->node_size - 4; num_recs = 1; @@ -262,8 +248,6 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) /* panic? */ hfs_bnode_put(node); hfs_bnode_put(new_node); - if (next_node) - hfs_bnode_put(next_node); return ERR_PTR(-ENOSPC); } @@ -318,7 +302,8 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc)); /* update next bnode header */ - if (next_node) { + if (new_node->next) { + struct hfs_bnode *next_node = hfs_bnode_find(tree, new_node->next); next_node->prev = new_node->this; hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc)); node_desc.prev = cpu_to_be32(next_node->prev); diff --git a/trunk/fs/hfsplus/btree.c b/trunk/fs/hfsplus/btree.c index 22e4d4e32999..e49fcee1e293 100644 --- a/trunk/fs/hfsplus/btree.c +++ b/trunk/fs/hfsplus/btree.c @@ -30,7 +30,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) if (!tree) return NULL; - mutex_init(&tree->tree_lock); + init_MUTEX(&tree->tree_lock); spin_lock_init(&tree->hash_lock); tree->sb = sb; tree->cnid = id; @@ -39,16 +39,10 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) goto free_tree; tree->inode = inode; - if (!HFSPLUS_I(tree->inode)->first_blocks) { - printk(KERN_ERR - "hfs: invalid btree extent records (0 size).\n"); - goto free_inode; - } - mapping = tree->inode->i_mapping; page = read_mapping_page(mapping, 0, NULL); if (IS_ERR(page)) - goto free_inode; + goto free_tree; /* Load the header */ head = (struct hfs_btree_header_rec *)(kmap(page) + sizeof(struct hfs_bnode_desc)); @@ -63,56 +57,27 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) tree->max_key_len = be16_to_cpu(head->max_key_len); tree->depth = be16_to_cpu(head->depth); - /* Verify the tree and set the correct compare function */ - switch (id) { - case HFSPLUS_EXT_CNID: - if (tree->max_key_len != HFSPLUS_EXT_KEYLEN - sizeof(u16)) { - printk(KERN_ERR "hfs: invalid extent max_key_len %d\n", - tree->max_key_len); - goto fail_page; - } - if (tree->attributes & HFS_TREE_VARIDXKEYS) { - printk(KERN_ERR "hfs: invalid extent btree flag\n"); - goto fail_page; - } - + /* Set the correct compare function */ + if (id == HFSPLUS_EXT_CNID) { tree->keycmp = hfsplus_ext_cmp_key; - break; - case HFSPLUS_CAT_CNID: - if (tree->max_key_len != HFSPLUS_CAT_KEYLEN - sizeof(u16)) { - printk(KERN_ERR "hfs: invalid catalog max_key_len %d\n", - tree->max_key_len); - goto fail_page; - } - if (!(tree->attributes & HFS_TREE_VARIDXKEYS)) { - printk(KERN_ERR "hfs: invalid catalog btree flag\n"); - goto fail_page; - } - - if (test_bit(HFSPLUS_SB_HFSX, &HFSPLUS_SB(sb)->flags) && + } else if (id == HFSPLUS_CAT_CNID) { + if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) && (head->key_type == HFSPLUS_KEY_BINARY)) tree->keycmp = hfsplus_cat_bin_cmp_key; else { tree->keycmp = hfsplus_cat_case_cmp_key; - set_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags); + HFSPLUS_SB(sb).flags |= HFSPLUS_SB_CASEFOLD; } - break; - default: + } else { printk(KERN_ERR "hfs: unknown B*Tree requested\n"); goto fail_page; } - if (!(tree->attributes & HFS_TREE_BIGKEYS)) { - printk(KERN_ERR "hfs: invalid btree flag\n"); - goto fail_page; - } - size = tree->node_size; if (!is_power_of_2(size)) goto fail_page; if (!tree->node_count) goto fail_page; - tree->node_size_shift = ffs(size) - 1; tree->pages_per_bnode = (tree->node_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; @@ -122,11 +87,10 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) return tree; fail_page: - page_cache_release(page); - free_inode: tree->inode->i_mapping->a_ops = &hfsplus_aops; - iput(tree->inode); + page_cache_release(page); free_tree: + iput(tree->inode); kfree(tree); return NULL; } @@ -228,18 +192,17 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) while (!tree->free_nodes) { struct inode *inode = tree->inode; - struct hfsplus_inode_info *hip = HFSPLUS_I(inode); u32 count; int res; res = hfsplus_file_extend(inode); if (res) return ERR_PTR(res); - hip->phys_size = inode->i_size = - (loff_t)hip->alloc_blocks << - HFSPLUS_SB(tree->sb)->alloc_blksz_shift; - hip->fs_blocks = - hip->alloc_blocks << HFSPLUS_SB(tree->sb)->fs_shift; + HFSPLUS_I(inode).phys_size = inode->i_size = + (loff_t)HFSPLUS_I(inode).alloc_blocks << + HFSPLUS_SB(tree->sb).alloc_blksz_shift; + HFSPLUS_I(inode).fs_blocks = HFSPLUS_I(inode).alloc_blocks << + HFSPLUS_SB(tree->sb).fs_shift; inode_set_bytes(inode, inode->i_size); count = inode->i_size >> tree->node_size_shift; tree->free_nodes = count - tree->node_count; diff --git a/trunk/fs/hfsplus/catalog.c b/trunk/fs/hfsplus/catalog.c index 8af45fc5b051..f6874acb2cf2 100644 --- a/trunk/fs/hfsplus/catalog.c +++ b/trunk/fs/hfsplus/catalog.c @@ -67,7 +67,7 @@ static void hfsplus_cat_build_key_uni(hfsplus_btree_key *key, u32 parent, key->key_len = cpu_to_be16(6 + ustrlen); } -void hfsplus_cat_set_perms(struct inode *inode, struct hfsplus_perm *perms) +static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms) { if (inode->i_flags & S_IMMUTABLE) perms->rootflags |= HFSPLUS_FLG_IMMUTABLE; @@ -77,24 +77,15 @@ void hfsplus_cat_set_perms(struct inode *inode, struct hfsplus_perm *perms) perms->rootflags |= HFSPLUS_FLG_APPEND; else perms->rootflags &= ~HFSPLUS_FLG_APPEND; - - perms->userflags = HFSPLUS_I(inode)->userflags; + HFSPLUS_I(inode).rootflags = perms->rootflags; + HFSPLUS_I(inode).userflags = perms->userflags; perms->mode = cpu_to_be16(inode->i_mode); perms->owner = cpu_to_be32(inode->i_uid); perms->group = cpu_to_be32(inode->i_gid); - - if (S_ISREG(inode->i_mode)) - perms->dev = cpu_to_be32(inode->i_nlink); - else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) - perms->dev = cpu_to_be32(inode->i_rdev); - else - perms->dev = 0; } static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct inode *inode) { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); - if (S_ISDIR(inode->i_mode)) { struct hfsplus_cat_folder *folder; @@ -102,13 +93,13 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i memset(folder, 0, sizeof(*folder)); folder->type = cpu_to_be16(HFSPLUS_FOLDER); folder->id = cpu_to_be32(inode->i_ino); - HFSPLUS_I(inode)->create_date = + HFSPLUS_I(inode).create_date = folder->create_date = folder->content_mod_date = folder->attribute_mod_date = folder->access_date = hfsp_now2mt(); - hfsplus_cat_set_perms(inode, &folder->permissions); - if (inode == sbi->hidden_dir) + hfsplus_set_perms(inode, &folder->permissions); + if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir) /* invisible and namelocked */ folder->user_info.frFlags = cpu_to_be16(0x5000); return sizeof(*folder); @@ -120,19 +111,19 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i file->type = cpu_to_be16(HFSPLUS_FILE); file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS); file->id = cpu_to_be32(cnid); - HFSPLUS_I(inode)->create_date = + HFSPLUS_I(inode).create_date = file->create_date = file->content_mod_date = file->attribute_mod_date = file->access_date = hfsp_now2mt(); if (cnid == inode->i_ino) { - hfsplus_cat_set_perms(inode, &file->permissions); + hfsplus_set_perms(inode, &file->permissions); if (S_ISLNK(inode->i_mode)) { file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE); file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR); } else { - file->user_info.fdType = cpu_to_be32(sbi->type); - file->user_info.fdCreator = cpu_to_be32(sbi->creator); + file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type); + file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator); } if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); @@ -140,8 +131,8 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE); file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR); file->user_info.fdFlags = cpu_to_be16(0x100); - file->create_date = HFSPLUS_I(sbi->hidden_dir)->create_date; - file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode)->linkid); + file->create_date = HFSPLUS_I(HFSPLUS_SB(inode->i_sb).hidden_dir).create_date; + file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev); } return sizeof(*file); } @@ -189,14 +180,15 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid, int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str, struct inode *inode) { - struct super_block *sb = dir->i_sb; struct hfs_find_data fd; + struct super_block *sb; hfsplus_cat_entry entry; int entry_size; int err; dprint(DBG_CAT_MOD, "create_cat: %s,%u(%d)\n", str->name, cnid, inode->i_nlink); - hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); + sb = dir->i_sb; + hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL); entry_size = hfsplus_fill_cat_thread(sb, &entry, S_ISDIR(inode->i_mode) ? @@ -242,7 +234,7 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str, struct ino int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) { - struct super_block *sb = dir->i_sb; + struct super_block *sb; struct hfs_find_data fd; struct hfsplus_fork_raw fork; struct list_head *pos; @@ -250,7 +242,8 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) u16 type; dprint(DBG_CAT_MOD, "delete_cat: %s,%u\n", str ? str->name : NULL, cnid); - hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); + sb = dir->i_sb; + hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); if (!str) { int len; @@ -286,7 +279,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str) hfsplus_free_fork(sb, cnid, &fork, HFSPLUS_TYPE_RSRC); } - list_for_each(pos, &HFSPLUS_I(dir)->open_dir_list) { + list_for_each(pos, &HFSPLUS_I(dir).open_dir_list) { struct hfsplus_readdir_data *rd = list_entry(pos, struct hfsplus_readdir_data, list); if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0) @@ -319,7 +312,7 @@ int hfsplus_rename_cat(u32 cnid, struct inode *src_dir, struct qstr *src_name, struct inode *dst_dir, struct qstr *dst_name) { - struct super_block *sb = src_dir->i_sb; + struct super_block *sb; struct hfs_find_data src_fd, dst_fd; hfsplus_cat_entry entry; int entry_size, type; @@ -327,7 +320,8 @@ int hfsplus_rename_cat(u32 cnid, dprint(DBG_CAT_MOD, "rename_cat: %u - %lu,%s - %lu,%s\n", cnid, src_dir->i_ino, src_name->name, dst_dir->i_ino, dst_name->name); - hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &src_fd); + sb = src_dir->i_sb; + hfs_find_init(HFSPLUS_SB(sb).cat_tree, &src_fd); dst_fd = src_fd; /* find the old dir entry and read the data */ diff --git a/trunk/fs/hfsplus/dir.c b/trunk/fs/hfsplus/dir.c index d236d85ec9d7..764fd1bdca88 100644 --- a/trunk/fs/hfsplus/dir.c +++ b/trunk/fs/hfsplus/dir.c @@ -39,7 +39,7 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry, dentry->d_op = &hfsplus_dentry_operations; dentry->d_fsdata = NULL; - hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); + hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name); again: err = hfs_brec_read(&fd, &entry, sizeof(entry)); @@ -68,9 +68,9 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry, cnid = be32_to_cpu(entry.file.id); if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) && entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) && - (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb)->hidden_dir)->create_date || - entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode)->create_date) && - HFSPLUS_SB(sb)->hidden_dir) { + (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb).hidden_dir).create_date || + entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode).create_date) && + HFSPLUS_SB(sb).hidden_dir) { struct qstr str; char name[32]; @@ -86,8 +86,7 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry, linkid = be32_to_cpu(entry.file.permissions.dev); str.len = sprintf(name, "iNode%d", linkid); str.name = name; - hfsplus_cat_build_key(sb, fd.search_key, - HFSPLUS_SB(sb)->hidden_dir->i_ino, &str); + hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str); goto again; } } else if (!dentry->d_fsdata) @@ -102,7 +101,7 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry, if (IS_ERR(inode)) return ERR_CAST(inode); if (S_ISREG(inode->i_mode)) - HFSPLUS_I(inode)->linkid = linkid; + HFSPLUS_I(inode).dev = linkid; out: d_add(dentry, inode); return NULL; @@ -125,7 +124,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) if (filp->f_pos >= inode->i_size) return 0; - hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); + hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); hfsplus_cat_build_key(sb, fd.search_key, inode->i_ino, NULL); err = hfs_brec_find(&fd); if (err) @@ -181,9 +180,8 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) err = -EIO; goto out; } - if (HFSPLUS_SB(sb)->hidden_dir && - HFSPLUS_SB(sb)->hidden_dir->i_ino == - be32_to_cpu(entry.folder.id)) + if (HFSPLUS_SB(sb).hidden_dir && + HFSPLUS_SB(sb).hidden_dir->i_ino == be32_to_cpu(entry.folder.id)) goto next; if (filldir(dirent, strbuf, len, filp->f_pos, be32_to_cpu(entry.folder.id), DT_DIR)) @@ -219,7 +217,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir) } filp->private_data = rd; rd->file = filp; - list_add(&rd->list, &HFSPLUS_I(inode)->open_dir_list); + list_add(&rd->list, &HFSPLUS_I(inode).open_dir_list); } memcpy(&rd->key, fd.key, sizeof(struct hfsplus_cat_key)); out: @@ -231,18 +229,38 @@ static int hfsplus_dir_release(struct inode *inode, struct file *file) { struct hfsplus_readdir_data *rd = file->private_data; if (rd) { - mutex_lock(&inode->i_mutex); list_del(&rd->list); - mutex_unlock(&inode->i_mutex); kfree(rd); } return 0; } +static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd) +{ + struct inode *inode; + int res; + + inode = hfsplus_new_inode(dir->i_sb, mode); + if (!inode) + return -ENOSPC; + + res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); + if (res) { + inode->i_nlink = 0; + hfsplus_delete_inode(inode); + iput(inode); + return res; + } + hfsplus_instantiate(dentry, inode, inode->i_ino); + mark_inode_dirty(inode); + return 0; +} + static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, struct dentry *dst_dentry) { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(dst_dir->i_sb); + struct super_block *sb = dst_dir->i_sb; struct inode *inode = src_dentry->d_inode; struct inode *src_dir = src_dentry->d_parent->d_inode; struct qstr str; @@ -252,10 +270,7 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, if (HFSPLUS_IS_RSRC(inode)) return -EPERM; - if (!S_ISREG(inode->i_mode)) - return -EPERM; - mutex_lock(&sbi->vh_mutex); if (inode->i_ino == (u32)(unsigned long)src_dentry->d_fsdata) { for (;;) { get_random_bytes(&id, sizeof(cnid)); @@ -264,41 +279,40 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, str.len = sprintf(name, "iNode%d", id); res = hfsplus_rename_cat(inode->i_ino, src_dir, &src_dentry->d_name, - sbi->hidden_dir, &str); + HFSPLUS_SB(sb).hidden_dir, &str); if (!res) break; if (res != -EEXIST) - goto out; + return res; } - HFSPLUS_I(inode)->linkid = id; - cnid = sbi->next_cnid++; + HFSPLUS_I(inode).dev = id; + cnid = HFSPLUS_SB(sb).next_cnid++; src_dentry->d_fsdata = (void *)(unsigned long)cnid; res = hfsplus_create_cat(cnid, src_dir, &src_dentry->d_name, inode); if (res) /* panic? */ - goto out; - sbi->file_count++; + return res; + HFSPLUS_SB(sb).file_count++; } - cnid = sbi->next_cnid++; + cnid = HFSPLUS_SB(sb).next_cnid++; res = hfsplus_create_cat(cnid, dst_dir, &dst_dentry->d_name, inode); if (res) - goto out; + return res; inc_nlink(inode); hfsplus_instantiate(dst_dentry, inode, cnid); atomic_inc(&inode->i_count); inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); - sbi->file_count++; - dst_dir->i_sb->s_dirt = 1; -out: - mutex_unlock(&sbi->vh_mutex); - return res; + HFSPLUS_SB(sb).file_count++; + sb->s_dirt = 1; + + return 0; } static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); + struct super_block *sb = dir->i_sb; struct inode *inode = dentry->d_inode; struct qstr str; char name[32]; @@ -308,22 +322,21 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) if (HFSPLUS_IS_RSRC(inode)) return -EPERM; - mutex_lock(&sbi->vh_mutex); cnid = (u32)(unsigned long)dentry->d_fsdata; if (inode->i_ino == cnid && - atomic_read(&HFSPLUS_I(inode)->opencnt)) { + atomic_read(&HFSPLUS_I(inode).opencnt)) { str.name = name; str.len = sprintf(name, "temp%lu", inode->i_ino); res = hfsplus_rename_cat(inode->i_ino, dir, &dentry->d_name, - sbi->hidden_dir, &str); + HFSPLUS_SB(sb).hidden_dir, &str); if (!res) inode->i_flags |= S_DEAD; - goto out; + return res; } res = hfsplus_delete_cat(cnid, dir, &dentry->d_name); if (res) - goto out; + return res; if (inode->i_nlink > 0) drop_nlink(inode); @@ -331,10 +344,10 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) clear_nlink(inode); if (!inode->i_nlink) { if (inode->i_ino != cnid) { - sbi->file_count--; - if (!atomic_read(&HFSPLUS_I(inode)->opencnt)) { + HFSPLUS_SB(sb).file_count--; + if (!atomic_read(&HFSPLUS_I(inode).opencnt)) { res = hfsplus_delete_cat(inode->i_ino, - sbi->hidden_dir, + HFSPLUS_SB(sb).hidden_dir, NULL); if (!res) hfsplus_delete_inode(inode); @@ -343,108 +356,107 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry) } else hfsplus_delete_inode(inode); } else - sbi->file_count--; + HFSPLUS_SB(sb).file_count--; inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); -out: - mutex_unlock(&sbi->vh_mutex); + return res; } +static int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode) +{ + struct inode *inode; + int res; + + inode = hfsplus_new_inode(dir->i_sb, S_IFDIR | mode); + if (!inode) + return -ENOSPC; + + res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); + if (res) { + inode->i_nlink = 0; + hfsplus_delete_inode(inode); + iput(inode); + return res; + } + hfsplus_instantiate(dentry, inode, inode->i_ino); + mark_inode_dirty(inode); + return 0; +} + static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry) { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); - struct inode *inode = dentry->d_inode; + struct inode *inode; int res; + inode = dentry->d_inode; if (inode->i_size != 2) return -ENOTEMPTY; - - mutex_lock(&sbi->vh_mutex); res = hfsplus_delete_cat(inode->i_ino, dir, &dentry->d_name); if (res) - goto out; + return res; clear_nlink(inode); inode->i_ctime = CURRENT_TIME_SEC; hfsplus_delete_inode(inode); mark_inode_dirty(inode); -out: - mutex_unlock(&sbi->vh_mutex); - return res; + return 0; } static int hfsplus_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); + struct super_block *sb; struct inode *inode; - int res = -ENOSPC; + int res; - mutex_lock(&sbi->vh_mutex); - inode = hfsplus_new_inode(dir->i_sb, S_IFLNK | S_IRWXUGO); + sb = dir->i_sb; + inode = hfsplus_new_inode(sb, S_IFLNK | S_IRWXUGO); if (!inode) - goto out; + return -ENOSPC; res = page_symlink(inode, symname, strlen(symname) + 1); - if (res) - goto out_err; + if (res) { + inode->i_nlink = 0; + hfsplus_delete_inode(inode); + iput(inode); + return res; + } + mark_inode_dirty(inode); res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); - if (res) - goto out_err; - hfsplus_instantiate(dentry, inode, inode->i_ino); - mark_inode_dirty(inode); - goto out; + if (!res) { + hfsplus_instantiate(dentry, inode, inode->i_ino); + mark_inode_dirty(inode); + } -out_err: - inode->i_nlink = 0; - hfsplus_delete_inode(inode); - iput(inode); -out: - mutex_unlock(&sbi->vh_mutex); return res; } static int hfsplus_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb); + struct super_block *sb; struct inode *inode; - int res = -ENOSPC; + int res; - mutex_lock(&sbi->vh_mutex); - inode = hfsplus_new_inode(dir->i_sb, mode); + sb = dir->i_sb; + inode = hfsplus_new_inode(sb, mode); if (!inode) - goto out; - - if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) - init_special_inode(inode, mode, rdev); + return -ENOSPC; res = hfsplus_create_cat(inode->i_ino, dir, &dentry->d_name, inode); if (res) { inode->i_nlink = 0; hfsplus_delete_inode(inode); iput(inode); - goto out; + return res; } - + init_special_inode(inode, mode, rdev); hfsplus_instantiate(dentry, inode, inode->i_ino); mark_inode_dirty(inode); -out: - mutex_unlock(&sbi->vh_mutex); - return res; -} -static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode, - struct nameidata *nd) -{ - return hfsplus_mknod(dir, dentry, mode, 0); -} - -static int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode) -{ - return hfsplus_mknod(dir, dentry, mode | S_IFDIR, 0); + return 0; } static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, @@ -454,10 +466,7 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, /* Unlink destination if it already exists */ if (new_dentry->d_inode) { - if (S_ISDIR(new_dentry->d_inode->i_mode)) - res = hfsplus_rmdir(new_dir, new_dentry); - else - res = hfsplus_unlink(new_dir, new_dentry); + res = hfsplus_unlink(new_dir, new_dentry); if (res) return res; } diff --git a/trunk/fs/hfsplus/extents.c b/trunk/fs/hfsplus/extents.c index 0c9cb1820a52..0022eec63cda 100644 --- a/trunk/fs/hfsplus/extents.c +++ b/trunk/fs/hfsplus/extents.c @@ -85,49 +85,35 @@ static u32 hfsplus_ext_lastblock(struct hfsplus_extent *ext) static void __hfsplus_ext_write_extent(struct inode *inode, struct hfs_find_data *fd) { - struct hfsplus_inode_info *hip = HFSPLUS_I(inode); int res; - WARN_ON(!mutex_is_locked(&hip->extents_lock)); - - hfsplus_ext_build_key(fd->search_key, inode->i_ino, hip->cached_start, - HFSPLUS_IS_RSRC(inode) ? - HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA); - + hfsplus_ext_build_key(fd->search_key, inode->i_ino, HFSPLUS_I(inode).cached_start, + HFSPLUS_IS_RSRC(inode) ? HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA); res = hfs_brec_find(fd); - if (hip->flags & HFSPLUS_FLG_EXT_NEW) { + if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_NEW) { if (res != -ENOENT) return; - hfs_brec_insert(fd, hip->cached_extents, - sizeof(hfsplus_extent_rec)); - hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); + hfs_brec_insert(fd, HFSPLUS_I(inode).cached_extents, sizeof(hfsplus_extent_rec)); + HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); } else { if (res) return; - hfs_bnode_write(fd->bnode, hip->cached_extents, - fd->entryoffset, fd->entrylength); - hip->flags &= ~HFSPLUS_FLG_EXT_DIRTY; + hfs_bnode_write(fd->bnode, HFSPLUS_I(inode).cached_extents, fd->entryoffset, fd->entrylength); + HFSPLUS_I(inode).flags &= ~HFSPLUS_FLG_EXT_DIRTY; } } -static void hfsplus_ext_write_extent_locked(struct inode *inode) +void hfsplus_ext_write_extent(struct inode *inode) { - if (HFSPLUS_I(inode)->flags & HFSPLUS_FLG_EXT_DIRTY) { + if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_DIRTY) { struct hfs_find_data fd; - hfs_find_init(HFSPLUS_SB(inode->i_sb)->ext_tree, &fd); + hfs_find_init(HFSPLUS_SB(inode->i_sb).ext_tree, &fd); __hfsplus_ext_write_extent(inode, &fd); hfs_find_exit(&fd); } } -void hfsplus_ext_write_extent(struct inode *inode) -{ - mutex_lock(&HFSPLUS_I(inode)->extents_lock); - hfsplus_ext_write_extent_locked(inode); - mutex_unlock(&HFSPLUS_I(inode)->extents_lock); -} - static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd, struct hfsplus_extent *extent, u32 cnid, u32 block, u8 type) @@ -150,39 +136,33 @@ static inline int __hfsplus_ext_read_extent(struct hfs_find_data *fd, static inline int __hfsplus_ext_cache_extent(struct hfs_find_data *fd, struct inode *inode, u32 block) { - struct hfsplus_inode_info *hip = HFSPLUS_I(inode); int res; - WARN_ON(!mutex_is_locked(&hip->extents_lock)); - - if (hip->flags & HFSPLUS_FLG_EXT_DIRTY) + if (HFSPLUS_I(inode).flags & HFSPLUS_FLG_EXT_DIRTY) __hfsplus_ext_write_extent(inode, fd); - res = __hfsplus_ext_read_extent(fd, hip->cached_extents, inode->i_ino, - block, HFSPLUS_IS_RSRC(inode) ? - HFSPLUS_TYPE_RSRC : - HFSPLUS_TYPE_DATA); + res = __hfsplus_ext_read_extent(fd, HFSPLUS_I(inode).cached_extents, inode->i_ino, + block, HFSPLUS_IS_RSRC(inode) ? HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA); if (!res) { - hip->cached_start = be32_to_cpu(fd->key->ext.start_block); - hip->cached_blocks = hfsplus_ext_block_count(hip->cached_extents); + HFSPLUS_I(inode).cached_start = be32_to_cpu(fd->key->ext.start_block); + HFSPLUS_I(inode).cached_blocks = hfsplus_ext_block_count(HFSPLUS_I(inode).cached_extents); } else { - hip->cached_start = hip->cached_blocks = 0; - hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); + HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).cached_blocks = 0; + HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); } return res; } static int hfsplus_ext_read_extent(struct inode *inode, u32 block) { - struct hfsplus_inode_info *hip = HFSPLUS_I(inode); struct hfs_find_data fd; int res; - if (block >= hip->cached_start && - block < hip->cached_start + hip->cached_blocks) + if (block >= HFSPLUS_I(inode).cached_start && + block < HFSPLUS_I(inode).cached_start + HFSPLUS_I(inode).cached_blocks) return 0; - hfs_find_init(HFSPLUS_SB(inode->i_sb)->ext_tree, &fd); + hfs_find_init(HFSPLUS_SB(inode->i_sb).ext_tree, &fd); res = __hfsplus_ext_cache_extent(&fd, inode, block); hfs_find_exit(&fd); return res; @@ -192,21 +172,21 @@ static int hfsplus_ext_read_extent(struct inode *inode, u32 block) int hfsplus_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) { - struct super_block *sb = inode->i_sb; - struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); - struct hfsplus_inode_info *hip = HFSPLUS_I(inode); + struct super_block *sb; int res = -EIO; u32 ablock, dblock, mask; int shift; + sb = inode->i_sb; + /* Convert inode block to disk allocation block */ - shift = sbi->alloc_blksz_shift - sb->s_blocksize_bits; - ablock = iblock >> sbi->fs_shift; + shift = HFSPLUS_SB(sb).alloc_blksz_shift - sb->s_blocksize_bits; + ablock = iblock >> HFSPLUS_SB(sb).fs_shift; - if (iblock >= hip->fs_blocks) { - if (iblock > hip->fs_blocks || !create) + if (iblock >= HFSPLUS_I(inode).fs_blocks) { + if (iblock > HFSPLUS_I(inode).fs_blocks || !create) return -EIO; - if (ablock >= hip->alloc_blocks) { + if (ablock >= HFSPLUS_I(inode).alloc_blocks) { res = hfsplus_file_extend(inode); if (res) return res; @@ -214,33 +194,33 @@ int hfsplus_get_block(struct inode *inode, sector_t iblock, } else create = 0; - if (ablock < hip->first_blocks) { - dblock = hfsplus_ext_find_block(hip->first_extents, ablock); + if (ablock < HFSPLUS_I(inode).first_blocks) { + dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).first_extents, ablock); goto done; } if (inode->i_ino == HFSPLUS_EXT_CNID) return -EIO; - mutex_lock(&hip->extents_lock); + mutex_lock(&HFSPLUS_I(inode).extents_lock); res = hfsplus_ext_read_extent(inode, ablock); if (!res) { - dblock = hfsplus_ext_find_block(hip->cached_extents, - ablock - hip->cached_start); + dblock = hfsplus_ext_find_block(HFSPLUS_I(inode).cached_extents, ablock - + HFSPLUS_I(inode).cached_start); } else { - mutex_unlock(&hip->extents_lock); + mutex_unlock(&HFSPLUS_I(inode).extents_lock); return -EIO; } - mutex_unlock(&hip->extents_lock); + mutex_unlock(&HFSPLUS_I(inode).extents_lock); done: dprint(DBG_EXTENT, "get_block(%lu): %llu - %u\n", inode->i_ino, (long long)iblock, dblock); - mask = (1 << sbi->fs_shift) - 1; - map_bh(bh_result, sb, (dblock << sbi->fs_shift) + sbi->blockoffset + (iblock & mask)); + mask = (1 << HFSPLUS_SB(sb).fs_shift) - 1; + map_bh(bh_result, sb, (dblock << HFSPLUS_SB(sb).fs_shift) + HFSPLUS_SB(sb).blockoffset + (iblock & mask)); if (create) { set_buffer_new(bh_result); - hip->phys_size += sb->s_blocksize; - hip->fs_blocks++; + HFSPLUS_I(inode).phys_size += sb->s_blocksize; + HFSPLUS_I(inode).fs_blocks++; inode_add_bytes(inode, sb->s_blocksize); mark_inode_dirty(inode); } @@ -347,7 +327,7 @@ int hfsplus_free_fork(struct super_block *sb, u32 cnid, struct hfsplus_fork_raw if (total_blocks == blocks) return 0; - hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd); + hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd); do { res = __hfsplus_ext_read_extent(&fd, ext_entry, cnid, total_blocks, type); @@ -368,33 +348,29 @@ int hfsplus_free_fork(struct super_block *sb, u32 cnid, struct hfsplus_fork_raw int hfsplus_file_extend(struct inode *inode) { struct super_block *sb = inode->i_sb; - struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); - struct hfsplus_inode_info *hip = HFSPLUS_I(inode); u32 start, len, goal; int res; - if (sbi->alloc_file->i_size * 8 < - sbi->total_blocks - sbi->free_blocks + 8) { + if (HFSPLUS_SB(sb).alloc_file->i_size * 8 < HFSPLUS_SB(sb).total_blocks - HFSPLUS_SB(sb).free_blocks + 8) { // extend alloc file - printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n", - sbi->alloc_file->i_size * 8, - sbi->total_blocks, sbi->free_blocks); + printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8, + HFSPLUS_SB(sb).total_blocks, HFSPLUS_SB(sb).free_blocks); return -ENOSPC; } - mutex_lock(&hip->extents_lock); - if (hip->alloc_blocks == hip->first_blocks) - goal = hfsplus_ext_lastblock(hip->first_extents); + mutex_lock(&HFSPLUS_I(inode).extents_lock); + if (HFSPLUS_I(inode).alloc_blocks == HFSPLUS_I(inode).first_blocks) + goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).first_extents); else { - res = hfsplus_ext_read_extent(inode, hip->alloc_blocks); + res = hfsplus_ext_read_extent(inode, HFSPLUS_I(inode).alloc_blocks); if (res) goto out; - goal = hfsplus_ext_lastblock(hip->cached_extents); + goal = hfsplus_ext_lastblock(HFSPLUS_I(inode).cached_extents); } - len = hip->clump_blocks; - start = hfsplus_block_allocate(sb, sbi->total_blocks, goal, &len); - if (start >= sbi->total_blocks) { + len = HFSPLUS_I(inode).clump_blocks; + start = hfsplus_block_allocate(sb, HFSPLUS_SB(sb).total_blocks, goal, &len); + if (start >= HFSPLUS_SB(sb).total_blocks) { start = hfsplus_block_allocate(sb, goal, 0, &len); if (start >= goal) { res = -ENOSPC; @@ -403,56 +379,56 @@ int hfsplus_file_extend(struct inode *inode) } dprint(DBG_EXTENT, "extend %lu: %u,%u\n", inode->i_ino, start, len); - - if (hip->alloc_blocks <= hip->first_blocks) { - if (!hip->first_blocks) { + if (HFSPLUS_I(inode).alloc_blocks <= HFSPLUS_I(inode).first_blocks) { + if (!HFSPLUS_I(inode).first_blocks) { dprint(DBG_EXTENT, "first extents\n"); /* no extents yet */ - hip->first_extents[0].start_block = cpu_to_be32(start); - hip->first_extents[0].block_count = cpu_to_be32(len); + HFSPLUS_I(inode).first_extents[0].start_block = cpu_to_be32(start); + HFSPLUS_I(inode).first_extents[0].block_count = cpu_to_be32(len); res = 0; } else { /* try to append to extents in inode */ - res = hfsplus_add_extent(hip->first_extents, - hip->alloc_blocks, + res = hfsplus_add_extent(HFSPLUS_I(inode).first_extents, + HFSPLUS_I(inode).alloc_blocks, start, len); if (res == -ENOSPC) goto insert_extent; } if (!res) { - hfsplus_dump_extent(hip->first_extents); - hip->first_blocks += len; + hfsplus_dump_extent(HFSPLUS_I(inode).first_extents); + HFSPLUS_I(inode).first_blocks += len; } } else { - res = hfsplus_add_extent(hip->cached_extents, - hip->alloc_blocks - hip->cached_start, + res = hfsplus_add_extent(HFSPLUS_I(inode).cached_extents, + HFSPLUS_I(inode).alloc_blocks - + HFSPLUS_I(inode).cached_start, start, len); if (!res) { - hfsplus_dump_extent(hip->cached_extents); - hip->flags |= HFSPLUS_FLG_EXT_DIRTY; - hip->cached_blocks += len; + hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents); + HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY; + HFSPLUS_I(inode).cached_blocks += len; } else if (res == -ENOSPC) goto insert_extent; } out: - mutex_unlock(&hip->extents_lock); + mutex_unlock(&HFSPLUS_I(inode).extents_lock); if (!res) { - hip->alloc_blocks += len; + HFSPLUS_I(inode).alloc_blocks += len; mark_inode_dirty(inode); } return res; insert_extent: dprint(DBG_EXTENT, "insert new extent\n"); - hfsplus_ext_write_extent_locked(inode); + hfsplus_ext_write_extent(inode); - memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec)); - hip->cached_extents[0].start_block = cpu_to_be32(start); - hip->cached_extents[0].block_count = cpu_to_be32(len); - hfsplus_dump_extent(hip->cached_extents); - hip->flags |= HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW; - hip->cached_start = hip->alloc_blocks; - hip->cached_blocks = len; + memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec)); + HFSPLUS_I(inode).cached_extents[0].start_block = cpu_to_be32(start); + HFSPLUS_I(inode).cached_extents[0].block_count = cpu_to_be32(len); + hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents); + HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW; + HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).alloc_blocks; + HFSPLUS_I(inode).cached_blocks = len; res = 0; goto out; @@ -461,15 +437,13 @@ int hfsplus_file_extend(struct inode *inode) void hfsplus_file_truncate(struct inode *inode) { struct super_block *sb = inode->i_sb; - struct hfsplus_inode_info *hip = HFSPLUS_I(inode); struct hfs_find_data fd; u32 alloc_cnt, blk_cnt, start; int res; - dprint(DBG_INODE, "truncate: %lu, %Lu -> %Lu\n", - inode->i_ino, (long long)hip->phys_size, inode->i_size); - - if (inode->i_size > hip->phys_size) { + dprint(DBG_INODE, "truncate: %lu, %Lu -> %Lu\n", inode->i_ino, + (long long)HFSPLUS_I(inode).phys_size, inode->i_size); + if (inode->i_size > HFSPLUS_I(inode).phys_size) { struct address_space *mapping = inode->i_mapping; struct page *page; void *fsdata; @@ -486,48 +460,47 @@ void hfsplus_file_truncate(struct inode *inode) return; mark_inode_dirty(inode); return; - } else if (inode->i_size == hip->phys_size) + } else if (inode->i_size == HFSPLUS_I(inode).phys_size) return; - blk_cnt = (inode->i_size + HFSPLUS_SB(sb)->alloc_blksz - 1) >> - HFSPLUS_SB(sb)->alloc_blksz_shift; - alloc_cnt = hip->alloc_blocks; + blk_cnt = (inode->i_size + HFSPLUS_SB(sb).alloc_blksz - 1) >> HFSPLUS_SB(sb).alloc_blksz_shift; + alloc_cnt = HFSPLUS_I(inode).alloc_blocks; if (blk_cnt == alloc_cnt) goto out; - mutex_lock(&hip->extents_lock); - hfs_find_init(HFSPLUS_SB(sb)->ext_tree, &fd); + mutex_lock(&HFSPLUS_I(inode).extents_lock); + hfs_find_init(HFSPLUS_SB(sb).ext_tree, &fd); while (1) { - if (alloc_cnt == hip->first_blocks) { - hfsplus_free_extents(sb, hip->first_extents, + if (alloc_cnt == HFSPLUS_I(inode).first_blocks) { + hfsplus_free_extents(sb, HFSPLUS_I(inode).first_extents, alloc_cnt, alloc_cnt - blk_cnt); - hfsplus_dump_extent(hip->first_extents); - hip->first_blocks = blk_cnt; + hfsplus_dump_extent(HFSPLUS_I(inode).first_extents); + HFSPLUS_I(inode).first_blocks = blk_cnt; break; } res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt); if (res) break; - start = hip->cached_start; - hfsplus_free_extents(sb, hip->cached_extents, + start = HFSPLUS_I(inode).cached_start; + hfsplus_free_extents(sb, HFSPLUS_I(inode).cached_extents, alloc_cnt - start, alloc_cnt - blk_cnt); - hfsplus_dump_extent(hip->cached_extents); + hfsplus_dump_extent(HFSPLUS_I(inode).cached_extents); if (blk_cnt > start) { - hip->flags |= HFSPLUS_FLG_EXT_DIRTY; + HFSPLUS_I(inode).flags |= HFSPLUS_FLG_EXT_DIRTY; break; } alloc_cnt = start; - hip->cached_start = hip->cached_blocks = 0; - hip->flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); + HFSPLUS_I(inode).cached_start = HFSPLUS_I(inode).cached_blocks = 0; + HFSPLUS_I(inode).flags &= ~(HFSPLUS_FLG_EXT_DIRTY | HFSPLUS_FLG_EXT_NEW); hfs_brec_remove(&fd); } hfs_find_exit(&fd); - mutex_unlock(&hip->extents_lock); + mutex_unlock(&HFSPLUS_I(inode).extents_lock); - hip->alloc_blocks = blk_cnt; + HFSPLUS_I(inode).alloc_blocks = blk_cnt; out: - hip->phys_size = inode->i_size; - hip->fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; - inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits); + HFSPLUS_I(inode).phys_size = inode->i_size; + HFSPLUS_I(inode).fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; + inode_set_bytes(inode, HFSPLUS_I(inode).fs_blocks << sb->s_blocksize_bits); mark_inode_dirty(inode); } diff --git a/trunk/fs/hfsplus/hfsplus_fs.h b/trunk/fs/hfsplus/hfsplus_fs.h index cb3653efb57a..dc856be3c2b0 100644 --- a/trunk/fs/hfsplus/hfsplus_fs.h +++ b/trunk/fs/hfsplus/hfsplus_fs.h @@ -62,7 +62,7 @@ struct hfs_btree { unsigned int depth; //unsigned int map1_size, map_size; - struct mutex tree_lock; + struct semaphore tree_lock; unsigned int pages_per_bnode; spinlock_t hash_lock; @@ -121,21 +121,16 @@ struct hfsplus_sb_info { u32 sect_count; int fs_shift; - /* immutable data from the volume header */ + /* Stuff in host order from Vol Header */ u32 alloc_blksz; int alloc_blksz_shift; u32 total_blocks; - u32 data_clump_blocks, rsrc_clump_blocks; - - /* mutable data from the volume header, protected by alloc_mutex */ u32 free_blocks; - struct mutex alloc_mutex; - - /* mutable data from the volume header, protected by vh_mutex */ + u32 next_alloc; u32 next_cnid; u32 file_count; u32 folder_count; - struct mutex vh_mutex; + u32 data_clump_blocks, rsrc_clump_blocks; /* Config options */ u32 creator; @@ -148,50 +143,40 @@ struct hfsplus_sb_info { int part, session; unsigned long flags; + + struct hlist_head rsrc_inodes; }; -#define HFSPLUS_SB_WRITEBACKUP 0 -#define HFSPLUS_SB_NODECOMPOSE 1 -#define HFSPLUS_SB_FORCE 2 -#define HFSPLUS_SB_HFSX 3 -#define HFSPLUS_SB_CASEFOLD 4 +#define HFSPLUS_SB_WRITEBACKUP 0x0001 +#define HFSPLUS_SB_NODECOMPOSE 0x0002 +#define HFSPLUS_SB_FORCE 0x0004 +#define HFSPLUS_SB_HFSX 0x0008 +#define HFSPLUS_SB_CASEFOLD 0x0010 struct hfsplus_inode_info { - atomic_t opencnt; - - /* - * Extent allocation information, protected by extents_lock. - */ - u32 first_blocks; - u32 clump_blocks; - u32 alloc_blocks; - u32 cached_start; - u32 cached_blocks; + struct mutex extents_lock; + u32 clump_blocks, alloc_blocks; + sector_t fs_blocks; + /* Allocation extents from catalog record or volume header */ hfsplus_extent_rec first_extents; + u32 first_blocks; hfsplus_extent_rec cached_extents; - unsigned long flags; - struct mutex extents_lock; + u32 cached_start, cached_blocks; + atomic_t opencnt; - /* - * Immutable data. - */ struct inode *rsrc_inode; - __be32 create_date; + unsigned long flags; - /* - * Protected by sbi->vh_mutex. - */ - u32 linkid; + __be32 create_date; + /* Device number in hfsplus_permissions in catalog */ + u32 dev; + /* BSD system and user file flags */ + u8 rootflags; + u8 userflags; - /* - * Protected by i_mutex. - */ - sector_t fs_blocks; - u8 userflags; /* BSD user file flags */ struct list_head open_dir_list; loff_t phys_size; - struct inode vfs_inode; }; @@ -199,8 +184,8 @@ struct hfsplus_inode_info { #define HFSPLUS_FLG_EXT_DIRTY 0x0002 #define HFSPLUS_FLG_EXT_NEW 0x0004 -#define HFSPLUS_IS_DATA(inode) (!(HFSPLUS_I(inode)->flags & HFSPLUS_FLG_RSRC)) -#define HFSPLUS_IS_RSRC(inode) (HFSPLUS_I(inode)->flags & HFSPLUS_FLG_RSRC) +#define HFSPLUS_IS_DATA(inode) (!(HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC)) +#define HFSPLUS_IS_RSRC(inode) (HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC) struct hfs_find_data { /* filled by caller */ @@ -326,7 +311,6 @@ int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *); int hfsplus_delete_cat(u32, struct inode *, struct qstr *); int hfsplus_rename_cat(u32, struct inode *, struct qstr *, struct inode *, struct qstr *); -void hfsplus_cat_set_perms(struct inode *inode, struct hfsplus_perm *perms); /* dir.c */ extern const struct inode_operations hfsplus_dir_inode_operations; @@ -388,15 +372,26 @@ int hfsplus_read_wrapper(struct super_block *); int hfs_part_find(struct super_block *, sector_t *, sector_t *); /* access macros */ +/* static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb) { return sb->s_fs_info; } - static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode) { return list_entry(inode, struct hfsplus_inode_info, vfs_inode); } +*/ +#define HFSPLUS_SB(super) (*(struct hfsplus_sb_info *)(super)->s_fs_info) +#define HFSPLUS_I(inode) (*list_entry(inode, struct hfsplus_inode_info, vfs_inode)) + +#if 1 +#define hfsplus_kmap(p) ({ struct page *__p = (p); kmap(__p); }) +#define hfsplus_kunmap(p) ({ struct page *__p = (p); kunmap(__p); __p; }) +#else +#define hfsplus_kmap(p) kmap(p) +#define hfsplus_kunmap(p) kunmap(p) +#endif #define sb_bread512(sb, sec, data) ({ \ struct buffer_head *__bh; \ @@ -424,4 +419,6 @@ static inline struct hfsplus_inode_info *HFSPLUS_I(struct inode *inode) #define hfsp_ut2mt(t) __hfsp_ut2mt((t).tv_sec) #define hfsp_now2mt() __hfsp_ut2mt(get_seconds()) +#define kdev_t_to_nr(x) (x) + #endif diff --git a/trunk/fs/hfsplus/hfsplus_raw.h b/trunk/fs/hfsplus/hfsplus_raw.h index 6892899fd6fb..fe99fe8db61a 100644 --- a/trunk/fs/hfsplus/hfsplus_raw.h +++ b/trunk/fs/hfsplus/hfsplus_raw.h @@ -200,7 +200,6 @@ struct hfsplus_cat_key { struct hfsplus_unistr name; } __packed; -#define HFSPLUS_CAT_KEYLEN (sizeof(struct hfsplus_cat_key)) /* Structs from hfs.h */ struct hfsp_point { @@ -324,7 +323,7 @@ struct hfsplus_ext_key { __be32 start_block; } __packed; -#define HFSPLUS_EXT_KEYLEN sizeof(struct hfsplus_ext_key) +#define HFSPLUS_EXT_KEYLEN 12 /* HFS+ generic BTree key */ typedef union { diff --git a/trunk/fs/hfsplus/inode.c b/trunk/fs/hfsplus/inode.c index 78449280dae0..c5a979d62c65 100644 --- a/trunk/fs/hfsplus/inode.c +++ b/trunk/fs/hfsplus/inode.c @@ -36,7 +36,7 @@ static int hfsplus_write_begin(struct file *file, struct address_space *mapping, *pagep = NULL; ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, hfsplus_get_block, - &HFSPLUS_I(mapping->host)->phys_size); + &HFSPLUS_I(mapping->host).phys_size); if (unlikely(ret)) { loff_t isize = mapping->host->i_size; if (pos + len > isize) @@ -62,13 +62,13 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask) switch (inode->i_ino) { case HFSPLUS_EXT_CNID: - tree = HFSPLUS_SB(sb)->ext_tree; + tree = HFSPLUS_SB(sb).ext_tree; break; case HFSPLUS_CAT_CNID: - tree = HFSPLUS_SB(sb)->cat_tree; + tree = HFSPLUS_SB(sb).cat_tree; break; case HFSPLUS_ATTR_CNID: - tree = HFSPLUS_SB(sb)->attr_tree; + tree = HFSPLUS_SB(sb).attr_tree; break; default: BUG(); @@ -172,13 +172,12 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent struct hfs_find_data fd; struct super_block *sb = dir->i_sb; struct inode *inode = NULL; - struct hfsplus_inode_info *hip; int err; if (HFSPLUS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc")) goto out; - inode = HFSPLUS_I(dir)->rsrc_inode; + inode = HFSPLUS_I(dir).rsrc_inode; if (inode) goto out; @@ -186,13 +185,12 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent if (!inode) return ERR_PTR(-ENOMEM); - hip = HFSPLUS_I(inode); inode->i_ino = dir->i_ino; - INIT_LIST_HEAD(&hip->open_dir_list); - mutex_init(&hip->extents_lock); - hip->flags = HFSPLUS_FLG_RSRC; + INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); + mutex_init(&HFSPLUS_I(inode).extents_lock); + HFSPLUS_I(inode).flags = HFSPLUS_FLG_RSRC; - hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd); + hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); err = hfsplus_find_cat(sb, dir->i_ino, &fd); if (!err) err = hfsplus_cat_read_inode(inode, &fd); @@ -201,18 +199,10 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent iput(inode); return ERR_PTR(err); } - hip->rsrc_inode = dir; - HFSPLUS_I(dir)->rsrc_inode = inode; + HFSPLUS_I(inode).rsrc_inode = dir; + HFSPLUS_I(dir).rsrc_inode = inode; igrab(dir); - - /* - * __mark_inode_dirty expects inodes to be hashed. Since we don't - * want resource fork inodes in the regular inode space, we make them - * appear hashed, but do not put on any lists. hlist_del() - * will work fine and require no locking. - */ - inode->i_hash.pprev = &inode->i_hash.next; - + hlist_add_head(&inode->i_hash, &HFSPLUS_SB(sb).rsrc_inodes); mark_inode_dirty(inode); out: d_add(dentry, inode); @@ -221,27 +211,30 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, int dir) { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); + struct super_block *sb = inode->i_sb; u16 mode; mode = be16_to_cpu(perms->mode); inode->i_uid = be32_to_cpu(perms->owner); if (!inode->i_uid && !mode) - inode->i_uid = sbi->uid; + inode->i_uid = HFSPLUS_SB(sb).uid; inode->i_gid = be32_to_cpu(perms->group); if (!inode->i_gid && !mode) - inode->i_gid = sbi->gid; + inode->i_gid = HFSPLUS_SB(sb).gid; if (dir) { - mode = mode ? (mode & S_IALLUGO) : (S_IRWXUGO & ~(sbi->umask)); + mode = mode ? (mode & S_IALLUGO) : + (S_IRWXUGO & ~(HFSPLUS_SB(sb).umask)); mode |= S_IFDIR; } else if (!mode) - mode = S_IFREG | ((S_IRUGO|S_IWUGO) & ~(sbi->umask)); + mode = S_IFREG | ((S_IRUGO|S_IWUGO) & + ~(HFSPLUS_SB(sb).umask)); inode->i_mode = mode; - HFSPLUS_I(inode)->userflags = perms->userflags; + HFSPLUS_I(inode).rootflags = perms->rootflags; + HFSPLUS_I(inode).userflags = perms->userflags; if (perms->rootflags & HFSPLUS_FLG_IMMUTABLE) inode->i_flags |= S_IMMUTABLE; else @@ -252,13 +245,30 @@ static void hfsplus_get_perms(struct inode *inode, struct hfsplus_perm *perms, i inode->i_flags &= ~S_APPEND; } +static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms) +{ + if (inode->i_flags & S_IMMUTABLE) + perms->rootflags |= HFSPLUS_FLG_IMMUTABLE; + else + perms->rootflags &= ~HFSPLUS_FLG_IMMUTABLE; + if (inode->i_flags & S_APPEND) + perms->rootflags |= HFSPLUS_FLG_APPEND; + else + perms->rootflags &= ~HFSPLUS_FLG_APPEND; + perms->userflags = HFSPLUS_I(inode).userflags; + perms->mode = cpu_to_be16(inode->i_mode); + perms->owner = cpu_to_be32(inode->i_uid); + perms->group = cpu_to_be32(inode->i_gid); + perms->dev = cpu_to_be32(HFSPLUS_I(inode).dev); +} + static int hfsplus_file_open(struct inode *inode, struct file *file) { if (HFSPLUS_IS_RSRC(inode)) - inode = HFSPLUS_I(inode)->rsrc_inode; + inode = HFSPLUS_I(inode).rsrc_inode; if (!(file->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) return -EOVERFLOW; - atomic_inc(&HFSPLUS_I(inode)->opencnt); + atomic_inc(&HFSPLUS_I(inode).opencnt); return 0; } @@ -267,13 +277,12 @@ static int hfsplus_file_release(struct inode *inode, struct file *file) struct super_block *sb = inode->i_sb; if (HFSPLUS_IS_RSRC(inode)) - inode = HFSPLUS_I(inode)->rsrc_inode; - if (atomic_dec_and_test(&HFSPLUS_I(inode)->opencnt)) { + inode = HFSPLUS_I(inode).rsrc_inode; + if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) { mutex_lock(&inode->i_mutex); hfsplus_file_truncate(inode); if (inode->i_flags & S_DEAD) { - hfsplus_delete_cat(inode->i_ino, - HFSPLUS_SB(sb)->hidden_dir, NULL); + hfsplus_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL); hfsplus_delete_inode(inode); } mutex_unlock(&inode->i_mutex); @@ -352,52 +361,47 @@ static const struct file_operations hfsplus_file_operations = { struct inode *hfsplus_new_inode(struct super_block *sb, int mode) { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); struct inode *inode = new_inode(sb); - struct hfsplus_inode_info *hip; - if (!inode) return NULL; - inode->i_ino = sbi->next_cnid++; + inode->i_ino = HFSPLUS_SB(sb).next_cnid++; inode->i_mode = mode; inode->i_uid = current_fsuid(); inode->i_gid = current_fsgid(); inode->i_nlink = 1; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; - - hip = HFSPLUS_I(inode); - INIT_LIST_HEAD(&hip->open_dir_list); - mutex_init(&hip->extents_lock); - atomic_set(&hip->opencnt, 0); - hip->flags = 0; - memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec)); - memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec)); - hip->alloc_blocks = 0; - hip->first_blocks = 0; - hip->cached_start = 0; - hip->cached_blocks = 0; - hip->phys_size = 0; - hip->fs_blocks = 0; - hip->rsrc_inode = NULL; + INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); + mutex_init(&HFSPLUS_I(inode).extents_lock); + atomic_set(&HFSPLUS_I(inode).opencnt, 0); + HFSPLUS_I(inode).flags = 0; + memset(HFSPLUS_I(inode).first_extents, 0, sizeof(hfsplus_extent_rec)); + memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec)); + HFSPLUS_I(inode).alloc_blocks = 0; + HFSPLUS_I(inode).first_blocks = 0; + HFSPLUS_I(inode).cached_start = 0; + HFSPLUS_I(inode).cached_blocks = 0; + HFSPLUS_I(inode).phys_size = 0; + HFSPLUS_I(inode).fs_blocks = 0; + HFSPLUS_I(inode).rsrc_inode = NULL; if (S_ISDIR(inode->i_mode)) { inode->i_size = 2; - sbi->folder_count++; + HFSPLUS_SB(sb).folder_count++; inode->i_op = &hfsplus_dir_inode_operations; inode->i_fop = &hfsplus_dir_operations; } else if (S_ISREG(inode->i_mode)) { - sbi->file_count++; + HFSPLUS_SB(sb).file_count++; inode->i_op = &hfsplus_file_inode_operations; inode->i_fop = &hfsplus_file_operations; inode->i_mapping->a_ops = &hfsplus_aops; - hip->clump_blocks = sbi->data_clump_blocks; + HFSPLUS_I(inode).clump_blocks = HFSPLUS_SB(sb).data_clump_blocks; } else if (S_ISLNK(inode->i_mode)) { - sbi->file_count++; + HFSPLUS_SB(sb).file_count++; inode->i_op = &page_symlink_inode_operations; inode->i_mapping->a_ops = &hfsplus_aops; - hip->clump_blocks = 1; + HFSPLUS_I(inode).clump_blocks = 1; } else - sbi->file_count++; + HFSPLUS_SB(sb).file_count++; insert_inode_hash(inode); mark_inode_dirty(inode); sb->s_dirt = 1; @@ -410,11 +414,11 @@ void hfsplus_delete_inode(struct inode *inode) struct super_block *sb = inode->i_sb; if (S_ISDIR(inode->i_mode)) { - HFSPLUS_SB(sb)->folder_count--; + HFSPLUS_SB(sb).folder_count--; sb->s_dirt = 1; return; } - HFSPLUS_SB(sb)->file_count--; + HFSPLUS_SB(sb).file_count--; if (S_ISREG(inode->i_mode)) { if (!inode->i_nlink) { inode->i_size = 0; @@ -430,39 +434,34 @@ void hfsplus_delete_inode(struct inode *inode) void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork) { struct super_block *sb = inode->i_sb; - struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); - struct hfsplus_inode_info *hip = HFSPLUS_I(inode); u32 count; int i; - memcpy(&hip->first_extents, &fork->extents, sizeof(hfsplus_extent_rec)); + memcpy(&HFSPLUS_I(inode).first_extents, &fork->extents, + sizeof(hfsplus_extent_rec)); for (count = 0, i = 0; i < 8; i++) count += be32_to_cpu(fork->extents[i].block_count); - hip->first_blocks = count; - memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec)); - hip->cached_start = 0; - hip->cached_blocks = 0; - - hip->alloc_blocks = be32_to_cpu(fork->total_blocks); - hip->phys_size = inode->i_size = be64_to_cpu(fork->total_size); - hip->fs_blocks = - (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; - inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits); - hip->clump_blocks = - be32_to_cpu(fork->clump_size) >> sbi->alloc_blksz_shift; - if (!hip->clump_blocks) { - hip->clump_blocks = HFSPLUS_IS_RSRC(inode) ? - sbi->rsrc_clump_blocks : - sbi->data_clump_blocks; - } + HFSPLUS_I(inode).first_blocks = count; + memset(HFSPLUS_I(inode).cached_extents, 0, sizeof(hfsplus_extent_rec)); + HFSPLUS_I(inode).cached_start = 0; + HFSPLUS_I(inode).cached_blocks = 0; + + HFSPLUS_I(inode).alloc_blocks = be32_to_cpu(fork->total_blocks); + inode->i_size = HFSPLUS_I(inode).phys_size = be64_to_cpu(fork->total_size); + HFSPLUS_I(inode).fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; + inode_set_bytes(inode, HFSPLUS_I(inode).fs_blocks << sb->s_blocksize_bits); + HFSPLUS_I(inode).clump_blocks = be32_to_cpu(fork->clump_size) >> HFSPLUS_SB(sb).alloc_blksz_shift; + if (!HFSPLUS_I(inode).clump_blocks) + HFSPLUS_I(inode).clump_blocks = HFSPLUS_IS_RSRC(inode) ? HFSPLUS_SB(sb).rsrc_clump_blocks : + HFSPLUS_SB(sb).data_clump_blocks; } void hfsplus_inode_write_fork(struct inode *inode, struct hfsplus_fork_raw *fork) { - memcpy(&fork->extents, &HFSPLUS_I(inode)->first_extents, + memcpy(&fork->extents, &HFSPLUS_I(inode).first_extents, sizeof(hfsplus_extent_rec)); fork->total_size = cpu_to_be64(inode->i_size); - fork->total_blocks = cpu_to_be32(HFSPLUS_I(inode)->alloc_blocks); + fork->total_blocks = cpu_to_be32(HFSPLUS_I(inode).alloc_blocks); } int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) @@ -473,7 +472,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset); - HFSPLUS_I(inode)->linkid = 0; + HFSPLUS_I(inode).dev = 0; if (type == HFSPLUS_FOLDER) { struct hfsplus_cat_folder *folder = &entry.folder; @@ -487,8 +486,8 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) inode->i_atime = hfsp_mt2ut(folder->access_date); inode->i_mtime = hfsp_mt2ut(folder->content_mod_date); inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date); - HFSPLUS_I(inode)->create_date = folder->create_date; - HFSPLUS_I(inode)->fs_blocks = 0; + HFSPLUS_I(inode).create_date = folder->create_date; + HFSPLUS_I(inode).fs_blocks = 0; inode->i_op = &hfsplus_dir_inode_operations; inode->i_fop = &hfsplus_dir_operations; } else if (type == HFSPLUS_FILE) { @@ -519,7 +518,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) inode->i_atime = hfsp_mt2ut(file->access_date); inode->i_mtime = hfsp_mt2ut(file->content_mod_date); inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date); - HFSPLUS_I(inode)->create_date = file->create_date; + HFSPLUS_I(inode).create_date = file->create_date; } else { printk(KERN_ERR "hfs: bad catalog entry used to create inode\n"); res = -EIO; @@ -534,12 +533,12 @@ int hfsplus_cat_write_inode(struct inode *inode) hfsplus_cat_entry entry; if (HFSPLUS_IS_RSRC(inode)) - main_inode = HFSPLUS_I(inode)->rsrc_inode; + main_inode = HFSPLUS_I(inode).rsrc_inode; if (!main_inode->i_nlink) return 0; - if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb)->cat_tree, &fd)) + if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb).cat_tree, &fd)) /* panic? */ return -EIO; @@ -555,7 +554,7 @@ int hfsplus_cat_write_inode(struct inode *inode) hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, sizeof(struct hfsplus_cat_folder)); /* simple node checks? */ - hfsplus_cat_set_perms(inode, &folder->permissions); + hfsplus_set_perms(inode, &folder->permissions); folder->access_date = hfsp_ut2mt(inode->i_atime); folder->content_mod_date = hfsp_ut2mt(inode->i_mtime); folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime); @@ -577,7 +576,11 @@ int hfsplus_cat_write_inode(struct inode *inode) hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, sizeof(struct hfsplus_cat_file)); hfsplus_inode_write_fork(inode, &file->data_fork); - hfsplus_cat_set_perms(inode, &file->permissions); + if (S_ISREG(inode->i_mode)) + HFSPLUS_I(inode).dev = inode->i_nlink; + if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) + HFSPLUS_I(inode).dev = kdev_t_to_nr(inode->i_rdev); + hfsplus_set_perms(inode, &file->permissions); if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE) file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); else diff --git a/trunk/fs/hfsplus/ioctl.c b/trunk/fs/hfsplus/ioctl.c index 5b4667e08ef7..ac405f099026 100644 --- a/trunk/fs/hfsplus/ioctl.c +++ b/trunk/fs/hfsplus/ioctl.c @@ -17,98 +17,83 @@ #include #include #include +#include #include #include "hfsplus_fs.h" -static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags) +long hfsplus_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - struct inode *inode = file->f_path.dentry->d_inode; - struct hfsplus_inode_info *hip = HFSPLUS_I(inode); - unsigned int flags = 0; - - if (inode->i_flags & S_IMMUTABLE) - flags |= FS_IMMUTABLE_FL; - if (inode->i_flags |= S_APPEND) - flags |= FS_APPEND_FL; - if (hip->userflags & HFSPLUS_FLG_NODUMP) - flags |= FS_NODUMP_FL; - - return put_user(flags, user_flags); -} - -static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags) -{ - struct inode *inode = file->f_path.dentry->d_inode; - struct hfsplus_inode_info *hip = HFSPLUS_I(inode); + struct inode *inode = filp->f_path.dentry->d_inode; unsigned int flags; - int err = 0; - - err = mnt_want_write(file->f_path.mnt); - if (err) - goto out; - - if (!is_owner_or_cap(inode)) { - err = -EACCES; - goto out_drop_write; - } - - if (get_user(flags, user_flags)) { - err = -EFAULT; - goto out_drop_write; - } - mutex_lock(&inode->i_mutex); + lock_kernel(); + switch (cmd) { + case HFSPLUS_IOC_EXT2_GETFLAGS: + flags = 0; + if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_IMMUTABLE) + flags |= FS_IMMUTABLE_FL; /* EXT2_IMMUTABLE_FL */ + if (HFSPLUS_I(inode).rootflags & HFSPLUS_FLG_APPEND) + flags |= FS_APPEND_FL; /* EXT2_APPEND_FL */ + if (HFSPLUS_I(inode).userflags & HFSPLUS_FLG_NODUMP) + flags |= FS_NODUMP_FL; /* EXT2_NODUMP_FL */ + return put_user(flags, (int __user *)arg); + case HFSPLUS_IOC_EXT2_SETFLAGS: { + int err = 0; + err = mnt_want_write(filp->f_path.mnt); + if (err) { + unlock_kernel(); + return err; + } - if ((flags & (FS_IMMUTABLE_FL|FS_APPEND_FL)) || - inode->i_flags & (S_IMMUTABLE|S_APPEND)) { - if (!capable(CAP_LINUX_IMMUTABLE)) { - err = -EPERM; - goto out_unlock_inode; + if (!is_owner_or_cap(inode)) { + err = -EACCES; + goto setflags_out; + } + if (get_user(flags, (int __user *)arg)) { + err = -EFAULT; + goto setflags_out; + } + if (flags & (FS_IMMUTABLE_FL|FS_APPEND_FL) || + HFSPLUS_I(inode).rootflags & (HFSPLUS_FLG_IMMUTABLE|HFSPLUS_FLG_APPEND)) { + if (!capable(CAP_LINUX_IMMUTABLE)) { + err = -EPERM; + goto setflags_out; + } } - } - /* don't silently ignore unsupported ext2 flags */ - if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) { - err = -EOPNOTSUPP; - goto out_unlock_inode; + /* don't silently ignore unsupported ext2 flags */ + if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) { + err = -EOPNOTSUPP; + goto setflags_out; + } + if (flags & FS_IMMUTABLE_FL) { /* EXT2_IMMUTABLE_FL */ + inode->i_flags |= S_IMMUTABLE; + HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_IMMUTABLE; + } else { + inode->i_flags &= ~S_IMMUTABLE; + HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_IMMUTABLE; + } + if (flags & FS_APPEND_FL) { /* EXT2_APPEND_FL */ + inode->i_flags |= S_APPEND; + HFSPLUS_I(inode).rootflags |= HFSPLUS_FLG_APPEND; + } else { + inode->i_flags &= ~S_APPEND; + HFSPLUS_I(inode).rootflags &= ~HFSPLUS_FLG_APPEND; + } + if (flags & FS_NODUMP_FL) /* EXT2_NODUMP_FL */ + HFSPLUS_I(inode).userflags |= HFSPLUS_FLG_NODUMP; + else + HFSPLUS_I(inode).userflags &= ~HFSPLUS_FLG_NODUMP; + + inode->i_ctime = CURRENT_TIME_SEC; + mark_inode_dirty(inode); +setflags_out: + mnt_drop_write(filp->f_path.mnt); + unlock_kernel(); + return err; } - - if (flags & FS_IMMUTABLE_FL) - inode->i_flags |= S_IMMUTABLE; - else - inode->i_flags &= ~S_IMMUTABLE; - - if (flags & FS_APPEND_FL) - inode->i_flags |= S_APPEND; - else - inode->i_flags &= ~S_APPEND; - - if (flags & FS_NODUMP_FL) - hip->userflags |= HFSPLUS_FLG_NODUMP; - else - hip->userflags &= ~HFSPLUS_FLG_NODUMP; - - inode->i_ctime = CURRENT_TIME_SEC; - mark_inode_dirty(inode); - -out_unlock_inode: - mutex_lock(&inode->i_mutex); -out_drop_write: - mnt_drop_write(file->f_path.mnt); -out: - return err; -} - -long hfsplus_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - void __user *argp = (void __user *)arg; - - switch (cmd) { - case HFSPLUS_IOC_EXT2_GETFLAGS: - return hfsplus_ioctl_getflags(file, argp); - case HFSPLUS_IOC_EXT2_SETFLAGS: - return hfsplus_ioctl_setflags(file, argp); default: + unlock_kernel(); return -ENOTTY; } } @@ -125,7 +110,7 @@ int hfsplus_setxattr(struct dentry *dentry, const char *name, if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode)) return -EOPNOTSUPP; - res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd); + res = hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd); if (res) return res; res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); @@ -168,7 +153,7 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, return -EOPNOTSUPP; if (size) { - res = hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd); + res = hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd); if (res) return res; res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); @@ -192,7 +177,7 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, } else res = size ? -ERANGE : 4; } else - res = -EOPNOTSUPP; + res = -ENODATA; out: if (size) hfs_find_exit(&fd); diff --git a/trunk/fs/hfsplus/options.c b/trunk/fs/hfsplus/options.c index f9ab276a4d8d..572628b4b07d 100644 --- a/trunk/fs/hfsplus/options.c +++ b/trunk/fs/hfsplus/options.c @@ -143,13 +143,13 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi) kfree(p); break; case opt_decompose: - clear_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags); + sbi->flags &= ~HFSPLUS_SB_NODECOMPOSE; break; case opt_nodecompose: - set_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags); + sbi->flags |= HFSPLUS_SB_NODECOMPOSE; break; case opt_force: - set_bit(HFSPLUS_SB_FORCE, &sbi->flags); + sbi->flags |= HFSPLUS_SB_FORCE; break; default: return 0; @@ -171,7 +171,7 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi) int hfsplus_show_options(struct seq_file *seq, struct vfsmount *mnt) { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(mnt->mnt_sb); + struct hfsplus_sb_info *sbi = &HFSPLUS_SB(mnt->mnt_sb); if (sbi->creator != HFSPLUS_DEF_CR_TYPE) seq_printf(seq, ",creator=%.4s", (char *)&sbi->creator); @@ -184,7 +184,7 @@ int hfsplus_show_options(struct seq_file *seq, struct vfsmount *mnt) seq_printf(seq, ",session=%u", sbi->session); if (sbi->nls) seq_printf(seq, ",nls=%s", sbi->nls->charset); - if (test_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags)) + if (sbi->flags & HFSPLUS_SB_NODECOMPOSE) seq_printf(seq, ",nodecompose"); return 0; } diff --git a/trunk/fs/hfsplus/part_tbl.c b/trunk/fs/hfsplus/part_tbl.c index 208b16c645cc..1528a6fd0299 100644 --- a/trunk/fs/hfsplus/part_tbl.c +++ b/trunk/fs/hfsplus/part_tbl.c @@ -74,7 +74,6 @@ struct old_pmap { int hfs_part_find(struct super_block *sb, sector_t *part_start, sector_t *part_size) { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); struct buffer_head *bh; __be16 *data; int i, size, res; @@ -96,7 +95,7 @@ int hfs_part_find(struct super_block *sb, for (i = 0; i < size; p++, i++) { if (p->pdStart && p->pdSize && p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ && - (sbi->part < 0 || sbi->part == i)) { + (HFSPLUS_SB(sb).part < 0 || HFSPLUS_SB(sb).part == i)) { *part_start += be32_to_cpu(p->pdStart); *part_size = be32_to_cpu(p->pdSize); res = 0; @@ -112,7 +111,7 @@ int hfs_part_find(struct super_block *sb, size = be32_to_cpu(pm->pmMapBlkCnt); for (i = 0; i < size;) { if (!memcmp(pm->pmPartType,"Apple_HFS", 9) && - (sbi->part < 0 || sbi->part == i)) { + (HFSPLUS_SB(sb).part < 0 || HFSPLUS_SB(sb).part == i)) { *part_start += be32_to_cpu(pm->pmPyPartStart); *part_size = be32_to_cpu(pm->pmPartBlkCnt); res = 0; diff --git a/trunk/fs/hfsplus/super.c b/trunk/fs/hfsplus/super.c index 9a88d7536103..3b55c050c742 100644 --- a/trunk/fs/hfsplus/super.c +++ b/trunk/fs/hfsplus/super.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -20,11 +21,40 @@ static void hfsplus_destroy_inode(struct inode *inode); #include "hfsplus_fs.h" -static int hfsplus_system_read_inode(struct inode *inode) +struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino) { - struct hfsplus_vh *vhdr = HFSPLUS_SB(inode->i_sb)->s_vhdr; + struct hfs_find_data fd; + struct hfsplus_vh *vhdr; + struct inode *inode; + long err = -EIO; - switch (inode->i_ino) { + inode = iget_locked(sb, ino); + if (!inode) + return ERR_PTR(-ENOMEM); + if (!(inode->i_state & I_NEW)) + return inode; + + INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list); + mutex_init(&HFSPLUS_I(inode).extents_lock); + HFSPLUS_I(inode).flags = 0; + HFSPLUS_I(inode).rsrc_inode = NULL; + atomic_set(&HFSPLUS_I(inode).opencnt, 0); + + if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) { + read_inode: + hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd); + err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); + if (!err) + err = hfsplus_cat_read_inode(inode, &fd); + hfs_find_exit(&fd); + if (err) + goto bad_inode; + goto done; + } + vhdr = HFSPLUS_SB(inode->i_sb).s_vhdr; + switch(inode->i_ino) { + case HFSPLUS_ROOT_CNID: + goto read_inode; case HFSPLUS_EXT_CNID: hfsplus_inode_read_fork(inode, &vhdr->ext_file); inode->i_mapping->a_ops = &hfsplus_btree_aops; @@ -45,101 +75,74 @@ static int hfsplus_system_read_inode(struct inode *inode) inode->i_mapping->a_ops = &hfsplus_btree_aops; break; default: - return -EIO; - } - - return 0; -} - -struct inode *hfsplus_iget(struct super_block *sb, unsigned long ino) -{ - struct hfs_find_data fd; - struct inode *inode; - int err; - - inode = iget_locked(sb, ino); - if (!inode) - return ERR_PTR(-ENOMEM); - if (!(inode->i_state & I_NEW)) - return inode; - - INIT_LIST_HEAD(&HFSPLUS_I(inode)->open_dir_list); - mutex_init(&HFSPLUS_I(inode)->extents_lock); - HFSPLUS_I(inode)->flags = 0; - HFSPLUS_I(inode)->rsrc_inode = NULL; - atomic_set(&HFSPLUS_I(inode)->opencnt, 0); - - if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID || - inode->i_ino == HFSPLUS_ROOT_CNID) { - hfs_find_init(HFSPLUS_SB(inode->i_sb)->cat_tree, &fd); - err = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd); - if (!err) - err = hfsplus_cat_read_inode(inode, &fd); - hfs_find_exit(&fd); - } else { - err = hfsplus_system_read_inode(inode); - } - - if (err) { - iget_failed(inode); - return ERR_PTR(err); + goto bad_inode; } +done: unlock_new_inode(inode); return inode; + +bad_inode: + iget_failed(inode); + return ERR_PTR(err); } -static int hfsplus_system_write_inode(struct inode *inode) +static int hfsplus_write_inode(struct inode *inode, + struct writeback_control *wbc) { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); - struct hfsplus_vh *vhdr = sbi->s_vhdr; - struct hfsplus_fork_raw *fork; - struct hfs_btree *tree = NULL; + struct hfsplus_vh *vhdr; + int ret = 0; + dprint(DBG_INODE, "hfsplus_write_inode: %lu\n", inode->i_ino); + hfsplus_ext_write_extent(inode); + if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) { + return hfsplus_cat_write_inode(inode); + } + vhdr = HFSPLUS_SB(inode->i_sb).s_vhdr; switch (inode->i_ino) { + case HFSPLUS_ROOT_CNID: + ret = hfsplus_cat_write_inode(inode); + break; case HFSPLUS_EXT_CNID: - fork = &vhdr->ext_file; - tree = sbi->ext_tree; + if (vhdr->ext_file.total_size != cpu_to_be64(inode->i_size)) { + HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; + inode->i_sb->s_dirt = 1; + } + hfsplus_inode_write_fork(inode, &vhdr->ext_file); + hfs_btree_write(HFSPLUS_SB(inode->i_sb).ext_tree); break; case HFSPLUS_CAT_CNID: - fork = &vhdr->cat_file; - tree = sbi->cat_tree; + if (vhdr->cat_file.total_size != cpu_to_be64(inode->i_size)) { + HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; + inode->i_sb->s_dirt = 1; + } + hfsplus_inode_write_fork(inode, &vhdr->cat_file); + hfs_btree_write(HFSPLUS_SB(inode->i_sb).cat_tree); break; case HFSPLUS_ALLOC_CNID: - fork = &vhdr->alloc_file; + if (vhdr->alloc_file.total_size != cpu_to_be64(inode->i_size)) { + HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; + inode->i_sb->s_dirt = 1; + } + hfsplus_inode_write_fork(inode, &vhdr->alloc_file); break; case HFSPLUS_START_CNID: - fork = &vhdr->start_file; + if (vhdr->start_file.total_size != cpu_to_be64(inode->i_size)) { + HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; + inode->i_sb->s_dirt = 1; + } + hfsplus_inode_write_fork(inode, &vhdr->start_file); break; case HFSPLUS_ATTR_CNID: - fork = &vhdr->attr_file; - tree = sbi->attr_tree; - default: - return -EIO; - } - - if (fork->total_size != cpu_to_be64(inode->i_size)) { - set_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags); - inode->i_sb->s_dirt = 1; + if (vhdr->attr_file.total_size != cpu_to_be64(inode->i_size)) { + HFSPLUS_SB(inode->i_sb).flags |= HFSPLUS_SB_WRITEBACKUP; + inode->i_sb->s_dirt = 1; + } + hfsplus_inode_write_fork(inode, &vhdr->attr_file); + hfs_btree_write(HFSPLUS_SB(inode->i_sb).attr_tree); + break; } - hfsplus_inode_write_fork(inode, fork); - if (tree) - hfs_btree_write(tree); - return 0; -} - -static int hfsplus_write_inode(struct inode *inode, - struct writeback_control *wbc) -{ - dprint(DBG_INODE, "hfsplus_write_inode: %lu\n", inode->i_ino); - - hfsplus_ext_write_extent(inode); - - if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID || - inode->i_ino == HFSPLUS_ROOT_CNID) - return hfsplus_cat_write_inode(inode); - else - return hfsplus_system_write_inode(inode); + return ret; } static void hfsplus_evict_inode(struct inode *inode) @@ -148,53 +151,51 @@ static void hfsplus_evict_inode(struct inode *inode) truncate_inode_pages(&inode->i_data, 0); end_writeback(inode); if (HFSPLUS_IS_RSRC(inode)) { - HFSPLUS_I(HFSPLUS_I(inode)->rsrc_inode)->rsrc_inode = NULL; - iput(HFSPLUS_I(inode)->rsrc_inode); + HFSPLUS_I(HFSPLUS_I(inode).rsrc_inode).rsrc_inode = NULL; + iput(HFSPLUS_I(inode).rsrc_inode); } } int hfsplus_sync_fs(struct super_block *sb, int wait) { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); - struct hfsplus_vh *vhdr = sbi->s_vhdr; + struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; dprint(DBG_SUPER, "hfsplus_write_super\n"); - mutex_lock(&sbi->vh_mutex); - mutex_lock(&sbi->alloc_mutex); + lock_super(sb); sb->s_dirt = 0; - vhdr->free_blocks = cpu_to_be32(sbi->free_blocks); - vhdr->next_cnid = cpu_to_be32(sbi->next_cnid); - vhdr->folder_count = cpu_to_be32(sbi->folder_count); - vhdr->file_count = cpu_to_be32(sbi->file_count); + vhdr->free_blocks = cpu_to_be32(HFSPLUS_SB(sb).free_blocks); + vhdr->next_alloc = cpu_to_be32(HFSPLUS_SB(sb).next_alloc); + vhdr->next_cnid = cpu_to_be32(HFSPLUS_SB(sb).next_cnid); + vhdr->folder_count = cpu_to_be32(HFSPLUS_SB(sb).folder_count); + vhdr->file_count = cpu_to_be32(HFSPLUS_SB(sb).file_count); - mark_buffer_dirty(sbi->s_vhbh); - if (test_and_clear_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags)) { - if (sbi->sect_count) { + mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh); + if (HFSPLUS_SB(sb).flags & HFSPLUS_SB_WRITEBACKUP) { + if (HFSPLUS_SB(sb).sect_count) { struct buffer_head *bh; u32 block, offset; - block = sbi->blockoffset; - block += (sbi->sect_count - 2) >> (sb->s_blocksize_bits - 9); - offset = ((sbi->sect_count - 2) << 9) & (sb->s_blocksize - 1); - printk(KERN_DEBUG "hfs: backup: %u,%u,%u,%u\n", - sbi->blockoffset, sbi->sect_count, - block, offset); + block = HFSPLUS_SB(sb).blockoffset; + block += (HFSPLUS_SB(sb).sect_count - 2) >> (sb->s_blocksize_bits - 9); + offset = ((HFSPLUS_SB(sb).sect_count - 2) << 9) & (sb->s_blocksize - 1); + printk(KERN_DEBUG "hfs: backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset, + HFSPLUS_SB(sb).sect_count, block, offset); bh = sb_bread(sb, block); if (bh) { vhdr = (struct hfsplus_vh *)(bh->b_data + offset); if (be16_to_cpu(vhdr->signature) == HFSPLUS_VOLHEAD_SIG) { - memcpy(vhdr, sbi->s_vhdr, sizeof(*vhdr)); + memcpy(vhdr, HFSPLUS_SB(sb).s_vhdr, sizeof(*vhdr)); mark_buffer_dirty(bh); brelse(bh); } else printk(KERN_WARNING "hfs: backup not found!\n"); } } + HFSPLUS_SB(sb).flags &= ~HFSPLUS_SB_WRITEBACKUP; } - mutex_unlock(&sbi->alloc_mutex); - mutex_unlock(&sbi->vh_mutex); + unlock_super(sb); return 0; } @@ -208,48 +209,48 @@ static void hfsplus_write_super(struct super_block *sb) static void hfsplus_put_super(struct super_block *sb) { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); - dprint(DBG_SUPER, "hfsplus_put_super\n"); - if (!sb->s_fs_info) return; + lock_kernel(); + if (sb->s_dirt) hfsplus_write_super(sb); - if (!(sb->s_flags & MS_RDONLY) && sbi->s_vhdr) { - struct hfsplus_vh *vhdr = sbi->s_vhdr; + if (!(sb->s_flags & MS_RDONLY) && HFSPLUS_SB(sb).s_vhdr) { + struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; vhdr->modify_date = hfsp_now2mt(); vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_UNMNT); vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_INCNSTNT); - mark_buffer_dirty(sbi->s_vhbh); - sync_dirty_buffer(sbi->s_vhbh); + mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh); + sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh); } - hfs_btree_close(sbi->cat_tree); - hfs_btree_close(sbi->ext_tree); - iput(sbi->alloc_file); - iput(sbi->hidden_dir); - brelse(sbi->s_vhbh); - unload_nls(sbi->nls); + hfs_btree_close(HFSPLUS_SB(sb).cat_tree); + hfs_btree_close(HFSPLUS_SB(sb).ext_tree); + iput(HFSPLUS_SB(sb).alloc_file); + iput(HFSPLUS_SB(sb).hidden_dir); + brelse(HFSPLUS_SB(sb).s_vhbh); + unload_nls(HFSPLUS_SB(sb).nls); kfree(sb->s_fs_info); sb->s_fs_info = NULL; + + unlock_kernel(); } static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; - struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); u64 id = huge_encode_dev(sb->s_bdev->bd_dev); buf->f_type = HFSPLUS_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; - buf->f_blocks = sbi->total_blocks << sbi->fs_shift; - buf->f_bfree = sbi->free_blocks << sbi->fs_shift; + buf->f_blocks = HFSPLUS_SB(sb).total_blocks << HFSPLUS_SB(sb).fs_shift; + buf->f_bfree = HFSPLUS_SB(sb).free_blocks << HFSPLUS_SB(sb).fs_shift; buf->f_bavail = buf->f_bfree; buf->f_files = 0xFFFFFFFF; - buf->f_ffree = 0xFFFFFFFF - sbi->next_cnid; + buf->f_ffree = 0xFFFFFFFF - HFSPLUS_SB(sb).next_cnid; buf->f_fsid.val[0] = (u32)id; buf->f_fsid.val[1] = (u32)(id >> 32); buf->f_namelen = HFSPLUS_MAX_STRLEN; @@ -262,11 +263,11 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data) if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) return 0; if (!(*flags & MS_RDONLY)) { - struct hfsplus_vh *vhdr = HFSPLUS_SB(sb)->s_vhdr; + struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; struct hfsplus_sb_info sbi; memset(&sbi, 0, sizeof(struct hfsplus_sb_info)); - sbi.nls = HFSPLUS_SB(sb)->nls; + sbi.nls = HFSPLUS_SB(sb).nls; if (!hfsplus_parse_options(data, &sbi)) return -EINVAL; @@ -275,7 +276,7 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data) "running fsck.hfsplus is recommended. leaving read-only.\n"); sb->s_flags |= MS_RDONLY; *flags |= MS_RDONLY; - } else if (test_bit(HFSPLUS_SB_FORCE, &sbi.flags)) { + } else if (sbi.flags & HFSPLUS_SB_FORCE) { /* nothing */ } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n"); @@ -319,8 +320,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) return -ENOMEM; sb->s_fs_info = sbi; - mutex_init(&sbi->alloc_mutex); - mutex_init(&sbi->vh_mutex); + INIT_HLIST_HEAD(&sbi->rsrc_inodes); hfsplus_fill_defaults(sbi); if (!hfsplus_parse_options(data, sbi)) { 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) err = -EINVAL; goto cleanup; } - vhdr = sbi->s_vhdr; + vhdr = HFSPLUS_SB(sb).s_vhdr; /* Copy parts of the volume header into the superblock */ sb->s_magic = HFSPLUS_VOLHEAD_SIG; @@ -353,19 +353,18 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) printk(KERN_ERR "hfs: wrong filesystem version\n"); goto cleanup; } - sbi->total_blocks = be32_to_cpu(vhdr->total_blocks); - sbi->free_blocks = be32_to_cpu(vhdr->free_blocks); - sbi->next_cnid = be32_to_cpu(vhdr->next_cnid); - sbi->file_count = be32_to_cpu(vhdr->file_count); - sbi->folder_count = be32_to_cpu(vhdr->folder_count); - sbi->data_clump_blocks = - be32_to_cpu(vhdr->data_clump_sz) >> sbi->alloc_blksz_shift; - if (!sbi->data_clump_blocks) - sbi->data_clump_blocks = 1; - sbi->rsrc_clump_blocks = - be32_to_cpu(vhdr->rsrc_clump_sz) >> sbi->alloc_blksz_shift; - if (!sbi->rsrc_clump_blocks) - sbi->rsrc_clump_blocks = 1; + HFSPLUS_SB(sb).total_blocks = be32_to_cpu(vhdr->total_blocks); + HFSPLUS_SB(sb).free_blocks = be32_to_cpu(vhdr->free_blocks); + HFSPLUS_SB(sb).next_alloc = be32_to_cpu(vhdr->next_alloc); + HFSPLUS_SB(sb).next_cnid = be32_to_cpu(vhdr->next_cnid); + HFSPLUS_SB(sb).file_count = be32_to_cpu(vhdr->file_count); + HFSPLUS_SB(sb).folder_count = be32_to_cpu(vhdr->folder_count); + HFSPLUS_SB(sb).data_clump_blocks = be32_to_cpu(vhdr->data_clump_sz) >> HFSPLUS_SB(sb).alloc_blksz_shift; + if (!HFSPLUS_SB(sb).data_clump_blocks) + HFSPLUS_SB(sb).data_clump_blocks = 1; + HFSPLUS_SB(sb).rsrc_clump_blocks = be32_to_cpu(vhdr->rsrc_clump_sz) >> HFSPLUS_SB(sb).alloc_blksz_shift; + if (!HFSPLUS_SB(sb).rsrc_clump_blocks) + HFSPLUS_SB(sb).rsrc_clump_blocks = 1; /* Set up operations so we can load metadata */ sb->s_op = &hfsplus_sops; @@ -375,7 +374,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) printk(KERN_WARNING "hfs: Filesystem was not cleanly unmounted, " "running fsck.hfsplus is recommended. mounting read-only.\n"); sb->s_flags |= MS_RDONLY; - } else if (test_and_clear_bit(HFSPLUS_SB_FORCE, &sbi->flags)) { + } else if (sbi->flags & HFSPLUS_SB_FORCE) { /* nothing */ } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only.\n"); @@ -385,15 +384,16 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) "use the force option at your own risk, mounting read-only.\n"); sb->s_flags |= MS_RDONLY; } + sbi->flags &= ~HFSPLUS_SB_FORCE; /* Load metadata objects (B*Trees) */ - sbi->ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); - if (!sbi->ext_tree) { + HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); + if (!HFSPLUS_SB(sb).ext_tree) { printk(KERN_ERR "hfs: failed to load extents file\n"); goto cleanup; } - sbi->cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID); - if (!sbi->cat_tree) { + HFSPLUS_SB(sb).cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID); + if (!HFSPLUS_SB(sb).cat_tree) { printk(KERN_ERR "hfs: failed to load catalog file\n"); goto cleanup; } @@ -404,7 +404,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) err = PTR_ERR(inode); goto cleanup; } - sbi->alloc_file = inode; + HFSPLUS_SB(sb).alloc_file = inode; /* Load the root directory */ root = hfsplus_iget(sb, HFSPLUS_ROOT_CNID); @@ -423,7 +423,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1; str.name = HFSP_HIDDENDIR_NAME; - hfs_find_init(sbi->cat_tree, &fd); + hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str); if (!hfs_brec_read(&fd, &entry, sizeof(entry))) { hfs_find_exit(&fd); @@ -434,7 +434,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) err = PTR_ERR(inode); goto cleanup; } - sbi->hidden_dir = inode; + HFSPLUS_SB(sb).hidden_dir = inode; } else hfs_find_exit(&fd); @@ -449,19 +449,15 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) be32_add_cpu(&vhdr->write_count, 1); vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT); vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT); - mark_buffer_dirty(sbi->s_vhbh); - sync_dirty_buffer(sbi->s_vhbh); + mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh); + sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh); - if (!sbi->hidden_dir) { + if (!HFSPLUS_SB(sb).hidden_dir) { printk(KERN_DEBUG "hfs: create hidden dir...\n"); - - mutex_lock(&sbi->vh_mutex); - sbi->hidden_dir = hfsplus_new_inode(sb, S_IFDIR); - hfsplus_create_cat(sbi->hidden_dir->i_ino, sb->s_root->d_inode, - &str, sbi->hidden_dir); - mutex_unlock(&sbi->vh_mutex); - - mark_inode_dirty(sbi->hidden_dir); + HFSPLUS_SB(sb).hidden_dir = hfsplus_new_inode(sb, S_IFDIR); + hfsplus_create_cat(HFSPLUS_SB(sb).hidden_dir->i_ino, sb->s_root->d_inode, + &str, HFSPLUS_SB(sb).hidden_dir); + mark_inode_dirty(HFSPLUS_SB(sb).hidden_dir); } out: unload_nls(sbi->nls); @@ -490,7 +486,7 @@ static struct inode *hfsplus_alloc_inode(struct super_block *sb) static void hfsplus_destroy_inode(struct inode *inode) { - kmem_cache_free(hfsplus_inode_cachep, HFSPLUS_I(inode)); + kmem_cache_free(hfsplus_inode_cachep, &HFSPLUS_I(inode)); } #define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info) diff --git a/trunk/fs/hfsplus/unicode.c b/trunk/fs/hfsplus/unicode.c index b66d67de882c..628ccf6fa402 100644 --- a/trunk/fs/hfsplus/unicode.c +++ b/trunk/fs/hfsplus/unicode.c @@ -121,7 +121,7 @@ static u16 *hfsplus_compose_lookup(u16 *p, u16 cc) int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, char *astr, int *len_p) { const hfsplus_unichr *ip; - struct nls_table *nls = HFSPLUS_SB(sb)->nls; + struct nls_table *nls = HFSPLUS_SB(sb).nls; u8 *op; u16 cc, c0, c1; u16 *ce1, *ce2; @@ -132,7 +132,7 @@ int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, c ustrlen = be16_to_cpu(ustr->length); len = *len_p; ce1 = NULL; - compose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags); + compose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); while (ustrlen > 0) { c0 = be16_to_cpu(*ip++); @@ -246,7 +246,7 @@ int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, c static inline int asc2unichar(struct super_block *sb, const char *astr, int len, wchar_t *uc) { - int size = HFSPLUS_SB(sb)->nls->char2uni(astr, len, uc); + int size = HFSPLUS_SB(sb).nls->char2uni(astr, len, uc); if (size <= 0) { *uc = '?'; size = 1; @@ -293,7 +293,7 @@ int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr, u16 *dstr, outlen = 0; wchar_t c; - decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags); + decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); while (outlen < HFSPLUS_MAX_STRLEN && len > 0) { size = asc2unichar(sb, astr, len, &c); @@ -330,8 +330,8 @@ int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str) wchar_t c; u16 c2; - casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags); - decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags); + casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD); + decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); hash = init_name_hash(); astr = str->name; len = str->len; @@ -373,8 +373,8 @@ int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr * u16 c1, c2; wchar_t c; - casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags); - decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags); + casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD); + decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); astr1 = s1->name; len1 = s1->len; astr2 = s2->name; diff --git a/trunk/fs/hfsplus/wrapper.c b/trunk/fs/hfsplus/wrapper.c index 8972c20b3216..bed78ac8f6d1 100644 --- a/trunk/fs/hfsplus/wrapper.c +++ b/trunk/fs/hfsplus/wrapper.c @@ -65,8 +65,8 @@ static int hfsplus_get_last_session(struct super_block *sb, *start = 0; *size = sb->s_bdev->bd_inode->i_size >> 9; - if (HFSPLUS_SB(sb)->session >= 0) { - te.cdte_track = HFSPLUS_SB(sb)->session; + if (HFSPLUS_SB(sb).session >= 0) { + te.cdte_track = HFSPLUS_SB(sb).session; te.cdte_format = CDROM_LBA; res = ioctl_by_bdev(sb->s_bdev, CDROMREADTOCENTRY, (unsigned long)&te); if (!res && (te.cdte_ctrl & CDROM_DATA_TRACK) == 4) { @@ -87,7 +87,6 @@ static int hfsplus_get_last_session(struct super_block *sb, /* Takes in super block, returns true if good data read */ int hfsplus_read_wrapper(struct super_block *sb) { - struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); struct buffer_head *bh; struct hfsplus_vh *vhdr; struct hfsplus_wd wd; @@ -123,7 +122,7 @@ int hfsplus_read_wrapper(struct super_block *sb) if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG)) break; if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) { - set_bit(HFSPLUS_SB_HFSX, &sbi->flags); + HFSPLUS_SB(sb).flags |= HFSPLUS_SB_HFSX; break; } brelse(bh); @@ -144,11 +143,11 @@ int hfsplus_read_wrapper(struct super_block *sb) if (blocksize < HFSPLUS_SECTOR_SIZE || ((blocksize - 1) & blocksize)) return -EINVAL; - sbi->alloc_blksz = blocksize; - sbi->alloc_blksz_shift = 0; + HFSPLUS_SB(sb).alloc_blksz = blocksize; + HFSPLUS_SB(sb).alloc_blksz_shift = 0; while ((blocksize >>= 1) != 0) - sbi->alloc_blksz_shift++; - blocksize = min(sbi->alloc_blksz, (u32)PAGE_SIZE); + HFSPLUS_SB(sb).alloc_blksz_shift++; + blocksize = min(HFSPLUS_SB(sb).alloc_blksz, (u32)PAGE_SIZE); /* align block size to block offset */ while (part_start & ((blocksize >> HFSPLUS_SECTOR_SHIFT) - 1)) @@ -159,26 +158,23 @@ int hfsplus_read_wrapper(struct super_block *sb) return -EINVAL; } - sbi->blockoffset = - part_start >> (sb->s_blocksize_bits - HFSPLUS_SECTOR_SHIFT); - sbi->sect_count = part_size; - sbi->fs_shift = sbi->alloc_blksz_shift - sb->s_blocksize_bits; + HFSPLUS_SB(sb).blockoffset = part_start >> + (sb->s_blocksize_bits - HFSPLUS_SECTOR_SHIFT); + HFSPLUS_SB(sb).sect_count = part_size; + HFSPLUS_SB(sb).fs_shift = HFSPLUS_SB(sb).alloc_blksz_shift - + sb->s_blocksize_bits; bh = sb_bread512(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, vhdr); if (!bh) return -EIO; /* should still be the same... */ - if (test_bit(HFSPLUS_SB_HFSX, &sbi->flags)) { - if (vhdr->signature != cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) - goto error; - } else { - if (vhdr->signature != cpu_to_be16(HFSPLUS_VOLHEAD_SIG)) - goto error; - } - - sbi->s_vhbh = bh; - sbi->s_vhdr = vhdr; + if (vhdr->signature != (HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX ? + cpu_to_be16(HFSPLUS_VOLHEAD_SIGX) : + cpu_to_be16(HFSPLUS_VOLHEAD_SIG))) + goto error; + HFSPLUS_SB(sb).s_vhbh = bh; + HFSPLUS_SB(sb).s_vhdr = vhdr; return 0; error: diff --git a/trunk/include/linux/types.h b/trunk/include/linux/types.h index 357dbc19606f..01a082f56ef4 100644 --- a/trunk/include/linux/types.h +++ b/trunk/include/linux/types.h @@ -121,15 +121,7 @@ typedef __u64 u_int64_t; typedef __s64 int64_t; #endif -/* - * aligned_u64 should be used in defining kernel<->userspace ABIs to avoid - * common 32/64-bit compat problems. - * 64-bit values align to 4-byte boundaries on x86_32 (and possibly other - * architectures) and to 8-byte boundaries on 64-bit architetures. The new - * aligned_64 type enforces 8-byte alignment so that structs containing - * aligned_64 values have the same alignment on 32-bit and 64-bit architectures. - * No conversions are necessary between 32-bit user-space and a 64-bit kernel. - */ +/* this is a special 64bit data type that is 8-byte aligned */ #define aligned_u64 __u64 __attribute__((aligned(8))) #define aligned_be64 __be64 __attribute__((aligned(8))) #define aligned_le64 __le64 __attribute__((aligned(8))) @@ -186,11 +178,6 @@ typedef __u64 __bitwise __be64; typedef __u16 __bitwise __sum16; typedef __u32 __bitwise __wsum; -/* this is a special 64bit data type that is 8-byte aligned */ -#define __aligned_u64 __u64 __attribute__((aligned(8))) -#define __aligned_be64 __be64 __attribute__((aligned(8))) -#define __aligned_le64 __le64 __attribute__((aligned(8))) - #ifdef __KERNEL__ typedef unsigned __bitwise__ gfp_t; typedef unsigned __bitwise__ fmode_t; diff --git a/trunk/kernel/hrtimer.c b/trunk/kernel/hrtimer.c index 72206cf5c6cf..1decafbb6b1a 100644 --- a/trunk/kernel/hrtimer.c +++ b/trunk/kernel/hrtimer.c @@ -931,7 +931,6 @@ static inline int remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base) { if (hrtimer_is_queued(timer)) { - unsigned long state; int reprogram; /* @@ -945,13 +944,8 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base) debug_deactivate(timer); timer_stats_hrtimer_clear_start_info(timer); reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases); - /* - * We must preserve the CALLBACK state flag here, - * otherwise we could move the timer base in - * switch_hrtimer_base. - */ - state = timer->state & HRTIMER_STATE_CALLBACK; - __remove_hrtimer(timer, base, state, reprogram); + __remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE, + reprogram); return 1; } return 0; @@ -1237,9 +1231,6 @@ static void __run_hrtimer(struct hrtimer *timer, ktime_t *now) BUG_ON(timer->state != HRTIMER_STATE_CALLBACK); enqueue_hrtimer(timer, base); } - - WARN_ON_ONCE(!(timer->state & HRTIMER_STATE_CALLBACK)); - timer->state &= ~HRTIMER_STATE_CALLBACK; } diff --git a/trunk/kernel/sysctl_check.c b/trunk/kernel/sysctl_check.c index 10b90d8a03c4..04cdcf72c827 100644 --- a/trunk/kernel/sysctl_check.c +++ b/trunk/kernel/sysctl_check.c @@ -143,6 +143,15 @@ int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table) if (!table->maxlen) set_fail(&fail, table, "No maxlen"); } + if ((table->proc_handler == proc_doulongvec_minmax) || + (table->proc_handler == proc_doulongvec_ms_jiffies_minmax)) { + if (table->maxlen > sizeof (unsigned long)) { + if (!table->extra1) + set_fail(&fail, table, "No min"); + if (!table->extra2) + set_fail(&fail, table, "No max"); + } + } #ifdef CONFIG_PROC_SYSCTL if (table->procname && !table->proc_handler) set_fail(&fail, table, "No proc_handler"); diff --git a/trunk/net/rds/page.c b/trunk/net/rds/page.c index 1dfbfea12e9b..595a952d4b17 100644 --- a/trunk/net/rds/page.c +++ b/trunk/net/rds/page.c @@ -57,17 +57,30 @@ int rds_page_copy_user(struct page *page, unsigned long offset, unsigned long ret; void *addr; - addr = kmap(page); - if (to_user) { + if (to_user) rds_stats_add(s_copy_to_user, bytes); - ret = copy_to_user(ptr, addr + offset, bytes); - } else { + else rds_stats_add(s_copy_from_user, bytes); - ret = copy_from_user(addr + offset, ptr, bytes); + + addr = kmap_atomic(page, KM_USER0); + if (to_user) + ret = __copy_to_user_inatomic(ptr, addr + offset, bytes); + else + ret = __copy_from_user_inatomic(addr + offset, ptr, bytes); + kunmap_atomic(addr, KM_USER0); + + if (ret) { + addr = kmap(page); + if (to_user) + ret = copy_to_user(ptr, addr + offset, bytes); + else + ret = copy_from_user(addr + offset, ptr, bytes); + kunmap(page); + if (ret) + return -EFAULT; } - kunmap(page); - return ret ? -EFAULT : 0; + return 0; } EXPORT_SYMBOL_GPL(rds_page_copy_user); diff --git a/trunk/sound/core/rawmidi.c b/trunk/sound/core/rawmidi.c index cbbed0db9e56..a7868ad4d530 100644 --- a/trunk/sound/core/rawmidi.c +++ b/trunk/sound/core/rawmidi.c @@ -535,15 +535,13 @@ static int snd_rawmidi_release(struct inode *inode, struct file *file) { struct snd_rawmidi_file *rfile; struct snd_rawmidi *rmidi; - struct module *module; rfile = file->private_data; rmidi = rfile->rmidi; rawmidi_release_priv(rfile); kfree(rfile); - module = rmidi->card->module; snd_card_file_remove(rmidi->card, file); - module_put(module); + module_put(rmidi->card->module); return 0; }