Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 7 Aug 2011 22:52:19 +0000 (15:52 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 7 Aug 2011 22:52:19 +0000 (15:52 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc:
  sparc: Fix build with DEBUG_PAGEALLOC enabled.

82 files changed:
Documentation/ABI/testing/sysfs-platform-ideapad-laptop
Documentation/CodingStyle
Documentation/feature-removal-schedule.txt
Documentation/power/runtime_pm.txt
arch/arm/kernel/armksyms.c
arch/arm/lib/Makefile
arch/arm/lib/sha1.S [deleted file]
arch/x86/xen/Makefile
arch/x86/xen/setup.c
arch/x86/xen/trace.c
crypto/md5.c
drivers/acpi/battery.c
drivers/base/power/domain.c
drivers/base/power/runtime.c
drivers/char/random.c
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/acerhdf.c
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/asus-wmi.h
drivers/platform/x86/dell-laptop.c
drivers/platform/x86/dell-wmi.c
drivers/platform/x86/eeepc-wmi.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel_ips.c
drivers/platform/x86/intel_menlow.c
drivers/platform/x86/intel_mid_thermal.c
drivers/platform/x86/intel_rar_register.c
drivers/platform/x86/intel_scu_ipc.c
drivers/platform/x86/msi-laptop.c
drivers/platform/x86/msi-wmi.c
drivers/platform/x86/samsung-laptop.c
drivers/platform/x86/samsung-q10.c [new file with mode: 0644]
drivers/platform/x86/thinkpad_acpi.c
drivers/tty/serial/sh-sci.c
drivers/video/savage/savagefb.h
drivers/xen/Kconfig
fs/cifs/cifs_dfs_ref.c
fs/cifs/cifsfs.c
fs/cifs/dns_resolve.c
fs/cifs/inode.c
fs/cifs/sess.c
fs/cifs/transport.c
fs/dcache.c
fs/exofs/Kbuild
fs/exofs/Kconfig
fs/exofs/exofs.h
fs/exofs/inode.c
fs/exofs/ios.c [deleted file]
fs/exofs/ore.c [new file with mode: 0644]
fs/exofs/pnfs.h [deleted file]
fs/exofs/super.c
fs/inode.c
fs/namei.c
fs/proc/base.c
fs/stat.c
include/linux/cred.h
include/linux/cryptohash.h
include/linux/dcache.h
include/linux/fs.h
include/linux/input.h
include/linux/nfs_xdr.h
include/linux/random.h
include/net/secure_seq.h [new file with mode: 0644]
include/scsi/osd_ore.h [new file with mode: 0644]
lib/Makefile
lib/md5.c [new file with mode: 0644]
lib/sha1.c
net/core/Makefile
net/core/secure_seq.c [new file with mode: 0644]
net/dccp/ipv4.c
net/dccp/ipv6.c
net/ipv4/inet_hashtables.c
net/ipv4/inetpeer.c
net/ipv4/netfilter/nf_nat_proto_common.c
net/ipv4/route.c
net/ipv4/tcp_ipv4.c
net/ipv6/inet6_hashtables.c
net/ipv6/tcp_ipv6.c

index 807fca2ae2a424f844a42d5d9e22b2b0bfe13578..ff53183c3848d20ea357c276fb1bf930693cbd5c 100644 (file)
@@ -4,3 +4,20 @@ KernelVersion: 2.6.37
 Contact:       "Ike Panhc <ike.pan@canonical.com>"
 Description:
                Control the power of camera module. 1 means on, 0 means off.
+
+What:          /sys/devices/platform/ideapad/cfg
+Date:          Jun 2011
+KernelVersion: 3.1
+Contact:       "Ike Panhc <ike.pan@canonical.com>"
+Description:
+               Ideapad capability bits.
+               Bit 8-10: 1 - Intel graphic only
+                         2 - ATI graphic only
+                         3 - Nvidia graphic only
+                         4 - Intel and ATI graphic
+                         5 - Intel and Nvidia graphic
+               Bit 16: Bluetooth exist (1 for exist)
+               Bit 17: 3G exist (1 for exist)
+               Bit 18: Wifi exist (1 for exist)
+               Bit 19: Camera exist (1 for exist)
+
index fa6e25b94a54bfe1d39450cd9bc568c4043ddfa3..c940239d967811083278cf3c88c4342df18092ba 100644 (file)
@@ -80,22 +80,13 @@ available tools.
 The limit on the length of lines is 80 columns and this is a strongly
 preferred limit.
 
-Statements longer than 80 columns will be broken into sensible chunks.
-Descendants are always substantially shorter than the parent and are placed
-substantially to the right. The same applies to function headers with a long
-argument list. Long strings are as well broken into shorter strings. The
-only exception to this is where exceeding 80 columns significantly increases
-readability and does not hide information.
-
-void fun(int a, int b, int c)
-{
-       if (condition)
-               printk(KERN_WARNING "Warning this is a long printk with "
-                                               "3 parameters a: %u b: %u "
-                                               "c: %u \n", a, b, c);
-       else
-               next_statement;
-}
+Statements longer than 80 columns will be broken into sensible chunks, unless
+exceeding 80 columns significantly increases readability and does not hide
+information. Descendants are always substantially shorter than the parent and
+are placed substantially to the right. The same applies to function headers
+with a long argument list. However, never break user-visible strings such as
+printk messages, because that breaks the ability to grep for them.
+
 
                Chapter 3: Placing Braces and Spaces
 
index 43f48098220d8e8e011d6b8ba2e18aec73306532..c4a6e148732ae549be7e25b8863912a2f924d254 100644 (file)
@@ -581,3 +581,14 @@ Why:       This driver has been superseded by g_mass_storage.
 Who:   Alan Stern <stern@rowland.harvard.edu>
 
 ----------------------------
+
+What:   threeg and interface sysfs files in /sys/devices/platform/acer-wmi
+When:   2012
+Why:    In 3.0, we can now autodetect internal 3G device and already have
+       the threeg rfkill device. So, we plan to remove threeg sysfs support
+       for it's no longer necessary.
+
+       We also plan to remove interface sysfs file that exposed which ACPI-WMI
+       interface that was used by acer-wmi driver. It will replaced by
+       information log when acer-wmi initial.
+Who:    Lee, Chun-Yi <jlee@novell.com>
index 14dd3c6ad97ee852d0273a7a66c57b5ebe74b34b..4ce5450ab6e833cef372ef2755993353cae50935 100644 (file)
@@ -54,11 +54,10 @@ referred to as subsystem-level callbacks in what follows.
 By default, the callbacks are always invoked in process context with interrupts
 enabled.  However, subsystems can use the pm_runtime_irq_safe() helper function
 to tell the PM core that a device's ->runtime_suspend() and ->runtime_resume()
-callbacks should be invoked in atomic context with interrupts disabled
-(->runtime_idle() is still invoked the default way).  This implies that these
-callback routines must not block or sleep, but it also means that the
-synchronous helper functions listed at the end of Section 4 can be used within
-an interrupt handler or in an atomic context.
+callbacks should be invoked in atomic context with interrupts disabled.
+This implies that these callback routines must not block or sleep, but it also
+means that the synchronous helper functions listed at the end of Section 4 can
+be used within an interrupt handler or in an atomic context.
 
 The subsystem-level suspend callback is _entirely_ _responsible_ for handling
 the suspend of the device as appropriate, which may, but need not include
@@ -483,6 +482,7 @@ pm_runtime_suspend()
 pm_runtime_autosuspend()
 pm_runtime_resume()
 pm_runtime_get_sync()
+pm_runtime_put_sync()
 pm_runtime_put_sync_suspend()
 
 5. Runtime PM Initialization, Device Probing and Removal
index acca35aebe285d013c0228c532556de2efc038bc..aeef960ff795fce24d2387dd80446072d3bb9263 100644 (file)
@@ -112,9 +112,6 @@ EXPORT_SYMBOL(__put_user_4);
 EXPORT_SYMBOL(__put_user_8);
 #endif
 
-       /* crypto hash */
-EXPORT_SYMBOL(sha_transform);
-
        /* gcc lib functions */
 EXPORT_SYMBOL(__ashldi3);
 EXPORT_SYMBOL(__ashrdi3);
index 59ff42ddf0aed656f3def2c44859f0eec414b1d3..cf73a7f742ddf15a6aebce74b8e81b3d2e3614c5 100644 (file)
@@ -12,7 +12,7 @@ lib-y         := backtrace.o changebit.o csumipv6.o csumpartial.o   \
                   strchr.o strrchr.o                                 \
                   testchangebit.o testclearbit.o testsetbit.o        \
                   ashldi3.o ashrdi3.o lshrdi3.o muldi3.o             \
-                  ucmpdi2.o lib1funcs.o div64.o sha1.o               \
+                  ucmpdi2.o lib1funcs.o div64.o                      \
                   io-readsb.o io-writesb.o io-readsl.o io-writesl.o
 
 mmu-y  := clear_user.o copy_page.o getuser.o putuser.o
diff --git a/arch/arm/lib/sha1.S b/arch/arm/lib/sha1.S
deleted file mode 100644 (file)
index eb0edb8..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- *  linux/arch/arm/lib/sha1.S
- *
- *  SHA transform optimized for ARM
- *
- *  Copyright: (C) 2005 by Nicolas Pitre <nico@fluxnic.net>
- *  Created:   September 17, 2005
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- *
- *  The reference implementation for this code is linux/lib/sha1.c
- */
-
-#include <linux/linkage.h>
-
-       .text
-
-
-/*
- * void sha_transform(__u32 *digest, const char *in, __u32 *W)
- *
- * Note: the "in" ptr may be unaligned.
- */
-
-ENTRY(sha_transform)
-
-       stmfd   sp!, {r4 - r8, lr}
-
-       @ for (i = 0; i < 16; i++)
-       @         W[i] = be32_to_cpu(in[i]);
-
-#ifdef __ARMEB__
-       mov     r4, r0
-       mov     r0, r2
-       mov     r2, #64
-       bl      memcpy
-       mov     r2, r0
-       mov     r0, r4
-#else
-       mov     r3, r2
-       mov     lr, #16
-1:     ldrb    r4, [r1], #1
-       ldrb    r5, [r1], #1
-       ldrb    r6, [r1], #1
-       ldrb    r7, [r1], #1
-       subs    lr, lr, #1
-       orr     r5, r5, r4, lsl #8
-       orr     r6, r6, r5, lsl #8
-       orr     r7, r7, r6, lsl #8
-       str     r7, [r3], #4
-       bne     1b
-#endif
-
-       @ for (i = 0; i < 64; i++)
-       @         W[i+16] = ror(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i], 31);
-
-       sub     r3, r2, #4
-       mov     lr, #64
-2:     ldr     r4, [r3, #4]!
-       subs    lr, lr, #1
-       ldr     r5, [r3, #8]
-       ldr     r6, [r3, #32]
-       ldr     r7, [r3, #52]
-       eor     r4, r4, r5
-       eor     r4, r4, r6
-       eor     r4, r4, r7
-       mov     r4, r4, ror #31
-       str     r4, [r3, #64]
-       bne     2b
-
-       /*
-        * The SHA functions are:
-        *
-        * f1(B,C,D) = (D ^ (B & (C ^ D)))
-        * f2(B,C,D) = (B ^ C ^ D)
-        * f3(B,C,D) = ((B & C) | (D & (B | C)))
-        *
-        * Then the sub-blocks are processed as follows:
-        *
-        * A' = ror(A, 27) + f(B,C,D) + E + K + *W++
-        * B' = A
-        * C' = ror(B, 2)
-        * D' = C
-        * E' = D
-        *
-        * We therefore unroll each loop 5 times to avoid register shuffling.
-        * Also the ror for C (and also D and E which are successivelyderived
-        * from it) is applied in place to cut on an additional mov insn for
-        * each round.
-        */
-
-       .macro  sha_f1, A, B, C, D, E
-       ldr     r3, [r2], #4
-       eor     ip, \C, \D
-       add     \E, r1, \E, ror #2
-       and     ip, \B, ip, ror #2
-       add     \E, \E, \A, ror #27
-       eor     ip, ip, \D, ror #2
-       add     \E, \E, r3
-       add     \E, \E, ip
-       .endm
-
-       .macro  sha_f2, A, B, C, D, E
-       ldr     r3, [r2], #4
-       add     \E, r1, \E, ror #2
-       eor     ip, \B, \C, ror #2
-       add     \E, \E, \A, ror #27
-       eor     ip, ip, \D, ror #2
-       add     \E, \E, r3
-       add     \E, \E, ip
-       .endm
-
-       .macro  sha_f3, A, B, C, D, E
-       ldr     r3, [r2], #4
-       add     \E, r1, \E, ror #2
-       orr     ip, \B, \C, ror #2
-       add     \E, \E, \A, ror #27
-       and     ip, ip, \D, ror #2
-       add     \E, \E, r3
-       and     r3, \B, \C, ror #2
-       orr     ip, ip, r3
-       add     \E, \E, ip
-       .endm
-
-       ldmia   r0, {r4 - r8}
-
-       mov     lr, #4
-       ldr     r1, .L_sha_K + 0
-
-       /* adjust initial values */
-       mov     r6, r6, ror #30
-       mov     r7, r7, ror #30
-       mov     r8, r8, ror #30
-
-3:     subs    lr, lr, #1
-       sha_f1  r4, r5, r6, r7, r8
-       sha_f1  r8, r4, r5, r6, r7
-       sha_f1  r7, r8, r4, r5, r6
-       sha_f1  r6, r7, r8, r4, r5
-       sha_f1  r5, r6, r7, r8, r4
-       bne     3b
-
-       ldr     r1, .L_sha_K + 4
-       mov     lr, #4
-
-4:     subs    lr, lr, #1
-       sha_f2  r4, r5, r6, r7, r8
-       sha_f2  r8, r4, r5, r6, r7
-       sha_f2  r7, r8, r4, r5, r6
-       sha_f2  r6, r7, r8, r4, r5
-       sha_f2  r5, r6, r7, r8, r4
-       bne     4b
-
-       ldr     r1, .L_sha_K + 8
-       mov     lr, #4
-
-5:     subs    lr, lr, #1
-       sha_f3  r4, r5, r6, r7, r8
-       sha_f3  r8, r4, r5, r6, r7
-       sha_f3  r7, r8, r4, r5, r6
-       sha_f3  r6, r7, r8, r4, r5
-       sha_f3  r5, r6, r7, r8, r4
-       bne     5b
-
-       ldr     r1, .L_sha_K + 12
-       mov     lr, #4
-
-6:     subs    lr, lr, #1
-       sha_f2  r4, r5, r6, r7, r8
-       sha_f2  r8, r4, r5, r6, r7
-       sha_f2  r7, r8, r4, r5, r6
-       sha_f2  r6, r7, r8, r4, r5
-       sha_f2  r5, r6, r7, r8, r4
-       bne     6b
-
-       ldmia   r0, {r1, r2, r3, ip, lr}
-       add     r4, r1, r4
-       add     r5, r2, r5
-       add     r6, r3, r6, ror #2
-       add     r7, ip, r7, ror #2
-       add     r8, lr, r8, ror #2
-       stmia   r0, {r4 - r8}
-
-       ldmfd   sp!, {r4 - r8, pc}
-
-ENDPROC(sha_transform)
-
-       .align  2
-.L_sha_K:
-       .word   0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6
-
-
-/*
- * void sha_init(__u32 *buf)
- */
-
-       .align  2
-.L_sha_initial_digest:
-       .word   0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0
-
-ENTRY(sha_init)
-
-       str     lr, [sp, #-4]!
-       adr     r1, .L_sha_initial_digest
-       ldmia   r1, {r1, r2, r3, ip, lr}
-       stmia   r0, {r1, r2, r3, ip, lr}
-       ldr     pc, [sp], #4
-
-ENDPROC(sha_init)
index 45e94aca5bcef5aed5546c4a0cd25e1de5521e4e..3326204e251f3108650944ef1d558c98745c1935 100644 (file)
@@ -15,7 +15,7 @@ obj-y         := enlighten.o setup.o multicalls.o mmu.o irq.o \
                        grant-table.o suspend.o platform-pci-unplug.o \
                        p2m.o
 
-obj-$(CONFIG_FUNCTION_TRACER) += trace.o
+obj-$(CONFIG_FTRACE) += trace.o
 
 obj-$(CONFIG_SMP)              += smp.o
 obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
index a9627e2e3295a9fb97b4032ef6f95d746f2931a5..df118a825f395cbb4e79b9282594caa77aa6a4ca 100644 (file)
@@ -93,8 +93,6 @@ static unsigned long __init xen_release_chunk(phys_addr_t start_addr,
        if (end <= start)
                return 0;
 
-       printk(KERN_INFO "xen_release_chunk: looking at area pfn %lx-%lx: ",
-              start, end);
        for(pfn = start; pfn < end; pfn++) {
                unsigned long mfn = pfn_to_mfn(pfn);
 
@@ -107,14 +105,14 @@ static unsigned long __init xen_release_chunk(phys_addr_t start_addr,
 
                ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
                                           &reservation);
-               WARN(ret != 1, "Failed to release memory %lx-%lx err=%d\n",
-                    start, end, ret);
+               WARN(ret != 1, "Failed to release pfn %lx err=%d\n", pfn, ret);
                if (ret == 1) {
                        __set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
                        len++;
                }
        }
-       printk(KERN_CONT "%ld pages freed\n", len);
+       printk(KERN_INFO "Freeing  %lx-%lx pfn range: %lu pages freed\n",
+              start, end, len);
 
        return len;
 }
@@ -140,7 +138,7 @@ static unsigned long __init xen_return_unused_memory(unsigned long max_pfn,
        if (last_end < max_addr)
                released += xen_release_chunk(last_end, max_addr);
 
-       printk(KERN_INFO "released %ld pages of unused memory\n", released);
+       printk(KERN_INFO "released %lu pages of unused memory\n", released);
        return released;
 }
 
index 734beba2a08c41fbfd48b5d5f91865c79614d376..520022d1a18134715b6ebc16a86341aa3a7f104a 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/ftrace.h>
+#include <xen/interface/xen.h>
 
 #define N(x)   [__HYPERVISOR_##x] = "("#x")"
 static const char *xen_hypercall_names[] = {
index 30efc7dad89173e86fcf65b6ac7c20d858abfeb2..7febeaab923bcd724f607ca536ae6ab202e182ea 100644 (file)
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/types.h>
+#include <linux/cryptohash.h>
 #include <asm/byteorder.h>
 
-#define F1(x, y, z)    (z ^ (x & (y ^ z)))
-#define F2(x, y, z)    F1(z, x, y)
-#define F3(x, y, z)    (x ^ y ^ z)
-#define F4(x, y, z)    (y ^ (x | ~z))
-
-#define MD5STEP(f, w, x, y, z, in, s) \
-       (w += f(x, y, z) + in, w = (w<<s | w>>(32-s)) + x)
-
-static void md5_transform(u32 *hash, u32 const *in)
-{
-       u32 a, b, c, d;
-
-       a = hash[0];
-       b = hash[1];
-       c = hash[2];
-       d = hash[3];
-
-       MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
-       MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
-       MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
-       MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
-       MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
-       MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
-       MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
-       MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
-       MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
-       MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
-       MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
-       MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
-       MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
-       MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
-       MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
-       MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
-
-       MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
-       MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
-       MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
-       MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
-       MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
-       MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
-       MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
-       MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
-       MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
-       MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
-       MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
-       MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
-       MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
-       MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
-       MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
-       MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
-
-       MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
-       MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
-       MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
-       MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
-       MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
-       MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
-       MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
-       MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
-       MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
-       MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
-       MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
-       MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
-       MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
-       MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
-       MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
-       MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
-
-       MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
-       MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
-       MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
-       MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
-       MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
-       MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
-       MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
-       MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
-       MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
-       MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
-       MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
-       MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
-       MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
-       MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
-       MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
-       MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
-
-       hash[0] += a;
-       hash[1] += b;
-       hash[2] += c;
-       hash[3] += d;
-}
-
 /* XXX: this stuff can be optimized */
 static inline void le32_to_cpu_array(u32 *buf, unsigned int words)
 {
index 87c0a8daa99aa434d30bb2565732dfaab82ed1d1..7711d94a04091442fcf7bf261c09d7db93186ebc 100644 (file)
@@ -99,6 +99,7 @@ enum {
 
 struct acpi_battery {
        struct mutex lock;
+       struct mutex sysfs_lock;
        struct power_supply bat;
        struct acpi_device *device;
        struct notifier_block pm_nb;
@@ -573,16 +574,16 @@ static int sysfs_add_battery(struct acpi_battery *battery)
 
 static void sysfs_remove_battery(struct acpi_battery *battery)
 {
-       mutex_lock(&battery->lock);
+       mutex_lock(&battery->sysfs_lock);
        if (!battery->bat.dev) {
-               mutex_unlock(&battery->lock);
+               mutex_unlock(&battery->sysfs_lock);
                return;
        }
 
        device_remove_file(battery->bat.dev, &alarm_attr);
        power_supply_unregister(&battery->bat);
        battery->bat.dev = NULL;
-       mutex_unlock(&battery->lock);
+       mutex_unlock(&battery->sysfs_lock);
 }
 
 /*
@@ -982,6 +983,7 @@ static int acpi_battery_add(struct acpi_device *device)
        strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
        device->driver_data = battery;
        mutex_init(&battery->lock);
+       mutex_init(&battery->sysfs_lock);
        if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle,
                        "_BIX", &handle)))
                set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
@@ -1010,6 +1012,7 @@ static int acpi_battery_add(struct acpi_device *device)
 fail:
        sysfs_remove_battery(battery);
        mutex_destroy(&battery->lock);
+       mutex_destroy(&battery->sysfs_lock);
        kfree(battery);
        return result;
 }
@@ -1027,6 +1030,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
 #endif
        sysfs_remove_battery(battery);
        mutex_destroy(&battery->lock);
+       mutex_destroy(&battery->sysfs_lock);
        kfree(battery);
        return 0;
 }
index be8714aa9dd6cbfcf46fc2216f12d922d48b6b3d..e18566a0fedd4c9f7492eab168ffed2bc8d36932 100644 (file)
@@ -80,7 +80,6 @@ static void genpd_set_active(struct generic_pm_domain *genpd)
 int pm_genpd_poweron(struct generic_pm_domain *genpd)
 {
        struct generic_pm_domain *parent = genpd->parent;
-       DEFINE_WAIT(wait);
        int ret = 0;
 
  start:
@@ -112,7 +111,7 @@ int pm_genpd_poweron(struct generic_pm_domain *genpd)
        }
 
        if (genpd->power_on) {
-               int ret = genpd->power_on(genpd);
+               ret = genpd->power_on(genpd);
                if (ret)
                        goto out;
        }
index 8dc247c974affdc3432d4ec73087f76cd1889ce6..acb3f83b8079486e214dc23e315ca3f9f6f755c4 100644 (file)
@@ -226,11 +226,17 @@ static int rpm_idle(struct device *dev, int rpmflags)
                callback = NULL;
 
        if (callback) {
-               spin_unlock_irq(&dev->power.lock);
+               if (dev->power.irq_safe)
+                       spin_unlock(&dev->power.lock);
+               else
+                       spin_unlock_irq(&dev->power.lock);
 
                callback(dev);
 
-               spin_lock_irq(&dev->power.lock);
+               if (dev->power.irq_safe)
+                       spin_lock(&dev->power.lock);
+               else
+                       spin_lock_irq(&dev->power.lock);
        }
 
        dev->power.idle_notification = false;
index 729281961f22199c7bddec04c3f30f79271d3677..c35a785005b08e132f23447ac31365853b5acd9c 100644 (file)
@@ -1300,345 +1300,14 @@ ctl_table random_table[] = {
 };
 #endif         /* CONFIG_SYSCTL */
 
-/********************************************************************
- *
- * Random functions for networking
- *
- ********************************************************************/
-
-/*
- * TCP initial sequence number picking.  This uses the random number
- * generator to pick an initial secret value.  This value is hashed
- * along with the TCP endpoint information to provide a unique
- * starting point for each pair of TCP endpoints.  This defeats
- * attacks which rely on guessing the initial TCP sequence number.
- * This algorithm was suggested by Steve Bellovin.
- *
- * Using a very strong hash was taking an appreciable amount of the total
- * TCP connection establishment time, so this is a weaker hash,
- * compensated for by changing the secret periodically.
- */
-
-/* F, G and H are basic MD4 functions: selection, majority, parity */
-#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-
-/*
- * The generic round function.  The application is so specific that
- * we don't bother protecting all the arguments with parens, as is generally
- * good macro practice, in favor of extra legibility.
- * Rotation is separate from addition to prevent recomputation
- */
-#define ROUND(f, a, b, c, d, x, s)     \
-       (a += f(b, c, d) + x, a = (a << s) | (a >> (32 - s)))
-#define K1 0
-#define K2 013240474631UL
-#define K3 015666365641UL
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-
-static __u32 twothirdsMD4Transform(__u32 const buf[4], __u32 const in[12])
-{
-       __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
-
-       /* Round 1 */
-       ROUND(F, a, b, c, d, in[ 0] + K1,  3);
-       ROUND(F, d, a, b, c, in[ 1] + K1,  7);
-       ROUND(F, c, d, a, b, in[ 2] + K1, 11);
-       ROUND(F, b, c, d, a, in[ 3] + K1, 19);
-       ROUND(F, a, b, c, d, in[ 4] + K1,  3);
-       ROUND(F, d, a, b, c, in[ 5] + K1,  7);
-       ROUND(F, c, d, a, b, in[ 6] + K1, 11);
-       ROUND(F, b, c, d, a, in[ 7] + K1, 19);
-       ROUND(F, a, b, c, d, in[ 8] + K1,  3);
-       ROUND(F, d, a, b, c, in[ 9] + K1,  7);
-       ROUND(F, c, d, a, b, in[10] + K1, 11);
-       ROUND(F, b, c, d, a, in[11] + K1, 19);
-
-       /* Round 2 */
-       ROUND(G, a, b, c, d, in[ 1] + K2,  3);
-       ROUND(G, d, a, b, c, in[ 3] + K2,  5);
-       ROUND(G, c, d, a, b, in[ 5] + K2,  9);
-       ROUND(G, b, c, d, a, in[ 7] + K2, 13);
-       ROUND(G, a, b, c, d, in[ 9] + K2,  3);
-       ROUND(G, d, a, b, c, in[11] + K2,  5);
-       ROUND(G, c, d, a, b, in[ 0] + K2,  9);
-       ROUND(G, b, c, d, a, in[ 2] + K2, 13);
-       ROUND(G, a, b, c, d, in[ 4] + K2,  3);
-       ROUND(G, d, a, b, c, in[ 6] + K2,  5);
-       ROUND(G, c, d, a, b, in[ 8] + K2,  9);
-       ROUND(G, b, c, d, a, in[10] + K2, 13);
-
-       /* Round 3 */
-       ROUND(H, a, b, c, d, in[ 3] + K3,  3);
-       ROUND(H, d, a, b, c, in[ 7] + K3,  9);
-       ROUND(H, c, d, a, b, in[11] + K3, 11);
-       ROUND(H, b, c, d, a, in[ 2] + K3, 15);
-       ROUND(H, a, b, c, d, in[ 6] + K3,  3);
-       ROUND(H, d, a, b, c, in[10] + K3,  9);
-       ROUND(H, c, d, a, b, in[ 1] + K3, 11);
-       ROUND(H, b, c, d, a, in[ 5] + K3, 15);
-       ROUND(H, a, b, c, d, in[ 9] + K3,  3);
-       ROUND(H, d, a, b, c, in[ 0] + K3,  9);
-       ROUND(H, c, d, a, b, in[ 4] + K3, 11);
-       ROUND(H, b, c, d, a, in[ 8] + K3, 15);
-
-       return buf[1] + b; /* "most hashed" word */
-       /* Alternative: return sum of all words? */
-}
-#endif
-
-#undef ROUND
-#undef F
-#undef G
-#undef H
-#undef K1
-#undef K2
-#undef K3
-
-/* This should not be decreased so low that ISNs wrap too fast. */
-#define REKEY_INTERVAL (300 * HZ)
-/*
- * Bit layout of the tcp sequence numbers (before adding current time):
- * bit 24-31: increased after every key exchange
- * bit 0-23: hash(source,dest)
- *
- * The implementation is similar to the algorithm described
- * in the Appendix of RFC 1185, except that
- * - it uses a 1 MHz clock instead of a 250 kHz clock
- * - it performs a rekey every 5 minutes, which is equivalent
- *     to a (source,dest) tulple dependent forward jump of the
- *     clock by 0..2^(HASH_BITS+1)
- *
- * Thus the average ISN wraparound time is 68 minutes instead of
- * 4.55 hours.
- *
- * SMP cleanup and lock avoidance with poor man's RCU.
- *                     Manfred Spraul <manfred@colorfullife.com>
- *
- */
-#define COUNT_BITS 8
-#define COUNT_MASK ((1 << COUNT_BITS) - 1)
-#define HASH_BITS 24
-#define HASH_MASK ((1 << HASH_BITS) - 1)
+static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned;
 
-static struct keydata {
-       __u32 count; /* already shifted to the final position */
-       __u32 secret[12];
-} ____cacheline_aligned ip_keydata[2];
-
-static unsigned int ip_cnt;
-
-static void rekey_seq_generator(struct work_struct *work);
-
-static DECLARE_DELAYED_WORK(rekey_work, rekey_seq_generator);
-
-/*
- * Lock avoidance:
- * The ISN generation runs lockless - it's just a hash over random data.
- * State changes happen every 5 minutes when the random key is replaced.
- * Synchronization is performed by having two copies of the hash function
- * state and rekey_seq_generator always updates the inactive copy.
- * The copy is then activated by updating ip_cnt.
- * The implementation breaks down if someone blocks the thread
- * that processes SYN requests for more than 5 minutes. Should never
- * happen, and even if that happens only a not perfectly compliant
- * ISN is generated, nothing fatal.
- */
-static void rekey_seq_generator(struct work_struct *work)
+static int __init random_int_secret_init(void)
 {
-       struct keydata *keyptr = &ip_keydata[1 ^ (ip_cnt & 1)];
-
-       get_random_bytes(keyptr->secret, sizeof(keyptr->secret));
-       keyptr->count = (ip_cnt & COUNT_MASK) << HASH_BITS;
-       smp_wmb();
-       ip_cnt++;
-       schedule_delayed_work(&rekey_work,
-                             round_jiffies_relative(REKEY_INTERVAL));
-}
-
-static inline struct keydata *get_keyptr(void)
-{
-       struct keydata *keyptr = &ip_keydata[ip_cnt & 1];
-
-       smp_rmb();
-
-       return keyptr;
-}
-
-static __init int seqgen_init(void)
-{
-       rekey_seq_generator(NULL);
+       get_random_bytes(random_int_secret, sizeof(random_int_secret));
        return 0;
 }
-late_initcall(seqgen_init);
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-__u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
-                                  __be16 sport, __be16 dport)
-{
-       __u32 seq;
-       __u32 hash[12];
-       struct keydata *keyptr = get_keyptr();
-
-       /* The procedure is the same as for IPv4, but addresses are longer.
-        * Thus we must use twothirdsMD4Transform.
-        */
-
-       memcpy(hash, saddr, 16);
-       hash[4] = ((__force u16)sport << 16) + (__force u16)dport;
-       memcpy(&hash[5], keyptr->secret, sizeof(__u32) * 7);
-
-       seq = twothirdsMD4Transform((const __u32 *)daddr, hash) & HASH_MASK;
-       seq += keyptr->count;
-
-       seq += ktime_to_ns(ktime_get_real());
-
-       return seq;
-}
-EXPORT_SYMBOL(secure_tcpv6_sequence_number);
-#endif
-
-/*  The code below is shamelessly stolen from secure_tcp_sequence_number().
- *  All blames to Andrey V. Savochkin <saw@msu.ru>.
- */
-__u32 secure_ip_id(__be32 daddr)
-{
-       struct keydata *keyptr;
-       __u32 hash[4];
-
-       keyptr = get_keyptr();
-
-       /*
-        *  Pick a unique starting offset for each IP destination.
-        *  The dest ip address is placed in the starting vector,
-        *  which is then hashed with random data.
-        */
-       hash[0] = (__force __u32)daddr;
-       hash[1] = keyptr->secret[9];
-       hash[2] = keyptr->secret[10];
-       hash[3] = keyptr->secret[11];
-
-       return half_md4_transform(hash, keyptr->secret);
-}
-
-__u32 secure_ipv6_id(const __be32 daddr[4])
-{
-       const struct keydata *keyptr;
-       __u32 hash[4];
-
-       keyptr = get_keyptr();
-
-       hash[0] = (__force __u32)daddr[0];
-       hash[1] = (__force __u32)daddr[1];
-       hash[2] = (__force __u32)daddr[2];
-       hash[3] = (__force __u32)daddr[3];
-
-       return half_md4_transform(hash, keyptr->secret);
-}
-
-#ifdef CONFIG_INET
-
-__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
-                                __be16 sport, __be16 dport)
-{
-       __u32 seq;
-       __u32 hash[4];
-       struct keydata *keyptr = get_keyptr();
-
-       /*
-        *  Pick a unique starting offset for each TCP connection endpoints
-        *  (saddr, daddr, sport, dport).
-        *  Note that the words are placed into the starting vector, which is
-        *  then mixed with a partial MD4 over random data.
-        */
-       hash[0] = (__force u32)saddr;
-       hash[1] = (__force u32)daddr;
-       hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
-       hash[3] = keyptr->secret[11];
-
-       seq = half_md4_transform(hash, keyptr->secret) & HASH_MASK;
-       seq += keyptr->count;
-       /*
-        *      As close as possible to RFC 793, which
-        *      suggests using a 250 kHz clock.
-        *      Further reading shows this assumes 2 Mb/s networks.
-        *      For 10 Mb/s Ethernet, a 1 MHz clock is appropriate.
-        *      For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but
-        *      we also need to limit the resolution so that the u32 seq
-        *      overlaps less than one time per MSL (2 minutes).
-        *      Choosing a clock of 64 ns period is OK. (period of 274 s)
-        */
-       seq += ktime_to_ns(ktime_get_real()) >> 6;
-
-       return seq;
-}
-
-/* Generate secure starting point for ephemeral IPV4 transport port search */
-u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
-{
-       struct keydata *keyptr = get_keyptr();
-       u32 hash[4];
-
-       /*
-        *  Pick a unique starting offset for each ephemeral port search
-        *  (saddr, daddr, dport) and 48bits of random data.
-        */
-       hash[0] = (__force u32)saddr;
-       hash[1] = (__force u32)daddr;
-       hash[2] = (__force u32)dport ^ keyptr->secret[10];
-       hash[3] = keyptr->secret[11];
-
-       return half_md4_transform(hash, keyptr->secret);
-}
-EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral);
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
-                              __be16 dport)
-{
-       struct keydata *keyptr = get_keyptr();
-       u32 hash[12];
-
-       memcpy(hash, saddr, 16);
-       hash[4] = (__force u32)dport;
-       memcpy(&hash[5], keyptr->secret, sizeof(__u32) * 7);
-
-       return twothirdsMD4Transform((const __u32 *)daddr, hash);
-}
-#endif
-
-#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
-/* Similar to secure_tcp_sequence_number but generate a 48 bit value
- * bit's 32-47 increase every key exchange
- *       0-31  hash(source, dest)
- */
-u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
-                               __be16 sport, __be16 dport)
-{
-       u64 seq;
-       __u32 hash[4];
-       struct keydata *keyptr = get_keyptr();
-
-       hash[0] = (__force u32)saddr;
-       hash[1] = (__force u32)daddr;
-       hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
-       hash[3] = keyptr->secret[11];
-
-       seq = half_md4_transform(hash, keyptr->secret);
-       seq |= ((u64)keyptr->count) << (32 - HASH_BITS);
-
-       seq += ktime_to_ns(ktime_get_real());
-       seq &= (1ull << 48) - 1;
-
-       return seq;
-}
-EXPORT_SYMBOL(secure_dccp_sequence_number);
-#endif
-
-#endif /* CONFIG_INET */
-
+late_initcall(random_int_secret_init);
 
 /*
  * Get a random word for internal kernel use only. Similar to urandom but
@@ -1646,17 +1315,15 @@ EXPORT_SYMBOL(secure_dccp_sequence_number);
  * value is not cryptographically secure but for several uses the cost of
  * depleting entropy is too high
  */
-DEFINE_PER_CPU(__u32 [4], get_random_int_hash);
+DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
 unsigned int get_random_int(void)
 {
-       struct keydata *keyptr;
        __u32 *hash = get_cpu_var(get_random_int_hash);
-       int ret;
+       unsigned int ret;
 
-       keyptr = get_keyptr();
        hash[0] += current->pid + jiffies + get_cycles();
-
-       ret = half_md4_transform(hash, keyptr->secret);
+       md5_transform(hash, random_int_secret);
+       ret = hash[0];
        put_cpu_var(get_random_int_hash);
 
        return ret;
index 45e0191c35ddff9f977af6d07a6876e47e0f1bce..1e88d478532156de395f609d2a750db792221164 100644 (file)
@@ -769,4 +769,12 @@ config INTEL_OAKTRAIL
          enable/disable the Camera, WiFi, BT etc. devices. If in doubt, say Y
          here; it will only load on supported platforms.
 
+config SAMSUNG_Q10
+       tristate "Samsung Q10 Extras"
+       depends on SERIO_I8042
+       select BACKLIGHT_CLASS_DEVICE
+       ---help---
+         This driver provides support for backlight control on Samsung Q10
+         and related laptops, including Dell Latitude X200.
+
 endif # X86_PLATFORM_DEVICES
index afc1f832aa67df8639131835bbd2416bb5ac7774..293a320d9faaec9003fff3fa402d3e73322c66ae 100644 (file)
@@ -44,3 +44,4 @@ obj-$(CONFIG_SAMSUNG_LAPTOP)  += samsung-laptop.o
 obj-$(CONFIG_MXM_WMI)          += mxm-wmi.o
 obj-$(CONFIG_INTEL_MID_POWER_BUTTON)   += intel_mid_powerbtn.o
 obj-$(CONFIG_INTEL_OAKTRAIL)   += intel_oaktrail.o
+obj-$(CONFIG_SAMSUNG_Q10)      += samsung-q10.o
index e1c4938b301bbcdacbcc1303e9b8cde5bf288585..af2bb20cb2fbd39bcc3be8d77e42565cb35b1877 100644 (file)
@@ -99,6 +99,7 @@ enum acer_wmi_event_ids {
 static const struct key_entry acer_wmi_keymap[] = {
        {KE_KEY, 0x01, {KEY_WLAN} },     /* WiFi */
        {KE_KEY, 0x03, {KEY_WLAN} },     /* WiFi */
+       {KE_KEY, 0x04, {KEY_WLAN} },     /* WiFi */
        {KE_KEY, 0x12, {KEY_BLUETOOTH} },       /* BT */
        {KE_KEY, 0x21, {KEY_PROG1} },    /* Backup */
        {KE_KEY, 0x22, {KEY_PROG2} },    /* Arcade */
@@ -304,6 +305,10 @@ static struct quirk_entry quirk_fujitsu_amilo_li_1718 = {
        .wireless = 2,
 };
 
+static struct quirk_entry quirk_lenovo_ideapad_s205 = {
+       .wireless = 3,
+};
+
 /* The Aspire One has a dummy ACPI-WMI interface - disable it */
 static struct dmi_system_id __devinitdata acer_blacklist[] = {
        {
@@ -450,6 +455,15 @@ static struct dmi_system_id acer_quirks[] = {
                },
                .driver_data = &quirk_medion_md_98300,
        },
+       {
+               .callback = dmi_matched,
+               .ident = "Lenovo Ideapad S205",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "10382LG"),
+               },
+               .driver_data = &quirk_lenovo_ideapad_s205,
+       },
        {}
 };
 
@@ -542,6 +556,12 @@ struct wmi_interface *iface)
                                return AE_ERROR;
                        *value = result & 0x1;
                        return AE_OK;
+               case 3:
+                       err = ec_read(0x78, &result);
+                       if (err)
+                               return AE_ERROR;
+                       *value = result & 0x1;
+                       return AE_OK;
                default:
                        err = ec_read(0xA, &result);
                        if (err)
@@ -1266,8 +1286,13 @@ static void acer_rfkill_update(struct work_struct *ignored)
        acpi_status status;
 
        status = get_u32(&state, ACER_CAP_WIRELESS);
-       if (ACPI_SUCCESS(status))
-               rfkill_set_sw_state(wireless_rfkill, !state);
+       if (ACPI_SUCCESS(status)) {
+               if (quirks->wireless == 3) {
+                       rfkill_set_hw_state(wireless_rfkill, !state);
+               } else {
+                       rfkill_set_sw_state(wireless_rfkill, !state);
+               }
+       }
 
        if (has_cap(ACER_CAP_BLUETOOTH)) {
                status = get_u32(&state, ACER_CAP_BLUETOOTH);
@@ -1400,6 +1425,9 @@ static ssize_t show_bool_threeg(struct device *dev,
 {
        u32 result; \
        acpi_status status;
+
+       pr_info("This threeg sysfs will be removed in 2012"
+               " - used by: %s\n", current->comm);
        if (wmi_has_guid(WMID_GUID3))
                status = wmid3_get_device_status(&result,
                                ACER_WMID3_GDS_THREEG);
@@ -1415,8 +1443,10 @@ static ssize_t set_bool_threeg(struct device *dev,
 {
        u32 tmp = simple_strtoul(buf, NULL, 10);
        acpi_status status = set_u32(tmp, ACER_CAP_THREEG);
-               if (ACPI_FAILURE(status))
-                       return -EINVAL;
+       pr_info("This threeg sysfs will be removed in 2012"
+               " - used by: %s\n", current->comm);
+       if (ACPI_FAILURE(status))
+               return -EINVAL;
        return count;
 }
 static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
@@ -1425,6 +1455,8 @@ static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
 static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
        char *buf)
 {
+       pr_info("This interface sysfs will be removed in 2012"
+               " - used by: %s\n", current->comm);
        switch (interface->type) {
        case ACER_AMW0:
                return sprintf(buf, "AMW0\n");
index fca3489218b76b0c48a08fb5ef2cc0e0ad3250ed..760c6d7624fe505f5da3f40060a1df9d0eaf12b0 100644 (file)
@@ -182,6 +182,7 @@ static const struct bios_settings_t bios_tbl[] = {
        {"Acer", "Aspire 1810T",  "v1.3308", 0x55, 0x58, {0x9e, 0x00} },
        {"Acer", "Aspire 1810TZ", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
        {"Acer", "Aspire 1810T",  "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
+       {"Acer", "Aspire 1810TZ", "v1.3314", 0x55, 0x58, {0x9e, 0x00} },
        /* Acer 531 */
        {"Acer", "AO531h", "v0.3201", 0x55, 0x58, {0x20, 0x00} },
        /* Gateway */
@@ -703,15 +704,15 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Peter Feuerer");
 MODULE_DESCRIPTION("Aspire One temperature and fan driver");
 MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:");
-MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1410*:");
-MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1810*:");
+MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1410*:");
+MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1810*:");
 MODULE_ALIAS("dmi:*:*Acer*:pnAO531*:");
 MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:");
 MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:");
-MODULE_ALIAS("dmi:*:*Packard Bell*:pnAOA*:");
-MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOA*:");
-MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMU*:");
-MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMA*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnAOA*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOA*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMU*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMA*:");
 
 module_init(acerhdf_init);
 module_exit(acerhdf_exit);
index d65df92e2acc63fb9eea85d82434c359ed8654fd..fa6d7ec68b269670b4de8ca24cb97b3d55160acc 100644 (file)
@@ -70,11 +70,10 @@ MODULE_LICENSE("GPL");
  * WAPF defines the behavior of the Fn+Fx wlan key
  * The significance of values is yet to be found, but
  * most of the time:
- * 0x0 will do nothing
- * 0x1 will allow to control the device with Fn+Fx key.
- * 0x4 will send an ACPI event (0x88) while pressing the Fn+Fx key
- * 0x5 like 0x1 or 0x4
- * So, if something doesn't work as you want, just try other values =)
+ * Bit | Bluetooth | WLAN
+ *  0  | Hardware  | Hardware
+ *  1  | Hardware  | Software
+ *  4  | Software  | Software
  */
 static uint wapf = 1;
 module_param(wapf, uint, 0444);
index 0580d99b0798e9bf68f03cd8877bf07a141dff94..b0859d4183e8307d27ef9c3979bf613d4548c603 100644 (file)
@@ -38,6 +38,24 @@ MODULE_LICENSE("GPL");
 
 MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID);
 
+/*
+ * WAPF defines the behavior of the Fn+Fx wlan key
+ * The significance of values is yet to be found, but
+ * most of the time:
+ * Bit | Bluetooth | WLAN
+ *  0  | Hardware  | Hardware
+ *  1  | Hardware  | Software
+ *  4  | Software  | Software
+ */
+static uint wapf;
+module_param(wapf, uint, 0444);
+MODULE_PARM_DESC(wapf, "WAPF value");
+
+static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver)
+{
+       driver->wapf = wapf;
+}
+
 static const struct key_entry asus_nb_wmi_keymap[] = {
        { KE_KEY, 0x30, { KEY_VOLUMEUP } },
        { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
@@ -53,16 +71,16 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
        { KE_KEY, 0x51, { KEY_WWW } },
        { KE_KEY, 0x55, { KEY_CALC } },
        { KE_KEY, 0x5C, { KEY_F15 } },  /* Power Gear key */
-       { KE_KEY, 0x5D, { KEY_WLAN } },
-       { KE_KEY, 0x5E, { KEY_WLAN } },
-       { KE_KEY, 0x5F, { KEY_WLAN } },
+       { KE_KEY, 0x5D, { KEY_WLAN } }, /* Wireless console Toggle */
+       { KE_KEY, 0x5E, { KEY_WLAN } }, /* Wireless console Enable */
+       { KE_KEY, 0x5F, { KEY_WLAN } }, /* Wireless console Disable */
        { KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } },
        { KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } },
        { KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } },
        { KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } },
        { KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } },
-       { KE_KEY, 0x7E, { KEY_BLUETOOTH } },
        { KE_KEY, 0x7D, { KEY_BLUETOOTH } },
+       { KE_KEY, 0x7E, { KEY_BLUETOOTH } },
        { KE_KEY, 0x82, { KEY_CAMERA } },
        { KE_KEY, 0x88, { KEY_RFKILL  } },
        { KE_KEY, 0x8A, { KEY_PROG1 } },
@@ -81,6 +99,7 @@ static struct asus_wmi_driver asus_nb_wmi_driver = {
        .keymap = asus_nb_wmi_keymap,
        .input_name = "Asus WMI hotkeys",
        .input_phys = ASUS_NB_WMI_FILE "/input0",
+       .quirks = asus_nb_wmi_quirks,
 };
 
 
index 65b66aa44c786f64dba15a94d607b292260630e7..95cba9ebf6c08ddab129840447367fb0e83aea9e 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/platform_device.h>
+#include <linux/thermal.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
@@ -66,6 +67,8 @@ MODULE_LICENSE("GPL");
 #define NOTIFY_BRNUP_MAX               0x1f
 #define NOTIFY_BRNDOWN_MIN             0x20
 #define NOTIFY_BRNDOWN_MAX             0x2e
+#define NOTIFY_KBD_BRTUP               0xc4
+#define NOTIFY_KBD_BRTDWN              0xc5
 
 /* WMI Methods */
 #define ASUS_WMI_METHODID_SPEC         0x43455053 /* BIOS SPECification */
@@ -93,6 +96,7 @@ MODULE_LICENSE("GPL");
 /* Wireless */
 #define ASUS_WMI_DEVID_HW_SWITCH       0x00010001
 #define ASUS_WMI_DEVID_WIRELESS_LED    0x00010002
+#define ASUS_WMI_DEVID_CWAP            0x00010003
 #define ASUS_WMI_DEVID_WLAN            0x00010011
 #define ASUS_WMI_DEVID_BLUETOOTH       0x00010013
 #define ASUS_WMI_DEVID_GPS             0x00010015
@@ -102,6 +106,12 @@ MODULE_LICENSE("GPL");
 
 /* Leds */
 /* 0x000200XX and 0x000400XX */
+#define ASUS_WMI_DEVID_LED1            0x00020011
+#define ASUS_WMI_DEVID_LED2            0x00020012
+#define ASUS_WMI_DEVID_LED3            0x00020013
+#define ASUS_WMI_DEVID_LED4            0x00020014
+#define ASUS_WMI_DEVID_LED5            0x00020015
+#define ASUS_WMI_DEVID_LED6            0x00020016
 
 /* Backlight and Brightness */
 #define ASUS_WMI_DEVID_BACKLIGHT       0x00050011
@@ -174,13 +184,18 @@ struct asus_wmi {
 
        struct led_classdev tpd_led;
        int tpd_led_wk;
+       struct led_classdev kbd_led;
+       int kbd_led_wk;
        struct workqueue_struct *led_workqueue;
        struct work_struct tpd_led_work;
+       struct work_struct kbd_led_work;
 
        struct asus_rfkill wlan;
        struct asus_rfkill bluetooth;
        struct asus_rfkill wimax;
        struct asus_rfkill wwan3g;
+       struct asus_rfkill gps;
+       struct asus_rfkill uwb;
 
        struct hotplug_slot *hotplug_slot;
        struct mutex hotplug_lock;
@@ -205,6 +220,7 @@ static int asus_wmi_input_init(struct asus_wmi *asus)
        asus->inputdev->phys = asus->driver->input_phys;
        asus->inputdev->id.bustype = BUS_HOST;
        asus->inputdev->dev.parent = &asus->platform_device->dev;
+       set_bit(EV_REP, asus->inputdev->evbit);
 
        err = sparse_keymap_setup(asus->inputdev, asus->driver->keymap, NULL);
        if (err)
@@ -359,30 +375,80 @@ static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
        return read_tpd_led_state(asus);
 }
 
-static int asus_wmi_led_init(struct asus_wmi *asus)
+static void kbd_led_update(struct work_struct *work)
 {
-       int rv;
+       int ctrl_param = 0;
+       struct asus_wmi *asus;
 
-       if (read_tpd_led_state(asus) < 0)
-               return 0;
+       asus = container_of(work, struct asus_wmi, kbd_led_work);
 
-       asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
-       if (!asus->led_workqueue)
-               return -ENOMEM;
-       INIT_WORK(&asus->tpd_led_work, tpd_led_update);
+       /*
+        * bits 0-2: level
+        * bit 7: light on/off
+        */
+       if (asus->kbd_led_wk > 0)
+               ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
 
-       asus->tpd_led.name = "asus::touchpad";
-       asus->tpd_led.brightness_set = tpd_led_set;
-       asus->tpd_led.brightness_get = tpd_led_get;
-       asus->tpd_led.max_brightness = 1;
+       asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL);
+}
 
-       rv = led_classdev_register(&asus->platform_device->dev, &asus->tpd_led);
-       if (rv) {
-               destroy_workqueue(asus->led_workqueue);
-               return rv;
+static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)
+{
+       int retval;
+
+       /*
+        * bits 0-2: level
+        * bit 7: light on/off
+        * bit 8-10: environment (0: dark, 1: normal, 2: light)
+        * bit 17: status unknown
+        */
+       retval = asus_wmi_get_devstate_bits(asus, ASUS_WMI_DEVID_KBD_BACKLIGHT,
+                                           0xFFFF);
+
+       /* Unknown status is considered as off */
+       if (retval == 0x8000)
+               retval = 0;
+
+       if (retval >= 0) {
+               if (level)
+                       *level = retval & 0x80 ? retval & 0x7F : 0;
+               if (env)
+                       *env = (retval >> 8) & 0x7F;
+               retval = 0;
        }
 
-       return 0;
+       return retval;
+}
+
+static void kbd_led_set(struct led_classdev *led_cdev,
+                       enum led_brightness value)
+{
+       struct asus_wmi *asus;
+
+       asus = container_of(led_cdev, struct asus_wmi, kbd_led);
+
+       if (value > asus->kbd_led.max_brightness)
+               value = asus->kbd_led.max_brightness;
+       else if (value < 0)
+               value = 0;
+
+       asus->kbd_led_wk = value;
+       queue_work(asus->led_workqueue, &asus->kbd_led_work);
+}
+
+static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
+{
+       struct asus_wmi *asus;
+       int retval, value;
+
+       asus = container_of(led_cdev, struct asus_wmi, kbd_led);
+
+       retval = kbd_led_read(asus, &value, NULL);
+
+       if (retval < 0)
+               return retval;
+
+       return value;
 }
 
 static void asus_wmi_led_exit(struct asus_wmi *asus)
@@ -393,6 +459,48 @@ static void asus_wmi_led_exit(struct asus_wmi *asus)
                destroy_workqueue(asus->led_workqueue);
 }
 
+static int asus_wmi_led_init(struct asus_wmi *asus)
+{
+       int rv = 0;
+
+       asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
+       if (!asus->led_workqueue)
+               return -ENOMEM;
+
+       if (read_tpd_led_state(asus) >= 0) {
+               INIT_WORK(&asus->tpd_led_work, tpd_led_update);
+
+               asus->tpd_led.name = "asus::touchpad";
+               asus->tpd_led.brightness_set = tpd_led_set;
+               asus->tpd_led.brightness_get = tpd_led_get;
+               asus->tpd_led.max_brightness = 1;
+
+               rv = led_classdev_register(&asus->platform_device->dev,
+                                          &asus->tpd_led);
+               if (rv)
+                       goto error;
+       }
+
+       if (kbd_led_read(asus, NULL, NULL) >= 0) {
+               INIT_WORK(&asus->kbd_led_work, kbd_led_update);
+
+               asus->kbd_led.name = "asus::kbd_backlight";
+               asus->kbd_led.brightness_set = kbd_led_set;
+               asus->kbd_led.brightness_get = kbd_led_get;
+               asus->kbd_led.max_brightness = 3;
+
+               rv = led_classdev_register(&asus->platform_device->dev,
+                                          &asus->kbd_led);
+       }
+
+error:
+       if (rv)
+               asus_wmi_led_exit(asus);
+
+       return rv;
+}
+
+
 /*
  * PCI hotplug (for wlan rfkill)
  */
@@ -729,6 +837,16 @@ static void asus_wmi_rfkill_exit(struct asus_wmi *asus)
                rfkill_destroy(asus->wwan3g.rfkill);
                asus->wwan3g.rfkill = NULL;
        }
+       if (asus->gps.rfkill) {
+               rfkill_unregister(asus->gps.rfkill);
+               rfkill_destroy(asus->gps.rfkill);
+               asus->gps.rfkill = NULL;
+       }
+       if (asus->uwb.rfkill) {
+               rfkill_unregister(asus->uwb.rfkill);
+               rfkill_destroy(asus->uwb.rfkill);
+               asus->uwb.rfkill = NULL;
+       }
 }
 
 static int asus_wmi_rfkill_init(struct asus_wmi *asus)
@@ -763,6 +881,18 @@ static int asus_wmi_rfkill_init(struct asus_wmi *asus)
        if (result && result != -ENODEV)
                goto exit;
 
+       result = asus_new_rfkill(asus, &asus->gps, "asus-gps",
+                                RFKILL_TYPE_GPS, ASUS_WMI_DEVID_GPS);
+
+       if (result && result != -ENODEV)
+               goto exit;
+
+       result = asus_new_rfkill(asus, &asus->uwb, "asus-uwb",
+                                RFKILL_TYPE_UWB, ASUS_WMI_DEVID_UWB);
+
+       if (result && result != -ENODEV)
+               goto exit;
+
        if (!asus->driver->hotplug_wireless)
                goto exit;
 
@@ -797,8 +927,8 @@ exit:
  * Hwmon device
  */
 static ssize_t asus_hwmon_pwm1(struct device *dev,
-                           struct device_attribute *attr,
-                           char *buf)
+                              struct device_attribute *attr,
+                              char *buf)
 {
        struct asus_wmi *asus = dev_get_drvdata(dev);
        u32 value;
@@ -809,7 +939,7 @@ static ssize_t asus_hwmon_pwm1(struct device *dev,
        if (err < 0)
                return err;
 
-       value |= 0xFF;
+       value &= 0xFF;
 
        if (value == 1) /* Low Speed */
                value = 85;
@@ -825,7 +955,26 @@ static ssize_t asus_hwmon_pwm1(struct device *dev,
        return sprintf(buf, "%d\n", value);
 }
 
+static ssize_t asus_hwmon_temp1(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct asus_wmi *asus = dev_get_drvdata(dev);
+       u32 value;
+       int err;
+
+       err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_THERMAL_CTRL, &value);
+
+       if (err < 0)
+               return err;
+
+       value = KELVIN_TO_CELSIUS((value & 0xFFFF)) * 1000;
+
+       return sprintf(buf, "%d\n", value);
+}
+
 static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, asus_hwmon_pwm1, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL, 0);
 
 static ssize_t
 show_name(struct device *dev, struct device_attribute *attr, char *buf)
@@ -836,12 +985,13 @@ static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
 
 static struct attribute *hwmon_attributes[] = {
        &sensor_dev_attr_pwm1.dev_attr.attr,
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
        &sensor_dev_attr_name.dev_attr.attr,
        NULL
 };
 
 static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
-                                   struct attribute *attr, int idx)
+                                         struct attribute *attr, int idx)
 {
        struct device *dev = container_of(kobj, struct device, kobj);
        struct platform_device *pdev = to_platform_device(dev->parent);
@@ -852,6 +1002,8 @@ static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
 
        if (attr == &sensor_dev_attr_pwm1.dev_attr.attr)
                dev_id = ASUS_WMI_DEVID_FAN_CTRL;
+       else if (attr == &sensor_dev_attr_temp1_input.dev_attr.attr)
+               dev_id = ASUS_WMI_DEVID_THERMAL_CTRL;
 
        if (dev_id != -1) {
                int err = asus_wmi_get_devstate(asus, dev_id, &value);
@@ -869,9 +1021,13 @@ static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
                 * - reverved bits are non-zero
                 * - sfun and presence bit are not set
                 */
-               if (value != ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
+               if (value == ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
                    || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT)))
                        ok = false;
+       } else if (dev_id == ASUS_WMI_DEVID_THERMAL_CTRL) {
+               /* If value is zero, something is clearly wrong */
+               if (value == 0)
+                       ok = false;
        }
 
        return ok ? attr->mode : 0;
@@ -904,6 +1060,7 @@ static int asus_wmi_hwmon_init(struct asus_wmi *asus)
                pr_err("Could not register asus hwmon device\n");
                return PTR_ERR(hwmon);
        }
+       dev_set_drvdata(hwmon, asus);
        asus->hwmon_device = hwmon;
        result = sysfs_create_group(&hwmon->kobj, &hwmon_attribute_group);
        if (result)
@@ -1060,6 +1217,8 @@ static void asus_wmi_notify(u32 value, void *context)
        acpi_status status;
        int code;
        int orig_code;
+       unsigned int key_value = 1;
+       bool autorelease = 1;
 
        status = wmi_get_event_data(value, &response);
        if (status != AE_OK) {
@@ -1075,6 +1234,13 @@ static void asus_wmi_notify(u32 value, void *context)
        code = obj->integer.value;
        orig_code = code;
 
+       if (asus->driver->key_filter) {
+               asus->driver->key_filter(asus->driver, &code, &key_value,
+                                        &autorelease);
+               if (code == ASUS_WMI_KEY_IGNORE)
+                       goto exit;
+       }
+
        if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
                code = NOTIFY_BRNUP_MIN;
        else if (code >= NOTIFY_BRNDOWN_MIN &&
@@ -1084,7 +1250,8 @@ static void asus_wmi_notify(u32 value, void *context)
        if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
                if (!acpi_video_backlight_support())
                        asus_wmi_backlight_notify(asus, orig_code);
-       } else if (!sparse_keymap_report_event(asus->inputdev, code, 1, true))
+       } else if (!sparse_keymap_report_event(asus->inputdev, code,
+                                              key_value, autorelease))
                pr_info("Unknown key %x pressed\n", code);
 
 exit:
@@ -1164,14 +1331,18 @@ ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER);
 static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
                           const char *buf, size_t count)
 {
-       int value;
+       int value, rv;
 
        if (!count || sscanf(buf, "%i", &value) != 1)
                return -EINVAL;
        if (value < 0 || value > 2)
                return -EINVAL;
 
-       return asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
+       rv = asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
+       if (rv < 0)
+               return rv;
+
+       return count;
 }
 
 static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
@@ -1234,7 +1405,7 @@ static int asus_wmi_platform_init(struct asus_wmi *asus)
 
        /* We don't know yet what to do with this version... */
        if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SPEC, 0, 0x9, &rv)) {
-               pr_info("BIOS WMI version: %d.%d", rv >> 8, rv & 0xFF);
+               pr_info("BIOS WMI version: %d.%d", rv >> 16, rv & 0xFF);
                asus->spec = rv;
        }
 
@@ -1266,6 +1437,12 @@ static int asus_wmi_platform_init(struct asus_wmi *asus)
                return -ENODEV;
        }
 
+       /* CWAP allow to define the behavior of the Fn+F2 key,
+        * this method doesn't seems to be present on Eee PCs */
+       if (asus->driver->wapf >= 0)
+               asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,
+                                     asus->driver->wapf, NULL);
+
        return asus_wmi_sysfs_init(asus->platform_device);
 }
 
@@ -1568,6 +1745,14 @@ static int asus_hotk_restore(struct device *device)
                bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WWAN3G);
                rfkill_set_sw_state(asus->wwan3g.rfkill, bl);
        }
+       if (asus->gps.rfkill) {
+               bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPS);
+               rfkill_set_sw_state(asus->gps.rfkill, bl);
+       }
+       if (asus->uwb.rfkill) {
+               bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_UWB);
+               rfkill_set_sw_state(asus->uwb.rfkill, bl);
+       }
 
        return 0;
 }
@@ -1604,7 +1789,7 @@ static int asus_wmi_probe(struct platform_device *pdev)
 
 static bool used;
 
-int asus_wmi_register_driver(struct asus_wmi_driver *driver)
+int __init_or_module asus_wmi_register_driver(struct asus_wmi_driver *driver)
 {
        struct platform_driver *platform_driver;
        struct platform_device *platform_device;
index c044522c87661ad59d38ab78d4d4931bde97d5dc..8147c10161cc590d729c2afcfc03c43df7df3e1f 100644 (file)
 
 #include <linux/platform_device.h>
 
+#define ASUS_WMI_KEY_IGNORE (-1)
+
 struct module;
 struct key_entry;
 struct asus_wmi;
 
 struct asus_wmi_driver {
        bool                    hotplug_wireless;
+       int                     wapf;
 
        const char              *name;
        struct module           *owner;
@@ -44,6 +47,10 @@ struct asus_wmi_driver {
        const struct key_entry  *keymap;
        const char              *input_name;
        const char              *input_phys;
+       /* Returns new code, value, and autorelease values in arguments.
+        * Return ASUS_WMI_KEY_IGNORE in code if event should be ignored. */
+       void (*key_filter) (struct asus_wmi_driver *driver, int *code,
+                           unsigned int *value, bool *autorelease);
 
        int (*probe) (struct platform_device *device);
        void (*quirks) (struct asus_wmi_driver *driver);
index e39ab1d3ed878b6044a391db4be16b58224da0d2..f31fa4efa725504bc4a9e6b251686453d0cb7e6d 100644 (file)
@@ -612,7 +612,6 @@ static int __init dell_init(void)
        if (!bufferpage)
                goto fail_buffer;
        buffer = page_address(bufferpage);
-       mutex_init(&buffer_mutex);
 
        ret = dell_setup_rfkill();
 
index ce790827e199ab4d4d9784850023ac4321c7bcc2..fa9a2171cc134b733c837f89a4f1b80aeb0989ea 100644 (file)
@@ -54,6 +54,8 @@ MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
  */
 
 static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
+       { KE_IGNORE, 0x003a, { KEY_CAPSLOCK } },
+
        { KE_KEY, 0xe045, { KEY_PROG1 } },
        { KE_KEY, 0xe009, { KEY_EJECTCD } },
 
@@ -85,6 +87,11 @@ static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
        { KE_IGNORE, 0xe013, { KEY_RESERVED } },
 
        { KE_IGNORE, 0xe020, { KEY_MUTE } },
+
+       /* Shortcut and audio panel keys */
+       { KE_IGNORE, 0xe025, { KEY_RESERVED } },
+       { KE_IGNORE, 0xe026, { KEY_RESERVED } },
+
        { KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } },
        { KE_IGNORE, 0xe030, { KEY_VOLUMEUP } },
        { KE_IGNORE, 0xe033, { KEY_KBDILLUMUP } },
@@ -92,6 +99,9 @@ static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
        { KE_IGNORE, 0xe03a, { KEY_CAPSLOCK } },
        { KE_IGNORE, 0xe045, { KEY_NUMLOCK } },
        { KE_IGNORE, 0xe046, { KEY_SCROLLLOCK } },
+       { KE_IGNORE, 0xe0f7, { KEY_MUTE } },
+       { KE_IGNORE, 0xe0f8, { KEY_VOLUMEDOWN } },
+       { KE_IGNORE, 0xe0f9, { KEY_VOLUMEUP } },
        { KE_END, 0 }
 };
 
index 4aa867a9b88b8411f5231e9ac7a4298ffc9b8860..9f6e64302b457b04fb0871524e9ac906af34399f 100644 (file)
@@ -56,6 +56,11 @@ MODULE_PARM_DESC(hotplug_wireless,
                 "If your laptop needs that, please report to "
                 "acpi4asus-user@lists.sourceforge.net.");
 
+/* Values for T101MT "Home" key */
+#define HOME_PRESS     0xe4
+#define HOME_HOLD      0xea
+#define HOME_RELEASE   0xe5
+
 static const struct key_entry eeepc_wmi_keymap[] = {
        /* Sleep already handled via generic ACPI code */
        { KE_KEY, 0x30, { KEY_VOLUMEUP } },
@@ -71,6 +76,7 @@ static const struct key_entry eeepc_wmi_keymap[] = {
        { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
        { KE_KEY, 0xe0, { KEY_PROG1 } }, /* Task Manager */
        { KE_KEY, 0xe1, { KEY_F14 } }, /* Change Resolution */
+       { KE_KEY, HOME_PRESS, { KEY_CONFIG } }, /* Home/Express gate key */
        { KE_KEY, 0xe8, { KEY_SCREENLOCK } },
        { KE_KEY, 0xe9, { KEY_BRIGHTNESS_ZERO } },
        { KE_KEY, 0xeb, { KEY_CAMERA_ZOOMOUT } },
@@ -81,6 +87,25 @@ static const struct key_entry eeepc_wmi_keymap[] = {
        { KE_END, 0},
 };
 
+static void eeepc_wmi_key_filter(struct asus_wmi_driver *asus_wmi, int *code,
+                                unsigned int *value, bool *autorelease)
+{
+       switch (*code) {
+       case HOME_PRESS:
+               *value = 1;
+               *autorelease = 0;
+               break;
+       case HOME_HOLD:
+               *code = ASUS_WMI_KEY_IGNORE;
+               break;
+       case HOME_RELEASE:
+               *code = HOME_PRESS;
+               *value = 0;
+               *autorelease = 0;
+               break;
+       }
+}
+
 static acpi_status eeepc_wmi_parse_device(acpi_handle handle, u32 level,
                                                 void *context, void **retval)
 {
@@ -141,6 +166,7 @@ static void eeepc_dmi_check(struct asus_wmi_driver *driver)
 static void eeepc_wmi_quirks(struct asus_wmi_driver *driver)
 {
        driver->hotplug_wireless = hotplug_wireless;
+       driver->wapf = -1;
        eeepc_dmi_check(driver);
 }
 
@@ -151,6 +177,7 @@ static struct asus_wmi_driver asus_wmi_driver = {
        .keymap = eeepc_wmi_keymap,
        .input_name = "Eee PC WMI hotkeys",
        .input_phys = EEEPC_WMI_FILE "/input0",
+       .key_filter = eeepc_wmi_key_filter,
        .probe = eeepc_wmi_probe,
        .quirks = eeepc_wmi_quirks,
 };
index bfdda33feb26547dea8a5187543bb4b58de38f01..0c595410e78897e8b6b3f4b9e9c84e765ac0ba57 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
 
 #define IDEAPAD_RFKILL_DEV_NUM (3)
 
+#define CFG_BT_BIT     (16)
+#define CFG_3G_BIT     (17)
+#define CFG_WIFI_BIT   (18)
+#define CFG_CAMERA_BIT (19)
+
 struct ideapad_private {
        struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
        struct platform_device *platform_device;
        struct input_dev *inputdev;
+       struct backlight_device *blightdev;
+       unsigned long cfg;
 };
 
 static acpi_handle ideapad_handle;
@@ -155,7 +164,7 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
 }
 
 /*
- * camera power
+ * sysfs
  */
 static ssize_t show_ideapad_cam(struct device *dev,
                                struct device_attribute *attr,
@@ -186,6 +195,44 @@ static ssize_t store_ideapad_cam(struct device *dev,
 
 static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
 
+static ssize_t show_ideapad_cfg(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct ideapad_private *priv = dev_get_drvdata(dev);
+
+       return sprintf(buf, "0x%.8lX\n", priv->cfg);
+}
+
+static DEVICE_ATTR(cfg, 0444, show_ideapad_cfg, NULL);
+
+static struct attribute *ideapad_attributes[] = {
+       &dev_attr_camera_power.attr,
+       &dev_attr_cfg.attr,
+       NULL
+};
+
+static mode_t ideapad_is_visible(struct kobject *kobj,
+                                struct attribute *attr,
+                                int idx)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct ideapad_private *priv = dev_get_drvdata(dev);
+       bool supported;
+
+       if (attr == &dev_attr_camera_power.attr)
+               supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg));
+       else
+               supported = true;
+
+       return supported ? attr->mode : 0;
+}
+
+static struct attribute_group ideapad_attribute_group = {
+       .is_visible = ideapad_is_visible,
+       .attrs = ideapad_attributes
+};
+
 /*
  * Rfkill
  */
@@ -197,9 +244,9 @@ struct ideapad_rfk_data {
 };
 
 const struct ideapad_rfk_data ideapad_rfk_data[] = {
-       { "ideapad_wlan",       18, 0x15, RFKILL_TYPE_WLAN },
-       { "ideapad_bluetooth",  16, 0x17, RFKILL_TYPE_BLUETOOTH },
-       { "ideapad_3g",         17, 0x20, RFKILL_TYPE_WWAN },
+       { "ideapad_wlan",      CFG_WIFI_BIT, 0x15, RFKILL_TYPE_WLAN },
+       { "ideapad_bluetooth", CFG_BT_BIT,   0x17, RFKILL_TYPE_BLUETOOTH },
+       { "ideapad_3g",        CFG_3G_BIT,   0x20, RFKILL_TYPE_WWAN },
 };
 
 static int ideapad_rfk_set(void *data, bool blocked)
@@ -265,8 +312,7 @@ static int __devinit ideapad_register_rfkill(struct acpi_device *adevice,
        return 0;
 }
 
-static void __devexit ideapad_unregister_rfkill(struct acpi_device *adevice,
-                                               int dev)
+static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev)
 {
        struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
 
@@ -280,15 +326,6 @@ static void __devexit ideapad_unregister_rfkill(struct acpi_device *adevice,
 /*
  * Platform device
  */
-static struct attribute *ideapad_attributes[] = {
-       &dev_attr_camera_power.attr,
-       NULL
-};
-
-static struct attribute_group ideapad_attribute_group = {
-       .attrs = ideapad_attributes
-};
-
 static int __devinit ideapad_platform_init(struct ideapad_private *priv)
 {
        int result;
@@ -369,7 +406,7 @@ err_free_dev:
        return error;
 }
 
-static void __devexit ideapad_input_exit(struct ideapad_private *priv)
+static void ideapad_input_exit(struct ideapad_private *priv)
 {
        sparse_keymap_free(priv->inputdev);
        input_unregister_device(priv->inputdev);
@@ -382,6 +419,98 @@ static void ideapad_input_report(struct ideapad_private *priv,
        sparse_keymap_report_event(priv->inputdev, scancode, 1, true);
 }
 
+/*
+ * backlight
+ */
+static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
+{
+       unsigned long now;
+
+       if (read_ec_data(ideapad_handle, 0x12, &now))
+               return -EIO;
+       return now;
+}
+
+static int ideapad_backlight_update_status(struct backlight_device *blightdev)
+{
+       if (write_ec_cmd(ideapad_handle, 0x13, blightdev->props.brightness))
+               return -EIO;
+       if (write_ec_cmd(ideapad_handle, 0x33,
+                        blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1))
+               return -EIO;
+
+       return 0;
+}
+
+static const struct backlight_ops ideapad_backlight_ops = {
+       .get_brightness = ideapad_backlight_get_brightness,
+       .update_status = ideapad_backlight_update_status,
+};
+
+static int ideapad_backlight_init(struct ideapad_private *priv)
+{
+       struct backlight_device *blightdev;
+       struct backlight_properties props;
+       unsigned long max, now, power;
+
+       if (read_ec_data(ideapad_handle, 0x11, &max))
+               return -EIO;
+       if (read_ec_data(ideapad_handle, 0x12, &now))
+               return -EIO;
+       if (read_ec_data(ideapad_handle, 0x18, &power))
+               return -EIO;
+
+       memset(&props, 0, sizeof(struct backlight_properties));
+       props.max_brightness = max;
+       props.type = BACKLIGHT_PLATFORM;
+       blightdev = backlight_device_register("ideapad",
+                                             &priv->platform_device->dev,
+                                             priv,
+                                             &ideapad_backlight_ops,
+                                             &props);
+       if (IS_ERR(blightdev)) {
+               pr_err("Could not register backlight device\n");
+               return PTR_ERR(blightdev);
+       }
+
+       priv->blightdev = blightdev;
+       blightdev->props.brightness = now;
+       blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
+       backlight_update_status(blightdev);
+
+       return 0;
+}
+
+static void ideapad_backlight_exit(struct ideapad_private *priv)
+{
+       if (priv->blightdev)
+               backlight_device_unregister(priv->blightdev);
+       priv->blightdev = NULL;
+}
+
+static void ideapad_backlight_notify_power(struct ideapad_private *priv)
+{
+       unsigned long power;
+       struct backlight_device *blightdev = priv->blightdev;
+
+       if (read_ec_data(ideapad_handle, 0x18, &power))
+               return;
+       blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
+}
+
+static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
+{
+       unsigned long now;
+
+       /* if we control brightness via acpi video driver */
+       if (priv->blightdev == NULL) {
+               read_ec_data(ideapad_handle, 0x12, &now);
+               return;
+       }
+
+       backlight_force_update(priv->blightdev, BACKLIGHT_UPDATE_HOTKEY);
+}
+
 /*
  * module init/exit
  */
@@ -393,10 +522,11 @@ MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
 
 static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
 {
-       int ret, i, cfg;
+       int ret, i;
+       unsigned long cfg;
        struct ideapad_private *priv;
 
-       if (read_method_int(adevice->handle, "_CFG", &cfg))
+       if (read_method_int(adevice->handle, "_CFG", (int *)&cfg))
                return -ENODEV;
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -404,6 +534,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
                return -ENOMEM;
        dev_set_drvdata(&adevice->dev, priv);
        ideapad_handle = adevice->handle;
+       priv->cfg = cfg;
 
        ret = ideapad_platform_init(priv);
        if (ret)
@@ -414,15 +545,25 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
                goto input_failed;
 
        for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) {
-               if (test_bit(ideapad_rfk_data[i].cfgbit, (unsigned long *)&cfg))
+               if (test_bit(ideapad_rfk_data[i].cfgbit, &cfg))
                        ideapad_register_rfkill(adevice, i);
                else
                        priv->rfk[i] = NULL;
        }
        ideapad_sync_rfk_state(adevice);
 
+       if (!acpi_video_backlight_support()) {
+               ret = ideapad_backlight_init(priv);
+               if (ret && ret != -ENODEV)
+                       goto backlight_failed;
+       }
+
        return 0;
 
+backlight_failed:
+       for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
+               ideapad_unregister_rfkill(adevice, i);
+       ideapad_input_exit(priv);
 input_failed:
        ideapad_platform_exit(priv);
 platform_failed:
@@ -435,6 +576,7 @@ static int __devexit ideapad_acpi_remove(struct acpi_device *adevice, int type)
        struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
        int i;
 
+       ideapad_backlight_exit(priv);
        for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
                ideapad_unregister_rfkill(adevice, i);
        ideapad_input_exit(priv);
@@ -459,12 +601,19 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
        vpc1 = (vpc2 << 8) | vpc1;
        for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
                if (test_bit(vpc_bit, &vpc1)) {
-                       if (vpc_bit == 9)
+                       switch (vpc_bit) {
+                       case 9:
                                ideapad_sync_rfk_state(adevice);
-                       else if (vpc_bit == 4)
-                               read_ec_data(handle, 0x12, &vpc2);
-                       else
+                               break;
+                       case 4:
+                               ideapad_backlight_notify_brightness(priv);
+                               break;
+                       case 2:
+                               ideapad_backlight_notify_power(priv);
+                               break;
+                       default:
                                ideapad_input_report(priv, vpc_bit);
+                       }
                }
        }
 }
index 5ffe7c3981482f7076ea95172cd0e960a04e465f..809a3ae943c6997f65a20328f8fe2fb02690cd6c 100644 (file)
@@ -403,7 +403,7 @@ static void ips_cpu_raise(struct ips_driver *ips)
 
        thm_writew(THM_MPCPC, (new_tdp_limit * 10) / 8);
 
-       turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDC_OVR_EN;
+       turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDP_OVR_EN;
        wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
 
        turbo_override &= ~TURBO_TDP_MASK;
@@ -438,7 +438,7 @@ static void ips_cpu_lower(struct ips_driver *ips)
 
        thm_writew(THM_MPCPC, (new_limit * 10) / 8);
 
-       turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDC_OVR_EN;
+       turbo_override |= TURBO_TDC_OVR_EN | TURBO_TDP_OVR_EN;
        wrmsrl(TURBO_POWER_CURRENT_LIMIT, turbo_override);
 
        turbo_override &= ~TURBO_TDP_MASK;
index 809adea4965f96a8fca6f703fd94b40523d33072..abddc83e9fd7eb55d3e0ad3c0a4d8a5ad01070f0 100644 (file)
@@ -477,6 +477,8 @@ static acpi_status intel_menlow_register_sensor(acpi_handle handle, u32 lvl,
                return AE_ERROR;
        }
 
+       return AE_OK;
+
  aux1_not_found:
        if (status == AE_NOT_FOUND)
                return AE_OK;
index 3a578323122b7b18750de7d31ecb570b878cef43..ccd7b1f8351929992891f8cf3c31f3e30e9b3998 100644 (file)
@@ -493,20 +493,30 @@ static int mid_thermal_probe(struct platform_device *pdev)
 
        /* Register each sensor with the generic thermal framework*/
        for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
+               struct thermal_device_info *td_info = initialize_sensor(i);
+
+               if (!td_info) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
                pinfo->tzd[i] = thermal_zone_device_register(name[i],
-                               0, initialize_sensor(i), &tzd_ops, 0, 0, 0, 0);
-               if (IS_ERR(pinfo->tzd[i]))
-                       goto reg_fail;
+                               0, td_info, &tzd_ops, 0, 0, 0, 0);
+               if (IS_ERR(pinfo->tzd[i])) {
+                       kfree(td_info);
+                       ret = PTR_ERR(pinfo->tzd[i]);
+                       goto err;
+               }
        }
 
        pinfo->pdev = pdev;
        platform_set_drvdata(pdev, pinfo);
        return 0;
 
-reg_fail:
-       ret = PTR_ERR(pinfo->tzd[i]);
-       while (--i >= 0)
+err:
+       while (--i >= 0) {
+               kfree(pinfo->tzd[i]->devdata);
                thermal_zone_device_unregister(pinfo->tzd[i]);
+       }
        configure_adc(0);
        kfree(pinfo);
        return ret;
@@ -524,8 +534,10 @@ static int mid_thermal_remove(struct platform_device *pdev)
        int i;
        struct platform_info *pinfo = platform_get_drvdata(pdev);
 
-       for (i = 0; i < MSIC_THERMAL_SENSORS; i++)
+       for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
+               kfree(pinfo->tzd[i]->devdata);
                thermal_zone_device_unregister(pinfo->tzd[i]);
+       }
 
        kfree(pinfo);
        platform_set_drvdata(pdev, NULL);
index bde47e9080cd9a131dc76563e42d01e273bab990..c8a6aed452778d489a53bb9a60c2a9af2ec72470 100644 (file)
@@ -637,15 +637,13 @@ end_function:
        return error;
 }
 
-const struct pci_device_id rar_pci_id_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(rar_pci_id_tbl) = {
        { PCI_VDEVICE(INTEL, 0x4110) },
        { 0 }
 };
 
 MODULE_DEVICE_TABLE(pci, rar_pci_id_tbl);
 
-const struct pci_device_id *my_id_table = rar_pci_id_tbl;
-
 /* field for registering driver to PCI device */
 static struct pci_driver rar_pci_driver = {
        .name = "rar_register_driver",
index 940accbe28d3a2db53c745217bf85f2dd36a1bc0..c86665369a22d4b24a23707d5b7f24d955dc2a1a 100644 (file)
@@ -725,7 +725,7 @@ static void ipc_remove(struct pci_dev *pdev)
        intel_scu_devices_destroy();
 }
 
-static const struct pci_device_id pci_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(pci_ids) = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080e)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x082a)},
        { 0,}
index 3ff629df9f01b0b1a0a6ff2be71115d922c71b88..f204643c5052640908063b07e0288263ca8f8548 100644 (file)
@@ -538,6 +538,15 @@ static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = {
                },
                .callback = dmi_check_cb
        },
+       {
+               .ident = "MSI U270",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                               "Micro-Star International Co., Ltd."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "U270 series"),
+               },
+               .callback = dmi_check_cb
+       },
        { }
 };
 
@@ -996,3 +1005,4 @@ MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N034:*");
 MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N051:*");
 MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N014:*");
 MODULE_ALIAS("dmi:*:svnMicro-StarInternational*:pnCR620:*");
+MODULE_ALIAS("dmi:*:svnMicro-StarInternational*:pnU270series:*");
index c832e3356cd61f03036ad8802919285add489466..6f40bf202dc7cf9e6baa80a329a3ea1810fcb5ed 100644 (file)
@@ -272,6 +272,7 @@ static int __init msi_wmi_init(void)
 err_free_backlight:
        backlight_device_unregister(backlight);
 err_free_input:
+       sparse_keymap_free(msi_wmi_input_dev);
        input_unregister_device(msi_wmi_input_dev);
 err_uninstall_notifier:
        wmi_remove_notify_handler(MSIWMI_EVENT_GUID);
index d347116d150e38146eedf6e817e51afc84898169..359163011044d4fced62b95164a7d8baee399cc1 100644 (file)
@@ -520,6 +520,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
                },
                .callback = dmi_check_cb,
        },
+       {
+               .ident = "N510",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "N510"),
+                       DMI_MATCH(DMI_BOARD_NAME, "N510"),
+               },
+               .callback = dmi_check_cb,
+       },
        {
                .ident = "X125",
                .matches = {
@@ -600,6 +610,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
                },
                .callback = dmi_check_cb,
        },
+       {
+               .ident = "N150/N210/N220",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
+                       DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
+               },
+               .callback = dmi_check_cb,
+       },
        {
                .ident = "N150/N210/N220/N230",
                .matches = {
diff --git a/drivers/platform/x86/samsung-q10.c b/drivers/platform/x86/samsung-q10.c
new file mode 100644 (file)
index 0000000..1e54ae7
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ *  Driver for Samsung Q10 and related laptops: controls the backlight
+ *
+ *  Copyright (c) 2011 Frederick van der Wyck <fvanderwyck@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/backlight.h>
+#include <linux/i8042.h>
+#include <linux/dmi.h>
+
+#define SAMSUNGQ10_BL_MAX_INTENSITY      255
+#define SAMSUNGQ10_BL_DEFAULT_INTENSITY  185
+
+#define SAMSUNGQ10_BL_8042_CMD           0xbe
+#define SAMSUNGQ10_BL_8042_DATA          { 0x89, 0x91 }
+
+static int samsungq10_bl_brightness;
+
+static bool force;
+module_param(force, bool, 0);
+MODULE_PARM_DESC(force,
+               "Disable the DMI check and force the driver to be loaded");
+
+static int samsungq10_bl_set_intensity(struct backlight_device *bd)
+{
+
+       int brightness = bd->props.brightness;
+       unsigned char c[3] = SAMSUNGQ10_BL_8042_DATA;
+
+       c[2] = (unsigned char)brightness;
+       i8042_lock_chip();
+       i8042_command(c, (0x30 << 8) | SAMSUNGQ10_BL_8042_CMD);
+       i8042_unlock_chip();
+       samsungq10_bl_brightness = brightness;
+
+       return 0;
+}
+
+static int samsungq10_bl_get_intensity(struct backlight_device *bd)
+{
+       return samsungq10_bl_brightness;
+}
+
+static const struct backlight_ops samsungq10_bl_ops = {
+       .get_brightness = samsungq10_bl_get_intensity,
+       .update_status  = samsungq10_bl_set_intensity,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int samsungq10_suspend(struct device *dev)
+{
+       return 0;
+}
+
+static int samsungq10_resume(struct device *dev)
+{
+
+       struct backlight_device *bd = dev_get_drvdata(dev);
+
+       samsungq10_bl_set_intensity(bd);
+       return 0;
+}
+#else
+#define samsungq10_suspend NULL
+#define samsungq10_resume  NULL
+#endif
+
+static SIMPLE_DEV_PM_OPS(samsungq10_pm_ops,
+                         samsungq10_suspend, samsungq10_resume);
+
+static int __devinit samsungq10_probe(struct platform_device *pdev)
+{
+
+       struct backlight_properties props;
+       struct backlight_device *bd;
+
+       memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_PLATFORM;
+       props.max_brightness = SAMSUNGQ10_BL_MAX_INTENSITY;
+       bd = backlight_device_register("samsung", &pdev->dev, NULL,
+                                      &samsungq10_bl_ops, &props);
+       if (IS_ERR(bd))
+               return PTR_ERR(bd);
+
+       platform_set_drvdata(pdev, bd);
+
+       bd->props.brightness = SAMSUNGQ10_BL_DEFAULT_INTENSITY;
+       samsungq10_bl_set_intensity(bd);
+
+       return 0;
+}
+
+static int __devexit samsungq10_remove(struct platform_device *pdev)
+{
+
+       struct backlight_device *bd = platform_get_drvdata(pdev);
+
+       bd->props.brightness = SAMSUNGQ10_BL_DEFAULT_INTENSITY;
+       samsungq10_bl_set_intensity(bd);
+
+       backlight_device_unregister(bd);
+
+       return 0;
+}
+
+static struct platform_driver samsungq10_driver = {
+       .driver         = {
+               .name   = KBUILD_MODNAME,
+               .owner  = THIS_MODULE,
+               .pm     = &samsungq10_pm_ops,
+       },
+       .probe          = samsungq10_probe,
+       .remove         = __devexit_p(samsungq10_remove),
+};
+
+static struct platform_device *samsungq10_device;
+
+static int __init dmi_check_callback(const struct dmi_system_id *id)
+{
+       printk(KERN_INFO KBUILD_MODNAME ": found model '%s'\n", id->ident);
+       return 1;
+}
+
+static struct dmi_system_id __initdata samsungq10_dmi_table[] = {
+       {
+               .ident = "Samsung Q10",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Samsung"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "SQ10"),
+               },
+               .callback = dmi_check_callback,
+       },
+       {
+               .ident = "Samsung Q20",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG Electronics"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "SENS Q20"),
+               },
+               .callback = dmi_check_callback,
+       },
+       {
+               .ident = "Samsung Q25",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG Electronics"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "NQ25"),
+               },
+               .callback = dmi_check_callback,
+       },
+       {
+               .ident = "Dell Latitude X200",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X200"),
+               },
+               .callback = dmi_check_callback,
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(dmi, samsungq10_dmi_table);
+
+static int __init samsungq10_init(void)
+{
+       if (!force && !dmi_check_system(samsungq10_dmi_table))
+               return -ENODEV;
+
+       samsungq10_device = platform_create_bundle(&samsungq10_driver,
+                                                  samsungq10_probe,
+                                                  NULL, 0, NULL, 0);
+
+       if (IS_ERR(samsungq10_device))
+               return PTR_ERR(samsungq10_device);
+
+       return 0;
+}
+
+static void __exit samsungq10_exit(void)
+{
+       platform_device_unregister(samsungq10_device);
+       platform_driver_unregister(&samsungq10_driver);
+}
+
+module_init(samsungq10_init);
+module_exit(samsungq10_exit);
+
+MODULE_AUTHOR("Frederick van der Wyck <fvanderwyck@gmail.com>");
+MODULE_DESCRIPTION("Samsung Q10 Driver");
+MODULE_LICENSE("GPL");
index 26c5b117df22d5011c46c64f2f588f83dd7ed58c..7bd829f247eb5ae98fa3b2c61914d16cf554a941 100644 (file)
@@ -3185,9 +3185,18 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 
                KEY_VENDOR,     /* 0x17: Thinkpad/AccessIBM/Lenovo */
 
+               /* (assignments unknown, please report if found) */
+               KEY_UNKNOWN, KEY_UNKNOWN,
+
+               /*
+                * The mic mute button only sends 0x1a.  It does not
+                * automatically mute the mic or change the mute light.
+                */
+               KEY_MICMUTE,    /* 0x1a: Mic mute (since ?400 or so) */
+
                /* (assignments unknown, please report if found) */
                KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
-               KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
+               KEY_UNKNOWN,
                },
        };
 
index d0a56235c50eedc5e9ed4dd9097e0b86b504ebda..2ec57b2fb2783a232df5aad9df1a276a6f2edd1e 100644 (file)
@@ -1889,7 +1889,7 @@ static int __devinit sci_init_single(struct platform_device *dev,
 
        if (p->regtype == SCIx_PROBE_REGTYPE) {
                ret = sci_probe_regmap(p);
-               if (unlikely(!ret))
+               if (unlikely(ret))
                        return ret;
        }
 
index 32549d177b198ae2f7f2b9a738d6b8a0cb9de049..dcaab9012ca20564dacbe33c6d00b305869252b2 100644 (file)
@@ -55,7 +55,7 @@
 
 #define S3_SAVAGE3D_SERIES(chip)  ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
 
-#define S3_SAVAGE4_SERIES(chip)   ((chip>=S3_SAVAGE4) || (chip<=S3_PROSAVAGEDDR))
+#define S3_SAVAGE4_SERIES(chip)   ((chip>=S3_SAVAGE4) && (chip<=S3_PROSAVAGEDDR))
 
 #define S3_SAVAGE_MOBILE_SERIES(chip)  ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE))
 
index f815283667affd00f568fd16e8452d11ede21f89..5f7ff8e2fc1433c39229fce28d4fca39fe8ace73 100644 (file)
@@ -11,7 +11,7 @@ config XEN_BALLOON
 
 config XEN_SELFBALLOONING
        bool "Dynamically self-balloon kernel memory to target"
-       depends on XEN && XEN_BALLOON && CLEANCACHE && SWAP
+       depends on XEN && XEN_BALLOON && CLEANCACHE && SWAP && XEN_TMEM
        default n
        help
          Self-ballooning dynamically balloons available kernel memory driven
index 8d8f28c94c0fe608f61684c2b34e5045f01489f9..6873bb634a97652f36bc477b08044e164c749b30 100644 (file)
@@ -141,10 +141,11 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
 
        rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
        if (rc < 0) {
-               cERROR(1, "%s: Failed to resolve server part of %s to IP: %d",
-                         __func__, *devname, rc);
+               cFYI(1, "%s: Failed to resolve server part of %s to IP: %d",
+                       __func__, *devname, rc);
                goto compose_mount_options_err;
        }
+
        /* md_len = strlen(...) + 12 for 'sep+prefixpath='
         * assuming that we have 'unc=' and 'ip=' in
         * the original sb_mountdata
index 212e5629cc1d01880263aaa6f0b12ef6a1a46291..f93eb948d0716203b96a23f619866ce50678cada 100644 (file)
@@ -563,6 +563,10 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
                mutex_unlock(&dir->i_mutex);
                dput(dentry);
                dentry = child;
+               if (!dentry->d_inode) {
+                       dput(dentry);
+                       dentry = ERR_PTR(-ENOENT);
+               }
        } while (!IS_ERR(dentry));
        _FreeXid(xid);
        kfree(full_path);
index 548f06230a6df50063b5c747b77330c4815fdd2e..1d2d91d9bf65c861ababf2ec19a82538fb86c2d7 100644 (file)
@@ -79,8 +79,8 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
        /* Perform the upcall */
        rc = dns_query(NULL, hostname, len, NULL, ip_addr, NULL);
        if (rc < 0)
-               cERROR(1, "%s: unable to resolve: %*.*s",
-                      __func__, len, len, hostname);
+               cFYI(1, "%s: unable to resolve: %*.*s",
+                       __func__, len, len, hostname);
        else
                cFYI(1, "%s: resolved: %*.*s to %s",
                     __func__, len, len, hostname, *ip_addr);
index 9b018c8334fa1d67bf090db12f8821700341c1df..a7b2dcd4a53ec1b5404729ea29e2e9ff79fabdeb 100644 (file)
@@ -764,20 +764,10 @@ char *cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
        if (full_path == NULL)
                return full_path;
 
-       if (dfsplen) {
+       if (dfsplen)
                strncpy(full_path, tcon->treeName, dfsplen);
-               /* switch slash direction in prepath depending on whether
-                * windows or posix style path names
-                */
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
-                       int i;
-                       for (i = 0; i < dfsplen; i++) {
-                               if (full_path[i] == '\\')
-                                       full_path[i] = '/';
-                       }
-               }
-       }
        strncpy(full_path + dfsplen, vol->prepath, pplen);
+       convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
        full_path[dfsplen + pplen] = 0; /* add trailing null */
        return full_path;
 }
index 243d5872051319c78e680fc0965f2119bab8749d..d3e619692ee0f0437e26d9d91d61545859f248bc 100644 (file)
@@ -124,8 +124,7 @@ static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB)
        /*      that we use in next few lines                               */
        /* Note that header is initialized to zero in header_assemble */
        pSMB->req.AndXCommand = 0xFF;
-       pSMB->req.MaxBufferSize = cpu_to_le16(min_t(u32, CIFSMaxBufSize - 4,
-                                               USHRT_MAX));
+       pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
        pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
        pSMB->req.VcNumber = get_next_vcnum(ses);
 
index 147aa22c3c3a4b0f2b647b6978ec31340ff1a5da..c1b9c4b107398bd31504f594f294c5bb6dc7ef60 100644 (file)
@@ -362,6 +362,8 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
        mid = AllocMidQEntry(hdr, server);
        if (mid == NULL) {
                mutex_unlock(&server->srv_mutex);
+               atomic_dec(&server->inFlight);
+               wake_up(&server->request_q);
                return -ENOMEM;
        }
 
index c83cae19161e93b8fa5032dba84e46d87b2e90bf..a88948b8bd17d8b16c42af20ee55bcf47f358923 100644 (file)
@@ -1729,7 +1729,7 @@ seqretry:
                 */
                if (read_seqcount_retry(&dentry->d_seq, *seq))
                        goto seqretry;
-               if (parent->d_flags & DCACHE_OP_COMPARE) {
+               if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) {
                        if (parent->d_op->d_compare(parent, *inode,
                                                dentry, i,
                                                tlen, tname, name))
index 2d0f757fda3e499986c0a3ce37936bd69a4125ce..c5a5855a6c44ebce210628c391819637c87fd45d 100644 (file)
@@ -12,5 +12,8 @@
 # Kbuild - Gets included from the Kernels Makefile and build system
 #
 
-exofs-y := ios.o inode.o file.o symlink.o namei.o dir.o super.o
+# ore module library
+obj-$(CONFIG_ORE) += ore.o
+
+exofs-y := inode.o file.o symlink.o namei.o dir.o super.o
 obj-$(CONFIG_EXOFS_FS) += exofs.o
index 86194b2f799dc2f6b29f352cba159e19d1b074e6..70bae41492913aac865898bcb84ffa38b458f787 100644 (file)
@@ -1,6 +1,10 @@
+config ORE
+       tristate
+
 config EXOFS_FS
        tristate "exofs: OSD based file system support"
        depends on SCSI_OSD_ULD
+       select ORE
        help
          EXOFS is a file system that uses an OSD storage device,
          as its backing storage.
index c965806c2821c0900b05f17bb450210c655525e5..f4e442ec74452ce993c22c4f65051fd86855f188 100644 (file)
 #include <linux/fs.h>
 #include <linux/time.h>
 #include <linux/backing-dev.h>
-#include "common.h"
+#include <scsi/osd_ore.h>
 
-/* FIXME: Remove once pnfs hits mainline
- * #include <linux/exportfs/pnfs_osd_xdr.h>
- */
-#include "pnfs.h"
+#include "common.h"
 
 #define EXOFS_ERR(fmt, a...) printk(KERN_ERR "exofs: " fmt, ##a)
 
 /* u64 has problems with printk this will cast it to unsigned long long */
 #define _LLU(x) (unsigned long long)(x)
 
-struct exofs_layout {
-       osd_id          s_pid;                  /* partition ID of file system*/
-
-       /* Our way of looking at the data_map */
-       unsigned stripe_unit;
-       unsigned mirrors_p1;
-
-       unsigned group_width;
-       u64      group_depth;
-       unsigned group_count;
-
-       enum exofs_inode_layout_gen_functions lay_func;
-
-       unsigned        s_numdevs;              /* Num of devices in array    */
-       struct osd_dev  *s_ods[0];              /* Variable length            */
-};
-
 /*
  * our extension to the in-memory superblock
  */
 struct exofs_sb_info {
+       struct backing_dev_info bdi;            /* register our bdi with VFS  */
        struct exofs_sb_stats s_ess;            /* Written often, pre-allocate*/
        int             s_timeout;              /* timeout for OSD operations */
        uint64_t        s_nextid;               /* highest object ID used     */
@@ -84,16 +65,13 @@ struct exofs_sb_info {
        spinlock_t      s_next_gen_lock;        /* spinlock for gen # update  */
        u32             s_next_generation;      /* next gen # to use          */
        atomic_t        s_curr_pending;         /* number of pending commands */
-       uint8_t         s_cred[OSD_CAP_LEN];    /* credential for the fscb    */
-       struct          backing_dev_info bdi;   /* register our bdi with VFS  */
 
        struct pnfs_osd_data_map data_map;      /* Default raid to use
                                                 * FIXME: Needed ?
                                                 */
-/*     struct exofs_layout     dir_layout;*/   /* Default dir layout */
-       struct exofs_layout     layout;         /* Default files layout,
-                                                * contains the variable osd_dev
-                                                * array. Keep last */
+       struct ore_layout       layout;         /* Default files layout       */
+       struct ore_comp one_comp;               /* id & cred of partition id=0*/
+       struct ore_components comps;            /* comps for the partition    */
        struct osd_dev  *_min_one_dev[1];       /* Place holder for one dev   */
 };
 
@@ -107,7 +85,8 @@ struct exofs_i_info {
        uint32_t       i_data[EXOFS_IDATA];/*short symlink names and device #s*/
        uint32_t       i_dir_start_lookup; /* which page to start lookup      */
        uint64_t       i_commit_size;      /* the object's written length     */
-       uint8_t        i_cred[OSD_CAP_LEN];/* all-powerful credential         */
+       struct ore_comp one_comp;          /* same component for all devices  */
+       struct ore_components comps;       /* inode view of the device table  */
 };
 
 static inline osd_id exofs_oi_objno(struct exofs_i_info *oi)
@@ -115,52 +94,6 @@ static inline osd_id exofs_oi_objno(struct exofs_i_info *oi)
        return oi->vfs_inode.i_ino + EXOFS_OBJ_OFF;
 }
 
-struct exofs_io_state;
-typedef void (*exofs_io_done_fn)(struct exofs_io_state *or, void *private);
-
-struct exofs_io_state {
-       struct kref             kref;
-
-       void                    *private;
-       exofs_io_done_fn        done;
-
-       struct exofs_layout     *layout;
-       struct osd_obj_id       obj;
-       u8                      *cred;
-
-       /* Global read/write IO*/
-       loff_t                  offset;
-       unsigned long           length;
-       void                    *kern_buff;
-
-       struct page             **pages;
-       unsigned                nr_pages;
-       unsigned                pgbase;
-       unsigned                pages_consumed;
-
-       /* Attributes */
-       unsigned                in_attr_len;
-       struct osd_attr         *in_attr;
-       unsigned                out_attr_len;
-       struct osd_attr         *out_attr;
-
-       /* Variable array of size numdevs */
-       unsigned numdevs;
-       struct exofs_per_dev_state {
-               struct osd_request *or;
-               struct bio *bio;
-               loff_t offset;
-               unsigned length;
-               unsigned dev;
-       } per_dev[];
-};
-
-static inline unsigned exofs_io_state_size(unsigned numdevs)
-{
-       return sizeof(struct exofs_io_state) +
-               sizeof(struct exofs_per_dev_state) * numdevs;
-}
-
 /*
  * our inode flags
  */
@@ -204,12 +137,6 @@ static inline struct exofs_i_info *exofs_i(struct inode *inode)
        return container_of(inode, struct exofs_i_info, vfs_inode);
 }
 
-/*
- * Given a layout, object_number and stripe_index return the associated global
- * dev_index
- */
-unsigned exofs_layout_od_id(struct exofs_layout *layout,
-                           osd_id obj_no, unsigned layout_index);
 /*
  * Maximum count of links to a file
  */
@@ -219,44 +146,8 @@ unsigned exofs_layout_od_id(struct exofs_layout *layout,
  * function declarations *
  *************************/
 
-/* ios.c */
-void exofs_make_credential(u8 cred_a[OSD_CAP_LEN],
-                          const struct osd_obj_id *obj);
-int exofs_read_kern(struct osd_dev *od, u8 *cred, struct osd_obj_id *obj,
-                   u64 offset, void *p, unsigned length);
-
-int  exofs_get_io_state(struct exofs_layout *layout,
-                       struct exofs_io_state **ios);
-void exofs_put_io_state(struct exofs_io_state *ios);
-
-int exofs_check_io(struct exofs_io_state *ios, u64 *resid);
-
-int exofs_sbi_create(struct exofs_io_state *ios);
-int exofs_sbi_remove(struct exofs_io_state *ios);
-int exofs_sbi_write(struct exofs_io_state *ios);
-int exofs_sbi_read(struct exofs_io_state *ios);
-
-int extract_attr_from_ios(struct exofs_io_state *ios, struct osd_attr *attr);
-
-int exofs_oi_truncate(struct exofs_i_info *oi, u64 new_len);
-static inline int exofs_oi_write(struct exofs_i_info *oi,
-                                struct exofs_io_state *ios)
-{
-       ios->obj.id = exofs_oi_objno(oi);
-       ios->cred = oi->i_cred;
-       return exofs_sbi_write(ios);
-}
-
-static inline int exofs_oi_read(struct exofs_i_info *oi,
-                               struct exofs_io_state *ios)
-{
-       ios->obj.id = exofs_oi_objno(oi);
-       ios->cred = oi->i_cred;
-       return exofs_sbi_read(ios);
-}
-
 /* inode.c               */
-unsigned exofs_max_io_pages(struct exofs_layout *layout,
+unsigned exofs_max_io_pages(struct ore_layout *layout,
                            unsigned expected_pages);
 int exofs_setattr(struct dentry *, struct iattr *);
 int exofs_write_begin(struct file *file, struct address_space *mapping,
@@ -281,6 +172,8 @@ int exofs_set_link(struct inode *, struct exofs_dir_entry *, struct page *,
                    struct inode *);
 
 /* super.c               */
+void exofs_make_credential(u8 cred_a[OSD_CAP_LEN],
+                          const struct osd_obj_id *obj);
 int exofs_sbi_write_stats(struct exofs_sb_info *sbi);
 
 /*********************
@@ -295,7 +188,6 @@ extern const struct file_operations exofs_file_operations;
 
 /* inode.c           */
 extern const struct address_space_operations exofs_aops;
-extern const struct osd_attr g_attr_logical_length;
 
 /* namei.c           */
 extern const struct inode_operations exofs_dir_inode_operations;
@@ -305,4 +197,33 @@ extern const struct inode_operations exofs_special_inode_operations;
 extern const struct inode_operations exofs_symlink_inode_operations;
 extern const struct inode_operations exofs_fast_symlink_inode_operations;
 
+/* exofs_init_comps will initialize an ore_components device array
+ * pointing to a single ore_comp struct, and a round-robin view
+ * of the device table.
+ * The first device of each inode is the [inode->ino % num_devices]
+ * and the rest of the devices sequentially following where the
+ * first device is after the last device.
+ * It is assumed that the global device array at @sbi is twice
+ * bigger and that the device table repeats twice.
+ * See: exofs_read_lookup_dev_table()
+ */
+static inline void exofs_init_comps(struct ore_components *comps,
+                                   struct ore_comp *one_comp,
+                                   struct exofs_sb_info *sbi, osd_id oid)
+{
+       unsigned dev_mod = (unsigned)oid, first_dev;
+
+       one_comp->obj.partition = sbi->one_comp.obj.partition;
+       one_comp->obj.id = oid;
+       exofs_make_credential(one_comp->cred, &one_comp->obj);
+
+       comps->numdevs = sbi->comps.numdevs;
+       comps->single_comp = EC_SINGLE_COMP;
+       comps->comps = one_comp;
+
+       /* Round robin device view of the table */
+       first_dev = (dev_mod * sbi->layout.mirrors_p1) % sbi->comps.numdevs;
+       comps->ods = sbi->comps.ods + first_dev;
+}
+
 #endif
index 8472c098445ddbe332c0ee33aa10988cb03a9b15..f39a38fc234935f42afa419c6e30227687b3dd38 100644 (file)
@@ -43,7 +43,7 @@ enum { BIO_MAX_PAGES_KMALLOC =
                PAGE_SIZE / sizeof(struct page *),
 };
 
-unsigned exofs_max_io_pages(struct exofs_layout *layout,
+unsigned exofs_max_io_pages(struct ore_layout *layout,
                            unsigned expected_pages)
 {
        unsigned pages = min_t(unsigned, expected_pages, MAX_PAGES_KMALLOC);
@@ -58,7 +58,7 @@ struct page_collect {
        struct exofs_sb_info *sbi;
        struct inode *inode;
        unsigned expected_pages;
-       struct exofs_io_state *ios;
+       struct ore_io_state *ios;
 
        struct page **pages;
        unsigned alloc_pages;
@@ -110,13 +110,6 @@ static int pcol_try_alloc(struct page_collect *pcol)
 {
        unsigned pages;
 
-       if (!pcol->ios) { /* First time allocate io_state */
-               int ret = exofs_get_io_state(&pcol->sbi->layout, &pcol->ios);
-
-               if (ret)
-                       return ret;
-       }
-
        /* TODO: easily support bio chaining */
        pages =  exofs_max_io_pages(&pcol->sbi->layout, pcol->expected_pages);
 
@@ -140,7 +133,7 @@ static void pcol_free(struct page_collect *pcol)
        pcol->pages = NULL;
 
        if (pcol->ios) {
-               exofs_put_io_state(pcol->ios);
+               ore_put_io_state(pcol->ios);
                pcol->ios = NULL;
        }
 }
@@ -200,7 +193,7 @@ static int __readpages_done(struct page_collect *pcol)
        u64 resid;
        u64 good_bytes;
        u64 length = 0;
-       int ret = exofs_check_io(pcol->ios, &resid);
+       int ret = ore_check_io(pcol->ios, &resid);
 
        if (likely(!ret))
                good_bytes = pcol->length;
@@ -241,7 +234,7 @@ static int __readpages_done(struct page_collect *pcol)
 }
 
 /* callback of async reads */
-static void readpages_done(struct exofs_io_state *ios, void *p)
+static void readpages_done(struct ore_io_state *ios, void *p)
 {
        struct page_collect *pcol = p;
 
@@ -269,20 +262,28 @@ static void _unlock_pcol_pages(struct page_collect *pcol, int ret, int rw)
 static int read_exec(struct page_collect *pcol)
 {
        struct exofs_i_info *oi = exofs_i(pcol->inode);
-       struct exofs_io_state *ios = pcol->ios;
+       struct ore_io_state *ios;
        struct page_collect *pcol_copy = NULL;
        int ret;
 
        if (!pcol->pages)
                return 0;
 
+       if (!pcol->ios) {
+               int ret = ore_get_rw_state(&pcol->sbi->layout, &oi->comps, true,
+                                            pcol->pg_first << PAGE_CACHE_SHIFT,
+                                            pcol->length, &pcol->ios);
+
+               if (ret)
+                       return ret;
+       }
+
+       ios = pcol->ios;
        ios->pages = pcol->pages;
        ios->nr_pages = pcol->nr_pages;
-       ios->length = pcol->length;
-       ios->offset = pcol->pg_first << PAGE_CACHE_SHIFT;
 
        if (pcol->read_4_write) {
-               exofs_oi_read(oi, pcol->ios);
+               ore_read(pcol->ios);
                return __readpages_done(pcol);
        }
 
@@ -295,14 +296,14 @@ static int read_exec(struct page_collect *pcol)
        *pcol_copy = *pcol;
        ios->done = readpages_done;
        ios->private = pcol_copy;
-       ret = exofs_oi_read(oi, ios);
+       ret = ore_read(ios);
        if (unlikely(ret))
                goto err;
 
        atomic_inc(&pcol->sbi->s_curr_pending);
 
        EXOFS_DBGMSG2("read_exec obj=0x%llx start=0x%llx length=0x%lx\n",
-                 ios->obj.id, _LLU(ios->offset), pcol->length);
+                 oi->one_comp.obj.id, _LLU(ios->offset), pcol->length);
 
        /* pages ownership was passed to pcol_copy */
        _pcol_reset(pcol);
@@ -457,14 +458,14 @@ static int exofs_readpage(struct file *file, struct page *page)
 }
 
 /* Callback for osd_write. All writes are asynchronous */
-static void writepages_done(struct exofs_io_state *ios, void *p)
+static void writepages_done(struct ore_io_state *ios, void *p)
 {
        struct page_collect *pcol = p;
        int i;
        u64 resid;
        u64  good_bytes;
        u64  length = 0;
-       int ret = exofs_check_io(ios, &resid);
+       int ret = ore_check_io(ios, &resid);
 
        atomic_dec(&pcol->sbi->s_curr_pending);
 
@@ -507,13 +508,21 @@ static void writepages_done(struct exofs_io_state *ios, void *p)
 static int write_exec(struct page_collect *pcol)
 {
        struct exofs_i_info *oi = exofs_i(pcol->inode);
-       struct exofs_io_state *ios = pcol->ios;
+       struct ore_io_state *ios;
        struct page_collect *pcol_copy = NULL;
        int ret;
 
        if (!pcol->pages)
                return 0;
 
+       BUG_ON(pcol->ios);
+       ret = ore_get_rw_state(&pcol->sbi->layout, &oi->comps, false,
+                                pcol->pg_first << PAGE_CACHE_SHIFT,
+                                pcol->length, &pcol->ios);
+
+       if (unlikely(ret))
+               goto err;
+
        pcol_copy = kmalloc(sizeof(*pcol_copy), GFP_KERNEL);
        if (!pcol_copy) {
                EXOFS_ERR("write_exec: Failed to kmalloc(pcol)\n");
@@ -523,16 +532,15 @@ static int write_exec(struct page_collect *pcol)
 
        *pcol_copy = *pcol;
 
+       ios = pcol->ios;
        ios->pages = pcol_copy->pages;
        ios->nr_pages = pcol_copy->nr_pages;
-       ios->offset = pcol_copy->pg_first << PAGE_CACHE_SHIFT;
-       ios->length = pcol_copy->length;
        ios->done = writepages_done;
        ios->private = pcol_copy;
 
-       ret = exofs_oi_write(oi, ios);
+       ret = ore_write(ios);
        if (unlikely(ret)) {
-               EXOFS_ERR("write_exec: exofs_oi_write() Failed\n");
+               EXOFS_ERR("write_exec: ore_write() Failed\n");
                goto err;
        }
 
@@ -844,17 +852,15 @@ static inline int exofs_inode_is_fast_symlink(struct inode *inode)
        return S_ISLNK(inode->i_mode) && (oi->i_data[0] != 0);
 }
 
-const struct osd_attr g_attr_logical_length = ATTR_DEF(
-       OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8);
-
 static int _do_truncate(struct inode *inode, loff_t newsize)
 {
        struct exofs_i_info *oi = exofs_i(inode);
+       struct exofs_sb_info *sbi = inode->i_sb->s_fs_info;
        int ret;
 
        inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 
-       ret = exofs_oi_truncate(oi, (u64)newsize);
+       ret = ore_truncate(&sbi->layout, &oi->comps, (u64)newsize);
        if (likely(!ret))
                truncate_setsize(inode, newsize);
 
@@ -917,30 +923,26 @@ static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi,
                [1] = g_attr_inode_file_layout,
                [2] = g_attr_inode_dir_layout,
        };
-       struct exofs_io_state *ios;
+       struct ore_io_state *ios;
        struct exofs_on_disk_inode_layout *layout;
        int ret;
 
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+       ret = ore_get_io_state(&sbi->layout, &oi->comps, &ios);
        if (unlikely(ret)) {
-               EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__);
+               EXOFS_ERR("%s: ore_get_io_state failed.\n", __func__);
                return ret;
        }
 
-       ios->obj.id = exofs_oi_objno(oi);
-       exofs_make_credential(oi->i_cred, &ios->obj);
-       ios->cred = oi->i_cred;
-
-       attrs[1].len = exofs_on_disk_inode_layout_size(sbi->layout.s_numdevs);
-       attrs[2].len = exofs_on_disk_inode_layout_size(sbi->layout.s_numdevs);
+       attrs[1].len = exofs_on_disk_inode_layout_size(sbi->comps.numdevs);
+       attrs[2].len = exofs_on_disk_inode_layout_size(sbi->comps.numdevs);
 
        ios->in_attr = attrs;
        ios->in_attr_len = ARRAY_SIZE(attrs);
 
-       ret = exofs_sbi_read(ios);
+       ret = ore_read(ios);
        if (unlikely(ret)) {
                EXOFS_ERR("object(0x%llx) corrupted, return empty file=>%d\n",
-                         _LLU(ios->obj.id), ret);
+                         _LLU(oi->one_comp.obj.id), ret);
                memset(inode, 0, sizeof(*inode));
                inode->i_mode = 0040000 | (0777 & ~022);
                /* If object is lost on target we might as well enable it's
@@ -990,7 +992,7 @@ static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi,
        }
 
 out:
-       exofs_put_io_state(ios);
+       ore_put_io_state(ios);
        return ret;
 }
 
@@ -1016,6 +1018,8 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino)
                return inode;
        oi = exofs_i(inode);
        __oi_init(oi);
+       exofs_init_comps(&oi->comps, &oi->one_comp, sb->s_fs_info,
+                        exofs_oi_objno(oi));
 
        /* read the inode from the osd */
        ret = exofs_get_inode(sb, oi, &fcb);
@@ -1107,21 +1111,22 @@ int __exofs_wait_obj_created(struct exofs_i_info *oi)
  * set the obj_created flag so that other methods know that the object exists on
  * the OSD.
  */
-static void create_done(struct exofs_io_state *ios, void *p)
+static void create_done(struct ore_io_state *ios, void *p)
 {
        struct inode *inode = p;
        struct exofs_i_info *oi = exofs_i(inode);
        struct exofs_sb_info *sbi = inode->i_sb->s_fs_info;
        int ret;
 
-       ret = exofs_check_io(ios, NULL);
-       exofs_put_io_state(ios);
+       ret = ore_check_io(ios, NULL);
+       ore_put_io_state(ios);
 
        atomic_dec(&sbi->s_curr_pending);
 
        if (unlikely(ret)) {
                EXOFS_ERR("object=0x%llx creation failed in pid=0x%llx",
-                         _LLU(exofs_oi_objno(oi)), _LLU(sbi->layout.s_pid));
+                         _LLU(exofs_oi_objno(oi)),
+                         _LLU(oi->one_comp.obj.partition));
                /*TODO: When FS is corrupted creation can fail, object already
                 * exist. Get rid of this asynchronous creation, if exist
                 * increment the obj counter and try the next object. Until we
@@ -1140,14 +1145,13 @@ static void create_done(struct exofs_io_state *ios, void *p)
  */
 struct inode *exofs_new_inode(struct inode *dir, int mode)
 {
-       struct super_block *sb;
+       struct super_block *sb = dir->i_sb;
+       struct exofs_sb_info *sbi = sb->s_fs_info;
        struct inode *inode;
        struct exofs_i_info *oi;
-       struct exofs_sb_info *sbi;
-       struct exofs_io_state *ios;
+       struct ore_io_state *ios;
        int ret;
 
-       sb = dir->i_sb;
        inode = new_inode(sb);
        if (!inode)
                return ERR_PTR(-ENOMEM);
@@ -1157,8 +1161,6 @@ struct inode *exofs_new_inode(struct inode *dir, int mode)
 
        set_obj_2bcreated(oi);
 
-       sbi = sb->s_fs_info;
-
        inode->i_mapping->backing_dev_info = sb->s_bdi;
        inode_init_owner(inode, dir, mode);
        inode->i_ino = sbi->s_nextid++;
@@ -1170,25 +1172,24 @@ struct inode *exofs_new_inode(struct inode *dir, int mode)
        spin_unlock(&sbi->s_next_gen_lock);
        insert_inode_hash(inode);
 
+       exofs_init_comps(&oi->comps, &oi->one_comp, sb->s_fs_info,
+                        exofs_oi_objno(oi));
        exofs_sbi_write_stats(sbi); /* Make sure new sbi->s_nextid is on disk */
 
        mark_inode_dirty(inode);
 
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+       ret = ore_get_io_state(&sbi->layout, &oi->comps, &ios);
        if (unlikely(ret)) {
-               EXOFS_ERR("exofs_new_inode: exofs_get_io_state failed\n");
+               EXOFS_ERR("exofs_new_inode: ore_get_io_state failed\n");
                return ERR_PTR(ret);
        }
 
-       ios->obj.id = exofs_oi_objno(oi);
-       exofs_make_credential(oi->i_cred, &ios->obj);
-
        ios->done = create_done;
        ios->private = inode;
-       ios->cred = oi->i_cred;
-       ret = exofs_sbi_create(ios);
+
+       ret = ore_create(ios);
        if (ret) {
-               exofs_put_io_state(ios);
+               ore_put_io_state(ios);
                return ERR_PTR(ret);
        }
        atomic_inc(&sbi->s_curr_pending);
@@ -1207,11 +1208,11 @@ struct updatei_args {
 /*
  * Callback function from exofs_update_inode().
  */
-static void updatei_done(struct exofs_io_state *ios, void *p)
+static void updatei_done(struct ore_io_state *ios, void *p)
 {
        struct updatei_args *args = p;
 
-       exofs_put_io_state(ios);
+       ore_put_io_state(ios);
 
        atomic_dec(&args->sbi->s_curr_pending);
 
@@ -1227,7 +1228,7 @@ static int exofs_update_inode(struct inode *inode, int do_sync)
        struct exofs_i_info *oi = exofs_i(inode);
        struct super_block *sb = inode->i_sb;
        struct exofs_sb_info *sbi = sb->s_fs_info;
-       struct exofs_io_state *ios;
+       struct ore_io_state *ios;
        struct osd_attr attr;
        struct exofs_fcb *fcb;
        struct updatei_args *args;
@@ -1266,9 +1267,9 @@ static int exofs_update_inode(struct inode *inode, int do_sync)
        } else
                memcpy(fcb->i_data, oi->i_data, sizeof(fcb->i_data));
 
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+       ret = ore_get_io_state(&sbi->layout, &oi->comps, &ios);
        if (unlikely(ret)) {
-               EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__);
+               EXOFS_ERR("%s: ore_get_io_state failed.\n", __func__);
                goto free_args;
        }
 
@@ -1285,13 +1286,13 @@ static int exofs_update_inode(struct inode *inode, int do_sync)
                ios->private = args;
        }
 
-       ret = exofs_oi_write(oi, ios);
+       ret = ore_write(ios);
        if (!do_sync && !ret) {
                atomic_inc(&sbi->s_curr_pending);
                goto out; /* deallocation in updatei_done */
        }
 
-       exofs_put_io_state(ios);
+       ore_put_io_state(ios);
 free_args:
        kfree(args);
 out:
@@ -1310,11 +1311,11 @@ int exofs_write_inode(struct inode *inode, struct writeback_control *wbc)
  * Callback function from exofs_delete_inode() - don't have much cleaning up to
  * do.
  */
-static void delete_done(struct exofs_io_state *ios, void *p)
+static void delete_done(struct ore_io_state *ios, void *p)
 {
        struct exofs_sb_info *sbi = p;
 
-       exofs_put_io_state(ios);
+       ore_put_io_state(ios);
 
        atomic_dec(&sbi->s_curr_pending);
 }
@@ -1329,7 +1330,7 @@ void exofs_evict_inode(struct inode *inode)
        struct exofs_i_info *oi = exofs_i(inode);
        struct super_block *sb = inode->i_sb;
        struct exofs_sb_info *sbi = sb->s_fs_info;
-       struct exofs_io_state *ios;
+       struct ore_io_state *ios;
        int ret;
 
        truncate_inode_pages(&inode->i_data, 0);
@@ -1349,20 +1350,19 @@ void exofs_evict_inode(struct inode *inode)
        /* ignore the error, attempt a remove anyway */
 
        /* Now Remove the OSD objects */
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+       ret = ore_get_io_state(&sbi->layout, &oi->comps, &ios);
        if (unlikely(ret)) {
-               EXOFS_ERR("%s: exofs_get_io_state failed\n", __func__);
+               EXOFS_ERR("%s: ore_get_io_state failed\n", __func__);
                return;
        }
 
-       ios->obj.id = exofs_oi_objno(oi);
        ios->done = delete_done;
        ios->private = sbi;
-       ios->cred = oi->i_cred;
-       ret = exofs_sbi_remove(ios);
+
+       ret = ore_remove(ios);
        if (ret) {
-               EXOFS_ERR("%s: exofs_sbi_remove failed\n", __func__);
-               exofs_put_io_state(ios);
+               EXOFS_ERR("%s: ore_remove failed\n", __func__);
+               ore_put_io_state(ios);
                return;
        }
        atomic_inc(&sbi->s_curr_pending);
diff --git a/fs/exofs/ios.c b/fs/exofs/ios.c
deleted file mode 100644 (file)
index f74a2ec..0000000
+++ /dev/null
@@ -1,803 +0,0 @@
-/*
- * Copyright (C) 2005, 2006
- * Avishay Traeger (avishay@gmail.com)
- * Copyright (C) 2008, 2009
- * Boaz Harrosh <bharrosh@panasas.com>
- *
- * This file is part of exofs.
- *
- * exofs is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation.  Since it is based on ext2, and the only
- * valid version of GPL for the Linux kernel is version 2, the only valid
- * version of GPL for exofs is version 2.
- *
- * exofs is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with exofs; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <linux/slab.h>
-#include <scsi/scsi_device.h>
-#include <asm/div64.h>
-
-#include "exofs.h"
-
-#define EXOFS_DBGMSG2(M...) do {} while (0)
-/* #define EXOFS_DBGMSG2 EXOFS_DBGMSG */
-
-void exofs_make_credential(u8 cred_a[OSD_CAP_LEN], const struct osd_obj_id *obj)
-{
-       osd_sec_init_nosec_doall_caps(cred_a, obj, false, true);
-}
-
-int exofs_read_kern(struct osd_dev *od, u8 *cred, struct osd_obj_id *obj,
-                   u64 offset, void *p, unsigned length)
-{
-       struct osd_request *or = osd_start_request(od, GFP_KERNEL);
-/*     struct osd_sense_info osi = {.key = 0};*/
-       int ret;
-
-       if (unlikely(!or)) {
-               EXOFS_DBGMSG("%s: osd_start_request failed.\n", __func__);
-               return -ENOMEM;
-       }
-       ret = osd_req_read_kern(or, obj, offset, p, length);
-       if (unlikely(ret)) {
-               EXOFS_DBGMSG("%s: osd_req_read_kern failed.\n", __func__);
-               goto out;
-       }
-
-       ret = osd_finalize_request(or, 0, cred, NULL);
-       if (unlikely(ret)) {
-               EXOFS_DBGMSG("Failed to osd_finalize_request() => %d\n", ret);
-               goto out;
-       }
-
-       ret = osd_execute_request(or);
-       if (unlikely(ret))
-               EXOFS_DBGMSG("osd_execute_request() => %d\n", ret);
-       /* osd_req_decode_sense(or, ret); */
-
-out:
-       osd_end_request(or);
-       return ret;
-}
-
-int exofs_get_io_state(struct exofs_layout *layout,
-                      struct exofs_io_state **pios)
-{
-       struct exofs_io_state *ios;
-
-       /*TODO: Maybe use kmem_cach per sbi of size
-        * exofs_io_state_size(layout->s_numdevs)
-        */
-       ios = kzalloc(exofs_io_state_size(layout->s_numdevs), GFP_KERNEL);
-       if (unlikely(!ios)) {
-               EXOFS_DBGMSG("Failed kzalloc bytes=%d\n",
-                            exofs_io_state_size(layout->s_numdevs));
-               *pios = NULL;
-               return -ENOMEM;
-       }
-
-       ios->layout = layout;
-       ios->obj.partition = layout->s_pid;
-       *pios = ios;
-       return 0;
-}
-
-void exofs_put_io_state(struct exofs_io_state *ios)
-{
-       if (ios) {
-               unsigned i;
-
-               for (i = 0; i < ios->numdevs; i++) {
-                       struct exofs_per_dev_state *per_dev = &ios->per_dev[i];
-
-                       if (per_dev->or)
-                               osd_end_request(per_dev->or);
-                       if (per_dev->bio)
-                               bio_put(per_dev->bio);
-               }
-
-               kfree(ios);
-       }
-}
-
-unsigned exofs_layout_od_id(struct exofs_layout *layout,
-                           osd_id obj_no, unsigned layout_index)
-{
-/*     switch (layout->lay_func) {
-       case LAYOUT_MOVING_WINDOW:
-       {*/
-               unsigned dev_mod = obj_no;
-
-               return (layout_index + dev_mod * layout->mirrors_p1) %
-                                                             layout->s_numdevs;
-/*     }
-       case LAYOUT_FUNC_IMPLICT:
-               return layout->devs[layout_index];
-       }*/
-}
-
-static inline struct osd_dev *exofs_ios_od(struct exofs_io_state *ios,
-                                          unsigned layout_index)
-{
-       return ios->layout->s_ods[
-               exofs_layout_od_id(ios->layout, ios->obj.id, layout_index)];
-}
-
-static void _sync_done(struct exofs_io_state *ios, void *p)
-{
-       struct completion *waiting = p;
-
-       complete(waiting);
-}
-
-static void _last_io(struct kref *kref)
-{
-       struct exofs_io_state *ios = container_of(
-                                       kref, struct exofs_io_state, kref);
-
-       ios->done(ios, ios->private);
-}
-
-static void _done_io(struct osd_request *or, void *p)
-{
-       struct exofs_io_state *ios = p;
-
-       kref_put(&ios->kref, _last_io);
-}
-
-static int exofs_io_execute(struct exofs_io_state *ios)
-{
-       DECLARE_COMPLETION_ONSTACK(wait);
-       bool sync = (ios->done == NULL);
-       int i, ret;
-
-       if (sync) {
-               ios->done = _sync_done;
-               ios->private = &wait;
-       }
-
-       for (i = 0; i < ios->numdevs; i++) {
-               struct osd_request *or = ios->per_dev[i].or;
-               if (unlikely(!or))
-                       continue;
-
-               ret = osd_finalize_request(or, 0, ios->cred, NULL);
-               if (unlikely(ret)) {
-                       EXOFS_DBGMSG("Failed to osd_finalize_request() => %d\n",
-                                    ret);
-                       return ret;
-               }
-       }
-
-       kref_init(&ios->kref);
-
-       for (i = 0; i < ios->numdevs; i++) {
-               struct osd_request *or = ios->per_dev[i].or;
-               if (unlikely(!or))
-                       continue;
-
-               kref_get(&ios->kref);
-               osd_execute_request_async(or, _done_io, ios);
-       }
-
-       kref_put(&ios->kref, _last_io);
-       ret = 0;
-
-       if (sync) {
-               wait_for_completion(&wait);
-               ret = exofs_check_io(ios, NULL);
-       }
-       return ret;
-}
-
-static void _clear_bio(struct bio *bio)
-{
-       struct bio_vec *bv;
-       unsigned i;
-
-       __bio_for_each_segment(bv, bio, i, 0) {
-               unsigned this_count = bv->bv_len;
-
-               if (likely(PAGE_SIZE == this_count))
-                       clear_highpage(bv->bv_page);
-               else
-                       zero_user(bv->bv_page, bv->bv_offset, this_count);
-       }
-}
-
-int exofs_check_io(struct exofs_io_state *ios, u64 *resid)
-{
-       enum osd_err_priority acumulated_osd_err = 0;
-       int acumulated_lin_err = 0;
-       int i;
-
-       for (i = 0; i < ios->numdevs; i++) {
-               struct osd_sense_info osi;
-               struct osd_request *or = ios->per_dev[i].or;
-               int ret;
-
-               if (unlikely(!or))
-                       continue;
-
-               ret = osd_req_decode_sense(or, &osi);
-               if (likely(!ret))
-                       continue;
-
-               if (OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) {
-                       /* start read offset passed endof file */
-                       _clear_bio(ios->per_dev[i].bio);
-                       EXOFS_DBGMSG("start read offset passed end of file "
-                               "offset=0x%llx, length=0x%llx\n",
-                               _LLU(ios->per_dev[i].offset),
-                               _LLU(ios->per_dev[i].length));
-
-                       continue; /* we recovered */
-               }
-
-               if (osi.osd_err_pri >= acumulated_osd_err) {
-                       acumulated_osd_err = osi.osd_err_pri;
-                       acumulated_lin_err = ret;
-               }
-       }
-
-       /* TODO: raid specific residual calculations */
-       if (resid) {
-               if (likely(!acumulated_lin_err))
-                       *resid = 0;
-               else
-                       *resid = ios->length;
-       }
-
-       return acumulated_lin_err;
-}
-
-/*
- * L - logical offset into the file
- *
- * U - The number of bytes in a stripe within a group
- *
- *     U = stripe_unit * group_width
- *
- * T - The number of bytes striped within a group of component objects
- *     (before advancing to the next group)
- *
- *     T = stripe_unit * group_width * group_depth
- *
- * S - The number of bytes striped across all component objects
- *     before the pattern repeats
- *
- *     S = stripe_unit * group_width * group_depth * group_count
- *
- * M - The "major" (i.e., across all components) stripe number
- *
- *     M = L / S
- *
- * G - Counts the groups from the beginning of the major stripe
- *
- *     G = (L - (M * S)) / T   [or (L % S) / T]
- *
- * H - The byte offset within the group
- *
- *     H = (L - (M * S)) % T   [or (L % S) % T]
- *
- * N - The "minor" (i.e., across the group) stripe number
- *
- *     N = H / U
- *
- * C - The component index coresponding to L
- *
- *     C = (H - (N * U)) / stripe_unit + G * group_width
- *     [or (L % U) / stripe_unit + G * group_width]
- *
- * O - The component offset coresponding to L
- *
- *     O = L % stripe_unit + N * stripe_unit + M * group_depth * stripe_unit
- */
-struct _striping_info {
-       u64 obj_offset;
-       u64 group_length;
-       unsigned dev;
-       unsigned unit_off;
-};
-
-static void _calc_stripe_info(struct exofs_io_state *ios, u64 file_offset,
-                             struct _striping_info *si)
-{
-       u32     stripe_unit = ios->layout->stripe_unit;
-       u32     group_width = ios->layout->group_width;
-       u64     group_depth = ios->layout->group_depth;
-
-       u32     U = stripe_unit * group_width;
-       u64     T = U * group_depth;
-       u64     S = T * ios->layout->group_count;
-       u64     M = div64_u64(file_offset, S);
-
-       /*
-       G = (L - (M * S)) / T
-       H = (L - (M * S)) % T
-       */
-       u64     LmodS = file_offset - M * S;
-       u32     G = div64_u64(LmodS, T);
-       u64     H = LmodS - G * T;
-
-       u32     N = div_u64(H, U);
-
-       /* "H - (N * U)" is just "H % U" so it's bound to u32 */
-       si->dev = (u32)(H - (N * U)) / stripe_unit + G * group_width;
-       si->dev *= ios->layout->mirrors_p1;
-
-       div_u64_rem(file_offset, stripe_unit, &si->unit_off);
-
-       si->obj_offset = si->unit_off + (N * stripe_unit) +
-                                 (M * group_depth * stripe_unit);
-
-       si->group_length = T - H;
-}
-
-static int _add_stripe_unit(struct exofs_io_state *ios,  unsigned *cur_pg,
-               unsigned pgbase, struct exofs_per_dev_state *per_dev,
-               int cur_len)
-{
-       unsigned pg = *cur_pg;
-       struct request_queue *q =
-                       osd_request_queue(exofs_ios_od(ios, per_dev->dev));
-
-       per_dev->length += cur_len;
-
-       if (per_dev->bio == NULL) {
-               unsigned pages_in_stripe = ios->layout->group_width *
-                                       (ios->layout->stripe_unit / PAGE_SIZE);
-               unsigned bio_size = (ios->nr_pages + pages_in_stripe) /
-                                               ios->layout->group_width;
-
-               per_dev->bio = bio_kmalloc(GFP_KERNEL, bio_size);
-               if (unlikely(!per_dev->bio)) {
-                       EXOFS_DBGMSG("Failed to allocate BIO size=%u\n",
-                                    bio_size);
-                       return -ENOMEM;
-               }
-       }
-
-       while (cur_len > 0) {
-               unsigned pglen = min_t(unsigned, PAGE_SIZE - pgbase, cur_len);
-               unsigned added_len;
-
-               BUG_ON(ios->nr_pages <= pg);
-               cur_len -= pglen;
-
-               added_len = bio_add_pc_page(q, per_dev->bio, ios->pages[pg],
-                                           pglen, pgbase);
-               if (unlikely(pglen != added_len))
-                       return -ENOMEM;
-               pgbase = 0;
-               ++pg;
-       }
-       BUG_ON(cur_len);
-
-       *cur_pg = pg;
-       return 0;
-}
-
-static int _prepare_one_group(struct exofs_io_state *ios, u64 length,
-                             struct _striping_info *si)
-{
-       unsigned stripe_unit = ios->layout->stripe_unit;
-       unsigned mirrors_p1 = ios->layout->mirrors_p1;
-       unsigned devs_in_group = ios->layout->group_width * mirrors_p1;
-       unsigned dev = si->dev;
-       unsigned first_dev = dev - (dev % devs_in_group);
-       unsigned max_comp = ios->numdevs ? ios->numdevs - mirrors_p1 : 0;
-       unsigned cur_pg = ios->pages_consumed;
-       int ret = 0;
-
-       while (length) {
-               struct exofs_per_dev_state *per_dev = &ios->per_dev[dev];
-               unsigned cur_len, page_off = 0;
-
-               if (!per_dev->length) {
-                       per_dev->dev = dev;
-                       if (dev < si->dev) {
-                               per_dev->offset = si->obj_offset + stripe_unit -
-                                                                  si->unit_off;
-                               cur_len = stripe_unit;
-                       } else if (dev == si->dev) {
-                               per_dev->offset = si->obj_offset;
-                               cur_len = stripe_unit - si->unit_off;
-                               page_off = si->unit_off & ~PAGE_MASK;
-                               BUG_ON(page_off && (page_off != ios->pgbase));
-                       } else { /* dev > si->dev */
-                               per_dev->offset = si->obj_offset - si->unit_off;
-                               cur_len = stripe_unit;
-                       }
-
-                       if (max_comp < dev)
-                               max_comp = dev;
-               } else {
-                       cur_len = stripe_unit;
-               }
-               if (cur_len >= length)
-                       cur_len = length;
-
-               ret = _add_stripe_unit(ios, &cur_pg, page_off , per_dev,
-                                      cur_len);
-               if (unlikely(ret))
-                       goto out;
-
-               dev += mirrors_p1;
-               dev = (dev % devs_in_group) + first_dev;
-
-               length -= cur_len;
-       }
-out:
-       ios->numdevs = max_comp + mirrors_p1;
-       ios->pages_consumed = cur_pg;
-       return ret;
-}
-
-static int _prepare_for_striping(struct exofs_io_state *ios)
-{
-       u64 length = ios->length;
-       u64 offset = ios->offset;
-       struct _striping_info si;
-       int ret = 0;
-
-       if (!ios->pages) {
-               if (ios->kern_buff) {
-                       struct exofs_per_dev_state *per_dev = &ios->per_dev[0];
-
-                       _calc_stripe_info(ios, ios->offset, &si);
-                       per_dev->offset = si.obj_offset;
-                       per_dev->dev = si.dev;
-
-                       /* no cross device without page array */
-                       BUG_ON((ios->layout->group_width > 1) &&
-                              (si.unit_off + ios->length >
-                               ios->layout->stripe_unit));
-               }
-               ios->numdevs = ios->layout->mirrors_p1;
-               return 0;
-       }
-
-       while (length) {
-               _calc_stripe_info(ios, offset, &si);
-
-               if (length < si.group_length)
-                       si.group_length = length;
-
-               ret = _prepare_one_group(ios, si.group_length, &si);
-               if (unlikely(ret))
-                       goto out;
-
-               offset += si.group_length;
-               length -= si.group_length;
-       }
-
-out:
-       return ret;
-}
-
-int exofs_sbi_create(struct exofs_io_state *ios)
-{
-       int i, ret;
-
-       for (i = 0; i < ios->layout->s_numdevs; i++) {
-               struct osd_request *or;
-
-               or = osd_start_request(exofs_ios_od(ios, i), GFP_KERNEL);
-               if (unlikely(!or)) {
-                       EXOFS_ERR("%s: osd_start_request failed\n", __func__);
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               ios->per_dev[i].or = or;
-               ios->numdevs++;
-
-               osd_req_create_object(or, &ios->obj);
-       }
-       ret = exofs_io_execute(ios);
-
-out:
-       return ret;
-}
-
-int exofs_sbi_remove(struct exofs_io_state *ios)
-{
-       int i, ret;
-
-       for (i = 0; i < ios->layout->s_numdevs; i++) {
-               struct osd_request *or;
-
-               or = osd_start_request(exofs_ios_od(ios, i), GFP_KERNEL);
-               if (unlikely(!or)) {
-                       EXOFS_ERR("%s: osd_start_request failed\n", __func__);
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               ios->per_dev[i].or = or;
-               ios->numdevs++;
-
-               osd_req_remove_object(or, &ios->obj);
-       }
-       ret = exofs_io_execute(ios);
-
-out:
-       return ret;
-}
-
-static int _sbi_write_mirror(struct exofs_io_state *ios, int cur_comp)
-{
-       struct exofs_per_dev_state *master_dev = &ios->per_dev[cur_comp];
-       unsigned dev = ios->per_dev[cur_comp].dev;
-       unsigned last_comp = cur_comp + ios->layout->mirrors_p1;
-       int ret = 0;
-
-       if (ios->pages && !master_dev->length)
-               return 0; /* Just an empty slot */
-
-       for (; cur_comp < last_comp; ++cur_comp, ++dev) {
-               struct exofs_per_dev_state *per_dev = &ios->per_dev[cur_comp];
-               struct osd_request *or;
-
-               or = osd_start_request(exofs_ios_od(ios, dev), GFP_KERNEL);
-               if (unlikely(!or)) {
-                       EXOFS_ERR("%s: osd_start_request failed\n", __func__);
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               per_dev->or = or;
-               per_dev->offset = master_dev->offset;
-
-               if (ios->pages) {
-                       struct bio *bio;
-
-                       if (per_dev != master_dev) {
-                               bio = bio_kmalloc(GFP_KERNEL,
-                                                 master_dev->bio->bi_max_vecs);
-                               if (unlikely(!bio)) {
-                                       EXOFS_DBGMSG(
-                                             "Failed to allocate BIO size=%u\n",
-                                             master_dev->bio->bi_max_vecs);
-                                       ret = -ENOMEM;
-                                       goto out;
-                               }
-
-                               __bio_clone(bio, master_dev->bio);
-                               bio->bi_bdev = NULL;
-                               bio->bi_next = NULL;
-                               per_dev->length = master_dev->length;
-                               per_dev->bio =  bio;
-                               per_dev->dev = dev;
-                       } else {
-                               bio = master_dev->bio;
-                               /* FIXME: bio_set_dir() */
-                               bio->bi_rw |= REQ_WRITE;
-                       }
-
-                       osd_req_write(or, &ios->obj, per_dev->offset, bio,
-                                     per_dev->length);
-                       EXOFS_DBGMSG("write(0x%llx) offset=0x%llx "
-                                     "length=0x%llx dev=%d\n",
-                                    _LLU(ios->obj.id), _LLU(per_dev->offset),
-                                    _LLU(per_dev->length), dev);
-               } else if (ios->kern_buff) {
-                       ret = osd_req_write_kern(or, &ios->obj, per_dev->offset,
-                                          ios->kern_buff, ios->length);
-                       if (unlikely(ret))
-                               goto out;
-                       EXOFS_DBGMSG2("write_kern(0x%llx) offset=0x%llx "
-                                     "length=0x%llx dev=%d\n",
-                                    _LLU(ios->obj.id), _LLU(per_dev->offset),
-                                    _LLU(ios->length), dev);
-               } else {
-                       osd_req_set_attributes(or, &ios->obj);
-                       EXOFS_DBGMSG2("obj(0x%llx) set_attributes=%d dev=%d\n",
-                                    _LLU(ios->obj.id), ios->out_attr_len, dev);
-               }
-
-               if (ios->out_attr)
-                       osd_req_add_set_attr_list(or, ios->out_attr,
-                                                 ios->out_attr_len);
-
-               if (ios->in_attr)
-                       osd_req_add_get_attr_list(or, ios->in_attr,
-                                                 ios->in_attr_len);
-       }
-
-out:
-       return ret;
-}
-
-int exofs_sbi_write(struct exofs_io_state *ios)
-{
-       int i;
-       int ret;
-
-       ret = _prepare_for_striping(ios);
-       if (unlikely(ret))
-               return ret;
-
-       for (i = 0; i < ios->numdevs; i += ios->layout->mirrors_p1) {
-               ret = _sbi_write_mirror(ios, i);
-               if (unlikely(ret))
-                       return ret;
-       }
-
-       ret = exofs_io_execute(ios);
-       return ret;
-}
-
-static int _sbi_read_mirror(struct exofs_io_state *ios, unsigned cur_comp)
-{
-       struct osd_request *or;
-       struct exofs_per_dev_state *per_dev = &ios->per_dev[cur_comp];
-       unsigned first_dev = (unsigned)ios->obj.id;
-
-       if (ios->pages && !per_dev->length)
-               return 0; /* Just an empty slot */
-
-       first_dev = per_dev->dev + first_dev % ios->layout->mirrors_p1;
-       or = osd_start_request(exofs_ios_od(ios, first_dev), GFP_KERNEL);
-       if (unlikely(!or)) {
-               EXOFS_ERR("%s: osd_start_request failed\n", __func__);
-               return -ENOMEM;
-       }
-       per_dev->or = or;
-
-       if (ios->pages) {
-               osd_req_read(or, &ios->obj, per_dev->offset,
-                               per_dev->bio, per_dev->length);
-               EXOFS_DBGMSG("read(0x%llx) offset=0x%llx length=0x%llx"
-                            " dev=%d\n", _LLU(ios->obj.id),
-                            _LLU(per_dev->offset), _LLU(per_dev->length),
-                            first_dev);
-       } else if (ios->kern_buff) {
-               int ret = osd_req_read_kern(or, &ios->obj, per_dev->offset,
-                                           ios->kern_buff, ios->length);
-               EXOFS_DBGMSG2("read_kern(0x%llx) offset=0x%llx "
-                             "length=0x%llx dev=%d ret=>%d\n",
-                             _LLU(ios->obj.id), _LLU(per_dev->offset),
-                             _LLU(ios->length), first_dev, ret);
-               if (unlikely(ret))
-                       return ret;
-       } else {
-               osd_req_get_attributes(or, &ios->obj);
-               EXOFS_DBGMSG2("obj(0x%llx) get_attributes=%d dev=%d\n",
-                             _LLU(ios->obj.id), ios->in_attr_len, first_dev);
-       }
-       if (ios->out_attr)
-               osd_req_add_set_attr_list(or, ios->out_attr, ios->out_attr_len);
-
-       if (ios->in_attr)
-               osd_req_add_get_attr_list(or, ios->in_attr, ios->in_attr_len);
-
-       return 0;
-}
-
-int exofs_sbi_read(struct exofs_io_state *ios)
-{
-       int i;
-       int ret;
-
-       ret = _prepare_for_striping(ios);
-       if (unlikely(ret))
-               return ret;
-
-       for (i = 0; i < ios->numdevs; i += ios->layout->mirrors_p1) {
-               ret = _sbi_read_mirror(ios, i);
-               if (unlikely(ret))
-                       return ret;
-       }
-
-       ret = exofs_io_execute(ios);
-       return ret;
-}
-
-int extract_attr_from_ios(struct exofs_io_state *ios, struct osd_attr *attr)
-{
-       struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */
-       void *iter = NULL;
-       int nelem;
-
-       do {
-               nelem = 1;
-               osd_req_decode_get_attr_list(ios->per_dev[0].or,
-                                            &cur_attr, &nelem, &iter);
-               if ((cur_attr.attr_page == attr->attr_page) &&
-                   (cur_attr.attr_id == attr->attr_id)) {
-                       attr->len = cur_attr.len;
-                       attr->val_ptr = cur_attr.val_ptr;
-                       return 0;
-               }
-       } while (iter);
-
-       return -EIO;
-}
-
-static int _truncate_mirrors(struct exofs_io_state *ios, unsigned cur_comp,
-                            struct osd_attr *attr)
-{
-       int last_comp = cur_comp + ios->layout->mirrors_p1;
-
-       for (; cur_comp < last_comp; ++cur_comp) {
-               struct exofs_per_dev_state *per_dev = &ios->per_dev[cur_comp];
-               struct osd_request *or;
-
-               or = osd_start_request(exofs_ios_od(ios, cur_comp), GFP_KERNEL);
-               if (unlikely(!or)) {
-                       EXOFS_ERR("%s: osd_start_request failed\n", __func__);
-                       return -ENOMEM;
-               }
-               per_dev->or = or;
-
-               osd_req_set_attributes(or, &ios->obj);
-               osd_req_add_set_attr_list(or, attr, 1);
-       }
-
-       return 0;
-}
-
-int exofs_oi_truncate(struct exofs_i_info *oi, u64 size)
-{
-       struct exofs_sb_info *sbi = oi->vfs_inode.i_sb->s_fs_info;
-       struct exofs_io_state *ios;
-       struct exofs_trunc_attr {
-               struct osd_attr attr;
-               __be64 newsize;
-       } *size_attrs;
-       struct _striping_info si;
-       int i, ret;
-
-       ret = exofs_get_io_state(&sbi->layout, &ios);
-       if (unlikely(ret))
-               return ret;
-
-       size_attrs = kcalloc(ios->layout->group_width, sizeof(*size_attrs),
-                            GFP_KERNEL);
-       if (unlikely(!size_attrs)) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       ios->obj.id = exofs_oi_objno(oi);
-       ios->cred = oi->i_cred;
-
-       ios->numdevs = ios->layout->s_numdevs;
-       _calc_stripe_info(ios, size, &si);
-
-       for (i = 0; i < ios->layout->group_width; ++i) {
-               struct exofs_trunc_attr *size_attr = &size_attrs[i];
-               u64 obj_size;
-
-               if (i < si.dev)
-                       obj_size = si.obj_offset +
-                                       ios->layout->stripe_unit - si.unit_off;
-               else if (i == si.dev)
-                       obj_size = si.obj_offset;
-               else /* i > si.dev */
-                       obj_size = si.obj_offset - si.unit_off;
-
-               size_attr->newsize = cpu_to_be64(obj_size);
-               size_attr->attr = g_attr_logical_length;
-               size_attr->attr.val_ptr = &size_attr->newsize;
-
-               ret = _truncate_mirrors(ios, i * ios->layout->mirrors_p1,
-                                       &size_attr->attr);
-               if (unlikely(ret))
-                       goto out;
-       }
-       ret = exofs_io_execute(ios);
-
-out:
-       kfree(size_attrs);
-       exofs_put_io_state(ios);
-       return ret;
-}
diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c
new file mode 100644 (file)
index 0000000..25305af
--- /dev/null
@@ -0,0 +1,835 @@
+/*
+ * Copyright (C) 2005, 2006
+ * Avishay Traeger (avishay@gmail.com)
+ * Copyright (C) 2008, 2009
+ * Boaz Harrosh <bharrosh@panasas.com>
+ *
+ * This file is part of exofs.
+ *
+ * exofs is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.  Since it is based on ext2, and the only
+ * valid version of GPL for the Linux kernel is version 2, the only valid
+ * version of GPL for exofs is version 2.
+ *
+ * exofs is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with exofs; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/slab.h>
+#include <asm/div64.h>
+
+#include <scsi/osd_ore.h>
+
+#define ORE_ERR(fmt, a...) printk(KERN_ERR "ore: " fmt, ##a)
+
+#ifdef CONFIG_EXOFS_DEBUG
+#define ORE_DBGMSG(fmt, a...) \
+       printk(KERN_NOTICE "ore @%s:%d: " fmt, __func__, __LINE__, ##a)
+#else
+#define ORE_DBGMSG(fmt, a...) \
+       do { if (0) printk(fmt, ##a); } while (0)
+#endif
+
+/* u64 has problems with printk this will cast it to unsigned long long */
+#define _LLU(x) (unsigned long long)(x)
+
+#define ORE_DBGMSG2(M...) do {} while (0)
+/* #define ORE_DBGMSG2 ORE_DBGMSG */
+
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("Objects Raid Engine ore.ko");
+MODULE_LICENSE("GPL");
+
+static u8 *_ios_cred(struct ore_io_state *ios, unsigned index)
+{
+       return ios->comps->comps[index & ios->comps->single_comp].cred;
+}
+
+static struct osd_obj_id *_ios_obj(struct ore_io_state *ios, unsigned index)
+{
+       return &ios->comps->comps[index & ios->comps->single_comp].obj;
+}
+
+static struct osd_dev *_ios_od(struct ore_io_state *ios, unsigned index)
+{
+       return ios->comps->ods[index];
+}
+
+int  ore_get_rw_state(struct ore_layout *layout, struct ore_components *comps,
+                     bool is_reading, u64 offset, u64 length,
+                     struct ore_io_state **pios)
+{
+       struct ore_io_state *ios;
+
+       /*TODO: Maybe use kmem_cach per sbi of size
+        * exofs_io_state_size(layout->s_numdevs)
+        */
+       ios = kzalloc(ore_io_state_size(comps->numdevs), GFP_KERNEL);
+       if (unlikely(!ios)) {
+               ORE_DBGMSG("Failed kzalloc bytes=%d\n",
+                            ore_io_state_size(comps->numdevs));
+               *pios = NULL;
+               return -ENOMEM;
+       }
+
+       ios->layout = layout;
+       ios->comps = comps;
+       ios->offset = offset;
+       ios->length = length;
+       ios->reading = is_reading;
+
+       *pios = ios;
+       return 0;
+}
+EXPORT_SYMBOL(ore_get_rw_state);
+
+int  ore_get_io_state(struct ore_layout *layout, struct ore_components *comps,
+                     struct ore_io_state **ios)
+{
+       return ore_get_rw_state(layout, comps, true, 0, 0, ios);
+}
+EXPORT_SYMBOL(ore_get_io_state);
+
+void ore_put_io_state(struct ore_io_state *ios)
+{
+       if (ios) {
+               unsigned i;
+
+               for (i = 0; i < ios->numdevs; i++) {
+                       struct ore_per_dev_state *per_dev = &ios->per_dev[i];
+
+                       if (per_dev->or)
+                               osd_end_request(per_dev->or);
+                       if (per_dev->bio)
+                               bio_put(per_dev->bio);
+               }
+
+               kfree(ios);
+       }
+}
+EXPORT_SYMBOL(ore_put_io_state);
+
+static void _sync_done(struct ore_io_state *ios, void *p)
+{
+       struct completion *waiting = p;
+
+       complete(waiting);
+}
+
+static void _last_io(struct kref *kref)
+{
+       struct ore_io_state *ios = container_of(
+                                       kref, struct ore_io_state, kref);
+
+       ios->done(ios, ios->private);
+}
+
+static void _done_io(struct osd_request *or, void *p)
+{
+       struct ore_io_state *ios = p;
+
+       kref_put(&ios->kref, _last_io);
+}
+
+static int ore_io_execute(struct ore_io_state *ios)
+{
+       DECLARE_COMPLETION_ONSTACK(wait);
+       bool sync = (ios->done == NULL);
+       int i, ret;
+
+       if (sync) {
+               ios->done = _sync_done;
+               ios->private = &wait;
+       }
+
+       for (i = 0; i < ios->numdevs; i++) {
+               struct osd_request *or = ios->per_dev[i].or;
+               if (unlikely(!or))
+                       continue;
+
+               ret = osd_finalize_request(or, 0, _ios_cred(ios, i), NULL);
+               if (unlikely(ret)) {
+                       ORE_DBGMSG("Failed to osd_finalize_request() => %d\n",
+                                    ret);
+                       return ret;
+               }
+       }
+
+       kref_init(&ios->kref);
+
+       for (i = 0; i < ios->numdevs; i++) {
+               struct osd_request *or = ios->per_dev[i].or;
+               if (unlikely(!or))
+                       continue;
+
+               kref_get(&ios->kref);
+               osd_execute_request_async(or, _done_io, ios);
+       }
+
+       kref_put(&ios->kref, _last_io);
+       ret = 0;
+
+       if (sync) {
+               wait_for_completion(&wait);
+               ret = ore_check_io(ios, NULL);
+       }
+       return ret;
+}
+
+static void _clear_bio(struct bio *bio)
+{
+       struct bio_vec *bv;
+       unsigned i;
+
+       __bio_for_each_segment(bv, bio, i, 0) {
+               unsigned this_count = bv->bv_len;
+
+               if (likely(PAGE_SIZE == this_count))
+                       clear_highpage(bv->bv_page);
+               else
+                       zero_user(bv->bv_page, bv->bv_offset, this_count);
+       }
+}
+
+int ore_check_io(struct ore_io_state *ios, u64 *resid)
+{
+       enum osd_err_priority acumulated_osd_err = 0;
+       int acumulated_lin_err = 0;
+       int i;
+
+       for (i = 0; i < ios->numdevs; i++) {
+               struct osd_sense_info osi;
+               struct osd_request *or = ios->per_dev[i].or;
+               int ret;
+
+               if (unlikely(!or))
+                       continue;
+
+               ret = osd_req_decode_sense(or, &osi);
+               if (likely(!ret))
+                       continue;
+
+               if (OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) {
+                       /* start read offset passed endof file */
+                       _clear_bio(ios->per_dev[i].bio);
+                       ORE_DBGMSG("start read offset passed end of file "
+                               "offset=0x%llx, length=0x%llx\n",
+                               _LLU(ios->per_dev[i].offset),
+                               _LLU(ios->per_dev[i].length));
+
+                       continue; /* we recovered */
+               }
+
+               if (osi.osd_err_pri >= acumulated_osd_err) {
+                       acumulated_osd_err = osi.osd_err_pri;
+                       acumulated_lin_err = ret;
+               }
+       }
+
+       /* TODO: raid specific residual calculations */
+       if (resid) {
+               if (likely(!acumulated_lin_err))
+                       *resid = 0;
+               else
+                       *resid = ios->length;
+       }
+
+       return acumulated_lin_err;
+}
+EXPORT_SYMBOL(ore_check_io);
+
+/*
+ * L - logical offset into the file
+ *
+ * U - The number of bytes in a stripe within a group
+ *
+ *     U = stripe_unit * group_width
+ *
+ * T - The number of bytes striped within a group of component objects
+ *     (before advancing to the next group)
+ *
+ *     T = stripe_unit * group_width * group_depth
+ *
+ * S - The number of bytes striped across all component objects
+ *     before the pattern repeats
+ *
+ *     S = stripe_unit * group_width * group_depth * group_count
+ *
+ * M - The "major" (i.e., across all components) stripe number
+ *
+ *     M = L / S
+ *
+ * G - Counts the groups from the beginning of the major stripe
+ *
+ *     G = (L - (M * S)) / T   [or (L % S) / T]
+ *
+ * H - The byte offset within the group
+ *
+ *     H = (L - (M * S)) % T   [or (L % S) % T]
+ *
+ * N - The "minor" (i.e., across the group) stripe number
+ *
+ *     N = H / U
+ *
+ * C - The component index coresponding to L
+ *
+ *     C = (H - (N * U)) / stripe_unit + G * group_width
+ *     [or (L % U) / stripe_unit + G * group_width]
+ *
+ * O - The component offset coresponding to L
+ *
+ *     O = L % stripe_unit + N * stripe_unit + M * group_depth * stripe_unit
+ */
+struct _striping_info {
+       u64 obj_offset;
+       u64 group_length;
+       u64 M; /* for truncate */
+       unsigned dev;
+       unsigned unit_off;
+};
+
+static void _calc_stripe_info(struct ore_layout *layout, u64 file_offset,
+                             struct _striping_info *si)
+{
+       u32     stripe_unit = layout->stripe_unit;
+       u32     group_width = layout->group_width;
+       u64     group_depth = layout->group_depth;
+
+       u32     U = stripe_unit * group_width;
+       u64     T = U * group_depth;
+       u64     S = T * layout->group_count;
+       u64     M = div64_u64(file_offset, S);
+
+       /*
+       G = (L - (M * S)) / T
+       H = (L - (M * S)) % T
+       */
+       u64     LmodS = file_offset - M * S;
+       u32     G = div64_u64(LmodS, T);
+       u64     H = LmodS - G * T;
+
+       u32     N = div_u64(H, U);
+
+       /* "H - (N * U)" is just "H % U" so it's bound to u32 */
+       si->dev = (u32)(H - (N * U)) / stripe_unit + G * group_width;
+       si->dev *= layout->mirrors_p1;
+
+       div_u64_rem(file_offset, stripe_unit, &si->unit_off);
+
+       si->obj_offset = si->unit_off + (N * stripe_unit) +
+                                 (M * group_depth * stripe_unit);
+
+       si->group_length = T - H;
+       si->M = M;
+}
+
+static int _add_stripe_unit(struct ore_io_state *ios,  unsigned *cur_pg,
+               unsigned pgbase, struct ore_per_dev_state *per_dev,
+               int cur_len)
+{
+       unsigned pg = *cur_pg;
+       struct request_queue *q =
+                       osd_request_queue(_ios_od(ios, per_dev->dev));
+
+       per_dev->length += cur_len;
+
+       if (per_dev->bio == NULL) {
+               unsigned pages_in_stripe = ios->layout->group_width *
+                                       (ios->layout->stripe_unit / PAGE_SIZE);
+               unsigned bio_size = (ios->nr_pages + pages_in_stripe) /
+                                               ios->layout->group_width;
+
+               per_dev->bio = bio_kmalloc(GFP_KERNEL, bio_size);
+               if (unlikely(!per_dev->bio)) {
+                       ORE_DBGMSG("Failed to allocate BIO size=%u\n",
+                                    bio_size);
+                       return -ENOMEM;
+               }
+       }
+
+       while (cur_len > 0) {
+               unsigned pglen = min_t(unsigned, PAGE_SIZE - pgbase, cur_len);
+               unsigned added_len;
+
+               BUG_ON(ios->nr_pages <= pg);
+               cur_len -= pglen;
+
+               added_len = bio_add_pc_page(q, per_dev->bio, ios->pages[pg],
+                                           pglen, pgbase);
+               if (unlikely(pglen != added_len))
+                       return -ENOMEM;
+               pgbase = 0;
+               ++pg;
+       }
+       BUG_ON(cur_len);
+
+       *cur_pg = pg;
+       return 0;
+}
+
+static int _prepare_one_group(struct ore_io_state *ios, u64 length,
+                             struct _striping_info *si)
+{
+       unsigned stripe_unit = ios->layout->stripe_unit;
+       unsigned mirrors_p1 = ios->layout->mirrors_p1;
+       unsigned devs_in_group = ios->layout->group_width * mirrors_p1;
+       unsigned dev = si->dev;
+       unsigned first_dev = dev - (dev % devs_in_group);
+       unsigned max_comp = ios->numdevs ? ios->numdevs - mirrors_p1 : 0;
+       unsigned cur_pg = ios->pages_consumed;
+       int ret = 0;
+
+       while (length) {
+               struct ore_per_dev_state *per_dev = &ios->per_dev[dev];
+               unsigned cur_len, page_off = 0;
+
+               if (!per_dev->length) {
+                       per_dev->dev = dev;
+                       if (dev < si->dev) {
+                               per_dev->offset = si->obj_offset + stripe_unit -
+                                                                  si->unit_off;
+                               cur_len = stripe_unit;
+                       } else if (dev == si->dev) {
+                               per_dev->offset = si->obj_offset;
+                               cur_len = stripe_unit - si->unit_off;
+                               page_off = si->unit_off & ~PAGE_MASK;
+                               BUG_ON(page_off && (page_off != ios->pgbase));
+                       } else { /* dev > si->dev */
+                               per_dev->offset = si->obj_offset - si->unit_off;
+                               cur_len = stripe_unit;
+                       }
+
+                       if (max_comp < dev)
+                               max_comp = dev;
+               } else {
+                       cur_len = stripe_unit;
+               }
+               if (cur_len >= length)
+                       cur_len = length;
+
+               ret = _add_stripe_unit(ios, &cur_pg, page_off , per_dev,
+                                      cur_len);
+               if (unlikely(ret))
+                       goto out;
+
+               dev += mirrors_p1;
+               dev = (dev % devs_in_group) + first_dev;
+
+               length -= cur_len;
+       }
+out:
+       ios->numdevs = max_comp + mirrors_p1;
+       ios->pages_consumed = cur_pg;
+       return ret;
+}
+
+static int _prepare_for_striping(struct ore_io_state *ios)
+{
+       u64 length = ios->length;
+       u64 offset = ios->offset;
+       struct _striping_info si;
+       int ret = 0;
+
+       if (!ios->pages) {
+               if (ios->kern_buff) {
+                       struct ore_per_dev_state *per_dev = &ios->per_dev[0];
+
+                       _calc_stripe_info(ios->layout, ios->offset, &si);
+                       per_dev->offset = si.obj_offset;
+                       per_dev->dev = si.dev;
+
+                       /* no cross device without page array */
+                       BUG_ON((ios->layout->group_width > 1) &&
+                              (si.unit_off + ios->length >
+                               ios->layout->stripe_unit));
+               }
+               ios->numdevs = ios->layout->mirrors_p1;
+               return 0;
+       }
+
+       while (length) {
+               _calc_stripe_info(ios->layout, offset, &si);
+
+               if (length < si.group_length)
+                       si.group_length = length;
+
+               ret = _prepare_one_group(ios, si.group_length, &si);
+               if (unlikely(ret))
+                       goto out;
+
+               offset += si.group_length;
+               length -= si.group_length;
+       }
+
+out:
+       return ret;
+}
+
+int ore_create(struct ore_io_state *ios)
+{
+       int i, ret;
+
+       for (i = 0; i < ios->comps->numdevs; i++) {
+               struct osd_request *or;
+
+               or = osd_start_request(_ios_od(ios, i), GFP_KERNEL);
+               if (unlikely(!or)) {
+                       ORE_ERR("%s: osd_start_request failed\n", __func__);
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               ios->per_dev[i].or = or;
+               ios->numdevs++;
+
+               osd_req_create_object(or, _ios_obj(ios, i));
+       }
+       ret = ore_io_execute(ios);
+
+out:
+       return ret;
+}
+EXPORT_SYMBOL(ore_create);
+
+int ore_remove(struct ore_io_state *ios)
+{
+       int i, ret;
+
+       for (i = 0; i < ios->comps->numdevs; i++) {
+               struct osd_request *or;
+
+               or = osd_start_request(_ios_od(ios, i), GFP_KERNEL);
+               if (unlikely(!or)) {
+                       ORE_ERR("%s: osd_start_request failed\n", __func__);
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               ios->per_dev[i].or = or;
+               ios->numdevs++;
+
+               osd_req_remove_object(or, _ios_obj(ios, i));
+       }
+       ret = ore_io_execute(ios);
+
+out:
+       return ret;
+}
+EXPORT_SYMBOL(ore_remove);
+
+static int _write_mirror(struct ore_io_state *ios, int cur_comp)
+{
+       struct ore_per_dev_state *master_dev = &ios->per_dev[cur_comp];
+       unsigned dev = ios->per_dev[cur_comp].dev;
+       unsigned last_comp = cur_comp + ios->layout->mirrors_p1;
+       int ret = 0;
+
+       if (ios->pages && !master_dev->length)
+               return 0; /* Just an empty slot */
+
+       for (; cur_comp < last_comp; ++cur_comp, ++dev) {
+               struct ore_per_dev_state *per_dev = &ios->per_dev[cur_comp];
+               struct osd_request *or;
+
+               or = osd_start_request(_ios_od(ios, dev), GFP_KERNEL);
+               if (unlikely(!or)) {
+                       ORE_ERR("%s: osd_start_request failed\n", __func__);
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               per_dev->or = or;
+               per_dev->offset = master_dev->offset;
+
+               if (ios->pages) {
+                       struct bio *bio;
+
+                       if (per_dev != master_dev) {
+                               bio = bio_kmalloc(GFP_KERNEL,
+                                                 master_dev->bio->bi_max_vecs);
+                               if (unlikely(!bio)) {
+                                       ORE_DBGMSG(
+                                             "Failed to allocate BIO size=%u\n",
+                                             master_dev->bio->bi_max_vecs);
+                                       ret = -ENOMEM;
+                                       goto out;
+                               }
+
+                               __bio_clone(bio, master_dev->bio);
+                               bio->bi_bdev = NULL;
+                               bio->bi_next = NULL;
+                               per_dev->length = master_dev->length;
+                               per_dev->bio =  bio;
+                               per_dev->dev = dev;
+                       } else {
+                               bio = master_dev->bio;
+                               /* FIXME: bio_set_dir() */
+                               bio->bi_rw |= REQ_WRITE;
+                       }
+
+                       osd_req_write(or, _ios_obj(ios, dev), per_dev->offset,
+                                     bio, per_dev->length);
+                       ORE_DBGMSG("write(0x%llx) offset=0x%llx "
+                                     "length=0x%llx dev=%d\n",
+                                    _LLU(_ios_obj(ios, dev)->id),
+                                    _LLU(per_dev->offset),
+                                    _LLU(per_dev->length), dev);
+               } else if (ios->kern_buff) {
+                       ret = osd_req_write_kern(or, _ios_obj(ios, dev),
+                                                per_dev->offset,
+                                                ios->kern_buff, ios->length);
+                       if (unlikely(ret))
+                               goto out;
+                       ORE_DBGMSG2("write_kern(0x%llx) offset=0x%llx "
+                                     "length=0x%llx dev=%d\n",
+                                    _LLU(_ios_obj(ios, dev)->id),
+                                    _LLU(per_dev->offset),
+                                    _LLU(ios->length), dev);
+               } else {
+                       osd_req_set_attributes(or, _ios_obj(ios, dev));
+                       ORE_DBGMSG2("obj(0x%llx) set_attributes=%d dev=%d\n",
+                                    _LLU(_ios_obj(ios, dev)->id),
+                                    ios->out_attr_len, dev);
+               }
+
+               if (ios->out_attr)
+                       osd_req_add_set_attr_list(or, ios->out_attr,
+                                                 ios->out_attr_len);
+
+               if (ios->in_attr)
+                       osd_req_add_get_attr_list(or, ios->in_attr,
+                                                 ios->in_attr_len);
+       }
+
+out:
+       return ret;
+}
+
+int ore_write(struct ore_io_state *ios)
+{
+       int i;
+       int ret;
+
+       ret = _prepare_for_striping(ios);
+       if (unlikely(ret))
+               return ret;
+
+       for (i = 0; i < ios->numdevs; i += ios->layout->mirrors_p1) {
+               ret = _write_mirror(ios, i);
+               if (unlikely(ret))
+                       return ret;
+       }
+
+       ret = ore_io_execute(ios);
+       return ret;
+}
+EXPORT_SYMBOL(ore_write);
+
+static int _read_mirror(struct ore_io_state *ios, unsigned cur_comp)
+{
+       struct osd_request *or;
+       struct ore_per_dev_state *per_dev = &ios->per_dev[cur_comp];
+       struct osd_obj_id *obj = _ios_obj(ios, cur_comp);
+       unsigned first_dev = (unsigned)obj->id;
+
+       if (ios->pages && !per_dev->length)
+               return 0; /* Just an empty slot */
+
+       first_dev = per_dev->dev + first_dev % ios->layout->mirrors_p1;
+       or = osd_start_request(_ios_od(ios, first_dev), GFP_KERNEL);
+       if (unlikely(!or)) {
+               ORE_ERR("%s: osd_start_request failed\n", __func__);
+               return -ENOMEM;
+       }
+       per_dev->or = or;
+
+       if (ios->pages) {
+               osd_req_read(or, obj, per_dev->offset,
+                               per_dev->bio, per_dev->length);
+               ORE_DBGMSG("read(0x%llx) offset=0x%llx length=0x%llx"
+                            " dev=%d\n", _LLU(obj->id),
+                            _LLU(per_dev->offset), _LLU(per_dev->length),
+                            first_dev);
+       } else if (ios->kern_buff) {
+               int ret = osd_req_read_kern(or, obj, per_dev->offset,
+                                           ios->kern_buff, ios->length);
+               ORE_DBGMSG2("read_kern(0x%llx) offset=0x%llx "
+                             "length=0x%llx dev=%d ret=>%d\n",
+                             _LLU(obj->id), _LLU(per_dev->offset),
+                             _LLU(ios->length), first_dev, ret);
+               if (unlikely(ret))
+                       return ret;
+       } else {
+               osd_req_get_attributes(or, obj);
+               ORE_DBGMSG2("obj(0x%llx) get_attributes=%d dev=%d\n",
+                             _LLU(obj->id),
+                             ios->in_attr_len, first_dev);
+       }
+       if (ios->out_attr)
+               osd_req_add_set_attr_list(or, ios->out_attr, ios->out_attr_len);
+
+       if (ios->in_attr)
+               osd_req_add_get_attr_list(or, ios->in_attr, ios->in_attr_len);
+
+       return 0;
+}
+
+int ore_read(struct ore_io_state *ios)
+{
+       int i;
+       int ret;
+
+       ret = _prepare_for_striping(ios);
+       if (unlikely(ret))
+               return ret;
+
+       for (i = 0; i < ios->numdevs; i += ios->layout->mirrors_p1) {
+               ret = _read_mirror(ios, i);
+               if (unlikely(ret))
+                       return ret;
+       }
+
+       ret = ore_io_execute(ios);
+       return ret;
+}
+EXPORT_SYMBOL(ore_read);
+
+int extract_attr_from_ios(struct ore_io_state *ios, struct osd_attr *attr)
+{
+       struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */
+       void *iter = NULL;
+       int nelem;
+
+       do {
+               nelem = 1;
+               osd_req_decode_get_attr_list(ios->per_dev[0].or,
+                                            &cur_attr, &nelem, &iter);
+               if ((cur_attr.attr_page == attr->attr_page) &&
+                   (cur_attr.attr_id == attr->attr_id)) {
+                       attr->len = cur_attr.len;
+                       attr->val_ptr = cur_attr.val_ptr;
+                       return 0;
+               }
+       } while (iter);
+
+       return -EIO;
+}
+EXPORT_SYMBOL(extract_attr_from_ios);
+
+static int _truncate_mirrors(struct ore_io_state *ios, unsigned cur_comp,
+                            struct osd_attr *attr)
+{
+       int last_comp = cur_comp + ios->layout->mirrors_p1;
+
+       for (; cur_comp < last_comp; ++cur_comp) {
+               struct ore_per_dev_state *per_dev = &ios->per_dev[cur_comp];
+               struct osd_request *or;
+
+               or = osd_start_request(_ios_od(ios, cur_comp), GFP_KERNEL);
+               if (unlikely(!or)) {
+                       ORE_ERR("%s: osd_start_request failed\n", __func__);
+                       return -ENOMEM;
+               }
+               per_dev->or = or;
+
+               osd_req_set_attributes(or, _ios_obj(ios, cur_comp));
+               osd_req_add_set_attr_list(or, attr, 1);
+       }
+
+       return 0;
+}
+
+struct _trunc_info {
+       struct _striping_info si;
+       u64 prev_group_obj_off;
+       u64 next_group_obj_off;
+
+       unsigned first_group_dev;
+       unsigned nex_group_dev;
+       unsigned max_devs;
+};
+
+void _calc_trunk_info(struct ore_layout *layout, u64 file_offset,
+                      struct _trunc_info *ti)
+{
+       unsigned stripe_unit = layout->stripe_unit;
+
+       _calc_stripe_info(layout, file_offset, &ti->si);
+
+       ti->prev_group_obj_off = ti->si.M * stripe_unit;
+       ti->next_group_obj_off = ti->si.M ? (ti->si.M - 1) * stripe_unit : 0;
+
+       ti->first_group_dev = ti->si.dev - (ti->si.dev % layout->group_width);
+       ti->nex_group_dev = ti->first_group_dev + layout->group_width;
+       ti->max_devs = layout->group_width * layout->group_count;
+}
+
+int ore_truncate(struct ore_layout *layout, struct ore_components *comps,
+                  u64 size)
+{
+       struct ore_io_state *ios;
+       struct exofs_trunc_attr {
+               struct osd_attr attr;
+               __be64 newsize;
+       } *size_attrs;
+       struct _trunc_info ti;
+       int i, ret;
+
+       ret = ore_get_io_state(layout, comps, &ios);
+       if (unlikely(ret))
+               return ret;
+
+       _calc_trunk_info(ios->layout, size, &ti);
+
+       size_attrs = kcalloc(ti.max_devs, sizeof(*size_attrs),
+                            GFP_KERNEL);
+       if (unlikely(!size_attrs)) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ios->numdevs = ios->comps->numdevs;
+
+       for (i = 0; i < ti.max_devs; ++i) {
+               struct exofs_trunc_attr *size_attr = &size_attrs[i];
+               u64 obj_size;
+
+               if (i < ti.first_group_dev)
+                       obj_size = ti.prev_group_obj_off;
+               else if (i >= ti.nex_group_dev)
+                       obj_size = ti.next_group_obj_off;
+               else if (i < ti.si.dev) /* dev within this group */
+                       obj_size = ti.si.obj_offset +
+                                     ios->layout->stripe_unit - ti.si.unit_off;
+               else if (i == ti.si.dev)
+                       obj_size = ti.si.obj_offset;
+               else /* i > ti.dev */
+                       obj_size = ti.si.obj_offset - ti.si.unit_off;
+
+               size_attr->newsize = cpu_to_be64(obj_size);
+               size_attr->attr = g_attr_logical_length;
+               size_attr->attr.val_ptr = &size_attr->newsize;
+
+               ORE_DBGMSG("trunc(0x%llx) obj_offset=0x%llx dev=%d\n",
+                            _LLU(comps->comps->obj.id), _LLU(obj_size), i);
+               ret = _truncate_mirrors(ios, i * ios->layout->mirrors_p1,
+                                       &size_attr->attr);
+               if (unlikely(ret))
+                       goto out;
+       }
+       ret = ore_io_execute(ios);
+
+out:
+       kfree(size_attrs);
+       ore_put_io_state(ios);
+       return ret;
+}
+EXPORT_SYMBOL(ore_truncate);
+
+const struct osd_attr g_attr_logical_length = ATTR_DEF(
+       OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8);
+EXPORT_SYMBOL(g_attr_logical_length);
diff --git a/fs/exofs/pnfs.h b/fs/exofs/pnfs.h
deleted file mode 100644 (file)
index c52e988..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2008, 2009
- * Boaz Harrosh <bharrosh@panasas.com>
- *
- * This file is part of exofs.
- *
- * exofs is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License  version 2 as published by the Free
- * Software Foundation.
- *
- */
-
-/* FIXME: Remove this file once pnfs hits mainline */
-
-#ifndef __EXOFS_PNFS_H__
-#define __EXOFS_PNFS_H__
-
-#if ! defined(__PNFS_OSD_XDR_H__)
-
-enum pnfs_iomode {
-       IOMODE_READ = 1,
-       IOMODE_RW = 2,
-       IOMODE_ANY = 3,
-};
-
-/* Layout Structure */
-enum pnfs_osd_raid_algorithm4 {
-       PNFS_OSD_RAID_0         = 1,
-       PNFS_OSD_RAID_4         = 2,
-       PNFS_OSD_RAID_5         = 3,
-       PNFS_OSD_RAID_PQ        = 4     /* Reed-Solomon P+Q */
-};
-
-struct pnfs_osd_data_map {
-       u32     odm_num_comps;
-       u64     odm_stripe_unit;
-       u32     odm_group_width;
-       u32     odm_group_depth;
-       u32     odm_mirror_cnt;
-       u32     odm_raid_algorithm;
-};
-
-#endif /* ! defined(__PNFS_OSD_XDR_H__) */
-
-#endif /* __EXOFS_PNFS_H__ */
index c57beddcc217e3e3592fe977f8237f7f46ddf16f..274894053b025b69e9908012b11fc6d10ab32306 100644 (file)
@@ -40,6 +40,8 @@
 
 #include "exofs.h"
 
+#define EXOFS_DBGMSG2(M...) do {} while (0)
+
 /******************************************************************************
  * MOUNT OPTIONS
  *****************************************************************************/
@@ -208,10 +210,48 @@ static void destroy_inodecache(void)
 }
 
 /******************************************************************************
- * SUPERBLOCK FUNCTIONS
+ * Some osd helpers
  *****************************************************************************/
-static const struct super_operations exofs_sops;
-static const struct export_operations exofs_export_ops;
+void exofs_make_credential(u8 cred_a[OSD_CAP_LEN], const struct osd_obj_id *obj)
+{
+       osd_sec_init_nosec_doall_caps(cred_a, obj, false, true);
+}
+
+static int exofs_read_kern(struct osd_dev *od, u8 *cred, struct osd_obj_id *obj,
+                   u64 offset, void *p, unsigned length)
+{
+       struct osd_request *or = osd_start_request(od, GFP_KERNEL);
+/*     struct osd_sense_info osi = {.key = 0};*/
+       int ret;
+
+       if (unlikely(!or)) {
+               EXOFS_DBGMSG("%s: osd_start_request failed.\n", __func__);
+               return -ENOMEM;
+       }
+       ret = osd_req_read_kern(or, obj, offset, p, length);
+       if (unlikely(ret)) {
+               EXOFS_DBGMSG("%s: osd_req_read_kern failed.\n", __func__);
+               goto out;
+       }
+
+       ret = osd_finalize_request(or, 0, cred, NULL);
+       if (unlikely(ret)) {
+               EXOFS_DBGMSG("Failed to osd_finalize_request() => %d\n", ret);
+               goto out;
+       }
+
+       ret = osd_execute_request(or);
+       if (unlikely(ret))
+               EXOFS_DBGMSG("osd_execute_request() => %d\n", ret);
+       /* osd_req_decode_sense(or, ret); */
+
+out:
+       osd_end_request(or);
+       EXOFS_DBGMSG2("read_kern(0x%llx) offset=0x%llx "
+                     "length=0x%llx dev=%p ret=>%d\n",
+                     _LLU(obj->id), _LLU(offset), _LLU(length), od, ret);
+       return ret;
+}
 
 static const struct osd_attr g_attr_sb_stats = ATTR_DEF(
        EXOFS_APAGE_SB_DATA,
@@ -223,21 +263,19 @@ static int __sbi_read_stats(struct exofs_sb_info *sbi)
        struct osd_attr attrs[] = {
                [0] = g_attr_sb_stats,
        };
-       struct exofs_io_state *ios;
+       struct ore_io_state *ios;
        int ret;
 
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+       ret = ore_get_io_state(&sbi->layout, &sbi->comps, &ios);
        if (unlikely(ret)) {
-               EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__);
+               EXOFS_ERR("%s: ore_get_io_state failed.\n", __func__);
                return ret;
        }
 
-       ios->cred = sbi->s_cred;
-
        ios->in_attr = attrs;
        ios->in_attr_len = ARRAY_SIZE(attrs);
 
-       ret = exofs_sbi_read(ios);
+       ret = ore_read(ios);
        if (unlikely(ret)) {
                EXOFS_ERR("Error reading super_block stats => %d\n", ret);
                goto out;
@@ -264,13 +302,13 @@ static int __sbi_read_stats(struct exofs_sb_info *sbi)
        }
 
 out:
-       exofs_put_io_state(ios);
+       ore_put_io_state(ios);
        return ret;
 }
 
-static void stats_done(struct exofs_io_state *ios, void *p)
+static void stats_done(struct ore_io_state *ios, void *p)
 {
-       exofs_put_io_state(ios);
+       ore_put_io_state(ios);
        /* Good thanks nothing to do anymore */
 }
 
@@ -280,12 +318,12 @@ int exofs_sbi_write_stats(struct exofs_sb_info *sbi)
        struct osd_attr attrs[] = {
                [0] = g_attr_sb_stats,
        };
-       struct exofs_io_state *ios;
+       struct ore_io_state *ios;
        int ret;
 
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+       ret = ore_get_io_state(&sbi->layout, &sbi->comps, &ios);
        if (unlikely(ret)) {
-               EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__);
+               EXOFS_ERR("%s: ore_get_io_state failed.\n", __func__);
                return ret;
        }
 
@@ -293,21 +331,27 @@ int exofs_sbi_write_stats(struct exofs_sb_info *sbi)
        sbi->s_ess.s_numfiles = cpu_to_le64(sbi->s_numfiles);
        attrs[0].val_ptr = &sbi->s_ess;
 
-       ios->cred = sbi->s_cred;
+
        ios->done = stats_done;
        ios->private = sbi;
        ios->out_attr = attrs;
        ios->out_attr_len = ARRAY_SIZE(attrs);
 
-       ret = exofs_sbi_write(ios);
+       ret = ore_write(ios);
        if (unlikely(ret)) {
-               EXOFS_ERR("%s: exofs_sbi_write failed.\n", __func__);
-               exofs_put_io_state(ios);
+               EXOFS_ERR("%s: ore_write failed.\n", __func__);
+               ore_put_io_state(ios);
        }
 
        return ret;
 }
 
+/******************************************************************************
+ * SUPERBLOCK FUNCTIONS
+ *****************************************************************************/
+static const struct super_operations exofs_sops;
+static const struct export_operations exofs_export_ops;
+
 /*
  * Write the superblock to the OSD
  */
@@ -315,7 +359,9 @@ int exofs_sync_fs(struct super_block *sb, int wait)
 {
        struct exofs_sb_info *sbi;
        struct exofs_fscb *fscb;
-       struct exofs_io_state *ios;
+       struct ore_comp one_comp;
+       struct ore_components comps;
+       struct ore_io_state *ios;
        int ret = -ENOMEM;
 
        fscb = kmalloc(sizeof(*fscb), GFP_KERNEL);
@@ -331,7 +377,10 @@ int exofs_sync_fs(struct super_block *sb, int wait)
         * version). Otherwise the exofs_fscb is read-only from mkfs time. All
         * the writeable info is set in exofs_sbi_write_stats() above.
         */
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+
+       exofs_init_comps(&comps, &one_comp, sbi, EXOFS_SUPER_ID);
+
+       ret = ore_get_io_state(&sbi->layout, &comps, &ios);
        if (unlikely(ret))
                goto out;
 
@@ -345,14 +394,12 @@ int exofs_sync_fs(struct super_block *sb, int wait)
        fscb->s_newfs = 0;
        fscb->s_version = EXOFS_FSCB_VER;
 
-       ios->obj.id = EXOFS_SUPER_ID;
        ios->offset = 0;
        ios->kern_buff = fscb;
-       ios->cred = sbi->s_cred;
 
-       ret = exofs_sbi_write(ios);
+       ret = ore_write(ios);
        if (unlikely(ret))
-               EXOFS_ERR("%s: exofs_sbi_write failed.\n", __func__);
+               EXOFS_ERR("%s: ore_write failed.\n", __func__);
        else
                sb->s_dirt = 0;
 
@@ -360,7 +407,7 @@ int exofs_sync_fs(struct super_block *sb, int wait)
        unlock_super(sb);
 out:
        EXOFS_DBGMSG("s_nextid=0x%llx ret=%d\n", _LLU(sbi->s_nextid), ret);
-       exofs_put_io_state(ios);
+       ore_put_io_state(ios);
        kfree(fscb);
        return ret;
 }
@@ -384,15 +431,17 @@ static void _exofs_print_device(const char *msg, const char *dev_path,
 
 void exofs_free_sbi(struct exofs_sb_info *sbi)
 {
-       while (sbi->layout.s_numdevs) {
-               int i = --sbi->layout.s_numdevs;
-               struct osd_dev *od = sbi->layout.s_ods[i];
+       while (sbi->comps.numdevs) {
+               int i = --sbi->comps.numdevs;
+               struct osd_dev *od = sbi->comps.ods[i];
 
                if (od) {
-                       sbi->layout.s_ods[i] = NULL;
+                       sbi->comps.ods[i] = NULL;
                        osduld_put_device(od);
                }
        }
+       if (sbi->comps.ods != sbi->_min_one_dev)
+               kfree(sbi->comps.ods);
        kfree(sbi);
 }
 
@@ -419,8 +468,8 @@ static void exofs_put_super(struct super_block *sb)
                                  msecs_to_jiffies(100));
        }
 
-       _exofs_print_device("Unmounting", NULL, sbi->layout.s_ods[0],
-                           sbi->layout.s_pid);
+       _exofs_print_device("Unmounting", NULL, sbi->comps.ods[0],
+                           sbi->one_comp.obj.partition);
 
        bdi_destroy(&sbi->bdi);
        exofs_free_sbi(sbi);
@@ -501,10 +550,19 @@ static int _read_and_match_data_map(struct exofs_sb_info *sbi, unsigned numdevs,
                return -EINVAL;
        }
 
+       EXOFS_DBGMSG("exofs: layout: "
+               "num_comps=%u stripe_unit=0x%x group_width=%u "
+               "group_depth=0x%llx mirrors_p1=%u raid_algorithm=%u\n",
+               numdevs,
+               sbi->layout.stripe_unit,
+               sbi->layout.group_width,
+               _LLU(sbi->layout.group_depth),
+               sbi->layout.mirrors_p1,
+               sbi->data_map.odm_raid_algorithm);
        return 0;
 }
 
-static unsigned __ra_pages(struct exofs_layout *layout)
+static unsigned __ra_pages(struct ore_layout *layout)
 {
        const unsigned _MIN_RA = 32; /* min 128K read-ahead */
        unsigned ra_pages = layout->group_width * layout->stripe_unit /
@@ -547,13 +605,11 @@ static int exofs_devs_2_odi(struct exofs_dt_device_info *dt_dev,
        return !(odi->systemid_len || odi->osdname_len);
 }
 
-static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi,
+static int exofs_read_lookup_dev_table(struct exofs_sb_info *sbi,
+                                      struct osd_dev *fscb_od,
                                       unsigned table_count)
 {
-       struct exofs_sb_info *sbi = *psbi;
-       struct osd_dev *fscb_od;
-       struct osd_obj_id obj = {.partition = sbi->layout.s_pid,
-                                .id = EXOFS_DEVTABLE_ID};
+       struct ore_comp comp;
        struct exofs_device_table *dt;
        unsigned table_bytes = table_count * sizeof(dt->dt_dev_table[0]) +
                                             sizeof(*dt);
@@ -567,10 +623,14 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi,
                return -ENOMEM;
        }
 
-       fscb_od = sbi->layout.s_ods[0];
-       sbi->layout.s_ods[0] = NULL;
-       sbi->layout.s_numdevs = 0;
-       ret = exofs_read_kern(fscb_od, sbi->s_cred, &obj, 0, dt, table_bytes);
+       sbi->comps.numdevs = 0;
+
+       comp.obj.partition = sbi->one_comp.obj.partition;
+       comp.obj.id = EXOFS_DEVTABLE_ID;
+       exofs_make_credential(comp.cred, &comp.obj);
+
+       ret = exofs_read_kern(fscb_od, comp.cred, &comp.obj, 0, dt,
+                             table_bytes);
        if (unlikely(ret)) {
                EXOFS_ERR("ERROR: reading device table\n");
                goto out;
@@ -588,16 +648,18 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi,
                goto out;
 
        if (likely(numdevs > 1)) {
-               unsigned size = numdevs * sizeof(sbi->layout.s_ods[0]);
+               unsigned size = numdevs * sizeof(sbi->comps.ods[0]);
 
-               sbi = krealloc(sbi, sizeof(*sbi) + size, GFP_KERNEL);
-               if (unlikely(!sbi)) {
+               /* Twice bigger table: See exofs_init_comps() and below
+                * comment
+                */
+               sbi->comps.ods = kzalloc(size + size - 1, GFP_KERNEL);
+               if (unlikely(!sbi->comps.ods)) {
+                       EXOFS_ERR("ERROR: faild allocating Device array[%d]\n",
+                                 numdevs);
                        ret = -ENOMEM;
                        goto out;
                }
-               memset(&sbi->layout.s_ods[1], 0,
-                      size - sizeof(sbi->layout.s_ods[0]));
-               *psbi = sbi;
        }
 
        for (i = 0; i < numdevs; i++) {
@@ -619,8 +681,8 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi,
                 * line. We always keep them in device-table order.
                 */
                if (fscb_od && osduld_device_same(fscb_od, &odi)) {
-                       sbi->layout.s_ods[i] = fscb_od;
-                       ++sbi->layout.s_numdevs;
+                       sbi->comps.ods[i] = fscb_od;
+                       ++sbi->comps.numdevs;
                        fscb_od = NULL;
                        continue;
                }
@@ -633,13 +695,13 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi,
                        goto out;
                }
 
-               sbi->layout.s_ods[i] = od;
-               ++sbi->layout.s_numdevs;
+               sbi->comps.ods[i] = od;
+               ++sbi->comps.numdevs;
 
                /* Read the fscb of the other devices to make sure the FS
                 * partition is there.
                 */
-               ret = exofs_read_kern(od, sbi->s_cred, &obj, 0, &fscb,
+               ret = exofs_read_kern(od, comp.cred, &comp.obj, 0, &fscb,
                                      sizeof(fscb));
                if (unlikely(ret)) {
                        EXOFS_ERR("ERROR: Malformed participating device "
@@ -656,13 +718,22 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi,
 
 out:
        kfree(dt);
-       if (unlikely(!ret && fscb_od)) {
-               EXOFS_ERR(
-                     "ERROR: Bad device-table container device not present\n");
-               osduld_put_device(fscb_od);
-               ret = -EINVAL;
-       }
+       if (likely(!ret)) {
+               unsigned numdevs = sbi->comps.numdevs;
 
+               if (unlikely(fscb_od)) {
+                       EXOFS_ERR("ERROR: Bad device-table container device not present\n");
+                       osduld_put_device(fscb_od);
+                       return -EINVAL;
+               }
+               /* exofs round-robins the device table view according to inode
+                * number. We hold a: twice bigger table hence inodes can point
+                * to any device and have a sequential view of the table
+                * starting at this device. See exofs_init_comps()
+                */
+               for (i = 0; i < numdevs - 1; ++i)
+                       sbi->comps.ods[i + numdevs] = sbi->comps.ods[i];
+       }
        return ret;
 }
 
@@ -676,7 +747,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
        struct exofs_sb_info *sbi;      /*extended info                  */
        struct osd_dev *od;             /* Master device                 */
        struct exofs_fscb fscb;         /*on-disk superblock info        */
-       struct osd_obj_id obj;
+       struct ore_comp comp;
        unsigned table_count;
        int ret;
 
@@ -684,10 +755,6 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
        if (!sbi)
                return -ENOMEM;
 
-       ret = bdi_setup_and_register(&sbi->bdi, "exofs", BDI_CAP_MAP_COPY);
-       if (ret)
-               goto free_bdi;
-
        /* use mount options to fill superblock */
        if (opts->is_osdname) {
                struct osd_dev_info odi = {.systemid_len = 0};
@@ -695,6 +762,8 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
                odi.osdname_len = strlen(opts->dev_name);
                odi.osdname = (u8 *)opts->dev_name;
                od = osduld_info_lookup(&odi);
+               kfree(opts->dev_name);
+               opts->dev_name = NULL;
        } else {
                od = osduld_path_lookup(opts->dev_name);
        }
@@ -709,11 +778,16 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
        sbi->layout.group_width = 1;
        sbi->layout.group_depth = -1;
        sbi->layout.group_count = 1;
-       sbi->layout.s_ods[0] = od;
-       sbi->layout.s_numdevs = 1;
-       sbi->layout.s_pid = opts->pid;
        sbi->s_timeout = opts->timeout;
 
+       sbi->one_comp.obj.partition = opts->pid;
+       sbi->one_comp.obj.id = 0;
+       exofs_make_credential(sbi->one_comp.cred, &sbi->one_comp.obj);
+       sbi->comps.numdevs = 1;
+       sbi->comps.single_comp = EC_SINGLE_COMP;
+       sbi->comps.comps = &sbi->one_comp;
+       sbi->comps.ods = sbi->_min_one_dev;
+
        /* fill in some other data by hand */
        memset(sb->s_id, 0, sizeof(sb->s_id));
        strcpy(sb->s_id, "exofs");
@@ -724,11 +798,11 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_bdev = NULL;
        sb->s_dev = 0;
 
-       obj.partition = sbi->layout.s_pid;
-       obj.id = EXOFS_SUPER_ID;
-       exofs_make_credential(sbi->s_cred, &obj);
+       comp.obj.partition = sbi->one_comp.obj.partition;
+       comp.obj.id = EXOFS_SUPER_ID;
+       exofs_make_credential(comp.cred, &comp.obj);
 
-       ret = exofs_read_kern(od, sbi->s_cred, &obj, 0, &fscb, sizeof(fscb));
+       ret = exofs_read_kern(od, comp.cred, &comp.obj, 0, &fscb, sizeof(fscb));
        if (unlikely(ret))
                goto free_sbi;
 
@@ -757,9 +831,11 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
 
        table_count = le64_to_cpu(fscb.s_dev_table_count);
        if (table_count) {
-               ret = exofs_read_lookup_dev_table(&sbi, table_count);
+               ret = exofs_read_lookup_dev_table(sbi, od, table_count);
                if (unlikely(ret))
                        goto free_sbi;
+       } else {
+               sbi->comps.ods[0] = od;
        }
 
        __sbi_read_stats(sbi);
@@ -793,20 +869,20 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
                goto free_sbi;
        }
 
-       _exofs_print_device("Mounting", opts->dev_name, sbi->layout.s_ods[0],
-                           sbi->layout.s_pid);
-       if (opts->is_osdname)
-               kfree(opts->dev_name);
+       ret = bdi_setup_and_register(&sbi->bdi, "exofs", BDI_CAP_MAP_COPY);
+       if (ret) {
+               EXOFS_DBGMSG("Failed to bdi_setup_and_register\n");
+               goto free_sbi;
+       }
+
+       _exofs_print_device("Mounting", opts->dev_name, sbi->comps.ods[0],
+                           sbi->one_comp.obj.partition);
        return 0;
 
 free_sbi:
-       bdi_destroy(&sbi->bdi);
-free_bdi:
        EXOFS_ERR("Unable to mount exofs on %s pid=0x%llx err=%d\n",
-                 opts->dev_name, sbi->layout.s_pid, ret);
+                 opts->dev_name, sbi->one_comp.obj.partition, ret);
        exofs_free_sbi(sbi);
-       if (opts->is_osdname)
-               kfree(opts->dev_name);
        return ret;
 }
 
@@ -837,7 +913,7 @@ static int exofs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct super_block *sb = dentry->d_sb;
        struct exofs_sb_info *sbi = sb->s_fs_info;
-       struct exofs_io_state *ios;
+       struct ore_io_state *ios;
        struct osd_attr attrs[] = {
                ATTR_DEF(OSD_APAGE_PARTITION_QUOTAS,
                        OSD_ATTR_PQ_CAPACITY_QUOTA, sizeof(__be64)),
@@ -846,21 +922,18 @@ static int exofs_statfs(struct dentry *dentry, struct kstatfs *buf)
        };
        uint64_t capacity = ULLONG_MAX;
        uint64_t used = ULLONG_MAX;
-       uint8_t cred_a[OSD_CAP_LEN];
        int ret;
 
-       ret = exofs_get_io_state(&sbi->layout, &ios);
+       ret = ore_get_io_state(&sbi->layout, &sbi->comps, &ios);
        if (ret) {
-               EXOFS_DBGMSG("exofs_get_io_state failed.\n");
+               EXOFS_DBGMSG("ore_get_io_state failed.\n");
                return ret;
        }
 
-       exofs_make_credential(cred_a, &ios->obj);
-       ios->cred = sbi->s_cred;
        ios->in_attr = attrs;
        ios->in_attr_len = ARRAY_SIZE(attrs);
 
-       ret = exofs_sbi_read(ios);
+       ret = ore_read(ios);
        if (unlikely(ret))
                goto out;
 
@@ -889,7 +962,7 @@ static int exofs_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_namelen = EXOFS_NAME_LEN;
 
 out:
-       exofs_put_io_state(ios);
+       ore_put_io_state(ios);
        return ret;
 }
 
index 5aab80dc008cf681e64f47a32759055bc013b13f..73920d555c8890b2bd0fd208ef2b469af142e358 100644 (file)
@@ -143,6 +143,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
        inode->i_op = &empty_iops;
        inode->i_fop = &empty_fops;
        inode->i_nlink = 1;
+       inode->i_opflags = 0;
        inode->i_uid = 0;
        inode->i_gid = 0;
        atomic_set(&inode->i_writecount, 0);
index 3d607bd80e09f683fac132d6387f152c1df11f4c..2826db35dc257bb15241376e3b6611582b2e4c92 100644 (file)
@@ -186,7 +186,7 @@ static int check_acl(struct inode *inode, int mask)
                /* no ->get_acl() calls in RCU mode... */
                if (acl == ACL_NOT_CACHED)
                        return -ECHILD;
-               return posix_acl_permission(inode, acl, mask);
+               return posix_acl_permission(inode, acl, mask & ~MAY_NOT_BLOCK);
        }
 
        acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
@@ -308,6 +308,26 @@ int generic_permission(struct inode *inode, int mask)
        return -EACCES;
 }
 
+/*
+ * We _really_ want to just do "generic_permission()" without
+ * even looking at the inode->i_op values. So we keep a cache
+ * flag in inode->i_opflags, that says "this has not special
+ * permission function, use the fast case".
+ */
+static inline int do_inode_permission(struct inode *inode, int mask)
+{
+       if (unlikely(!(inode->i_opflags & IOP_FASTPERM))) {
+               if (likely(inode->i_op->permission))
+                       return inode->i_op->permission(inode, mask);
+
+               /* This gets set once for the inode lifetime */
+               spin_lock(&inode->i_lock);
+               inode->i_opflags |= IOP_FASTPERM;
+               spin_unlock(&inode->i_lock);
+       }
+       return generic_permission(inode, mask);
+}
+
 /**
  * inode_permission  -  check for access rights to a given inode
  * @inode:     inode to check permission on
@@ -322,7 +342,7 @@ int inode_permission(struct inode *inode, int mask)
 {
        int retval;
 
-       if (mask & MAY_WRITE) {
+       if (unlikely(mask & MAY_WRITE)) {
                umode_t mode = inode->i_mode;
 
                /*
@@ -339,11 +359,7 @@ int inode_permission(struct inode *inode, int mask)
                        return -EACCES;
        }
 
-       if (inode->i_op->permission)
-               retval = inode->i_op->permission(inode, mask);
-       else
-               retval = generic_permission(inode, mask);
-
+       retval = do_inode_permission(inode, mask);
        if (retval)
                return retval;
 
@@ -1245,6 +1261,26 @@ static void terminate_walk(struct nameidata *nd)
        }
 }
 
+/*
+ * Do we need to follow links? We _really_ want to be able
+ * to do this check without having to look at inode->i_op,
+ * so we keep a cache of "no, this doesn't need follow_link"
+ * for the common case.
+ */
+static inline int should_follow_link(struct inode *inode, int follow)
+{
+       if (unlikely(!(inode->i_opflags & IOP_NOFOLLOW))) {
+               if (likely(inode->i_op->follow_link))
+                       return follow;
+
+               /* This gets set once for the inode lifetime */
+               spin_lock(&inode->i_lock);
+               inode->i_opflags |= IOP_NOFOLLOW;
+               spin_unlock(&inode->i_lock);
+       }
+       return 0;
+}
+
 static inline int walk_component(struct nameidata *nd, struct path *path,
                struct qstr *name, int type, int follow)
 {
@@ -1267,7 +1303,7 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
                terminate_walk(nd);
                return -ENOENT;
        }
-       if (unlikely(inode->i_op->follow_link) && follow) {
+       if (should_follow_link(inode, follow)) {
                if (nd->flags & LOOKUP_RCU) {
                        if (unlikely(unlazy_walk(nd, path->dentry))) {
                                terminate_walk(nd);
@@ -1319,6 +1355,26 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd)
        return res;
 }
 
+/*
+ * We really don't want to look at inode->i_op->lookup
+ * when we don't have to. So we keep a cache bit in
+ * the inode ->i_opflags field that says "yes, we can
+ * do lookup on this inode".
+ */
+static inline int can_lookup(struct inode *inode)
+{
+       if (likely(inode->i_opflags & IOP_LOOKUP))
+               return 1;
+       if (likely(!inode->i_op->lookup))
+               return 0;
+
+       /* We do this once for the lifetime of the inode */
+       spin_lock(&inode->i_lock);
+       inode->i_opflags |= IOP_LOOKUP;
+       spin_unlock(&inode->i_lock);
+       return 1;
+}
+
 /*
  * Name resolution.
  * This is the basic name resolution function, turning a pathname into
@@ -1398,10 +1454,10 @@ static int link_path_walk(const char *name, struct nameidata *nd)
                        if (err)
                                return err;
                }
+               if (can_lookup(nd->inode))
+                       continue;
                err = -ENOTDIR; 
-               if (!nd->inode->i_op->lookup)
-                       break;
-               continue;
+               break;
                /* here ends the main loop */
 
 last_component:
index 08e3eccf9a12071ae2007a076729851f5c431dbd..5eb02069e1b817730050b7b46304a9244c064bde 100644 (file)
@@ -1118,7 +1118,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
         * Warn that /proc/pid/oom_adj is deprecated, see
         * Documentation/feature-removal-schedule.txt.
         */
-       WARN_ONCE(1, "%s (%d): /proc/%d/oom_adj is deprecated, please use /proc/%d/oom_score_adj instead.\n",
+       printk_once(KERN_WARNING "%s (%d): /proc/%d/oom_adj is deprecated, please use /proc/%d/oom_score_adj instead.\n",
                  current->comm, task_pid_nr(current), task_pid_nr(task),
                  task_pid_nr(task));
        task->signal->oom_adj = oom_adjust;
@@ -1919,6 +1919,14 @@ static int proc_fd_info(struct inode *inode, struct path *path, char *info)
                spin_lock(&files->file_lock);
                file = fcheck_files(files, fd);
                if (file) {
+                       unsigned int f_flags;
+                       struct fdtable *fdt;
+
+                       fdt = files_fdtable(files);
+                       f_flags = file->f_flags & ~O_CLOEXEC;
+                       if (FD_ISSET(fd, fdt->close_on_exec))
+                               f_flags |= O_CLOEXEC;
+
                        if (path) {
                                *path = file->f_path;
                                path_get(&file->f_path);
@@ -1928,7 +1936,7 @@ static int proc_fd_info(struct inode *inode, struct path *path, char *info)
                                         "pos:\t%lli\n"
                                         "flags:\t0%o\n",
                                         (long long) file->f_pos,
-                                        file->f_flags);
+                                        f_flags);
                        spin_unlock(&files->file_lock);
                        put_files_struct(files);
                        return 0;
index 961039121cb8cbde185bf1b8399c6e4ccc71cdf5..ba5316ffac617679a4beae086c1048886d4ae209 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -27,12 +27,12 @@ void generic_fillattr(struct inode *inode, struct kstat *stat)
        stat->uid = inode->i_uid;
        stat->gid = inode->i_gid;
        stat->rdev = inode->i_rdev;
+       stat->size = i_size_read(inode);
        stat->atime = inode->i_atime;
        stat->mtime = inode->i_mtime;
        stat->ctime = inode->i_ctime;
-       stat->size = i_size_read(inode);
-       stat->blocks = inode->i_blocks;
        stat->blksize = (1 << inode->i_blkbits);
+       stat->blocks = inode->i_blocks;
 }
 
 EXPORT_SYMBOL(generic_fillattr);
index 48e82af1159b60065fd3081e46c236495c2f4ff2..98f46efbe2d21a422802d7fd7bbee06d0b993116 100644 (file)
@@ -265,10 +265,11 @@ static inline void put_cred(const struct cred *_cred)
 /**
  * current_cred - Access the current task's subjective credentials
  *
- * Access the subjective credentials of the current task.
+ * Access the subjective credentials of the current task.  RCU-safe,
+ * since nobody else can modify it.
  */
 #define current_cred() \
-       (current->cred)
+       (*(__force struct cred **)&current->cred)
 
 /**
  * __task_cred - Access a task's objective credentials
@@ -307,7 +308,7 @@ static inline void put_cred(const struct cred *_cred)
 ({                                                     \
        struct user_struct *__u;                        \
        struct cred *__cred;                            \
-       __cred = (struct cred *) current_cred();        \
+       __cred = current_cred();                        \
        __u = get_uid(__cred->user);                    \
        __u;                                            \
 })
@@ -322,7 +323,7 @@ static inline void put_cred(const struct cred *_cred)
 ({                                                     \
        struct group_info *__groups;                    \
        struct cred *__cred;                            \
-       __cred = (struct cred *) current_cred();        \
+       __cred = current_cred();                        \
        __groups = get_group_info(__cred->group_info);  \
        __groups;                                       \
 })
@@ -341,7 +342,7 @@ static inline void put_cred(const struct cred *_cred)
 
 #define current_cred_xxx(xxx)                  \
 ({                                             \
-       current->cred->xxx;                     \
+       current_cred()->xxx;                    \
 })
 
 #define current_uid()          (current_cred_xxx(uid))
index ec78a4bbe1d5b6ebbb2f4e1ab10406d700c7efe5..2cd9f1cf9fa366cff97c8f3c59297b2ea72594b1 100644 (file)
@@ -3,11 +3,16 @@
 
 #define SHA_DIGEST_WORDS 5
 #define SHA_MESSAGE_BYTES (512 /*bits*/ / 8)
-#define SHA_WORKSPACE_WORDS 80
+#define SHA_WORKSPACE_WORDS 16
 
 void sha_init(__u32 *buf);
 void sha_transform(__u32 *digest, const char *data, __u32 *W);
 
+#define MD5_DIGEST_WORDS 4
+#define MD5_MESSAGE_BYTES 64
+
+void md5_transform(__u32 *hash, __u32 const *in);
+
 __u32 half_md4_transform(__u32 buf[4], __u32 const in[8]);
 
 #endif
index d37d2a79309985c2cd7c0d119d52dd0a51cecde8..62157c03caf76698367dc5341a6b56c73119375e 100644 (file)
@@ -180,12 +180,12 @@ struct dentry_operations {
  */
 
 /* d_flags entries */
-#define DCACHE_AUTOFS_PENDING 0x0001    /* autofs: "under construction" */
-#define DCACHE_NFSFS_RENAMED  0x0002
-     /* this dentry has been "silly renamed" and has to be deleted on the last
-      * dput() */
+#define DCACHE_OP_HASH         0x0001
+#define DCACHE_OP_COMPARE      0x0002
+#define DCACHE_OP_REVALIDATE   0x0004
+#define DCACHE_OP_DELETE       0x0008
 
-#define        DCACHE_DISCONNECTED     0x0004
+#define        DCACHE_DISCONNECTED     0x0010
      /* This dentry is possibly not currently connected to the dcache tree, in
       * which case its parent will either be itself, or will have this flag as
       * well.  nfsd will not use a dentry with this bit set, but will first
@@ -196,22 +196,18 @@ struct dentry_operations {
       * dentry into place and return that dentry rather than the passed one,
       * typically using d_splice_alias. */
 
-#define DCACHE_REFERENCED      0x0008  /* Recently used, don't discard. */
-#define DCACHE_RCUACCESS       0x0010  /* Entry has ever been RCU-visible */
-#define DCACHE_INOTIFY_PARENT_WATCHED 0x0020
-     /* Parent inode is watched by inotify */
-
-#define DCACHE_COOKIE          0x0040  /* For use by dcookie subsystem */
-#define DCACHE_FSNOTIFY_PARENT_WATCHED 0x0080
-     /* Parent inode is watched by some fsnotify listener */
+#define DCACHE_REFERENCED      0x0020  /* Recently used, don't discard. */
+#define DCACHE_RCUACCESS       0x0040  /* Entry has ever been RCU-visible */
 
 #define DCACHE_CANT_MOUNT      0x0100
 #define DCACHE_GENOCIDE                0x0200
 
-#define DCACHE_OP_HASH         0x1000
-#define DCACHE_OP_COMPARE      0x2000
-#define DCACHE_OP_REVALIDATE   0x4000
-#define DCACHE_OP_DELETE       0x8000
+#define DCACHE_NFSFS_RENAMED   0x1000
+     /* this dentry has been "silly renamed" and has to be deleted on the last
+      * dput() */
+#define DCACHE_COOKIE          0x2000  /* For use by dcookie subsystem */
+#define DCACHE_FSNOTIFY_PARENT_WATCHED 0x4000
+     /* Parent inode is watched by some fsnotify listener */
 
 #define DCACHE_MOUNTED         0x10000 /* is a mountpoint */
 #define DCACHE_NEED_AUTOMOUNT  0x20000 /* handle automount on this dir */
index 786b3b1113cfb1acd5bf59848d04fe2e460e2de0..178cdb4f1d4afe81a66e631872de4b587e95d1c4 100644 (file)
@@ -738,22 +738,54 @@ static inline int mapping_writably_mapped(struct address_space *mapping)
 struct posix_acl;
 #define ACL_NOT_CACHED ((void *)(-1))
 
+#define IOP_FASTPERM   0x0001
+#define IOP_LOOKUP     0x0002
+#define IOP_NOFOLLOW   0x0004
+
+/*
+ * Keep mostly read-only and often accessed (especially for
+ * the RCU path lookup and 'stat' data) fields at the beginning
+ * of the 'struct inode'
+ */
 struct inode {
-       /* RCU path lookup touches following: */
        umode_t                 i_mode;
+       unsigned short          i_opflags;
        uid_t                   i_uid;
        gid_t                   i_gid;
+       unsigned int            i_flags;
+
+#ifdef CONFIG_FS_POSIX_ACL
+       struct posix_acl        *i_acl;
+       struct posix_acl        *i_default_acl;
+#endif
+
        const struct inode_operations   *i_op;
        struct super_block      *i_sb;
+       struct address_space    *i_mapping;
 
-       spinlock_t              i_lock; /* i_blocks, i_bytes, maybe i_size */
-       unsigned int            i_flags;
-       unsigned long           i_state;
 #ifdef CONFIG_SECURITY
        void                    *i_security;
 #endif
-       struct mutex            i_mutex;
 
+       /* Stat data, not accessed from path walking */
+       unsigned long           i_ino;
+       unsigned int            i_nlink;
+       dev_t                   i_rdev;
+       loff_t                  i_size;
+       struct timespec         i_atime;
+       struct timespec         i_mtime;
+       struct timespec         i_ctime;
+       unsigned int            i_blkbits;
+       blkcnt_t                i_blocks;
+
+#ifdef __NEED_I_SIZE_ORDERED
+       seqcount_t              i_size_seqcount;
+#endif
+
+       /* Misc */
+       unsigned long           i_state;
+       spinlock_t              i_lock; /* i_blocks, i_bytes, maybe i_size */
+       struct mutex            i_mutex;
 
        unsigned long           dirtied_when;   /* jiffies of first dirtying */
 
@@ -765,25 +797,12 @@ struct inode {
                struct list_head        i_dentry;
                struct rcu_head         i_rcu;
        };
-       unsigned long           i_ino;
        atomic_t                i_count;
-       unsigned int            i_nlink;
-       dev_t                   i_rdev;
-       unsigned int            i_blkbits;
        u64                     i_version;
-       loff_t                  i_size;
-#ifdef __NEED_I_SIZE_ORDERED
-       seqcount_t              i_size_seqcount;
-#endif
-       struct timespec         i_atime;
-       struct timespec         i_mtime;
-       struct timespec         i_ctime;
-       blkcnt_t                i_blocks;
        unsigned short          i_bytes;
        atomic_t                i_dio_count;
        const struct file_operations    *i_fop; /* former ->i_op->default_file_ops */
        struct file_lock        *i_flock;
-       struct address_space    *i_mapping;
        struct address_space    i_data;
 #ifdef CONFIG_QUOTA
        struct dquot            *i_dquot[MAXQUOTAS];
@@ -806,10 +825,6 @@ struct inode {
        atomic_t                i_readcount; /* struct files open RO */
 #endif
        atomic_t                i_writecount;
-#ifdef CONFIG_FS_POSIX_ACL
-       struct posix_acl        *i_acl;
-       struct posix_acl        *i_default_acl;
-#endif
        void                    *i_private; /* fs or device private pointer */
 };
 
index 068784e17972a1ffd907f4365bd5f774e70bcfdf..a637e781433499c8283f2991989ff35a35b7e66c 100644 (file)
@@ -438,6 +438,8 @@ struct input_keymap_entry {
 #define KEY_WIMAX              246
 #define KEY_RFKILL             247     /* Key that controls all radios */
 
+#define KEY_MICMUTE            248     /* Mute / unmute the microphone */
+
 /* Code 255 is reserved for special needs of AT keyboard driver */
 
 #define BTN_MISC               0x100
index 569ea5b76fda77f7b436eff5b873333dd3029121..abd615d74a2935bc2a1417712f7c45aa88ff1fdf 100644 (file)
@@ -773,6 +773,11 @@ struct nfs3_getaclres {
        struct posix_acl *      acl_default;
 };
 
+struct nfs4_string {
+       unsigned int len;
+       char *data;
+};
+
 #ifdef CONFIG_NFS_V4
 
 typedef u64 clientid4;
@@ -963,11 +968,6 @@ struct nfs4_server_caps_res {
        struct nfs4_sequence_res        seq_res;
 };
 
-struct nfs4_string {
-       unsigned int len;
-       char *data;
-};
-
 #define NFS4_PATHNAME_MAXCOMPONENTS 512
 struct nfs4_pathname {
        unsigned int ncomponents;
index ce29a040c8dce1fa5a0d2f17ff2ce529f77887c7..d13059f3ea32e5ab08859c08d71ac04a4d31817d 100644 (file)
@@ -57,18 +57,6 @@ extern void add_interrupt_randomness(int irq);
 extern void get_random_bytes(void *buf, int nbytes);
 void generate_random_uuid(unsigned char uuid_out[16]);
 
-extern __u32 secure_ip_id(__be32 daddr);
-extern __u32 secure_ipv6_id(const __be32 daddr[4]);
-extern u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
-extern u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
-                                     __be16 dport);
-extern __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
-                                       __be16 sport, __be16 dport);
-extern __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
-                                         __be16 sport, __be16 dport);
-extern u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
-                                      __be16 sport, __be16 dport);
-
 #ifndef MODULE
 extern const struct file_operations random_fops, urandom_fops;
 #endif
diff --git a/include/net/secure_seq.h b/include/net/secure_seq.h
new file mode 100644 (file)
index 0000000..d97f689
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _NET_SECURE_SEQ
+#define _NET_SECURE_SEQ
+
+#include <linux/types.h>
+
+extern __u32 secure_ip_id(__be32 daddr);
+extern __u32 secure_ipv6_id(const __be32 daddr[4]);
+extern u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
+extern u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
+                                     __be16 dport);
+extern __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
+                                       __be16 sport, __be16 dport);
+extern __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
+                                         __be16 sport, __be16 dport);
+extern u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
+                                      __be16 sport, __be16 dport);
+extern u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
+                                        __be16 sport, __be16 dport);
+
+#endif /* _NET_SECURE_SEQ */
diff --git a/include/scsi/osd_ore.h b/include/scsi/osd_ore.h
new file mode 100644 (file)
index 0000000..c5c5e00
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2011
+ * Boaz Harrosh <bharrosh@panasas.com>
+ *
+ * Public Declarations of the ORE API
+ *
+ * This file is part of the ORE (Object Raid Engine) library.
+ *
+ * ORE is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation. (GPL v2)
+ *
+ * ORE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the ORE; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef __ORE_H__
+#define __ORE_H__
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_attributes.h>
+#include <scsi/osd_sec.h>
+#include <linux/pnfs_osd_xdr.h>
+
+struct ore_comp {
+       struct osd_obj_id       obj;
+       u8                      cred[OSD_CAP_LEN];
+};
+
+struct ore_layout {
+       /* Our way of looking at the data_map */
+       unsigned stripe_unit;
+       unsigned mirrors_p1;
+
+       unsigned group_width;
+       u64      group_depth;
+       unsigned group_count;
+};
+
+struct ore_components {
+       unsigned        numdevs;                /* Num of devices in array    */
+       /* If @single_comp == EC_SINGLE_COMP, @comps points to a single
+        * component. else there are @numdevs components
+        */
+       enum EC_COMP_USAGE {
+               EC_SINGLE_COMP = 0, EC_MULTPLE_COMPS = 0xffffffff
+       }               single_comp;
+       struct ore_comp *comps;
+       struct osd_dev  **ods;                  /* osd_dev array              */
+};
+
+struct ore_io_state;
+typedef void (*ore_io_done_fn)(struct ore_io_state *ios, void *private);
+
+struct ore_io_state {
+       struct kref             kref;
+
+       void                    *private;
+       ore_io_done_fn  done;
+
+       struct ore_layout       *layout;
+       struct ore_components   *comps;
+
+       /* Global read/write IO*/
+       loff_t                  offset;
+       unsigned long           length;
+       void                    *kern_buff;
+
+       struct page             **pages;
+       unsigned                nr_pages;
+       unsigned                pgbase;
+       unsigned                pages_consumed;
+
+       /* Attributes */
+       unsigned                in_attr_len;
+       struct osd_attr         *in_attr;
+       unsigned                out_attr_len;
+       struct osd_attr         *out_attr;
+
+       bool                    reading;
+
+       /* Variable array of size numdevs */
+       unsigned numdevs;
+       struct ore_per_dev_state {
+               struct osd_request *or;
+               struct bio *bio;
+               loff_t offset;
+               unsigned length;
+               unsigned dev;
+       } per_dev[];
+};
+
+static inline unsigned ore_io_state_size(unsigned numdevs)
+{
+       return sizeof(struct ore_io_state) +
+               sizeof(struct ore_per_dev_state) * numdevs;
+}
+
+/* ore.c */
+int ore_get_rw_state(struct ore_layout *layout, struct ore_components *comps,
+                    bool is_reading, u64 offset, u64 length,
+                    struct ore_io_state **ios);
+int ore_get_io_state(struct ore_layout *layout, struct ore_components *comps,
+                    struct ore_io_state **ios);
+void ore_put_io_state(struct ore_io_state *ios);
+
+int ore_check_io(struct ore_io_state *ios, u64 *resid);
+
+int ore_create(struct ore_io_state *ios);
+int ore_remove(struct ore_io_state *ios);
+int ore_write(struct ore_io_state *ios);
+int ore_read(struct ore_io_state *ios);
+int ore_truncate(struct ore_layout *layout, struct ore_components *comps,
+                u64 size);
+
+int extract_attr_from_ios(struct ore_io_state *ios, struct osd_attr *attr);
+
+extern const struct osd_attr g_attr_logical_length;
+
+#endif
index 6457af4a7caf632d9bd26c70ac4b5744199e5079..d5d175c8a6ca3242b91e9d804e2b3f35209caea8 100644 (file)
@@ -10,7 +10,7 @@ endif
 lib-y := ctype.o string.o vsprintf.o cmdline.o \
         rbtree.o radix-tree.o dump_stack.o timerqueue.o\
         idr.o int_sqrt.o extable.o prio_tree.o \
-        sha1.o irq_regs.o reciprocal_div.o argv_split.o \
+        sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \
         proportions.o prio_heap.o ratelimit.o show_mem.o \
         is_single_threaded.o plist.o decompress.o find_next_bit.o
 
diff --git a/lib/md5.c b/lib/md5.c
new file mode 100644 (file)
index 0000000..c777180
--- /dev/null
+++ b/lib/md5.c
@@ -0,0 +1,95 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/cryptohash.h>
+
+#define F1(x, y, z)    (z ^ (x & (y ^ z)))
+#define F2(x, y, z)    F1(z, x, y)
+#define F3(x, y, z)    (x ^ y ^ z)
+#define F4(x, y, z)    (y ^ (x | ~z))
+
+#define MD5STEP(f, w, x, y, z, in, s) \
+       (w += f(x, y, z) + in, w = (w<<s | w>>(32-s)) + x)
+
+void md5_transform(__u32 *hash, __u32 const *in)
+{
+       u32 a, b, c, d;
+
+       a = hash[0];
+       b = hash[1];
+       c = hash[2];
+       d = hash[3];
+
+       MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+       MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+       MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+       MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+       MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+       MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+       MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+       MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+       MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+       MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+       MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+       MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+       MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+       MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+       MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+       MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+       MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+       MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+       MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+       MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+       MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+       MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+       MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+       MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+       MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+       MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+       MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+       MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+       MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+       MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+       MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+       MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+       MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+       MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+       MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+       MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+       MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+       MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+       MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+       MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+       MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+       MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+       MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+       MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+       MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+       MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+       MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+       MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+       MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+       MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+       MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+       MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+       MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+       MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+       MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+       MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+       MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+       MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+       MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+       MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+       MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+       MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+       MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+       MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+       hash[0] += a;
+       hash[1] += b;
+       hash[2] += c;
+       hash[3] += d;
+}
+EXPORT_SYMBOL(md5_transform);
index 4c45fd50e91367041d825a1146291a829b900eff..f33271dd00cbc7ee39637a1edff2975358daf567 100644 (file)
@@ -1,31 +1,72 @@
 /*
- * SHA transform algorithm, originally taken from code written by
- * Peter Gutmann, and placed in the public domain.
+ * SHA1 routine optimized to do word accesses rather than byte accesses,
+ * and to avoid unnecessary copies into the context array.
+ *
+ * This was based on the git SHA1 implementation.
  */
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/cryptohash.h>
+#include <linux/bitops.h>
+#include <asm/unaligned.h>
 
-/* The SHA f()-functions.  */
+/*
+ * If you have 32 registers or more, the compiler can (and should)
+ * try to change the array[] accesses into registers. However, on
+ * machines with less than ~25 registers, that won't really work,
+ * and at least gcc will make an unholy mess of it.
+ *
+ * So to avoid that mess which just slows things down, we force
+ * the stores to memory to actually happen (we might be better off
+ * with a 'W(t)=(val);asm("":"+m" (W(t))' there instead, as
+ * suggested by Artur Skawina - that will also make gcc unable to
+ * try to do the silly "optimize away loads" part because it won't
+ * see what the value will be).
+ *
+ * Ben Herrenschmidt reports that on PPC, the C version comes close
+ * to the optimized asm with this (ie on PPC you don't want that
+ * 'volatile', since there are lots of registers).
+ *
+ * On ARM we get the best code generation by forcing a full memory barrier
+ * between each SHA_ROUND, otherwise gcc happily get wild with spilling and
+ * the stack frame size simply explode and performance goes down the drain.
+ */
 
-#define f1(x,y,z)   (z ^ (x & (y ^ z)))                /* x ? y : z */
-#define f2(x,y,z)   (x ^ y ^ z)                        /* XOR */
-#define f3(x,y,z)   ((x & y) + (z & (x ^ y)))  /* majority */
+#ifdef CONFIG_X86
+  #define setW(x, val) (*(volatile __u32 *)&W(x) = (val))
+#elif defined(CONFIG_ARM)
+  #define setW(x, val) do { W(x) = (val); __asm__("":::"memory"); } while (0)
+#else
+  #define setW(x, val) (W(x) = (val))
+#endif
 
-/* The SHA Mysterious Constants */
+/* This "rolls" over the 512-bit array */
+#define W(x) (array[(x)&15])
 
-#define K1  0x5A827999L                        /* Rounds  0-19: sqrt(2) * 2^30 */
-#define K2  0x6ED9EBA1L                        /* Rounds 20-39: sqrt(3) * 2^30 */
-#define K3  0x8F1BBCDCL                        /* Rounds 40-59: sqrt(5) * 2^30 */
-#define K4  0xCA62C1D6L                        /* Rounds 60-79: sqrt(10) * 2^30 */
+/*
+ * Where do we get the source from? The first 16 iterations get it from
+ * the input data, the next mix it from the 512-bit array.
+ */
+#define SHA_SRC(t) get_unaligned_be32((__u32 *)data + t)
+#define SHA_MIX(t) rol32(W(t+13) ^ W(t+8) ^ W(t+2) ^ W(t), 1)
+
+#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \
+       __u32 TEMP = input(t); setW(t, TEMP); \
+       E += TEMP + rol32(A,5) + (fn) + (constant); \
+       B = ror32(B, 2); } while (0)
+
+#define T_0_15(t, A, B, C, D, E)  SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
+#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
+#define T_20_39(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0x6ed9eba1, A, B, C, D, E )
+#define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E )
+#define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) ,  0xca62c1d6, A, B, C, D, E )
 
 /**
  * sha_transform - single block SHA1 transform
  *
  * @digest: 160 bit digest to update
  * @data:   512 bits of data to hash
- * @W:      80 words of workspace (see note)
+ * @array:  16 words of workspace (see note)
  *
  * This function generates a SHA1 digest for a single 512-bit block.
  * Be warned, it does not handle padding and message digest, do not
  * to clear the workspace. This is left to the caller to avoid
  * unnecessary clears between chained hashing operations.
  */
-void sha_transform(__u32 *digest, const char *in, __u32 *W)
+void sha_transform(__u32 *digest, const char *data, __u32 *array)
 {
-       __u32 a, b, c, d, e, t, i;
-
-       for (i = 0; i < 16; i++)
-               W[i] = be32_to_cpu(((const __be32 *)in)[i]);
-
-       for (i = 0; i < 64; i++)
-               W[i+16] = rol32(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i], 1);
-
-       a = digest[0];
-       b = digest[1];
-       c = digest[2];
-       d = digest[3];
-       e = digest[4];
-
-       for (i = 0; i < 20; i++) {
-               t = f1(b, c, d) + K1 + rol32(a, 5) + e + W[i];
-               e = d; d = c; c = rol32(b, 30); b = a; a = t;
-       }
-
-       for (; i < 40; i ++) {
-               t = f2(b, c, d) + K2 + rol32(a, 5) + e + W[i];
-               e = d; d = c; c = rol32(b, 30); b = a; a = t;
-       }
-
-       for (; i < 60; i ++) {
-               t = f3(b, c, d) + K3 + rol32(a, 5) + e + W[i];
-               e = d; d = c; c = rol32(b, 30); b = a; a = t;
-       }
-
-       for (; i < 80; i ++) {
-               t = f2(b, c, d) + K4 + rol32(a, 5) + e + W[i];
-               e = d; d = c; c = rol32(b, 30); b = a; a = t;
-       }
-
-       digest[0] += a;
-       digest[1] += b;
-       digest[2] += c;
-       digest[3] += d;
-       digest[4] += e;
+       __u32 A, B, C, D, E;
+
+       A = digest[0];
+       B = digest[1];
+       C = digest[2];
+       D = digest[3];
+       E = digest[4];
+
+       /* Round 1 - iterations 0-16 take their input from 'data' */
+       T_0_15( 0, A, B, C, D, E);
+       T_0_15( 1, E, A, B, C, D);
+       T_0_15( 2, D, E, A, B, C);
+       T_0_15( 3, C, D, E, A, B);
+       T_0_15( 4, B, C, D, E, A);
+       T_0_15( 5, A, B, C, D, E);
+       T_0_15( 6, E, A, B, C, D);
+       T_0_15( 7, D, E, A, B, C);
+       T_0_15( 8, C, D, E, A, B);
+       T_0_15( 9, B, C, D, E, A);
+       T_0_15(10, A, B, C, D, E);
+       T_0_15(11, E, A, B, C, D);
+       T_0_15(12, D, E, A, B, C);
+       T_0_15(13, C, D, E, A, B);
+       T_0_15(14, B, C, D, E, A);
+       T_0_15(15, A, B, C, D, E);
+
+       /* Round 1 - tail. Input from 512-bit mixing array */
+       T_16_19(16, E, A, B, C, D);
+       T_16_19(17, D, E, A, B, C);
+       T_16_19(18, C, D, E, A, B);
+       T_16_19(19, B, C, D, E, A);
+
+       /* Round 2 */
+       T_20_39(20, A, B, C, D, E);
+       T_20_39(21, E, A, B, C, D);
+       T_20_39(22, D, E, A, B, C);
+       T_20_39(23, C, D, E, A, B);
+       T_20_39(24, B, C, D, E, A);
+       T_20_39(25, A, B, C, D, E);
+       T_20_39(26, E, A, B, C, D);
+       T_20_39(27, D, E, A, B, C);
+       T_20_39(28, C, D, E, A, B);
+       T_20_39(29, B, C, D, E, A);
+       T_20_39(30, A, B, C, D, E);
+       T_20_39(31, E, A, B, C, D);
+       T_20_39(32, D, E, A, B, C);
+       T_20_39(33, C, D, E, A, B);
+       T_20_39(34, B, C, D, E, A);
+       T_20_39(35, A, B, C, D, E);
+       T_20_39(36, E, A, B, C, D);
+       T_20_39(37, D, E, A, B, C);
+       T_20_39(38, C, D, E, A, B);
+       T_20_39(39, B, C, D, E, A);
+
+       /* Round 3 */
+       T_40_59(40, A, B, C, D, E);
+       T_40_59(41, E, A, B, C, D);
+       T_40_59(42, D, E, A, B, C);
+       T_40_59(43, C, D, E, A, B);
+       T_40_59(44, B, C, D, E, A);
+       T_40_59(45, A, B, C, D, E);
+       T_40_59(46, E, A, B, C, D);
+       T_40_59(47, D, E, A, B, C);
+       T_40_59(48, C, D, E, A, B);
+       T_40_59(49, B, C, D, E, A);
+       T_40_59(50, A, B, C, D, E);
+       T_40_59(51, E, A, B, C, D);
+       T_40_59(52, D, E, A, B, C);
+       T_40_59(53, C, D, E, A, B);
+       T_40_59(54, B, C, D, E, A);
+       T_40_59(55, A, B, C, D, E);
+       T_40_59(56, E, A, B, C, D);
+       T_40_59(57, D, E, A, B, C);
+       T_40_59(58, C, D, E, A, B);
+       T_40_59(59, B, C, D, E, A);
+
+       /* Round 4 */
+       T_60_79(60, A, B, C, D, E);
+       T_60_79(61, E, A, B, C, D);
+       T_60_79(62, D, E, A, B, C);
+       T_60_79(63, C, D, E, A, B);
+       T_60_79(64, B, C, D, E, A);
+       T_60_79(65, A, B, C, D, E);
+       T_60_79(66, E, A, B, C, D);
+       T_60_79(67, D, E, A, B, C);
+       T_60_79(68, C, D, E, A, B);
+       T_60_79(69, B, C, D, E, A);
+       T_60_79(70, A, B, C, D, E);
+       T_60_79(71, E, A, B, C, D);
+       T_60_79(72, D, E, A, B, C);
+       T_60_79(73, C, D, E, A, B);
+       T_60_79(74, B, C, D, E, A);
+       T_60_79(75, A, B, C, D, E);
+       T_60_79(76, E, A, B, C, D);
+       T_60_79(77, D, E, A, B, C);
+       T_60_79(78, C, D, E, A, B);
+       T_60_79(79, B, C, D, E, A);
+
+       digest[0] += A;
+       digest[1] += B;
+       digest[2] += C;
+       digest[3] += D;
+       digest[4] += E;
 }
 EXPORT_SYMBOL(sha_transform);
 
@@ -92,4 +197,3 @@ void sha_init(__u32 *buf)
        buf[3] = 0x10325476;
        buf[4] = 0xc3d2e1f0;
 }
-
index 8a04dd22cf77c706c8613edd9d0c64bf57fa3613..0d357b1c4e57db42d6a1938c0a7a870455fa7b1b 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \
-        gen_stats.o gen_estimator.o net_namespace.o
+        gen_stats.o gen_estimator.o net_namespace.o secure_seq.o
 
 obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
 
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c
new file mode 100644 (file)
index 0000000..45329d7
--- /dev/null
@@ -0,0 +1,184 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/cryptohash.h>
+#include <linux/module.h>
+#include <linux/cache.h>
+#include <linux/random.h>
+#include <linux/hrtimer.h>
+#include <linux/ktime.h>
+#include <linux/string.h>
+
+#include <net/secure_seq.h>
+
+static u32 net_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned;
+
+static int __init net_secret_init(void)
+{
+       get_random_bytes(net_secret, sizeof(net_secret));
+       return 0;
+}
+late_initcall(net_secret_init);
+
+static u32 seq_scale(u32 seq)
+{
+       /*
+        *      As close as possible to RFC 793, which
+        *      suggests using a 250 kHz clock.
+        *      Further reading shows this assumes 2 Mb/s networks.
+        *      For 10 Mb/s Ethernet, a 1 MHz clock is appropriate.
+        *      For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but
+        *      we also need to limit the resolution so that the u32 seq
+        *      overlaps less than one time per MSL (2 minutes).
+        *      Choosing a clock of 64 ns period is OK. (period of 274 s)
+        */
+       return seq + (ktime_to_ns(ktime_get_real()) >> 6);
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+__u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
+                                  __be16 sport, __be16 dport)
+{
+       u32 secret[MD5_MESSAGE_BYTES / 4];
+       u32 hash[MD5_DIGEST_WORDS];
+       u32 i;
+
+       memcpy(hash, saddr, 16);
+       for (i = 0; i < 4; i++)
+               secret[i] = net_secret[i] + daddr[i];
+       secret[4] = net_secret[4] +
+               (((__force u16)sport << 16) + (__force u16)dport);
+       for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
+               secret[i] = net_secret[i];
+
+       md5_transform(hash, secret);
+
+       return seq_scale(hash[0]);
+}
+EXPORT_SYMBOL(secure_tcpv6_sequence_number);
+
+u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
+                              __be16 dport)
+{
+       u32 secret[MD5_MESSAGE_BYTES / 4];
+       u32 hash[MD5_DIGEST_WORDS];
+       u32 i;
+
+       memcpy(hash, saddr, 16);
+       for (i = 0; i < 4; i++)
+               secret[i] = net_secret[i] + (__force u32) daddr[i];
+       secret[4] = net_secret[4] + (__force u32)dport;
+       for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
+               secret[i] = net_secret[i];
+
+       md5_transform(hash, secret);
+
+       return hash[0];
+}
+#endif
+
+#ifdef CONFIG_INET
+__u32 secure_ip_id(__be32 daddr)
+{
+       u32 hash[MD5_DIGEST_WORDS];
+
+       hash[0] = (__force __u32) daddr;
+       hash[1] = net_secret[13];
+       hash[2] = net_secret[14];
+       hash[3] = net_secret[15];
+
+       md5_transform(hash, net_secret);
+
+       return hash[0];
+}
+
+__u32 secure_ipv6_id(const __be32 daddr[4])
+{
+       __u32 hash[4];
+
+       memcpy(hash, daddr, 16);
+       md5_transform(hash, net_secret);
+
+       return hash[0];
+}
+
+__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
+                                __be16 sport, __be16 dport)
+{
+       u32 hash[MD5_DIGEST_WORDS];
+
+       hash[0] = (__force u32)saddr;
+       hash[1] = (__force u32)daddr;
+       hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
+       hash[3] = net_secret[15];
+
+       md5_transform(hash, net_secret);
+
+       return seq_scale(hash[0]);
+}
+
+u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
+{
+       u32 hash[MD5_DIGEST_WORDS];
+
+       hash[0] = (__force u32)saddr;
+       hash[1] = (__force u32)daddr;
+       hash[2] = (__force u32)dport ^ net_secret[14];
+       hash[3] = net_secret[15];
+
+       md5_transform(hash, net_secret);
+
+       return hash[0];
+}
+EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral);
+#endif
+
+#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
+u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
+                               __be16 sport, __be16 dport)
+{
+       u32 hash[MD5_DIGEST_WORDS];
+       u64 seq;
+
+       hash[0] = (__force u32)saddr;
+       hash[1] = (__force u32)daddr;
+       hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
+       hash[3] = net_secret[15];
+
+       md5_transform(hash, net_secret);
+
+       seq = hash[0] | (((u64)hash[1]) << 32);
+       seq += ktime_to_ns(ktime_get_real());
+       seq &= (1ull << 48) - 1;
+
+       return seq;
+}
+EXPORT_SYMBOL(secure_dccp_sequence_number);
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
+                                 __be16 sport, __be16 dport)
+{
+       u32 secret[MD5_MESSAGE_BYTES / 4];
+       u32 hash[MD5_DIGEST_WORDS];
+       u64 seq;
+       u32 i;
+
+       memcpy(hash, saddr, 16);
+       for (i = 0; i < 4; i++)
+               secret[i] = net_secret[i] + daddr[i];
+       secret[4] = net_secret[4] +
+               (((__force u16)sport << 16) + (__force u16)dport);
+       for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
+               secret[i] = net_secret[i];
+
+       md5_transform(hash, secret);
+
+       seq = hash[0] | (((u64)hash[1]) << 32);
+       seq += ktime_to_ns(ktime_get_real());
+       seq &= (1ull << 48) - 1;
+
+       return seq;
+}
+EXPORT_SYMBOL(secure_dccpv6_sequence_number);
+#endif
+#endif
index 8c36adfd19198e241c3c7abd952b4ae9534bf376..332639b56f4d76e93888006aedf6832df4ef47c3 100644 (file)
@@ -26,6 +26,7 @@
 #include <net/timewait_sock.h>
 #include <net/tcp_states.h>
 #include <net/xfrm.h>
+#include <net/secure_seq.h>
 
 #include "ackvec.h"
 #include "ccid.h"
index 8dc4348774a58a390fe1c9fcf6c4666dcdf59be3..b74f76117dcf6fde6e660cafe7334d22225bf40f 100644 (file)
@@ -29,6 +29,7 @@
 #include <net/transp_v6.h>
 #include <net/ip6_checksum.h>
 #include <net/xfrm.h>
+#include <net/secure_seq.h>
 
 #include "dccp.h"
 #include "ipv6.h"
@@ -69,13 +70,7 @@ static inline void dccp_v6_send_check(struct sock *sk, struct sk_buff *skb)
        dh->dccph_checksum = dccp_v6_csum_finish(skb, &np->saddr, &np->daddr);
 }
 
-static inline __u32 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
-                                                 __be16 sport, __be16 dport   )
-{
-       return secure_tcpv6_sequence_number(saddr, daddr, sport, dport);
-}
-
-static inline __u32 dccp_v6_init_sequence(struct sk_buff *skb)
+static inline __u64 dccp_v6_init_sequence(struct sk_buff *skb)
 {
        return secure_dccpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32,
                                             ipv6_hdr(skb)->saddr.s6_addr32,
index 3c0369a3a663693ac24e6acdd2730909ae5ddf4a..984ec656b03b5087ed88cb3e2a930d17761b5350 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <net/inet_connection_sock.h>
 #include <net/inet_hashtables.h>
+#include <net/secure_seq.h>
 #include <net/ip.h>
 
 /*
index e38213817d0a64727b0c298d8abf1d3f854d170e..86f13c67ea8579d32a4f076063ea1777c75e166b 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/net.h>
 #include <net/ip.h>
 #include <net/inetpeer.h>
+#include <net/secure_seq.h>
 
 /*
  *  Theory of operations.
index 3e61faf23a9a0c8636433dd9a1805274dfce4691..f52d41ea06901253e1eae173201c8d3e613ea0c8 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/ip.h>
 
 #include <linux/netfilter.h>
+#include <net/secure_seq.h>
 #include <net/netfilter/nf_nat.h>
 #include <net/netfilter/nf_nat_core.h>
 #include <net/netfilter/nf_nat_rule.h>
index 6afc4eb50591ae00e1d456b98e97ca073b9a8ca3..e3dec1c9f09d2d406197cf8e6216a7a6743782d6 100644 (file)
 #include <linux/sysctl.h>
 #endif
 #include <net/atmclip.h>
+#include <net/secure_seq.h>
 
 #define RT_FL_TOS(oldflp4) \
     ((u32)(oldflp4->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK)))
index 955b8e65b69e74111c5770c7ce792599df9d733a..1c12b8ec849dcff6b5363338a42ce00e06d9246a 100644 (file)
@@ -72,6 +72,7 @@
 #include <net/timewait_sock.h>
 #include <net/xfrm.h>
 #include <net/netdma.h>
+#include <net/secure_seq.h>
 
 #include <linux/inet.h>
 #include <linux/ipv6.h>
index b53197233709c71af7630581ee6dab590e15f5a3..73f1a00a96afcd194e5567c36e2d1956a62018ca 100644 (file)
@@ -20,6 +20,7 @@
 #include <net/inet_connection_sock.h>
 #include <net/inet_hashtables.h>
 #include <net/inet6_hashtables.h>
+#include <net/secure_seq.h>
 #include <net/ip.h>
 
 int __inet6_hash(struct sock *sk, struct inet_timewait_sock *tw)
index 78aa53492b3e30e527b6f45e75bb187fe9a91e13..d1fb63f4aeb76351bd55d8c6bfa8cf0e8e20c60f 100644 (file)
@@ -61,6 +61,7 @@
 #include <net/timewait_sock.h>
 #include <net/netdma.h>
 #include <net/inet_common.h>
+#include <net/secure_seq.h>
 
 #include <asm/uaccess.h>