Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
authorLinus Torvalds <torvalds@g5.osdl.org>
Tue, 31 Oct 2006 16:08:31 +0000 (08:08 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Tue, 31 Oct 2006 16:08:31 +0000 (08:08 -0800)
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
  [IPV6]: fix flowlabel seqfile handling
  [IPV6]: return EINVAL for invalid address with flowlabel lease request
  [SCTP]: Remove temporary associations from backlog and hash.
  [SCTP]: Correctly set IP id for SCTP traffic
  [NetLabel]: protect the CIPSOv4 socket option from setsockopt()
  [NETFILTER]: ip_tables: compat code module refcounting fix
  [NETFILTER]: nf_conntrack: add missing unlock in get_next_corpse()
  [NETFILTER]: ip_tables: compat error way cleanup
  [NETFILTER]: Missed and reordered checks in {arp,ip,ip6}_tables
  [NETFILTER]: remove masq/NAT from ip6tables Kconfig help
  [IPV6]: fix lockup via /proc/net/ip6_flowlabel
  [NET]: fix uaccess handling
  [SCTP]: Always linearise packet on input
  [ETH1394]: Fix unaligned accesses.
  [DCCP]: fix printk format warnings
  [NET]: Fix segmentation of linear packets
  [XFRM] xfrm_user: Fix unaligned accesses.
  [APPLETALK]: Fix potential OOPS in atalk_sendmsg().
  [NET] sealevel: uses arp_broken_ops

36 files changed:
Makefile
arch/mips/Kconfig
arch/mips/au1000/common/time.c
arch/mips/emma2rh/common/irq_emma2rh.c
arch/mips/emma2rh/markeins/irq_markeins.c
arch/mips/emma2rh/markeins/platform.c
arch/mips/jmr3927/rbhma3100/irq.c
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/mm/c-sb1.c
arch/mips/momentum/ocelot_g/ocelot_pld.h
arch/mips/momentum/ocelot_g/setup.c
arch/mips/oprofile/op_model_mipsxx.c
arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
arch/sparc64/kernel/prom.c
arch/sparc64/kernel/traps.c
arch/um/drivers/ubd_kern.c
arch/um/include/mconsole_kern.h
arch/um/kernel/dyn.lds.S
arch/um/kernel/tt/tracer.c
arch/um/kernel/uml.lds.S
block/ll_rw_blk.c
fs/block_dev.c
fs/ecryptfs/crypto.c
fs/ecryptfs/dentry.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/ecryptfs/keystore.c
fs/ecryptfs/main.c
fs/ecryptfs/super.c
include/asm-mips/unistd.h
include/asm-um/common.lds.S
kernel/taskstats.c

index 25b35992a02c7d66e537186ea68c469433aa43c1..95576199f3ca969ccdf6e72a3a7ea8edef1831aa 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 19
-EXTRAVERSION =-rc3
+EXTRAVERSION =-rc4
 NAME=Avast! A bilge rat!
 
 # *DOCUMENTATION*
index 14af6cce2fa22a57d5c76fa72db3051786ab04d2..74ba7637811346c479ea3902016060afede53405 100644 (file)
@@ -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
index 94f09194d63d636381cba295f41a031e3c4ac9d6..6768638883eadcd13d95fada2a3b1fedb444d336 100644 (file)
@@ -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);
index 7c930860c921e14f2a086556dda04ccc2e40a498..197ed4c2ba04d774dff5b10b3e89571c418680c6 100644 (file)
@@ -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;
index f23ae9fcffa0e63698c4ed23cca18fb9378b8cfc..0b36eb001e62770d920f0e8c30be0619e520ea36 100644 (file)
@@ -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;
index 15cc61df36223ba8b4a543035b363c097702bfad..11567702b155460a84adcbf9b08bca3c6c280a97 100644 (file)
 #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,
        },
 };
 
index 39a0243bed9ac10e13b0fea7dfe25c83f29fca74..de4a238c28bec5eb0c67bde8d937e0dddb0d5b96 100644 (file)
@@ -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
index 720fac3435d5aa9d49c1e2393fc476c7949c1168..a95f37de080eb563b600d0615d7e1cd62003ca07 100644 (file)
@@ -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
index 3a34f62c8b1b3152b9fb3ac68911a47484eb3743..8fb0f60f657bfc469c94b35458e339563761c4a8 100644 (file)
@@ -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
index 67b92a1d6c72268aa2ba12120011fd8754db4a71..0da5ca2040ff96f0487ca1ce66783e852b50f87b 100644 (file)
@@ -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
index 2875c4a3fa5801f8d5b87f1b895d91003b85f510..b9d00cae8b5f2f4c4db850f634ccbbc14370338e 100644 (file)
@@ -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
index 5537558f19f795d467e327a5225e662ff03dd7b6..ea49a775bf2859f0afc1fbfda7d2bab626c3f1c6 100644 (file)
@@ -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);
index fcb8275e219dc74d833fd041e07e7fd53b9e3d28..95e0534026d0756bfb99de5d4c2595538f01a05c 100644 (file)
@@ -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__ */
index 56ec47039c16b3cfe742d500d528baadb5c35aa3..d288f7b018426260a114fc240fa3083a7899b5fc 100644 (file)
@@ -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);
index dd0aec9c3ce1df31f45368087a0496edb006a937..1fb240c57bac356463346f45b5971fd7826b09ab 100644 (file)
 #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
index b926e6a75c29b8ace85a6fea448eacf92dc4bd48..08b20cdfd7b3cc4013ac7fb41adb94022d716588 100644 (file)
@@ -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)
index c60efb3cb22e037feec3b3017e0d8aef80f8d883..0917c24c4f08fe993967b64ae35ff89466185731 100644 (file)
@@ -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
index 68420e2dad0eb2c28857ce854563165fe62570fc..fe1796c939c395618e945b18b017c75d8717f5ed 100644 (file)
@@ -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,
index bc458f57921b0f232d0f078bc5014424281e8617..49c047b75cc556cbda484a5c6166d23d5b137f7c 100644 (file)
@@ -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)
 {
index d0b690197fd78fa5e8dc94e069e96bbe50dca287..1ea6d928e1cd2a5794057cebac2fa6636363048d 100644 (file)
@@ -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;
index 68ed24df5c8fa7f24d5089e305fa91e743c37e5a..e36f92b463ce04dc64ec0f076954e48cf0cb276a 100644 (file)
@@ -14,6 +14,7 @@ SECTIONS
    * is remapped.*/
   __binary_start = .;
   . = ALIGN(4096);             /* Init code and data */
+  _text = .;
   _stext = .;
   __init_begin = .;
   .init.text : {
index 9882342206ecf7a1a78a4661e530b3511af39ee2..b9195355075ab3e9540dd0e880be38b1cd08556a 100644 (file)
@@ -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);
 
index 8eca47a6ff082f171d76777ebb46d2601c282dcf..f6301274cf3cfea9fdb0eb3680cbe349da63fd57 100644 (file)
@@ -25,6 +25,7 @@ SECTIONS
   . = ALIGN(4096);             /* Init code and data */
 #endif
 
+  _text = .;
   _stext = .;
   __init_begin = .;
   .init.text : {
index 136066583c6810b6520c9a090f428427819d44c2..c7b1dac8bee91a6bae5a91981af92378d4a280a8 100644 (file)
@@ -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);
 }
index 702b88cbd91d2dc91eb81cb41784574b89df4edd..36c0e7af9d0f18df487aab2420414fd95b1f1302 100644 (file)
@@ -641,35 +641,48 @@ static void free_bd_holder(struct bd_holder *bo)
        kfree(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);
 
index ed35a9712fa15ae8a2c87e5a0c5405b3a162a835..f49f105394b70a91268a7ed63d56544aeff10fba 100644 (file)
@@ -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;
        }
index f0d2a433242b58757f33483fec2a301410ce2aab..0b9992ab990f4cab4983a89aa4eb4f4026a1820b 100644 (file)
@@ -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;
 }
 
index 872c9958531a0cf649d18de01805f65fae7d277d..f992533d1692b7a47d58f0f004712adc22efb01c 100644 (file)
@@ -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 */
index c8550c9f9cd277d43df40b966fb5e47930597cb4..a92ef05eff8f3d1ba52bdf481d14c728f9591eb1 100644 (file)
@@ -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
index efdd2b7b62d707da7d7fdba901d5cc4331be0e54..ff4865d24f0f1061dcc7dbd47fd169330f136869 100644 (file)
@@ -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,
index ba454785a0c5864c6878041980829cfeda477a82..c3746f56d1627ab2246d5086731103353f9537d3 100644 (file)
@@ -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;
index 5938a232d11bd3e3feed0ed01ae3ba5a04918c7f..a78d87d14bafb2256313753cc8aeaeeb6c0b381f 100644 (file)
@@ -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;
        }
index c337c0410fb14b890f2932682355ed1b4baa273c..825757ae48676d6a488f64413316a7429b55fbbc 100644 (file)
@@ -137,23 +137,6 @@ static void ecryptfs_clear_inode(struct inode *inode)
        iput(ecryptfs_inode_to_lower(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
  *
@@ -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
 };
index 30240a445dbbf3ff72f0d54ed6f6b1904f2eb330..ec56aa52f669f2092847290b9fccb8309d6ae35e 100644 (file)
 #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
 
 #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
 
 #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
index 1010153faaf93731054d8789c6105ea9057ae70a..f0454516dd318d2b30bd86988f900dd72c66adab 100644 (file)
        
   __initcall_start = .;
   .initcall.init : {
-       *(.initcall1.init) 
-       *(.initcall2.init) 
-       *(.initcall3.init) 
-       *(.initcall4.init) 
-       *(.initcall5.init) 
-       *(.initcall6.init) 
-       *(.initcall7.init)
+       INITCALLS
   }
   __initcall_end = .;
 
index 2039585ec5e1785b859ea6b9c0b6ca827dac7e29..f45c5e70773c0b2fd6437b3a69ecfbefc1e40bf6 100644 (file)
@@ -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;