diff options
36 files changed, 669 insertions, 496 deletions
@@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 19 -EXTRAVERSION =-rc3 +EXTRAVERSION =-rc4 NAME=Avast! A bilge rat! # *DOCUMENTATION* diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 14af6cce2fa..74ba7637811 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -408,7 +408,7 @@ config MOMENCO_OCELOT_C select SWAP_IO_SPACE select SYS_HAS_CPU_RM7000 select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL if BROKEN select SYS_SUPPORTS_BIG_ENDIAN help The Ocelot is a MIPS-based Single Board Computer (SBC) made by @@ -1690,6 +1690,7 @@ config NR_CPUS depends on SMP default "64" if SGI_IP27 default "2" + default "8" if MIPS_MT_SMTC help This allows you to specify the maximum number of CPUs which this kernel will support. The maximum supported value is 32 for 32-bit diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c index 94f09194d63..6768638883e 100644 --- a/arch/mips/au1000/common/time.c +++ b/arch/mips/au1000/common/time.c @@ -82,7 +82,6 @@ unsigned long wtimer; void mips_timer_interrupt(void) { int irq = 63; - unsigned long count; irq_enter(); kstat_this_cpu.irqs[irq]++; @@ -231,7 +230,6 @@ wakeup_counter0_set(int ticks) */ unsigned long cal_r4koff(void) { - unsigned long count; unsigned long cpu_speed; unsigned long flags; unsigned long counter; @@ -258,7 +256,7 @@ unsigned long cal_r4koff(void) #if defined(CONFIG_AU1000_USE32K) { - unsigned long start, end; + unsigned long start, end, count; start = au_readl(SYS_RTCREAD); start += 2; @@ -282,7 +280,6 @@ unsigned long cal_r4koff(void) #else cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; - count = cpu_speed / 2; #endif } else { @@ -291,10 +288,9 @@ unsigned long cal_r4koff(void) * NOTE: some old silicon doesn't allow reading the PLL. */ cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; - count = cpu_speed / 2; no_au1xxx_32khz = 1; } - mips_hpt_frequency = count; + mips_hpt_frequency = cpu_speed; // Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16)); spin_unlock_irqrestore(&time_lock, flags); diff --git a/arch/mips/emma2rh/common/irq_emma2rh.c b/arch/mips/emma2rh/common/irq_emma2rh.c index 7c930860c92..197ed4c2ba0 100644 --- a/arch/mips/emma2rh/common/irq_emma2rh.c +++ b/arch/mips/emma2rh/common/irq_emma2rh.c @@ -97,7 +97,7 @@ void emma2rh_irq_init(u32 irq_base) irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 1; - irq_desc[i].handler = &emma2rh_irq_controller; + irq_desc[i].chip = &emma2rh_irq_controller; } emma2rh_irq_base = irq_base; diff --git a/arch/mips/emma2rh/markeins/irq_markeins.c b/arch/mips/emma2rh/markeins/irq_markeins.c index f23ae9fcffa..0b36eb001e6 100644 --- a/arch/mips/emma2rh/markeins/irq_markeins.c +++ b/arch/mips/emma2rh/markeins/irq_markeins.c @@ -86,7 +86,7 @@ void emma2rh_sw_irq_init(u32 irq_base) irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 2; - irq_desc[i].handler = &emma2rh_sw_irq_controller; + irq_desc[i].chip = &emma2rh_sw_irq_controller; } emma2rh_sw_irq_base = irq_base; @@ -166,7 +166,7 @@ void emma2rh_gpio_irq_init(u32 irq_base) irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 2; - irq_desc[i].handler = &emma2rh_gpio_irq_controller; + irq_desc[i].chip = &emma2rh_gpio_irq_controller; } emma2rh_gpio_irq_base = irq_base; diff --git a/arch/mips/emma2rh/markeins/platform.c b/arch/mips/emma2rh/markeins/platform.c index 15cc61df362..11567702b15 100644 --- a/arch/mips/emma2rh/markeins/platform.c +++ b/arch/mips/emma2rh/markeins/platform.c @@ -44,18 +44,45 @@ #define I2C_EMMA2RH "emma2rh-iic" /* must be in sync with IIC driver */ static struct resource i2c_emma_resources_0[] = { - { NULL, EMMA2RH_IRQ_PIIC0, EMMA2RH_IRQ_PIIC0, IORESOURCE_IRQ }, - { NULL, KSEG1ADDR(EMMA2RH_PIIC0_BASE), KSEG1ADDR(EMMA2RH_PIIC0_BASE + 0x1000), 0 }, + { + .name = NULL, + .start = EMMA2RH_IRQ_PIIC0, + .end = EMMA2RH_IRQ_PIIC0, + .flags = IORESOURCE_IRQ + }, { + .name = NULL, + .start = EMMA2RH_PIIC0_BASE, + .end = EMMA2RH_PIIC0_BASE + 0x1000, + .flags = 0 + }, }; struct resource i2c_emma_resources_1[] = { - { NULL, EMMA2RH_IRQ_PIIC1, EMMA2RH_IRQ_PIIC1, IORESOURCE_IRQ }, - { NULL, KSEG1ADDR(EMMA2RH_PIIC1_BASE), KSEG1ADDR(EMMA2RH_PIIC1_BASE + 0x1000), 0 }, + { + .name = NULL, + .start = EMMA2RH_IRQ_PIIC1, + .end = EMMA2RH_IRQ_PIIC1, + .flags = IORESOURCE_IRQ + }, { + .name = NULL, + .start = EMMA2RH_PIIC1_BASE, + .end = EMMA2RH_PIIC1_BASE + 0x1000, + .flags = 0 + }, }; struct resource i2c_emma_resources_2[] = { - { NULL, EMMA2RH_IRQ_PIIC2, EMMA2RH_IRQ_PIIC2, IORESOURCE_IRQ }, - { NULL, KSEG1ADDR(EMMA2RH_PIIC2_BASE), KSEG1ADDR(EMMA2RH_PIIC2_BASE + 0x1000), 0 }, + { + .name = NULL, + .start = EMMA2RH_IRQ_PIIC2, + .end = EMMA2RH_IRQ_PIIC2, + .flags = IORESOURCE_IRQ + }, { + .name = NULL, + .start = EMMA2RH_PIIC2_BASE, + .end = EMMA2RH_PIIC2_BASE + 0x1000, + .flags = 0 + }, }; struct platform_device i2c_emma_devices[] = { @@ -83,32 +110,29 @@ struct platform_device i2c_emma_devices[] = { #define EMMA2RH_SERIAL_FLAGS UPF_BOOT_AUTOCONF | UPF_SKIP_TEST static struct plat_serial8250_port platform_serial_ports[] = { - [0] = { - .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3), - .irq = EMMA2RH_IRQ_PFUR0, - .uartclk = EMMA2RH_SERIAL_CLOCK, - .regshift = 4, - .iotype = UPIO_MEM, - .flags = EMMA2RH_SERIAL_FLAGS, - }, - [1] = { - .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3), - .irq = EMMA2RH_IRQ_PFUR1, - .uartclk = EMMA2RH_SERIAL_CLOCK, - .regshift = 4, - .iotype = UPIO_MEM, - .flags = EMMA2RH_SERIAL_FLAGS, - }, - [2] = { - .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR2_BASE + 3), - .irq = EMMA2RH_IRQ_PFUR2, - .uartclk = EMMA2RH_SERIAL_CLOCK, - .regshift = 4, - .iotype = UPIO_MEM, - .flags = EMMA2RH_SERIAL_FLAGS, - }, - [3] = { - .flags = 0, + [0] = { + .membase= (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3), + .irq = EMMA2RH_IRQ_PFUR0, + .uartclk = EMMA2RH_SERIAL_CLOCK, + .regshift = 4, + .iotype = UPIO_MEM, + .flags = EMMA2RH_SERIAL_FLAGS, + }, [1] = { + .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3), + .irq = EMMA2RH_IRQ_PFUR1, + .uartclk = EMMA2RH_SERIAL_CLOCK, + .regshift = 4, + .iotype = UPIO_MEM, + .flags = EMMA2RH_SERIAL_FLAGS, + }, [2] = { + .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR2_BASE + 3), + .irq = EMMA2RH_IRQ_PFUR2, + .uartclk = EMMA2RH_SERIAL_CLOCK, + .regshift = 4, + .iotype = UPIO_MEM, + .flags = EMMA2RH_SERIAL_FLAGS, + }, [3] = { + .flags = 0, }, }; diff --git a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c index 39a0243bed9..de4a238c28b 100644 --- a/arch/mips/jmr3927/rbhma3100/irq.c +++ b/arch/mips/jmr3927/rbhma3100/irq.c @@ -288,6 +288,8 @@ static void tx_branch_likely_bug_fixup(void) static void jmr3927_spurious(void) { + struct pt_regs * regs = get_irq_regs(); + #ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND tx_branch_likely_bug_fixup(); #endif @@ -297,6 +299,7 @@ static void jmr3927_spurious(void) asmlinkage void plat_irq_dispatch(void) { + struct pt_regs * regs = get_irq_regs(); int irq; #ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 720fac3435d..a95f37de080 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -654,6 +654,8 @@ einval: li v0, -EINVAL sys sys_set_robust_list 2 sys sys_get_robust_list 3 /* 4310 */ sys sys_ni_syscall 0 + sys sys_getcpu 3 + sys sys_epoll_pwait 6 .endm /* We pre-compute the number of _instruction_ bytes needed to diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index 3a34f62c8b1..8fb0f60f657 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -469,3 +469,5 @@ sys_call_table: PTR sys_set_robust_list PTR sys_get_robust_list PTR sys_ni_syscall /* 5270 */ + PTR sys_getcpu + PTR sys_epoll_pwait diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 67b92a1d6c7..0da5ca2040f 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -395,3 +395,5 @@ EXPORT(sysn32_call_table) PTR compat_sys_set_robust_list PTR compat_sys_get_robust_list PTR sys_ni_syscall + PTR sys_getcpu + PTR sys_epoll_pwait diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 2875c4a3fa5..b9d00cae8b5 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -517,4 +517,6 @@ sys_call_table: PTR compat_sys_set_robust_list PTR compat_sys_get_robust_list /* 4310 */ PTR sys_ni_syscall + PTR sys_getcpu + PTR sys_epoll_pwait .size sys_call_table,.-sys_call_table diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c index 5537558f19f..ea49a775bf2 100644 --- a/arch/mips/mm/c-sb1.c +++ b/arch/mips/mm/c-sb1.c @@ -49,6 +49,15 @@ static unsigned short dcache_sets; static unsigned int icache_range_cutoff; static unsigned int dcache_range_cutoff; +static inline void sb1_on_each_cpu(void (*func) (void *info), void *info, + int retry, int wait) +{ + preempt_disable(); + smp_call_function(func, info, retry, wait); + func(info); + preempt_enable(); +} + /* * The dcache is fully coherent to the system, with one * big caveat: the instruction stream. In other words, @@ -226,7 +235,7 @@ static void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, args.vma = vma; args.addr = addr; args.pfn = pfn; - on_each_cpu(sb1_flush_cache_page_ipi, (void *) &args, 1, 1); + sb1_on_each_cpu(sb1_flush_cache_page_ipi, (void *) &args, 1, 1); } #else void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn) @@ -249,7 +258,7 @@ void sb1___flush_cache_all_ipi(void *ignored) static void sb1___flush_cache_all(void) { - on_each_cpu(sb1___flush_cache_all_ipi, 0, 1, 1); + sb1_on_each_cpu(sb1___flush_cache_all_ipi, 0, 1, 1); } #else void sb1___flush_cache_all(void) @@ -299,7 +308,7 @@ void sb1_flush_icache_range(unsigned long start, unsigned long end) args.start = start; args.end = end; - on_each_cpu(sb1_flush_icache_range_ipi, &args, 1, 1); + sb1_on_each_cpu(sb1_flush_icache_range_ipi, &args, 1, 1); } #else void sb1_flush_icache_range(unsigned long start, unsigned long end) @@ -326,7 +335,7 @@ static void sb1_flush_cache_sigtramp_ipi(void *info) static void sb1_flush_cache_sigtramp(unsigned long addr) { - on_each_cpu(sb1_flush_cache_sigtramp_ipi, (void *) addr, 1, 1); + sb1_on_each_cpu(sb1_flush_cache_sigtramp_ipi, (void *) addr, 1, 1); } #else void sb1_flush_cache_sigtramp(unsigned long addr) @@ -444,7 +453,6 @@ static __init void probe_cache_sizes(void) void sb1_cache_init(void) { extern char except_vec2_sb1; - extern char handle_vec2_sb1; /* Special cache error handler for SB1 */ set_uncached_handler (0x100, &except_vec2_sb1, 0x80); diff --git a/arch/mips/momentum/ocelot_g/ocelot_pld.h b/arch/mips/momentum/ocelot_g/ocelot_pld.h index fcb8275e219..95e0534026d 100644 --- a/arch/mips/momentum/ocelot_g/ocelot_pld.h +++ b/arch/mips/momentum/ocelot_g/ocelot_pld.h @@ -23,8 +23,8 @@ #define OCELOT_REG_INTSET (12) #define OCELOT_REG_INTCLR (13) -#define OCELOT_PLD_WRITE(x, y) writeb(x, OCELOT_CS0_ADDR + OCELOT_REG_##y) -#define OCELOT_PLD_READ(x) readb(OCELOT_CS0_ADDR + OCELOT_REG_##x) - +#define __PLD_REG_TO_ADDR(reg) ((void *) OCELOT_CS0_ADDR + OCELOT_REG_##reg) +#define OCELOT_PLD_WRITE(x, reg) writeb(x, __PLD_REG_TO_ADDR(reg)) +#define OCELOT_PLD_READ(reg) readb(__PLD_REG_TO_ADDR(reg)) #endif /* __MOMENCO_OCELOT_PLD_H__ */ diff --git a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c index 56ec47039c1..d288f7b0184 100644 --- a/arch/mips/momentum/ocelot_g/setup.c +++ b/arch/mips/momentum/ocelot_g/setup.c @@ -57,6 +57,7 @@ #include <asm/gt64240.h> #include <asm/irq.h> #include <asm/pci.h> +#include <asm/pgtable.h> #include <asm/processor.h> #include <asm/reboot.h> #include <linux/bootmem.h> @@ -160,6 +161,10 @@ static void __init setup_l3cache(unsigned long size) printk("Done\n"); } +void __init plat_timer_setup(struct irqaction *irq) +{ +} + void __init plat_mem_setup(void) { void (*l3func)(unsigned long) = (void *) KSEG1ADDR(setup_l3cache); diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index dd0aec9c3ce..1fb240c57ba 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -31,16 +31,18 @@ #define M_COUNTER_OVERFLOW (1UL << 31) #ifdef CONFIG_MIPS_MT_SMP -#define WHAT (M_TC_EN_VPE | M_PERFCTL_VPEID(smp_processor_id())) +#define WHAT (M_TC_EN_VPE | M_PERFCTL_VPEID(smp_processor_id())) +#define vpe_id() smp_processor_id() #else -#define WHAT 0 +#define WHAT 0 +#define vpe_id() smp_processor_id() #endif #define __define_perf_accessors(r, n, np) \ \ static inline unsigned int r_c0_ ## r ## n(void) \ { \ - unsigned int cpu = smp_processor_id(); \ + unsigned int cpu = vpe_id(); \ \ switch (cpu) { \ case 0: \ @@ -55,7 +57,7 @@ static inline unsigned int r_c0_ ## r ## n(void) \ \ static inline void w_c0_ ## r ## n(unsigned int value) \ { \ - unsigned int cpu = smp_processor_id(); \ + unsigned int cpu = vpe_id(); \ \ switch (cpu) { \ case 0: \ @@ -218,7 +220,7 @@ static inline int n_counters(void) { int counters = __n_counters(); -#ifndef CONFIG_SMP +#ifdef CONFIG_MIPS_MT_SMP if (current_cpu_data.cputype == CPU_34K) return counters >> 1; #endif diff --git a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c b/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c index b926e6a75c2..08b20cdfd7b 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c @@ -36,14 +36,18 @@ void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on) static DECLARE_WAIT_QUEUE_HEAD(txx9_spi_wait); -static void txx9_spi_interrupt(int irq, void *dev_id) +static irqreturn_t txx9_spi_interrupt(int irq, void *dev_id) { /* disable rx intr */ tx4938_spiptr->cr0 &= ~TXx9_SPCR0_RBSIE; wake_up(&txx9_spi_wait); + + return IRQ_HANDLED; } + static struct irqaction txx9_spi_action = { - txx9_spi_interrupt, 0, 0, "spi", NULL, NULL, + .handler = txx9_spi_interrupt, + .name = "spi", }; void __init txx9_spi_irqinit(int irc_irq) diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index c60efb3cb22..0917c24c4f0 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -793,7 +793,7 @@ static unsigned int schizo_irq_build(struct device_node *dp, return virt_irq; } -static void schizo_irq_trans_init(struct device_node *dp) +static void __schizo_irq_trans_init(struct device_node *dp, int is_tomatillo) { struct linux_prom64_registers *regs; struct schizo_irq_data *irq_data; @@ -807,11 +807,24 @@ static void schizo_irq_trans_init(struct device_node *dp) dp->irq_trans->data = irq_data; irq_data->pbm_regs = regs[0].phys_addr; - irq_data->sync_reg = regs[3].phys_addr + 0x1a18UL; + if (is_tomatillo) + irq_data->sync_reg = regs[3].phys_addr + 0x1a18UL; + else + irq_data->sync_reg = 0UL; irq_data->portid = of_getintprop_default(dp, "portid", 0); irq_data->chip_version = of_getintprop_default(dp, "version#", 0); } +static void schizo_irq_trans_init(struct device_node *dp) +{ + __schizo_irq_trans_init(dp, 0); +} + +static void tomatillo_irq_trans_init(struct device_node *dp) +{ + __schizo_irq_trans_init(dp, 1); +} + static unsigned int pci_sun4v_irq_build(struct device_node *dp, unsigned int devino, void *_data) @@ -1050,8 +1063,8 @@ static struct irq_trans pci_irq_trans_table[] = { { "pci108e,8001", schizo_irq_trans_init }, { "SUNW,schizo+", schizo_irq_trans_init }, { "pci108e,8002", schizo_irq_trans_init }, - { "SUNW,tomatillo", schizo_irq_trans_init }, - { "pci108e,a801", schizo_irq_trans_init }, + { "SUNW,tomatillo", tomatillo_irq_trans_init }, + { "pci108e,a801", tomatillo_irq_trans_init }, { "SUNW,sun4v-pci", pci_sun4v_irq_trans_init }, }; #endif diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 68420e2dad0..fe1796c939c 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -87,6 +87,7 @@ static void dump_tl1_traplog(struct tl1_traplog *p) i + 1, p->trapstack[i].tstate, p->trapstack[i].tpc, p->trapstack[i].tnpc, p->trapstack[i].tt); + print_symbol("TRAPLOG: TPC<%s>\n", p->trapstack[i].tpc); } } @@ -1134,6 +1135,9 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in printk("%s" "ERROR(%d): TPC[%lx] TNPC[%lx] O7[%lx] TSTATE[%lx]\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), regs->tpc, regs->tnpc, regs->u_regs[UREG_I7], regs->tstate); + printk("%s" "ERROR(%d): ", + (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id()); + print_symbol("TPC<%s>\n", regs->tpc); printk("%s" "ERROR(%d): M_SYND(%lx), E_SYND(%lx)%s%s\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT, @@ -1741,6 +1745,7 @@ void cheetah_plus_parity_error(int type, struct pt_regs *regs) smp_processor_id(), (type & 0x1) ? 'I' : 'D', regs->tpc); + print_symbol(KERN_EMERG "TPC<%s>\n", regs->tpc); panic("Irrecoverable Cheetah+ parity error."); } @@ -1748,6 +1753,7 @@ void cheetah_plus_parity_error(int type, struct pt_regs *regs) smp_processor_id(), (type & 0x1) ? 'I' : 'D', regs->tpc); + print_symbol(KERN_WARNING "TPC<%s>\n", regs->tpc); } struct sun4v_error_entry { @@ -1946,6 +1952,7 @@ void sun4v_itlb_error_report(struct pt_regs *regs, int tl) printk(KERN_EMERG "SUN4V-ITLB: Error at TPC[%lx], tl %d\n", regs->tpc, tl); + print_symbol(KERN_EMERG "SUN4V-ITLB: TPC<%s>\n", regs->tpc); printk(KERN_EMERG "SUN4V-ITLB: vaddr[%lx] ctx[%lx] " "pte[%lx] error[%lx]\n", sun4v_err_itlb_vaddr, sun4v_err_itlb_ctx, @@ -1966,6 +1973,7 @@ void sun4v_dtlb_error_report(struct pt_regs *regs, int tl) printk(KERN_EMERG "SUN4V-DTLB: Error at TPC[%lx], tl %d\n", regs->tpc, tl); + print_symbol(KERN_EMERG "SUN4V-DTLB: TPC<%s>\n", regs->tpc); printk(KERN_EMERG "SUN4V-DTLB: vaddr[%lx] ctx[%lx] " "pte[%lx] error[%lx]\n", sun4v_err_dtlb_vaddr, sun4v_err_dtlb_ctx, diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index bc458f57921..49c047b75cc 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -106,10 +106,15 @@ static inline void ubd_set_bit(__u64 bit, unsigned char *data) #define DRIVER_NAME "uml-blkdev" +/* Can be taken in interrupt context, and is passed to the block layer to lock + * the request queue. Kernel side code knows that. */ static DEFINE_SPINLOCK(ubd_io_lock); -static DEFINE_SPINLOCK(ubd_lock); -static void (*do_ubd)(void); +static DEFINE_MUTEX(ubd_lock); + +/* XXX - this made sense in 2.4 days, now it's only used as a boolean, and + * probably it doesn't make sense even for that. */ +static int do_ubd; static int ubd_open(struct inode * inode, struct file * filp); static int ubd_release(struct inode * inode, struct file * file); @@ -117,7 +122,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo); -#define MAX_DEV (8) +#define MAX_DEV (16) static struct block_device_operations ubd_blops = { .owner = THIS_MODULE, @@ -150,8 +155,9 @@ static struct gendisk *fake_gendisk[MAX_DEV]; static struct openflags global_openflags = OPEN_FLAGS; struct cow { - /* This is the backing file, actually */ + /* backing file name */ char *file; + /* backing file fd */ int fd; unsigned long *bitmap; unsigned long bitmap_len; @@ -160,14 +166,16 @@ struct cow { }; struct ubd { + /* name (and fd, below) of the file opened for writing, either the + * backing or the cow file. */ char *file; int count; int fd; __u64 size; struct openflags boot_openflags; struct openflags openflags; - int shared; - int no_cow; + unsigned shared:1; + unsigned no_cow:1; struct cow cow; struct platform_device pdev; }; @@ -192,18 +200,7 @@ struct ubd { .cow = DEFAULT_COW, \ } -struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; - -static int ubd0_init(void) -{ - struct ubd *dev = &ubd_dev[0]; - - if(dev->file == NULL) - dev->file = "root_fs"; - return(0); -} - -__initcall(ubd0_init); +struct ubd ubd_devs[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; /* Only changed by fake_ide_setup which is a setup */ static int fake_ide = 0; @@ -277,7 +274,7 @@ static int parse_unit(char **ptr) return(-1); *ptr = end; } - else if (('a' <= *str) && (*str <= 'h')) { + else if (('a' <= *str) && (*str <= 'z')) { n = *str - 'a'; str++; *ptr = str; @@ -285,9 +282,13 @@ static int parse_unit(char **ptr) return(n); } +/* If *index_out == -1 at exit, the passed option was a general one; + * otherwise, the str pointer is used (and owned) inside ubd_devs array, so it + * should not be freed on exit. + */ static int ubd_setup_common(char *str, int *index_out) { - struct ubd *dev; + struct ubd *ubd_dev; struct openflags flags = global_openflags; char *backing_file; int n, err, i; @@ -311,7 +312,7 @@ static int ubd_setup_common(char *str, int *index_out) } err = 1; - spin_lock(&ubd_lock); + mutex_lock(&ubd_lock); if(fake_major != MAJOR_NR){ printk(KERN_ERR "Can't assign a fake major twice\n"); goto out1; @@ -323,7 +324,7 @@ static int ubd_setup_common(char *str, int *index_out) major); err = 0; out1: - spin_unlock(&ubd_lock); + mutex_unlock(&ubd_lock); return(err); } @@ -340,10 +341,10 @@ static int ubd_setup_common(char *str, int *index_out) } err = 1; - spin_lock(&ubd_lock); + mutex_lock(&ubd_lock); - dev = &ubd_dev[n]; - if(dev->file != NULL){ + ubd_dev = &ubd_devs[n]; + if(ubd_dev->file != NULL){ printk(KERN_ERR "ubd_setup : device already configured\n"); goto out; } @@ -360,10 +361,10 @@ static int ubd_setup_common(char *str, int *index_out) flags.s = 1; break; case 'd': - dev->no_cow = 1; + ubd_dev->no_cow = 1; break; case 'c': - dev->shared = 1; + ubd_dev->shared = 1; break; case '=': str++; @@ -390,7 +391,7 @@ break_loop: } if(backing_file){ - if(dev->no_cow) + if(ubd_dev->no_cow) printk(KERN_ERR "Can't specify both 'd' and a " "cow file\n"); else { @@ -398,11 +399,11 @@ break_loop: backing_file++; } } - dev->file = str; - dev->cow.file = backing_file; - dev->boot_openflags = flags; + ubd_dev->file = str; + ubd_dev->cow.file = backing_file; + ubd_dev->boot_openflags = flags; out: - spin_unlock(&ubd_lock); + mutex_unlock(&ubd_lock); return(err); } @@ -472,8 +473,9 @@ int thread_fd = -1; /* Changed by ubd_handler, which is serialized because interrupts only * happen on CPU 0. + * XXX: currently unused. */ -int intr_count = 0; +static int intr_count = 0; /* call ubd_finish if you need to serialize */ static void __ubd_finish(struct request *req, int error) @@ -493,6 +495,8 @@ static void __ubd_finish(struct request *req, int error) end_request(req, 1); } +/* Callable only from interrupt context - otherwise you need to do + * spin_lock_irq()/spin_lock_irqsave() */ static inline void ubd_finish(struct request *req, int error) { spin_lock(&ubd_io_lock); @@ -500,14 +504,15 @@ static inline void ubd_finish(struct request *req, int error) spin_unlock(&ubd_io_lock); } -/* Called without ubd_io_lock held */ +/* XXX - move this inside ubd_intr. */ +/* Called without ubd_io_lock held, and only in interrupt context. */ static void ubd_handler(void) { struct io_thread_req req; struct request *rq = elv_next_request(ubd_queue); int n; - do_ubd = NULL; + do_ubd = 0; intr_count++; n = os_read_file(thread_fd, &req, sizeof(req)); if(n != sizeof(req)){ @@ -521,7 +526,9 @@ static void ubd_handler(void) ubd_finish(rq, req.error); reactivate_fd(thread_fd, UBD_IRQ); + spin_lock(&ubd_io_lock); do_ubd_request(ubd_queue); + spin_unlock(&ubd_io_lock); } static irqreturn_t ubd_intr(int irq, void *dev) @@ -541,87 +548,90 @@ void kill_io_thread(void) __uml_exitcall(kill_io_thread); -static int ubd_file_size(struct ubd *dev, __u64 *size_out) +static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out) { char *file; - file = dev->cow.file ? dev->cow.file : dev->file; + file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file; return(os_file_size(file, size_out)); } -static void ubd_close(struct ubd *dev) +static void ubd_close_dev(struct ubd *ubd_dev) { - os_close_file(dev->fd); - if(dev->cow.file == NULL) + os_close_file(ubd_dev->fd); + if(ubd_dev->cow.file == NULL) return; - os_close_file(dev->cow.fd); - vfree(dev->cow.bitmap); - dev->cow.bitmap = NULL; + os_close_file(ubd_dev->cow.fd); + vfree(ubd_dev->cow.bitmap); + ubd_dev->cow.bitmap = NULL; } -static int ubd_open_dev(struct ubd *dev) +static int ubd_open_dev(struct ubd *ubd_dev) { struct openflags flags; char **back_ptr; int err, create_cow, *create_ptr; + int fd; - dev->openflags = dev->boot_openflags; + ubd_dev->openflags = ubd_dev->boot_openflags; create_cow = 0; - create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL; - back_ptr = dev->no_cow ? NULL : &dev->cow.file; - dev->fd = open_ubd_file(dev->file, &dev->openflags, dev->shared, - back_ptr, &dev->cow.bitmap_offset, - &dev->cow.bitmap_len, &dev->cow.data_offset, + create_ptr = (ubd_dev->cow.file != NULL) ? &create_cow : NULL; + back_ptr = ubd_dev->no_cow ? NULL : &ubd_dev->cow.file; + + fd = open_ubd_file(ubd_dev->file, &ubd_dev->openflags, ubd_dev->shared, + back_ptr, &ubd_dev->cow.bitmap_offset, + &ubd_dev->cow.bitmap_len, &ubd_dev->cow.data_offset, create_ptr); - if((dev->fd == -ENOENT) && create_cow){ - dev->fd = create_cow_file(dev->file, dev->cow.file, - dev->openflags, 1 << 9, PAGE_SIZE, - &dev->cow.bitmap_offset, - &dev->cow.bitmap_len, - &dev->cow.data_offset); - if(dev->fd >= 0){ + if((fd == -ENOENT) && create_cow){ + fd = create_cow_file(ubd_dev->file, ubd_dev->cow.file, + ubd_dev->openflags, 1 << 9, PAGE_SIZE, + &ubd_dev->cow.bitmap_offset, + &ubd_dev->cow.bitmap_len, + &ubd_dev->cow.data_offset); + if(fd >= 0){ printk(KERN_INFO "Creating \"%s\" as COW file for " - "\"%s\"\n", dev->file, dev->cow.file); + "\"%s\"\n", ubd_dev->file, ubd_dev->cow.file); } } - if(dev->fd < 0){ - printk("Failed to open '%s', errno = %d\n", dev->file, - -dev->fd); - return(dev->fd); + if(fd < 0){ + printk("Failed to open '%s', errno = %d\n", ubd_dev->file, + -fd); + return fd; } + ubd_dev->fd = fd; - if(dev->cow.file != NULL){ + if(ubd_dev->cow.file != NULL){ err = -ENOMEM; - dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len); - if(dev->cow.bitmap == NULL){ + ubd_dev->cow.bitmap = (void *) vmalloc(ubd_dev->cow.bitmap_len); + if(ubd_dev->cow.bitmap == NULL){ printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); goto error; } flush_tlb_kernel_vm(); - err = read_cow_bitmap(dev->fd, dev->cow.bitmap, - dev->cow.bitmap_offset, - dev->cow.bitmap_len); + err = read_cow_bitmap(ubd_dev->fd, ubd_dev->cow.bitmap, + ubd_dev->cow.bitmap_offset, + ubd_dev->cow.bitmap_len); if(err < 0) goto error; - flags = dev->openflags; + flags = ubd_dev->openflags; flags.w = 0; - err = open_ubd_file(dev->cow.file, &flags, dev->shared, NULL, + err = open_ubd_file(ubd_dev->cow.file, &flags, ubd_dev->shared, NULL, NULL, NULL, NULL, NULL); if(err < 0) goto error; - dev->cow.fd = err; + ubd_dev->cow.fd = err; } return(0); error: - os_close_file(dev->fd); + os_close_file(ubd_dev->fd); return(err); } -static int ubd_new_disk(int major, u64 size, int unit, +static int ubd_disk_register(int major, u64 size, int unit, struct gendisk **disk_out) { @@ -642,13 +652,13 @@ static int ubd_new_disk(int major, u64 size, int unit, /* sysfs register (not for ide fake devices) */ if (major == MAJOR_NR) { - ubd_dev[unit].pdev.id = unit; - ubd_dev[unit].pdev.name = DRIVER_NAME; - platform_device_register(&ubd_dev[unit].pdev); - disk->driverfs_dev = &ubd_dev[unit].pdev.dev; + ubd_devs[unit].pdev.id = unit; + ubd_devs[unit].pdev.name = DRIVER_NAME; + platform_device_register(&ubd_devs[unit].pdev); + disk->driverfs_dev = &ubd_devs[unit].pdev.dev; } - disk->private_data = &ubd_dev[unit]; + disk->private_data = &ubd_devs[unit]; disk->queue = ubd_queue; add_disk(disk); @@ -660,25 +670,25 @@ static int ubd_new_disk(int major, u64 size, int unit, static int ubd_add(int n) { - struct ubd *dev = &ubd_dev[n]; + struct ubd *ubd_dev = &ubd_devs[n]; int err; err = -ENODEV; - if(dev->file == NULL) + if(ubd_dev->file == NULL) goto out; - err = ubd_file_size(dev, &dev->size); + err = ubd_file_size(ubd_dev, &ubd_dev->size); if(err < 0) goto out; - dev->size = ROUND_BLOCK(dev->size); + ubd_dev->size = ROUND_BLOCK(ubd_dev->size); - err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]); + err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]); if(err) goto out; if(fake_major != MAJOR_NR) - ubd_new_disk(fake_major, dev->size, n, + ubd_disk_register(fake_major, ubd_dev->size, n, &fake_gendisk[n]); /* perhaps this should also be under the "if (fake_major)" above */ @@ -693,32 +703,41 @@ out: static int ubd_config(char *str) { - int n, err; + int n, ret; str = kstrdup(str, GFP_KERNEL); - if(str == NULL){ + if (str == NULL) { printk(KERN_ERR "ubd_config failed to strdup string\n"); - return(1); + ret = 1; + goto out; } - err = ubd_setup_common(str, &n); - if(err){ - kfree(str); - return(-1); + ret = ubd_setup_common(str, &n); + if (ret) { + ret = -1; + goto err_free; + } + if (n == -1) { + ret = 0; + goto err_free; } - if(n == -1) return(0); - spin_lock(&ubd_lock); - err = ubd_add(n); - if(err) - ubd_dev[n].file = NULL; - spin_unlock(&ubd_lock); + mutex_lock(&ubd_lock); + ret = ubd_add(n); + if (ret) + ubd_devs[n].file = NULL; + mutex_unlock(&ubd_lock); - return(err); +out: + return ret; + +err_free: + kfree(str); + goto out; } static int ubd_get_config(char *name, char *str, int size, char **error_out) { - struct ubd *dev; + struct ubd *ubd_dev; int n, len = 0; n = parse_unit(&name); @@ -727,24 +746,24 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out) return(-1); } - dev = &ubd_dev[n]; - spin_lock(&ubd_lock); + ubd_dev = &ubd_devs[n]; + mutex_lock(&ubd_lock); - if(dev->file == NULL){ + if(ubd_dev->file == NULL){ CONFIG_CHUNK(str, size, len, "", 1); goto out; } - CONFIG_CHUNK(str, size, len, dev->file, 0); + CONFIG_CHUNK(str, size, len, ubd_dev->file, 0); - if(dev->cow.file != NULL){ + if(ubd_dev->cow.file != NULL){ CONFIG_CHUNK(str, size, len, ",", 0); - CONFIG_CHUNK(str, size, len, dev->cow.file, 1); + CONFIG_CHUNK(str, size, len, ubd_dev->cow.file, 1); } else CONFIG_CHUNK(str, size, len, "", 1); out: - spin_unlock(&ubd_lock); + mutex_unlock(&ubd_lock); return(len); } @@ -760,22 +779,22 @@ static int ubd_id(char **str, int *start_out, int *end_out) static int ubd_remove(int n) { - struct ubd *dev; + struct ubd *ubd_dev; int err = -ENODEV; - spin_lock(&ubd_lock); + mutex_lock(&ubd_lock); if(ubd_gendisk[n] == NULL) goto out; - dev = &ubd_dev[n]; + ubd_dev = &ubd_devs[n]; - if(dev->file == NULL) + if(ubd_dev->file == NULL) goto out; /* you cannot remove a open disk */ err = -EBUSY; - if(dev->count > 0) + if(ubd_dev->count > 0) goto out; del_gendisk(ubd_gendisk[n]); @@ -788,14 +807,15 @@ static int ubd_remove(int n) fake_gendisk[n] = NULL; } - platform_device_unregister(&dev->pdev); - *dev = ((struct ubd) DEFAULT_UBD); + platform_device_unregister(&ubd_dev->pdev); + *ubd_dev = ((struct ubd) DEFAULT_UBD); err = 0; out: - spin_unlock(&ubd_lock); + mutex_unlock(&ubd_lock); return err; } +/* All these are called by mconsole in process context and without ubd-specific locks. */ static struct mc_device ubd_mc = { .name = "ubd", .config = ubd_config, @@ -804,7 +824,7 @@ static struct mc_device ubd_mc = { .remove = ubd_remove, }; -static int ubd_mc_init(void) +static int __init ubd_mc_init(void) { mconsole_register_dev(&ubd_mc); return 0; @@ -812,13 +832,24 @@ static int ubd_mc_init(void) __initcall(ubd_mc_init); +static int __init ubd0_init(void) +{ + struct ubd *ubd_dev = &ubd_devs[0]; + + if(ubd_dev->file == NULL) + ubd_dev->file = "root_fs"; + return(0); +} + +__initcall(ubd0_init); + static struct platform_driver ubd_driver = { .driver = { .name = DRIVER_NAME, }, }; -int ubd_init(void) +static int __init ubd_init(void) { int i; @@ -846,7 +877,7 @@ int ubd_init(void) late_initcall(ubd_init); -int ubd_driver_init(void){ +static int __init ubd_driver_init(void){ unsigned long stack; int err; @@ -867,7 +898,7 @@ int ubd_driver_init(void){ return(0); } err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, - IRQF_DISABLED, "ubd", ubd_dev); + IRQF_DISABLED, "ubd", ubd_devs); if(err != 0) printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); return 0; @@ -878,24 +909,24 @@ device_initcall(ubd_driver_init); static int ubd_open(struct inode *inode, struct file *filp) { struct gendisk *disk = inode->i_bdev->bd_disk; - struct ubd *dev = disk->private_data; + struct ubd *ubd_dev = disk->private_data; int err = 0; - if(dev->count == 0){ - err = ubd_open_dev(dev); + if(ubd_dev->count == 0){ + err = ubd_open_dev(ubd_dev); if(err){ printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n", - disk->disk_name, dev->file, -err); + disk->disk_name, ubd_dev->file, -err); goto out; } } - dev->count++; - set_disk_ro(disk, !dev->openflags.w); + ubd_dev->count++; + set_disk_ro(disk, !ubd_dev->openflags.w); /* This should no more be needed. And it didn't work anyway to exclude * read-write remounting of filesystems.*/ - /*if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){ - if(--dev->count == 0) ubd_close(dev); + /*if((filp->f_mode & FMODE_WRITE) && !ubd_dev->openflags.w){ + if(--ubd_dev->count == 0) ubd_close_dev(ubd_dev); err = -EROFS; }*/ out: @@ -905,10 +936,10 @@ static int ubd_open(struct inode *inode, struct file *filp) static int ubd_release(struct inode * inode, struct file * file) { struct gendisk *disk = inode->i_bdev->bd_disk; - struct ubd *dev = disk->private_data; + struct ubd *ubd_dev = disk->private_data; - if(--dev->count == 0) - ubd_close(dev); + if(--ubd_dev->count == 0) + ubd_close_dev(ubd_dev); return(0); } @@ -976,12 +1007,12 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, static int prepare_request(struct request *req, struct io_thread_req *io_req) { struct gendisk *disk = req->rq_disk; - struct ubd *dev = disk->private_data; + struct ubd *ubd_dev = disk->private_data; __u64 offset; int len; /* This should be impossible now */ - if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ + if((rq_data_dir(req) == WRITE) && !ubd_dev->openflags.w){ printk("Write attempted on readonly ubd device %s\n", disk->disk_name); end_request(req, 0); @@ -991,8 +1022,8 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) offset = ((__u64) req->sector) << 9; len = req->current_nr_sectors << 9; - io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd; - io_req->fds[1] = dev->fd; + io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : ubd_dev->fd; + io_req->fds[1] = ubd_dev->fd; io_req->cow_offset = -1; io_req->offset = offset; io_req->length = len; @@ -1001,13 +1032,13 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; io_req->offsets[0] = 0; - io_req->offsets[1] = dev->cow.data_offset; + io_req->offsets[1] = ubd_dev->cow.data_offset; io_req->buffer = req->buffer; io_req->sectorsize = 1 << 9; - if(dev->cow.file != NULL) - cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset, - dev->cow.bitmap_len); + if(ubd_dev->cow.file != NULL) + cowify_req(io_req, ubd_dev->cow.bitmap, ubd_dev->cow.bitmap_offset, + ubd_dev->cow.bitmap_len); return(0); } @@ -1033,7 +1064,7 @@ static void do_ubd_request(request_queue_t *q) return; err = prepare_request(req, &io_req); if(!err){ - do_ubd = ubd_handler; + do_ubd = 1; n = os_write_file(thread_fd, (char *) &io_req, sizeof(io_req)); if(n != sizeof(io_req)) @@ -1045,18 +1076,18 @@ static void do_ubd_request(request_queue_t *q) static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo) { - struct ubd *dev = bdev->bd_disk->private_data; + struct ubd *ubd_dev = bdev->bd_disk->private_data; geo->heads = 128; geo->sectors = 32; - geo->cylinders = dev->size / (128 * 32 * 512); + geo->cylinders = ubd_dev->size / (128 * 32 * 512); return 0; } static int ubd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { - struct ubd *dev = inode->i_bdev->bd_disk->private_data; + struct ubd *ubd_dev = inode->i_bdev->bd_disk->private_data; struct hd_driveid ubd_id = { .cyls = 0, .heads = 128, @@ -1066,7 +1097,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file, switch (cmd) { struct cdrom_volctrl volume; case HDIO_GET_IDENTITY: - ubd_id.cyls = dev->size / (128 * 32 * 512); + ubd_id.cyls = ubd_dev->size / (128 * 32 * 512); if(copy_to_user((char __user *) arg, (char *) &ubd_id, sizeof(ubd_id))) return(-EFAULT); @@ -1353,8 +1384,8 @@ void do_io(struct io_thread_req *req) */ int kernel_fd = -1; -/* Only changed by the io thread */ -int io_count = 0; +/* Only changed by the io thread. XXX: currently unused. */ +static int io_count = 0; int io_thread(void *arg) { diff --git a/arch/um/include/mconsole_kern.h b/arch/um/include/mconsole_kern.h index d0b690197fd..1ea6d928e1c 100644 --- a/arch/um/include/mconsole_kern.h +++ b/arch/um/include/mconsole_kern.h @@ -14,6 +14,7 @@ struct mconsole_entry { struct mc_request request; }; +/* All these methods are called in process context. */ struct mc_device { struct list_head list; char *name; diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index 68ed24df5c8..e36f92b463c 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S @@ -14,6 +14,7 @@ SECTIONS * is remapped.*/ __binary_start = .; . = ALIGN(4096); /* Init code and data */ + _text = .; _stext = .; __init_begin = .; .init.text : { diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c index 9882342206e..b9195355075 100644 --- a/arch/um/kernel/tt/tracer.c +++ b/arch/um/kernel/tt/tracer.c @@ -176,7 +176,6 @@ struct { int signal_index[32]; int nsignals = 0; int debug_trace = 0; -extern int io_nsignals, io_count, intr_count; extern void signal_usr1(int sig); diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index 8eca47a6ff0..f6301274cf3 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S @@ -25,6 +25,7 @@ SECTIONS . = ALIGN(4096); /* Init code and data */ #endif + _text = .; _stext = .; __init_begin = .; .init.text : { diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 136066583c6..c7b1dac8bee 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -2999,6 +2999,7 @@ void generic_make_request(struct bio *bio) { request_queue_t *q; sector_t maxsector; + sector_t old_sector; int ret, nr_sectors = bio_sectors(bio); dev_t old_dev; @@ -3027,7 +3028,7 @@ void generic_make_request(struct bio *bio) * NOTE: we don't repeat the blk_size check for each new device. * Stacking drivers are expected to know what they are doing. */ - maxsector = -1; + old_sector = -1; old_dev = 0; do { char b[BDEVNAME_SIZE]; @@ -3061,15 +3062,30 @@ end_io: */ blk_partition_remap(bio); - if (maxsector != -1) + if (old_sector != -1) blk_add_trace_remap(q, bio, old_dev, bio->bi_sector, - maxsector); + old_sector); blk_add_trace_bio(q, bio, BLK_TA_QUEUE); - maxsector = bio->bi_sector; + old_sector = bio->bi_sector; old_dev = bio->bi_bdev->bd_dev; + maxsector = bio->bi_bdev->bd_inode->i_size >> 9; + if (maxsector) { + sector_t sector = bio->bi_sector; + + if (maxsector < nr_sectors || maxsector - nr_sectors < sector) { + /* + * This may well happen - partitions are not checked + * to make sure they are within the size of the + * whole device. + */ + handle_bad_sector(bio); + goto end_io; + } + } + ret = q->make_request_fn(q, bio); } while (ret); } diff --git a/fs/block_dev.c b/fs/block_dev.c index 702b88cbd91..36c0e7af9d0 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -642,34 +642,47 @@ static void free_bd_holder(struct bd_holder *bo) } /** + * find_bd_holder - find matching struct bd_holder from the block device + * + * @bdev: struct block device to be searched + * @bo: target struct bd_holder + * + * Returns matching entry with @bo in @bdev->bd_holder_list. + * If found, increment the reference count and return the pointer. + * If not found, returns NULL. + */ +static struct bd_holder *find_bd_holder(struct block_device *bdev, + struct bd_holder *bo) +{ + struct bd_holder *tmp; + + list_for_each_entry(tmp, &bdev->bd_holder_list, list) + if (tmp->sdir == bo->sdir) { + tmp->count++; + return tmp; + } + + return NULL; +} + +/** * add_bd_holder - create sysfs symlinks for bd_claim() relationship * * @bdev: block device to be bd_claimed * @bo: preallocated and initialized by alloc_bd_holder() * - * If there is no matching entry with @bo in @bdev->bd_holder_list, - * add @bo to the list, create symlinks. + * Add @bo to @bdev->bd_holder_list, create symlinks. * - * Returns 0 if symlinks are created or already there. - * Returns -ve if something fails and @bo can be freed. + * Returns 0 if symlinks are created. + * Returns -ve if something fails. */ static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) { - struct bd_holder *tmp; int ret; if (!bo) return -EINVAL; - list_for_each_entry(tmp, &bdev->bd_holder_list, list) { - if (tmp->sdir == bo->sdir) { - tmp->count++; - /* We've already done what we need to do here. */ - free_bd_holder(bo); - return 0; - } - } - if (!bd_holder_grab_dirs(bdev, bo)) return -EBUSY; @@ -740,7 +753,7 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder, struct kobject *kobj) { int res; - struct bd_holder *bo; + struct bd_holder *bo, *found; if (!kobj) return -EINVAL; @@ -751,9 +764,16 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder, mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); res = bd_claim(bdev, holder); - if (res == 0) - res = add_bd_holder(bdev, bo); - if (res) + if (res == 0) { + found = find_bd_holder(bdev, bo); + if (found == NULL) { + res = add_bd_holder(bdev, bo); + if (res) + bd_release(bdev); + } + } + + if (res || found) free_bd_holder(bo); mutex_unlock(&bdev->bd_mutex); diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index ed35a9712fa..f49f105394b 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -94,25 +94,53 @@ static int ecryptfs_calculate_md5(char *dst, struct ecryptfs_crypt_stat *crypt_stat, char *src, int len) { - int rc = 0; struct scatterlist sg; + struct hash_desc desc = { + .tfm = crypt_stat->hash_tfm, + .flags = CRYPTO_TFM_REQ_MAY_SLEEP + }; + int rc = 0; - mutex_lock(&crypt_stat->cs_md5_tfm_mutex); + mutex_lock(&crypt_stat->cs_hash_tfm_mutex); sg_init_one(&sg, (u8 *)src, len); - if (!crypt_stat->md5_tfm) { - crypt_stat->md5_tfm = - crypto_alloc_tfm("md5", CRYPTO_TFM_REQ_MAY_SLEEP); - if (!crypt_stat->md5_tfm) { - rc = -ENOMEM; + if (!desc.tfm) { + desc.tfm = crypto_alloc_hash(ECRYPTFS_DEFAULT_HASH, 0, + CRYPTO_ALG_ASYNC); + if (IS_ERR(desc.tfm)) { + rc = PTR_ERR(desc.tfm); ecryptfs_printk(KERN_ERR, "Error attempting to " - "allocate crypto context\n"); + "allocate crypto context; rc = [%d]\n", + rc); goto out; } + crypt_stat->hash_tfm = desc.tfm; } - crypto_digest_init(crypt_stat->md5_tfm); - crypto_digest_update(crypt_stat->md5_tfm, &sg, 1); - crypto_digest_final(crypt_stat->md5_tfm, dst); - mutex_unlock(&crypt_stat->cs_md5_tfm_mutex); + crypto_hash_init(&desc); + crypto_hash_update(&desc, &sg, len); + crypto_hash_final(&desc, dst); + mutex_unlock(&crypt_stat->cs_hash_tfm_mutex); +out: + return rc; +} + +int ecryptfs_crypto_api_algify_cipher_name(char **algified_name, + char *cipher_name, + char *chaining_modifier) +{ + int cipher_name_len = strlen(cipher_name); + int chaining_modifier_len = strlen(chaining_modifier); + int algified_name_len; + int rc; + + algified_name_len = (chaining_modifier_len + cipher_name_len + 3); + (*algified_name) = kmalloc(algified_name_len, GFP_KERNEL); + if (!(algified_name)) { + rc = -ENOMEM; + goto out; + } + snprintf((*algified_name), algified_name_len, "%s(%s)", + chaining_modifier, cipher_name); + rc = 0; out: return rc; } @@ -178,7 +206,7 @@ ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) memset((void *)crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); mutex_init(&crypt_stat->cs_mutex); mutex_init(&crypt_stat->cs_tfm_mutex); - mutex_init(&crypt_stat->cs_md5_tfm_mutex); + mutex_init(&crypt_stat->cs_hash_tfm_mutex); ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_STRUCT_INITIALIZED); } @@ -191,9 +219,9 @@ ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) void ecryptfs_destruct_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) { if (crypt_stat->tfm) - crypto_free_tfm(crypt_stat->tfm); - if (crypt_stat->md5_tfm) - crypto_free_tfm(crypt_stat->md5_tfm); + crypto_free_blkcipher(crypt_stat->tfm); + if (crypt_stat->hash_tfm) + crypto_free_hash(crypt_stat->hash_tfm); memset(crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); } @@ -203,7 +231,7 @@ void ecryptfs_destruct_mount_crypt_stat( if (mount_crypt_stat->global_auth_tok_key) key_put(mount_crypt_stat->global_auth_tok_key); if (mount_crypt_stat->global_key_tfm) - crypto_free_tfm(mount_crypt_stat->global_key_tfm); + crypto_free_blkcipher(mount_crypt_stat->global_key_tfm); memset(mount_crypt_stat, 0, sizeof(struct ecryptfs_mount_crypt_stat)); } @@ -269,6 +297,11 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, struct scatterlist *src_sg, int size, unsigned char *iv) { + struct blkcipher_desc desc = { + .tfm = crypt_stat->tfm, + .info = iv, + .flags = CRYPTO_TFM_REQ_MAY_SLEEP + }; int rc = 0; BUG_ON(!crypt_stat || !crypt_stat->tfm @@ -282,8 +315,8 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, } /* Consider doing this once, when the file is opened */ mutex_lock(&crypt_stat->cs_tfm_mutex); - rc = crypto_cipher_setkey(crypt_stat->tfm, crypt_stat->key, - crypt_stat->key_size); + rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key, + crypt_stat->key_size); if (rc) { ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n", rc); @@ -292,7 +325,7 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, goto out; } ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size); - crypto_cipher_encrypt_iv(crypt_stat->tfm, dest_sg, src_sg, size, iv); + crypto_blkcipher_encrypt_iv(&desc, dest_sg, src_sg, size); mutex_unlock(&crypt_stat->cs_tfm_mutex); out: return rc; @@ -675,12 +708,17 @@ static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, struct scatterlist *src_sg, int size, unsigned char *iv) { + struct blkcipher_desc desc = { + .tfm = crypt_stat->tfm, + .info = iv, + .flags = CRYPTO_TFM_REQ_MAY_SLEEP + }; int rc = 0; /* Consider doing this once, when the file is opened */ mutex_lock(&crypt_stat->cs_tfm_mutex); - rc = crypto_cipher_setkey(crypt_stat->tfm, crypt_stat->key, - crypt_stat->key_size); + rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key, + crypt_stat->key_size); if (rc) { ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n", rc); @@ -689,8 +727,7 @@ static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, goto out; } ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size); - rc = crypto_cipher_decrypt_iv(crypt_stat->tfm, dest_sg, src_sg, size, - iv); + rc = crypto_blkcipher_decrypt_iv(&desc, dest_sg, src_sg, size); mutex_unlock(&crypt_stat->cs_tfm_mutex); if (rc) { ecryptfs_printk(KERN_ERR, "Error decrypting; rc = [%d]\n", @@ -759,6 +796,7 @@ ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, */ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat) { + char *full_alg_name; int rc = -EINVAL; if (!crypt_stat->cipher) { @@ -775,16 +813,24 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat) goto out; } mutex_lock(&crypt_stat->cs_tfm_mutex); - crypt_stat->tfm = crypto_alloc_tfm(crypt_stat->cipher, - ECRYPTFS_DEFAULT_CHAINING_MODE - | CRYPTO_TFM_REQ_WEAK_KEY); - mutex_unlock(&crypt_stat->cs_tfm_mutex); + rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, + crypt_stat->cipher, "cbc"); + if (rc) + goto out; + crypt_stat->tfm = crypto_alloc_blkcipher(full_alg_name, 0, + CRYPTO_ALG_ASYNC); + kfree(full_alg_name); if (!crypt_stat->tfm) { ecryptfs_printk(KERN_ERR, "cryptfs: init_crypt_ctx(): " "Error initializing cipher [%s]\n", crypt_stat->cipher); + mutex_unlock(&crypt_stat->cs_tfm_mutex); goto out; } + crypto_blkcipher_set_flags(crypt_stat->tfm, + (ECRYPTFS_DEFAULT_CHAINING_MODE + | CRYPTO_TFM_REQ_WEAK_KEY)); + mutex_unlock(&crypt_stat->cs_tfm_mutex); rc = 0; out: return rc; @@ -1145,28 +1191,28 @@ int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code) int ecryptfs_read_header_region(char *data, struct dentry *dentry, struct vfsmount *mnt) { - struct file *file; + struct file *lower_file; mm_segment_t oldfs; int rc; - mnt = mntget(mnt); - file = dentry_open(dentry, mnt, O_RDONLY); - if (IS_ERR(file)) { - ecryptfs_printk(KERN_DEBUG, "Error opening file to " - "read header region\n"); - mntput(mnt); - rc = PTR_ERR(file); + if ((rc = ecryptfs_open_lower_file(&lower_file, dentry, mnt, + O_RDONLY))) { + printk(KERN_ERR + "Error opening lower_file to read header region\n"); goto out; } - file->f_pos = 0; + lower_file->f_pos = 0; oldfs = get_fs(); set_fs(get_ds()); /* For releases 0.1 and 0.2, all of the header information * fits in the first data extent-sized region. */ - rc = file->f_op->read(file, (char __user *)data, - ECRYPTFS_DEFAULT_EXTENT_SIZE, &file->f_pos); + rc = lower_file->f_op->read(lower_file, (char __user *)data, + ECRYPTFS_DEFAULT_EXTENT_SIZE, &lower_file->f_pos); set_fs(oldfs); - fput(file); + if ((rc = ecryptfs_close_lower_file(lower_file))) { + printk(KERN_ERR "Error closing lower_file\n"); + goto out; + } rc = 0; out: return rc; @@ -1573,84 +1619,52 @@ out: /** * ecryptfs_process_cipher - Perform cipher initialization. - * @tfm: Crypto context set by this function * @key_tfm: Crypto context for key material, set by this function - * @cipher_name: Name of the cipher. - * @key_size: Size of the key in bytes. + * @cipher_name: Name of the cipher + * @key_size: Size of the key in bytes * * Returns zero on success. Any crypto_tfm structs allocated here * should be released by other functions, such as on a superblock put * event, regardless of whether this function succeeds for fails. */ int -ecryptfs_process_cipher(struct crypto_tfm **tfm, struct crypto_tfm **key_tfm, - char *cipher_name, size_t key_size) +ecryptfs_process_cipher(struct crypto_blkcipher **key_tfm, char *cipher_name, + size_t *key_size) { char dummy_key[ECRYPTFS_MAX_KEY_BYTES]; + char *full_alg_name; int rc; - *tfm = *key_tfm = NULL; - if (key_size > ECRYPTFS_MAX_KEY_BYTES) { + *key_tfm = NULL; + if (*key_size > ECRYPTFS_MAX_KEY_BYTES) { rc = -EINVAL; printk(KERN_ERR "Requested key size is [%Zd] bytes; maximum " - "allowable is [%d]\n", key_size, ECRYPTFS_MAX_KEY_BYTES); + "allowable is [%d]\n", *key_size, ECRYPTFS_MAX_KEY_BYTES); goto out; } - *tfm = crypto_alloc_tfm(cipher_name, (ECRYPTFS_DEFAULT_CHAINING_MODE - | CRYPTO_TFM_REQ_WEAK_KEY)); - if (!(*tfm)) { - rc = -EINVAL; - printk(KERN_ERR "Unable to allocate crypto cipher with name " - "[%s]\n", cipher_name); + rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, cipher_name, + "ecb"); + if (rc) goto out; - } - *key_tfm = crypto_alloc_tfm(cipher_name, CRYPTO_TFM_REQ_WEAK_KEY); - if (!(*key_tfm)) { - rc = -EINVAL; + *key_tfm = crypto_alloc_blkcipher(full_alg_name, 0, CRYPTO_ALG_ASYNC); + kfree(full_alg_name); + if (IS_ERR(*key_tfm)) { + rc = PTR_ERR(*key_tfm); printk(KERN_ERR "Unable to allocate crypto cipher with name " - "[%s]\n", cipher_name); - goto out; - } - if (key_size < crypto_tfm_alg_min_keysize(*tfm)) { - rc = -EINVAL; - printk(KERN_ERR "Request key size is [%Zd]; minimum key size " - "supported by cipher [%s] is [%d]\n", key_size, - cipher_name, crypto_tfm_alg_min_keysize(*tfm)); - goto out; - } - if (key_size < crypto_tfm_alg_min_keysize(*key_tfm)) { - rc = -EINVAL; - printk(KERN_ERR "Request key size is [%Zd]; minimum key size " - "supported by cipher [%s] is [%d]\n", key_size, - cipher_name, crypto_tfm_alg_min_keysize(*key_tfm)); + "[%s]; rc = [%d]\n", cipher_name, rc); goto out; } - if (key_size > crypto_tfm_alg_max_keysize(*tfm)) { - rc = -EINVAL; - printk(KERN_ERR "Request key size is [%Zd]; maximum key size " - "supported by cipher [%s] is [%d]\n", key_size, - cipher_name, crypto_tfm_alg_min_keysize(*tfm)); - goto out; - } - if (key_size > crypto_tfm_alg_max_keysize(*key_tfm)) { - rc = -EINVAL; - printk(KERN_ERR "Request key size is [%Zd]; maximum key size " - "supported by cipher [%s] is [%d]\n", key_size, - cipher_name, crypto_tfm_alg_min_keysize(*key_tfm)); - goto out; - } - get_random_bytes(dummy_key, key_size); - rc = crypto_cipher_setkey(*tfm, dummy_key, key_size); - if (rc) { - printk(KERN_ERR "Error attempting to set key of size [%Zd] for " - "cipher [%s]; rc = [%d]\n", key_size, cipher_name, rc); - rc = -EINVAL; - goto out; + crypto_blkcipher_set_flags(*key_tfm, CRYPTO_TFM_REQ_WEAK_KEY); + if (*key_size == 0) { + struct blkcipher_alg *alg = crypto_blkcipher_alg(*key_tfm); + + *key_size = alg->max_keysize; } - rc = crypto_cipher_setkey(*key_tfm, dummy_key, key_size); + get_random_bytes(dummy_key, *key_size); + rc = crypto_blkcipher_setkey(*key_tfm, dummy_key, *key_size); if (rc) { printk(KERN_ERR "Error attempting to set key of size [%Zd] for " - "cipher [%s]; rc = [%d]\n", key_size, cipher_name, rc); + "cipher [%s]; rc = [%d]\n", *key_size, cipher_name, rc); rc = -EINVAL; goto out; } diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c index f0d2a433242..0b9992ab990 100644 --- a/fs/ecryptfs/dentry.c +++ b/fs/ecryptfs/dentry.c @@ -24,6 +24,7 @@ #include <linux/dcache.h> #include <linux/namei.h> +#include <linux/mount.h> #include "ecryptfs_kernel.h" /** @@ -76,8 +77,13 @@ static void ecryptfs_d_release(struct dentry *dentry) if (ecryptfs_dentry_to_private(dentry)) kmem_cache_free(ecryptfs_dentry_info_cache, ecryptfs_dentry_to_private(dentry)); - if (lower_dentry) + if (lower_dentry) { + struct vfsmount *lower_mnt = + ecryptfs_dentry_to_lower_mnt(dentry); + + mntput(lower_mnt); dput(lower_dentry); + } return; } diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 872c9958531..f992533d169 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -175,6 +175,7 @@ ecryptfs_get_key_payload_data(struct key *key) #define ECRYPTFS_DEFAULT_CIPHER "aes" #define ECRYPTFS_DEFAULT_KEY_BYTES 16 #define ECRYPTFS_DEFAULT_CHAINING_MODE CRYPTO_TFM_MODE_CBC +#define ECRYPTFS_DEFAULT_HASH "md5" #define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C #define ECRYPTFS_TAG_11_PACKET_TYPE 0xED #define MD5_DIGEST_SIZE 16 @@ -204,15 +205,15 @@ struct ecryptfs_crypt_stat { size_t extent_shift; unsigned int extent_mask; struct ecryptfs_mount_crypt_stat *mount_crypt_stat; - struct crypto_tfm *tfm; - struct crypto_tfm *md5_tfm; /* Crypto context for generating - * the initialization vectors */ + struct crypto_blkcipher *tfm; + struct crypto_hash *hash_tfm; /* Crypto context for generating + * the initialization vectors */ unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE]; unsigned char key[ECRYPTFS_MAX_KEY_BYTES]; unsigned char root_iv[ECRYPTFS_MAX_IV_BYTES]; unsigned char keysigs[ECRYPTFS_MAX_NUM_KEYSIGS][ECRYPTFS_SIG_SIZE_HEX]; struct mutex cs_tfm_mutex; - struct mutex cs_md5_tfm_mutex; + struct mutex cs_hash_tfm_mutex; struct mutex cs_mutex; }; @@ -244,7 +245,7 @@ struct ecryptfs_mount_crypt_stat { struct ecryptfs_auth_tok *global_auth_tok; struct key *global_auth_tok_key; size_t global_default_cipher_key_size; - struct crypto_tfm *global_key_tfm; + struct crypto_blkcipher *global_key_tfm; struct mutex global_key_tfm_mutex; unsigned char global_default_cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1]; @@ -425,6 +426,9 @@ void ecryptfs_destruct_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat); void ecryptfs_destruct_mount_crypt_stat( struct ecryptfs_mount_crypt_stat *mount_crypt_stat); int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat); +int ecryptfs_crypto_api_algify_cipher_name(char **algified_name, + char *cipher_name, + char *chaining_modifier); int ecryptfs_write_inode_size_to_header(struct file *lower_file, struct inode *lower_inode, struct inode *inode); @@ -473,10 +477,14 @@ ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, unsigned char *src, struct dentry *ecryptfs_dentry); int ecryptfs_truncate(struct dentry *dentry, loff_t new_length); int -ecryptfs_process_cipher(struct crypto_tfm **tfm, struct crypto_tfm **key_tfm, - char *cipher_name, size_t key_size); +ecryptfs_process_cipher(struct crypto_blkcipher **key_tfm, char *cipher_name, + size_t *key_size); int ecryptfs_inode_test(struct inode *inode, void *candidate_lower_inode); int ecryptfs_inode_set(struct inode *inode, void *lower_inode); void ecryptfs_init_inode(struct inode *inode, struct inode *lower_inode); +int ecryptfs_open_lower_file(struct file **lower_file, + struct dentry *lower_dentry, + struct vfsmount *lower_mnt, int flags); +int ecryptfs_close_lower_file(struct file *lower_file); #endif /* #ifndef ECRYPTFS_KERNEL_H */ diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index c8550c9f9cd..a92ef05eff8 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -198,6 +198,33 @@ retry: struct kmem_cache *ecryptfs_file_info_cache; +int ecryptfs_open_lower_file(struct file **lower_file, + struct dentry *lower_dentry, + struct vfsmount *lower_mnt, int flags) +{ + int rc = 0; + + dget(lower_dentry); + mntget(lower_mnt); + *lower_file = dentry_open(lower_dentry, lower_mnt, flags); + if (IS_ERR(*lower_file)) { + printk(KERN_ERR "Error opening lower file for lower_dentry " + "[0x%p], lower_mnt [0x%p], and flags [0x%x]\n", + lower_dentry, lower_mnt, flags); + rc = PTR_ERR(*lower_file); + *lower_file = NULL; + goto out; + } +out: + return rc; +} + +int ecryptfs_close_lower_file(struct file *lower_file) +{ + fput(lower_file); + return 0; +} + /** * ecryptfs_open * @inode: inode speciying file to open @@ -244,19 +271,15 @@ static int ecryptfs_open(struct inode *inode, struct file *file) ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); } mutex_unlock(&crypt_stat->cs_mutex); - /* This mntget & dget is undone via fput when the file is released */ - dget(lower_dentry); lower_flags = file->f_flags; if ((lower_flags & O_ACCMODE) == O_WRONLY) lower_flags = (lower_flags & O_ACCMODE) | O_RDWR; if (file->f_flags & O_APPEND) lower_flags &= ~O_APPEND; lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); - mntget(lower_mnt); /* Corresponding fput() in ecryptfs_release() */ - lower_file = dentry_open(lower_dentry, lower_mnt, lower_flags); - if (IS_ERR(lower_file)) { - rc = PTR_ERR(lower_file); + if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt, + lower_flags))) { ecryptfs_printk(KERN_ERR, "Error opening lower file\n"); goto out_puts; } @@ -341,11 +364,16 @@ static int ecryptfs_release(struct inode *inode, struct file *file) struct file *lower_file = ecryptfs_file_to_lower(file); struct ecryptfs_file_info *file_info = ecryptfs_file_to_private(file); struct inode *lower_inode = ecryptfs_inode_to_lower(inode); + int rc; - fput(lower_file); + if ((rc = ecryptfs_close_lower_file(lower_file))) { + printk(KERN_ERR "Error closing lower_file\n"); + goto out; + } inode->i_blocks = lower_inode->i_blocks; kmem_cache_free(ecryptfs_file_info_cache, file_info); - return 0; +out: + return rc; } static int diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index efdd2b7b62d..ff4865d24f0 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -231,7 +231,6 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) int lower_flags; struct ecryptfs_crypt_stat *crypt_stat; struct dentry *lower_dentry; - struct dentry *tlower_dentry = NULL; struct file *lower_file; struct inode *inode, *lower_inode; struct vfsmount *lower_mnt; @@ -241,30 +240,19 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) lower_dentry->d_name.name); inode = ecryptfs_dentry->d_inode; crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; - tlower_dentry = dget(lower_dentry); - if (!tlower_dentry) { - rc = -ENOMEM; - ecryptfs_printk(KERN_ERR, "Error dget'ing lower_dentry\n"); - goto out; - } lower_flags = ((O_CREAT | O_WRONLY | O_TRUNC) & O_ACCMODE) | O_RDWR; #if BITS_PER_LONG != 32 lower_flags |= O_LARGEFILE; #endif lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); - mntget(lower_mnt); /* Corresponding fput() at end of this function */ - lower_file = dentry_open(tlower_dentry, lower_mnt, lower_flags); - if (IS_ERR(lower_file)) { - rc = PTR_ERR(lower_file); + if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt, + lower_flags))) { ecryptfs_printk(KERN_ERR, "Error opening dentry; rc = [%i]\n", rc); goto out; } - /* fput(lower_file) should handle the puts if we do this */ - lower_file->f_dentry = tlower_dentry; - lower_file->f_vfsmnt = lower_mnt; - lower_inode = tlower_dentry->d_inode; + lower_inode = lower_dentry->d_inode; if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); @@ -285,7 +273,8 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) } rc = grow_file(ecryptfs_dentry, lower_file, inode, lower_inode); out_fput: - fput(lower_file); + if ((rc = ecryptfs_close_lower_file(lower_file))) + printk(KERN_ERR "Error closing lower_file\n"); out: return rc; } @@ -336,7 +325,6 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, struct dentry *lower_dir_dentry; struct dentry *lower_dentry; struct vfsmount *lower_mnt; - struct dentry *tlower_dentry = NULL; char *encoded_name; unsigned int encoded_namelen; struct ecryptfs_crypt_stat *crypt_stat = NULL; @@ -347,27 +335,32 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, lower_dir_dentry = ecryptfs_dentry_to_lower(dentry->d_parent); dentry->d_op = &ecryptfs_dops; if ((dentry->d_name.len == 1 && !strcmp(dentry->d_name.name, ".")) - || (dentry->d_name.len == 2 && !strcmp(dentry->d_name.name, ".."))) - goto out_drop; + || (dentry->d_name.len == 2 + && !strcmp(dentry->d_name.name, ".."))) { + d_drop(dentry); + goto out; + } encoded_namelen = ecryptfs_encode_filename(crypt_stat, dentry->d_name.name, dentry->d_name.len, &encoded_name); if (encoded_namelen < 0) { rc = encoded_namelen; - goto out_drop; + d_drop(dentry); + goto out; } ecryptfs_printk(KERN_DEBUG, "encoded_name = [%s]; encoded_namelen " "= [%d]\n", encoded_name, encoded_namelen); lower_dentry = lookup_one_len(encoded_name, lower_dir_dentry, encoded_namelen - 1); kfree(encoded_name); - lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); if (IS_ERR(lower_dentry)) { ecryptfs_printk(KERN_ERR, "ERR from lower_dentry\n"); rc = PTR_ERR(lower_dentry); - goto out_drop; + d_drop(dentry); + goto out; } + lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); ecryptfs_printk(KERN_DEBUG, "lower_dentry = [%p]; lower_dentry->" "d_name.name = [%s]\n", lower_dentry, lower_dentry->d_name.name); @@ -408,12 +401,6 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, "as we *think* we are about to unlink\n"); goto out; } - tlower_dentry = dget(lower_dentry); - if (!tlower_dentry || IS_ERR(tlower_dentry)) { - rc = -ENOMEM; - ecryptfs_printk(KERN_ERR, "Cannot dget lower_dentry\n"); - goto out_dput; - } /* Released in this function */ page_virt = (char *)kmem_cache_alloc(ecryptfs_header_cache_2, @@ -425,7 +412,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, goto out_dput; } memset(page_virt, 0, PAGE_CACHE_SIZE); - rc = ecryptfs_read_header_region(page_virt, tlower_dentry, nd->mnt); + rc = ecryptfs_read_header_region(page_virt, lower_dentry, nd->mnt); crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) ecryptfs_set_default_sizes(crypt_stat); @@ -448,9 +435,6 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, out_dput: dput(lower_dentry); - if (tlower_dentry) - dput(tlower_dentry); -out_drop: d_drop(dentry); out: return ERR_PTR(rc); @@ -486,8 +470,8 @@ out_lock: unlock_dir(lower_dir_dentry); dput(lower_new_dentry); dput(lower_old_dentry); - if (!new_dentry->d_inode) - d_drop(new_dentry); + d_drop(new_dentry); + d_drop(old_dentry); return rc; } @@ -576,41 +560,24 @@ out: static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) { - int rc = 0; - struct dentry *tdentry = NULL; struct dentry *lower_dentry; - struct dentry *tlower_dentry = NULL; struct dentry *lower_dir_dentry; + int rc; lower_dentry = ecryptfs_dentry_to_lower(dentry); - if (!(tdentry = dget(dentry))) { - rc = -EINVAL; - ecryptfs_printk(KERN_ERR, "Error dget'ing dentry [%p]\n", - dentry); - goto out; - } + dget(dentry); lower_dir_dentry = lock_parent(lower_dentry); - if (!(tlower_dentry = dget(lower_dentry))) { - rc = -EINVAL; - ecryptfs_printk(KERN_ERR, "Error dget'ing lower_dentry " - "[%p]\n", lower_dentry); - goto out; - } + dget(lower_dentry); rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); - if (!rc) { - d_delete(tlower_dentry); - tlower_dentry = NULL; - } + dput(lower_dentry); + if (!rc) + d_delete(lower_dentry); ecryptfs_copy_attr_times(dir, lower_dir_dentry->d_inode); dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; unlock_dir(lower_dir_dentry); if (!rc) d_drop(dentry); -out: - if (tdentry) - dput(tdentry); - if (tlower_dentry) - dput(tlower_dentry); + dput(dentry); return rc; } @@ -832,12 +799,11 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) } lower_dentry = ecryptfs_dentry_to_lower(dentry); /* This dget & mntget is released through fput at out_fput: */ - dget(lower_dentry); lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); - mntget(lower_mnt); - lower_file = dentry_open(lower_dentry, lower_mnt, O_RDWR); - if (unlikely(IS_ERR(lower_file))) { - rc = PTR_ERR(lower_file); + if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt, + O_RDWR))) { + ecryptfs_printk(KERN_ERR, + "Error opening dentry; rc = [%i]\n", rc); goto out_free; } ecryptfs_set_file_lower(&fake_ecryptfs_file, lower_file); @@ -879,7 +845,8 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) = CURRENT_TIME; mark_inode_dirty_sync(inode); out_fput: - fput(lower_file); + if ((rc = ecryptfs_close_lower_file(lower_file))) + printk(KERN_ERR "Error closing lower_file\n"); out_free: if (ecryptfs_file_to_private(&fake_ecryptfs_file)) kmem_cache_free(ecryptfs_file_info_cache, diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index ba454785a0c..c3746f56d16 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -458,14 +458,16 @@ out: static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, struct ecryptfs_crypt_stat *crypt_stat) { - int rc = 0; struct ecryptfs_password *password_s_ptr; - struct crypto_tfm *tfm = NULL; struct scatterlist src_sg[2], dst_sg[2]; struct mutex *tfm_mutex = NULL; /* TODO: Use virt_to_scatterlist for these */ char *encrypted_session_key; char *session_key; + struct blkcipher_desc desc = { + .flags = CRYPTO_TFM_REQ_MAY_SLEEP + }; + int rc = 0; password_s_ptr = &auth_tok->token.password; if (ECRYPTFS_CHECK_FLAG(password_s_ptr->flags, @@ -482,30 +484,37 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, if (!strcmp(crypt_stat->cipher, crypt_stat->mount_crypt_stat->global_default_cipher_name) && crypt_stat->mount_crypt_stat->global_key_tfm) { - tfm = crypt_stat->mount_crypt_stat->global_key_tfm; + desc.tfm = crypt_stat->mount_crypt_stat->global_key_tfm; tfm_mutex = &crypt_stat->mount_crypt_stat->global_key_tfm_mutex; } else { - tfm = crypto_alloc_tfm(crypt_stat->cipher, - CRYPTO_TFM_REQ_WEAK_KEY); - if (!tfm) { - printk(KERN_ERR "Error allocating crypto context\n"); - rc = -ENOMEM; + char *full_alg_name; + + rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, + crypt_stat->cipher, + "ecb"); + if (rc) + goto out; + desc.tfm = crypto_alloc_blkcipher(full_alg_name, 0, + CRYPTO_ALG_ASYNC); + kfree(full_alg_name); + if (IS_ERR(desc.tfm)) { + rc = PTR_ERR(desc.tfm); + printk(KERN_ERR "Error allocating crypto context; " + "rc = [%d]\n", rc); goto out; } - } - if (password_s_ptr->session_key_encryption_key_bytes - < crypto_tfm_alg_min_keysize(tfm)) { - printk(KERN_WARNING "Session key encryption key is [%d] bytes; " - "minimum keysize for selected cipher is [%d] bytes.\n", - password_s_ptr->session_key_encryption_key_bytes, - crypto_tfm_alg_min_keysize(tfm)); - rc = -EINVAL; - goto out; + crypto_blkcipher_set_flags(desc.tfm, CRYPTO_TFM_REQ_WEAK_KEY); } if (tfm_mutex) mutex_lock(tfm_mutex); - crypto_cipher_setkey(tfm, password_s_ptr->session_key_encryption_key, - crypt_stat->key_size); + rc = crypto_blkcipher_setkey(desc.tfm, + password_s_ptr->session_key_encryption_key, + crypt_stat->key_size); + if (rc < 0) { + printk(KERN_ERR "Error setting key for crypto context\n"); + rc = -EINVAL; + goto out_free_tfm; + } /* TODO: virt_to_scatterlist */ encrypted_session_key = (char *)__get_free_page(GFP_KERNEL); if (!encrypted_session_key) { @@ -531,9 +540,12 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, auth_tok->session_key.decrypted_key_size = auth_tok->session_key.encrypted_key_size; dst_sg[0].length = auth_tok->session_key.encrypted_key_size; - /* TODO: Handle error condition */ - crypto_cipher_decrypt(tfm, dst_sg, src_sg, - auth_tok->session_key.encrypted_key_size); + rc = crypto_blkcipher_decrypt(&desc, dst_sg, src_sg, + auth_tok->session_key.encrypted_key_size); + if (rc) { + printk(KERN_ERR "Error decrypting; rc = [%d]\n", rc); + goto out_free_memory; + } auth_tok->session_key.decrypted_key_size = auth_tok->session_key.encrypted_key_size; memcpy(auth_tok->session_key.decrypted_key, session_key, @@ -546,6 +558,7 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, if (ecryptfs_verbosity > 0) ecryptfs_dump_hex(crypt_stat->key, crypt_stat->key_size); +out_free_memory: memset(encrypted_session_key, 0, PAGE_CACHE_SIZE); free_page((unsigned long)encrypted_session_key); memset(session_key, 0, PAGE_CACHE_SIZE); @@ -554,7 +567,7 @@ out_free_tfm: if (tfm_mutex) mutex_unlock(tfm_mutex); else - crypto_free_tfm(tfm); + crypto_free_blkcipher(desc.tfm); out: return rc; } @@ -803,19 +816,21 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, struct ecryptfs_crypt_stat *crypt_stat, struct ecryptfs_key_record *key_rec, size_t *packet_size) { - int rc = 0; - size_t i; size_t signature_is_valid = 0; size_t encrypted_session_key_valid = 0; char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES]; struct scatterlist dest_sg[2]; struct scatterlist src_sg[2]; - struct crypto_tfm *tfm = NULL; struct mutex *tfm_mutex = NULL; size_t key_rec_size; size_t packet_size_length; size_t cipher_code; + struct blkcipher_desc desc = { + .tfm = NULL, + .flags = CRYPTO_TFM_REQ_MAY_SLEEP + }; + int rc = 0; (*packet_size) = 0; /* Check for a valid signature on the auth_tok */ @@ -882,33 +897,48 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, if (!strcmp(crypt_stat->cipher, crypt_stat->mount_crypt_stat->global_default_cipher_name) && crypt_stat->mount_crypt_stat->global_key_tfm) { - tfm = crypt_stat->mount_crypt_stat->global_key_tfm; + desc.tfm = crypt_stat->mount_crypt_stat->global_key_tfm; tfm_mutex = &crypt_stat->mount_crypt_stat->global_key_tfm_mutex; - } else - tfm = crypto_alloc_tfm(crypt_stat->cipher, 0); - if (!tfm) { - ecryptfs_printk(KERN_ERR, "Could not initialize crypto " - "context for cipher [%s]\n", - crypt_stat->cipher); - rc = -EINVAL; - goto out; + } else { + char *full_alg_name; + + rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, + crypt_stat->cipher, + "ecb"); + if (rc) + goto out; + desc.tfm = crypto_alloc_blkcipher(full_alg_name, 0, + CRYPTO_ALG_ASYNC); + kfree(full_alg_name); + if (IS_ERR(desc.tfm)) { + rc = PTR_ERR(desc.tfm); + ecryptfs_printk(KERN_ERR, "Could not initialize crypto " + "context for cipher [%s]; rc = [%d]\n", + crypt_stat->cipher, rc); + goto out; + } + crypto_blkcipher_set_flags(desc.tfm, CRYPTO_TFM_REQ_WEAK_KEY); } if (tfm_mutex) mutex_lock(tfm_mutex); - rc = crypto_cipher_setkey(tfm, session_key_encryption_key, - crypt_stat->key_size); + rc = crypto_blkcipher_setkey(desc.tfm, session_key_encryption_key, + crypt_stat->key_size); if (rc < 0) { if (tfm_mutex) mutex_unlock(tfm_mutex); ecryptfs_printk(KERN_ERR, "Error setting key for crypto " - "context\n"); + "context; rc = [%d]\n", rc); goto out; } rc = 0; ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes of the key\n", crypt_stat->key_size); - crypto_cipher_encrypt(tfm, dest_sg, src_sg, - (*key_rec).enc_key_size); + rc = crypto_blkcipher_encrypt(&desc, dest_sg, src_sg, + (*key_rec).enc_key_size); + if (rc) { + printk(KERN_ERR "Error encrypting; rc = [%d]\n", rc); + goto out; + } if (tfm_mutex) mutex_unlock(tfm_mutex); ecryptfs_printk(KERN_DEBUG, "This should be the encrypted key:\n"); @@ -971,8 +1001,8 @@ encrypted_session_key_set: (*key_rec).enc_key_size); (*packet_size) += (*key_rec).enc_key_size; out: - if (tfm && !tfm_mutex) - crypto_free_tfm(tfm); + if (desc.tfm && !tfm_mutex) + crypto_free_blkcipher(desc.tfm); if (rc) (*packet_size) = 0; return rc; diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 5938a232d11..a78d87d14ba 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -208,7 +208,6 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options) char *cipher_name_dst; char *cipher_name_src; char *cipher_key_bytes_src; - struct crypto_tfm *tmp_tfm; int cipher_name_len; if (!options) { @@ -305,25 +304,19 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options) = '\0'; } if (!cipher_key_bytes_set) { - mount_crypt_stat->global_default_cipher_key_size = - ECRYPTFS_DEFAULT_KEY_BYTES; - ecryptfs_printk(KERN_DEBUG, "Cipher key size was not " - "specified. Defaulting to [%d]\n", - mount_crypt_stat-> - global_default_cipher_key_size); + mount_crypt_stat->global_default_cipher_key_size = 0; } rc = ecryptfs_process_cipher( - &tmp_tfm, &mount_crypt_stat->global_key_tfm, mount_crypt_stat->global_default_cipher_name, - mount_crypt_stat->global_default_cipher_key_size); - if (tmp_tfm) - crypto_free_tfm(tmp_tfm); + &mount_crypt_stat->global_default_cipher_key_size); if (rc) { printk(KERN_ERR "Error attempting to initialize cipher [%s] " "with key size [%Zd] bytes; rc = [%d]\n", mount_crypt_stat->global_default_cipher_name, mount_crypt_stat->global_default_cipher_key_size, rc); + mount_crypt_stat->global_key_tfm = NULL; + mount_crypt_stat->global_auth_tok_key = NULL; rc = -EINVAL; goto out; } diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index c337c0410fb..825757ae486 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c @@ -138,23 +138,6 @@ static void ecryptfs_clear_inode(struct inode *inode) } /** - * ecryptfs_umount_begin - * - * Called in do_umount(). - */ -static void ecryptfs_umount_begin(struct vfsmount *vfsmnt, int flags) -{ - struct vfsmount *lower_mnt = - ecryptfs_dentry_to_lower_mnt(vfsmnt->mnt_sb->s_root); - struct super_block *lower_sb; - - mntput(lower_mnt); - lower_sb = lower_mnt->mnt_sb; - if (lower_sb->s_op->umount_begin) - lower_sb->s_op->umount_begin(lower_mnt, flags); -} - -/** * ecryptfs_show_options * * Prints the directory we are currently mounted over. @@ -193,6 +176,5 @@ struct super_operations ecryptfs_sops = { .statfs = ecryptfs_statfs, .remount_fs = NULL, .clear_inode = ecryptfs_clear_inode, - .umount_begin = ecryptfs_umount_begin, .show_options = ecryptfs_show_options }; diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h index 30240a445db..ec56aa52f66 100644 --- a/include/asm-mips/unistd.h +++ b/include/asm-mips/unistd.h @@ -332,16 +332,18 @@ #define __NR_set_robust_list (__NR_Linux + 309) #define __NR_get_robust_list (__NR_Linux + 310) #define __NR_kexec_load (__NR_Linux + 311) +#define __NR_getcpu (__NR_Linux + 312) +#define __NR_epoll_pwait (__NR_Linux + 313) /* * Offset of the last Linux o32 flavoured syscall */ -#define __NR_Linux_syscalls 311 +#define __NR_Linux_syscalls 313 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #define __NR_O32_Linux 4000 -#define __NR_O32_Linux_syscalls 311 +#define __NR_O32_Linux_syscalls 313 #if _MIPS_SIM == _MIPS_SIM_ABI64 @@ -620,16 +622,18 @@ #define __NR_set_robust_list (__NR_Linux + 268) #define __NR_get_robust_list (__NR_Linux + 269) #define __NR_kexec_load (__NR_Linux + 270) +#define __NR_getcpu (__NR_Linux + 271) +#define __NR_epoll_pwait (__NR_Linux + 272) /* * Offset of the last Linux 64-bit flavoured syscall */ -#define __NR_Linux_syscalls 270 +#define __NR_Linux_syscalls 272 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ #define __NR_64_Linux 5000 -#define __NR_64_Linux_syscalls 270 +#define __NR_64_Linux_syscalls 272 #if _MIPS_SIM == _MIPS_SIM_NABI32 @@ -912,16 +916,18 @@ #define __NR_set_robust_list (__NR_Linux + 272) #define __NR_get_robust_list (__NR_Linux + 273) #define __NR_kexec_load (__NR_Linux + 274) +#define __NR_getcpu (__NR_Linux + 275) +#define __NR_epoll_pwait (__NR_Linux + 276) /* * Offset of the last N32 flavoured syscall */ -#define __NR_Linux_syscalls 274 +#define __NR_Linux_syscalls 276 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ #define __NR_N32_Linux 6000 -#define __NR_N32_Linux_syscalls 274 +#define __NR_N32_Linux_syscalls 276 #ifdef __KERNEL__ @@ -1189,6 +1195,7 @@ type name (atype a,btype b,ctype c,dtype d,etype e,ftype f) \ #endif /* (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) */ +#define __ARCH_OMIT_COMPAT_SYS_GETDENTS64 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_SYS_ALARM diff --git a/include/asm-um/common.lds.S b/include/asm-um/common.lds.S index 1010153faaf..f0454516dd3 100644 --- a/include/asm-um/common.lds.S +++ b/include/asm-um/common.lds.S @@ -42,13 +42,7 @@ __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) + INITCALLS } __initcall_end = .; diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 2039585ec5e..f45c5e70773 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -455,10 +455,9 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, int is_thread_group; struct nlattr *na; - if (!family_registered || !tidstats) + if (!family_registered) return; - rc = 0; /* * Size includes space for nested attributes */ @@ -466,8 +465,15 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); is_thread_group = (tsk->signal->stats != NULL); - if (is_thread_group) - size = 2 * size; /* PID + STATS + TGID + STATS */ + if (is_thread_group) { + /* PID + STATS + TGID + STATS */ + size = 2 * size; + /* fill the tsk->signal->stats structure */ + fill_tgid_exit(tsk); + } + + if (!tidstats) + return; rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, &reply, size); if (rc < 0) @@ -487,11 +493,8 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, goto send; /* - * tsk has/had a thread group so fill the tsk->signal->stats structure * Doesn't matter if tsk is the leader or the last group member leaving */ - - fill_tgid_exit(tsk); if (!group_dead) goto send; |