Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
Linus Torvalds [Mon, 14 Dec 2009 18:01:15 +0000 (10:01 -0800)]
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm:
  ARM: fix lh7a40x build
  ARM: fix sa1100 build
  ARM: fix clps711x, footbridge, integrator, ixp2000, ixp2300 and s3c build bug
  ARM: VFP: fix vfp thread init bug and document vfp notifier entry conditions
  ARM: pxa: fix now incorrect reference of skt->irq by using skt->socket.pci_irq
  [ARM] pxa/zeus: default configuration for Arcom Zeus SBC.
  [ARM] pxa/zeus: make Viper pcmcia support more generic to support Zeus
  [ARM] pxa/zeus: basic support for Arcom Zeus SBC
  [ARM] pxa/em-x270: fix usb hub power up/reset sequence
  PCMCIA: fix pxa2xx_lubbock modular build error
  ARM: RealView: Fix typo in the RealView/PBX Kconfig entry
  ARM: Do not allow the probing of the local timer
  ARM: Add an earlyprintk debug console

110 files changed:
Documentation/spinlocks.txt
arch/ia64/Kconfig
arch/ia64/include/asm/meminit.h
arch/ia64/include/asm/pgtable.h
arch/ia64/include/asm/processor.h
arch/ia64/kernel/acpi.c
arch/ia64/kernel/head.S
arch/ia64/kernel/ia64_ksyms.c
arch/ia64/kernel/mca_asm.S
arch/ia64/kernel/relocate_kernel.S
arch/ia64/kernel/setup.c
arch/ia64/kernel/vmlinux.lds.S
arch/ia64/mm/contig.c
arch/ia64/mm/discontig.c
arch/ia64/mm/init.c
arch/ia64/sn/kernel/sn2/sn2_smp.c
arch/ia64/xen/irq_xen.c
arch/ia64/xen/time.c
arch/m68k/include/asm/pgtable_mm.h
arch/m68k/sun3/mmu_emu.c
arch/mn10300/kernel/kprobes.c
arch/powerpc/include/asm/smp.h
arch/powerpc/kernel/perf_callchain.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/smp.c
arch/powerpc/platforms/cell/interrupt.c
arch/powerpc/platforms/pseries/dtl.c
arch/sparc/kernel/nmi.c
arch/x86/include/asm/percpu.h
arch/x86/kernel/apic/nmi.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/cpu_debug.c
arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
arch/x86/kernel/cpu/intel_cacheinfo.c
arch/x86/kernel/ds.c
arch/x86/kvm/svm.c
arch/x86/xen/smp.c
arch/x86/xen/time.c
crypto/cryptd.c
drivers/base/cpu.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/freq_table.c
drivers/crypto/padlock-aes.c
drivers/dma/dmaengine.c
drivers/infiniband/hw/ehca/ehca_irq.c
drivers/lguest/x86/core.c
drivers/net/chelsio/sge.c
drivers/net/loopback.c
drivers/net/veth.c
drivers/oprofile/cpu_buffer.c
drivers/oprofile/cpu_buffer.h
drivers/oprofile/oprofile_stats.c
drivers/s390/net/netiucv.c
fs/ext4/mballoc.c
fs/nfs/callback.c
fs/nfs/callback.h
fs/nfs/callback_proc.c
fs/nfs/callback_xdr.c
fs/nfs/client.c
fs/nfs/delegation.c
fs/nfs/delegation.h
fs/nfs/dir.c
fs/nfs/dns_resolve.c
fs/nfs/internal.h
fs/nfs/iostat.h
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfs/unlink.c
fs/nfs/write.c
fs/xfs/xfs_mount.c
include/asm-generic/percpu.h
include/linux/nfs4.h
include/linux/nfs_fs_sb.h
include/linux/nfs_xdr.h
include/linux/percpu-defs.h
include/linux/percpu.h
include/linux/sunrpc/sched.h
include/linux/vmstat.h
include/net/neighbour.h
include/net/netfilter/nf_conntrack.h
include/net/snmp.h
kernel/lockdep.c
kernel/module.c
kernel/rcutorture.c
kernel/sched.c
kernel/softirq.c
kernel/softlockup.c
kernel/time/timer_stats.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_functions_graph.c
kernel/trace/trace_hw_branches.c
mm/Makefile
mm/allocpercpu.c [deleted file]
mm/percpu.c
mm/slab.c
mm/vmalloc.c
mm/vmstat.c
net/sunrpc/addr.c
net/sunrpc/auth.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/clnt.c
net/sunrpc/rpcb_clnt.c
net/sunrpc/sunrpc_syms.c
net/sunrpc/xprt.c
net/sunrpc/xprtsock.c

index 619699d..178c831 100644 (file)
@@ -1,73 +1,8 @@
-SPIN_LOCK_UNLOCKED and RW_LOCK_UNLOCKED defeat lockdep state tracking and
-are hence deprecated.
+Lesson 1: Spin locks
 
-Please use DEFINE_SPINLOCK()/DEFINE_RWLOCK() or
-__SPIN_LOCK_UNLOCKED()/__RW_LOCK_UNLOCKED() as appropriate for static
-initialization.
-
-Most of the time, you can simply turn:
-
-       static spinlock_t xxx_lock = SPIN_LOCK_UNLOCKED;
-
-into:
-
-       static DEFINE_SPINLOCK(xxx_lock);
-
-Static structure member variables go from:
-
-       struct foo bar {
-               .lock   =       SPIN_LOCK_UNLOCKED;
-       };
-
-to:
-
-       struct foo bar {
-               .lock   =       __SPIN_LOCK_UNLOCKED(bar.lock);
-       };
-
-Declaration of static rw_locks undergo a similar transformation.
-
-Dynamic initialization, when necessary, may be performed as
-demonstrated below.
-
-   spinlock_t xxx_lock;
-   rwlock_t xxx_rw_lock;
-
-   static int __init xxx_init(void)
-   {
-       spin_lock_init(&xxx_lock);
-       rwlock_init(&xxx_rw_lock);
-       ...
-   }
-
-   module_init(xxx_init);
-
-The following discussion is still valid, however, with the dynamic
-initialization of spinlocks or with DEFINE_SPINLOCK, etc., used
-instead of SPIN_LOCK_UNLOCKED.
-
------------------------
-
-On Fri, 2 Jan 1998, Doug Ledford wrote:
-> 
-> I'm working on making the aic7xxx driver more SMP friendly (as well as
-> importing the latest FreeBSD sequencer code to have 7895 support) and wanted
-> to get some info from you.  The goal here is to make the various routines
-> SMP safe as well as UP safe during interrupts and other manipulating
-> routines.  So far, I've added a spin_lock variable to things like my queue
-> structs.  Now, from what I recall, there are some spin lock functions I can
-> use to lock these spin locks from other use as opposed to a (nasty)
-> save_flags(); cli(); stuff; restore_flags(); construct.  Where do I find
-> these routines and go about making use of them?  Do they only lock on a
-> per-processor basis or can they also lock say an interrupt routine from
-> mucking with a queue if the queue routine was manipulating it when the
-> interrupt occurred, or should I still use a cli(); based construct on that
-> one?
-
-See <asm/spinlock.h>. The basic version is:
-
-   spinlock_t xxx_lock = SPIN_LOCK_UNLOCKED;
+The most basic primitive for locking is spinlock.
 
+static DEFINE_SPINLOCK(xxx_lock);
 
        unsigned long flags;
 
@@ -75,13 +10,11 @@ See <asm/spinlock.h>. The basic version is:
        ... critical section here ..
        spin_unlock_irqrestore(&xxx_lock, flags);
 
-and the above is always safe. It will disable interrupts _locally_, but the
+The above is always safe. It will disable interrupts _locally_, but the
 spinlock itself will guarantee the global lock, so it will guarantee that
 there is only one thread-of-control within the region(s) protected by that
-lock. 
-
-Note that it works well even under UP - the above sequence under UP
-essentially is just the same as doing a
+lock. This works well even under UP. The above sequence under UP
+essentially is just the same as doing
 
        unsigned long flags;
 
@@ -91,15 +24,13 @@ essentially is just the same as doing a
 
 so the code does _not_ need to worry about UP vs SMP issues: the spinlocks
 work correctly under both (and spinlocks are actually more efficient on
-architectures that allow doing the "save_flags + cli" in one go because I
-don't export that interface normally).
+architectures that allow doing the "save_flags + cli" in one operation).
+
+   NOTE! Implications of spin_locks for memory are further described in:
 
-NOTE NOTE NOTE! The reason the spinlock is so much faster than a global
-interrupt lock under SMP is exactly because it disables interrupts only on
-the local CPU. The spin-lock is safe only when you _also_ use the lock
-itself to do locking across CPU's, which implies that EVERYTHING that
-touches a shared variable has to agree about the spinlock they want to
-use.
+     Documentation/memory-barriers.txt
+       (5) LOCK operations.
+       (6) UNLOCK operations.
 
 The above is usually pretty simple (you usually need and want only one
 spinlock for most things - using more than one spinlock can make things a
@@ -120,20 +51,24 @@ and another sequence that does
 then they are NOT mutually exclusive, and the critical regions can happen
 at the same time on two different CPU's. That's fine per se, but the
 critical regions had better be critical for different things (ie they
-can't stomp on each other). 
+can't stomp on each other).
 
 The above is a problem mainly if you end up mixing code - for example the
 routines in ll_rw_block() tend to use cli/sti to protect the atomicity of
 their actions, and if a driver uses spinlocks instead then you should
-think about issues like the above..
+think about issues like the above.
 
 This is really the only really hard part about spinlocks: once you start
 using spinlocks they tend to expand to areas you might not have noticed
 before, because you have to make sure the spinlocks correctly protect the
 shared data structures _everywhere_ they are used. The spinlocks are most
-easily added to places that are completely independent of other code (ie
-internal driver data structures that nobody else ever touches, for
-example). 
+easily added to places that are completely independent of other code (for
+example, internal driver data structures that nobody else ever touches).
+
+   NOTE! The spin-lock is safe only when you _also_ use the lock itself
+   to do locking across CPU's, which implies that EVERYTHING that
+   touches a shared variable has to agree about the spinlock they want
+   to use.
 
 ----
 
@@ -141,13 +76,17 @@ Lesson 2: reader-writer spinlocks.
 
 If your data accesses have a very natural pattern where you usually tend
 to mostly read from the shared variables, the reader-writer locks
-(rw_lock) versions of the spinlocks are often nicer. They allow multiple
+(rw_lock) versions of the spinlocks are sometimes useful. They allow multiple
 readers to be in the same critical region at once, but if somebody wants
-to change the variables it has to get an exclusive write lock. The
-routines look the same as above:
+to change the variables it has to get an exclusive write lock.
 
-   rwlock_t xxx_lock = RW_LOCK_UNLOCKED;
+   NOTE! reader-writer locks require more atomic memory operations than
+   simple spinlocks.  Unless the reader critical section is long, you
+   are better off just using spinlocks.
 
+The routines look the same as above:
+
+   rwlock_t xxx_lock = RW_LOCK_UNLOCKED;
 
        unsigned long flags;
 
@@ -159,18 +98,21 @@ routines look the same as above:
        .. read and write exclusive access to the info ...
        write_unlock_irqrestore(&xxx_lock, flags);
 
-The above kind of lock is useful for complex data structures like linked
-lists etc, especially when you know that most of the work is to just
-traverse the list searching for entries without changing the list itself,
-for example. Then you can use the read lock for that kind of list
-traversal, which allows many concurrent readers. Anything that _changes_
-the list will have to get the write lock. 
+The above kind of lock may be useful for complex data structures like
+linked lists, especially searching for entries without changing the list
+itself.  The read lock allows many concurrent readers.  Anything that
+_changes_ the list will have to get the write lock.
+
+   NOTE! RCU is better for list traversal, but requires careful
+   attention to design detail (see Documentation/RCU/listRCU.txt).
 
-Note: you cannot "upgrade" a read-lock to a write-lock, so if you at _any_
+Also, you cannot "upgrade" a read-lock to a write-lock, so if you at _any_
 time need to do any changes (even if you don't do it every time), you have
-to get the write-lock at the very beginning. I could fairly easily add a
-primitive to create a "upgradeable" read-lock, but it hasn't been an issue
-yet. Tell me if you'd want one. 
+to get the write-lock at the very beginning.
+
+   NOTE! We are working hard to remove reader-writer spinlocks in most
+   cases, so please don't add a new one without consensus.  (Instead, see
+   Documentation/RCU/rcu.txt for complete information.)
 
 ----
 
@@ -233,4 +175,46 @@ indeed), while write-locks need to protect themselves against interrupts.
 
                Linus
 
+----
+
+Reference information:
+
+For dynamic initialization, use spin_lock_init() or rwlock_init() as
+appropriate:
+
+   spinlock_t xxx_lock;
+   rwlock_t xxx_rw_lock;
+
+   static int __init xxx_init(void)
+   {
+       spin_lock_init(&xxx_lock);
+       rwlock_init(&xxx_rw_lock);
+       ...
+   }
+
+   module_init(xxx_init);
+
+For static initialization, use DEFINE_SPINLOCK() / DEFINE_RWLOCK() or
+__SPIN_LOCK_UNLOCKED() / __RW_LOCK_UNLOCKED() as appropriate.
+
+SPIN_LOCK_UNLOCKED and RW_LOCK_UNLOCKED are deprecated.  These interfere
+with lockdep state tracking.
+
+Most of the time, you can simply turn:
+       static spinlock_t xxx_lock = SPIN_LOCK_UNLOCKED;
+into:
+       static DEFINE_SPINLOCK(xxx_lock);
+
+Static structure member variables go from:
+
+       struct foo bar {
+               .lock   =       SPIN_LOCK_UNLOCKED;
+       };
+
+to:
 
+       struct foo bar {
+               .lock   =       __SPIN_LOCK_UNLOCKED(bar.lock);
+       };
+
+Declaration of static rw_locks undergo a similar transformation.
index 1ee596c..2d7f56a 100644 (file)
@@ -87,9 +87,6 @@ config GENERIC_TIME_VSYSCALL
        bool
        default y
 
-config HAVE_LEGACY_PER_CPU_AREA
-       def_bool y
-
 config HAVE_SETUP_PER_CPU_AREA
        def_bool y
 
index 688a812..61c7b17 100644 (file)
@@ -61,7 +61,7 @@ extern int register_active_ranges(u64 start, u64 len, int nid);
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
 # define LARGE_GAP     0x40000000 /* Use virtual mem map if hole is > than this */
-  extern unsigned long vmalloc_end;
+  extern unsigned long VMALLOC_END;
   extern struct page *vmem_map;
   extern int find_largest_hole(u64 start, u64 end, void *arg);
   extern int create_mem_map_page_table(u64 start, u64 end, void *arg);
index 8840a69..69bf138 100644 (file)
@@ -228,8 +228,7 @@ ia64_phys_addr_valid (unsigned long addr)
 #define VMALLOC_START          (RGN_BASE(RGN_GATE) + 0x200000000UL)
 #ifdef CONFIG_VIRTUAL_MEM_MAP
 # define VMALLOC_END_INIT      (RGN_BASE(RGN_GATE) + (1UL << (4*PAGE_SHIFT - 9)))
-# define VMALLOC_END           vmalloc_end
-  extern unsigned long vmalloc_end;
+extern unsigned long VMALLOC_END;
 #else
 #if defined(CONFIG_SPARSEMEM) && defined(CONFIG_SPARSEMEM_VMEMMAP)
 /* SPARSEMEM_VMEMMAP uses half of vmalloc... */
index 3eaeedf..7fa90f7 100644 (file)
@@ -229,7 +229,7 @@ struct cpuinfo_ia64 {
 #endif
 };
 
-DECLARE_PER_CPU(struct cpuinfo_ia64, cpu_info);
+DECLARE_PER_CPU(struct cpuinfo_ia64, ia64_cpu_info);
 
 /*
  * The "local" data variable.  It refers to the per-CPU data of the currently executing
@@ -237,8 +237,8 @@ DECLARE_PER_CPU(struct cpuinfo_ia64, cpu_info);
  * Do not use the address of local_cpu_data, since it will be different from
  * cpu_data(smp_processor_id())!
  */
-#define local_cpu_data         (&__ia64_per_cpu_var(cpu_info))
-#define cpu_data(cpu)          (&per_cpu(cpu_info, cpu))
+#define local_cpu_data         (&__ia64_per_cpu_var(ia64_cpu_info))
+#define cpu_data(cpu)          (&per_cpu(ia64_cpu_info, cpu))
 
 extern void print_cpu_info (struct cpuinfo_ia64 *);
 
index baec6f0..40574ae 100644 (file)
@@ -702,11 +702,23 @@ int __init early_acpi_boot_init(void)
                printk(KERN_ERR PREFIX
                       "Error parsing MADT - no LAPIC entries\n");
 
+#ifdef CONFIG_SMP
+       if (available_cpus == 0) {
+               printk(KERN_INFO "ACPI: Found 0 CPUS; assuming 1\n");
+               printk(KERN_INFO "CPU 0 (0x%04x)", hard_smp_processor_id());
+               smp_boot_data.cpu_phys_id[available_cpus] =
+                   hard_smp_processor_id();
+               available_cpus = 1;     /* We've got at least one of these, no? */
+       }
+       smp_boot_data.cpu_count = available_cpus;
+#endif
+       /* Make boot-up look pretty */
+       printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus,
+              total_cpus);
+
        return 0;
 }
 
-
-
 int __init acpi_boot_init(void)
 {
 
@@ -769,18 +781,8 @@ int __init acpi_boot_init(void)
        if (acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt))
                printk(KERN_ERR PREFIX "Can't find FADT\n");
 
+#ifdef CONFIG_ACPI_NUMA
 #ifdef CONFIG_SMP
-       if (available_cpus == 0) {
-               printk(KERN_INFO "ACPI: Found 0 CPUS; assuming 1\n");
-               printk(KERN_INFO "CPU 0 (0x%04x)", hard_smp_processor_id());
-               smp_boot_data.cpu_phys_id[available_cpus] =
-                   hard_smp_processor_id();
-               available_cpus = 1;     /* We've got at least one of these, no? */
-       }
-       smp_boot_data.cpu_count = available_cpus;
-
-       smp_build_cpu_map();
-# ifdef CONFIG_ACPI_NUMA
        if (srat_num_cpus == 0) {
                int cpu, i = 1;
                for (cpu = 0; cpu < smp_boot_data.cpu_count; cpu++)
@@ -789,14 +791,9 @@ int __init acpi_boot_init(void)
                                node_cpuid[i++].phys_id =
                                    smp_boot_data.cpu_phys_id[cpu];
        }
-# endif
 #endif
-#ifdef CONFIG_ACPI_NUMA
        build_cpu_to_node_map();
 #endif
-       /* Make boot-up look pretty */
-       printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus,
-              total_cpus);
        return 0;
 }
 
index 696eff2..17a9fba 100644 (file)
@@ -1051,7 +1051,7 @@ END(ia64_delay_loop)
  * intermediate precision so that we can produce a full 64-bit result.
  */
 GLOBAL_ENTRY(ia64_native_sched_clock)
-       addl r8=THIS_CPU(cpu_info) + IA64_CPUINFO_NSEC_PER_CYC_OFFSET,r0
+       addl r8=THIS_CPU(ia64_cpu_info) + IA64_CPUINFO_NSEC_PER_CYC_OFFSET,r0
        mov.m r9=ar.itc         // fetch cycle-counter                          (35 cyc)
        ;;
        ldf8 f8=[r8]
@@ -1077,7 +1077,7 @@ sched_clock = ia64_native_sched_clock
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 GLOBAL_ENTRY(cycle_to_cputime)
        alloc r16=ar.pfs,1,0,0,0
-       addl r8=THIS_CPU(cpu_info) + IA64_CPUINFO_NSEC_PER_CYC_OFFSET,r0
+       addl r8=THIS_CPU(ia64_cpu_info) + IA64_CPUINFO_NSEC_PER_CYC_OFFSET,r0
        ;;
        ldf8 f8=[r8]
        ;;
index 14d39e3..461b999 100644 (file)
@@ -30,7 +30,7 @@ EXPORT_SYMBOL(max_low_pfn);   /* defined by bootmem.c, but not exported by generic
 #endif
 
 #include <asm/processor.h>
-EXPORT_SYMBOL(per_cpu__cpu_info);
+EXPORT_SYMBOL(per_cpu__ia64_cpu_info);
 #ifdef CONFIG_SMP
 EXPORT_SYMBOL(per_cpu__local_per_cpu_offset);
 #endif
index 7461d25..d5bdf9d 100644 (file)
@@ -59,7 +59,7 @@
 ia64_do_tlb_purge:
 #define O(member)      IA64_CPUINFO_##member##_OFFSET
 
-       GET_THIS_PADDR(r2, cpu_info)    // load phys addr of cpu_info into r2
+       GET_THIS_PADDR(r2, ia64_cpu_info) // load phys addr of cpu_info into r2
        ;;
        addl r17=O(PTCE_STRIDE),r2
        addl r2=O(PTCE_BASE),r2
index 32f6fc1..c370e02 100644 (file)
@@ -61,7 +61,7 @@ GLOBAL_ENTRY(relocate_new_kernel)
 
        // purge all TC entries
 #define O(member)       IA64_CPUINFO_##member##_OFFSET
-        GET_THIS_PADDR(r2, cpu_info)    // load phys addr of cpu_info into r2
+        GET_THIS_PADDR(r2, ia64_cpu_info) // load phys addr of cpu_info into r2
         ;;
         addl r17=O(PTCE_STRIDE),r2
         addl r2=O(PTCE_BASE),r2
index 1de86c9..a1ea879 100644 (file)
@@ -74,7 +74,7 @@ unsigned long __per_cpu_offset[NR_CPUS];
 EXPORT_SYMBOL(__per_cpu_offset);
 #endif
 
-DEFINE_PER_CPU(struct cpuinfo_ia64, cpu_info);
+DEFINE_PER_CPU(struct cpuinfo_ia64, ia64_cpu_info);
 DEFINE_PER_CPU(unsigned long, local_per_cpu_offset);
 unsigned long ia64_cycles_per_usec;
 struct ia64_boot_param *ia64_boot_param;
@@ -566,19 +566,18 @@ setup_arch (char **cmdline_p)
        early_acpi_boot_init();
 # ifdef CONFIG_ACPI_NUMA
        acpi_numa_init();
-#ifdef CONFIG_ACPI_HOTPLUG_CPU
+#  ifdef CONFIG_ACPI_HOTPLUG_CPU
        prefill_possible_map();
-#endif
+#  endif
        per_cpu_scan_finalize((cpus_weight(early_cpu_possible_map) == 0 ?
                32 : cpus_weight(early_cpu_possible_map)),
                additional_cpus > 0 ? additional_cpus : 0);
 # endif
-#else
-# ifdef CONFIG_SMP
-       smp_build_cpu_map();    /* happens, e.g., with the Ski simulator */
-# endif
 #endif /* CONFIG_APCI_BOOT */
 
+#ifdef CONFIG_SMP
+       smp_build_cpu_map();
+#endif
        find_memory();
 
        /* process SAL system table: */
@@ -856,18 +855,6 @@ identify_cpu (struct cpuinfo_ia64 *c)
 }
 
 /*
- * In UP configuration, setup_per_cpu_areas() is defined in
- * include/linux/percpu.h
- */
-#ifdef CONFIG_SMP
-void __init
-setup_per_cpu_areas (void)
-{
-       /* start_kernel() requires this... */
-}
-#endif
-
-/*
  * Do the following calculations:
  *
  * 1. the max. cache line size.
@@ -980,7 +967,7 @@ cpu_init (void)
         * depends on the data returned by identify_cpu().  We break the dependency by
         * accessing cpu_data() through the canonical per-CPU address.
         */
-       cpu_info = cpu_data + ((char *) &__ia64_per_cpu_var(cpu_info) - __per_cpu_start);
+       cpu_info = cpu_data + ((char *) &__ia64_per_cpu_var(ia64_cpu_info) - __per_cpu_start);
        identify_cpu(cpu_info);
 
 #ifdef CONFIG_MCKINLEY
index 0a0c77b..1295ba3 100644 (file)
@@ -166,6 +166,12 @@ SECTIONS
        }
 #endif
 
+#ifdef CONFIG_SMP
+  . = ALIGN(PERCPU_PAGE_SIZE);
+  __cpu0_per_cpu = .;
+  . = . + PERCPU_PAGE_SIZE;    /* cpu0 per-cpu space */
+#endif
+
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
 
@@ -198,11 +204,6 @@ SECTIONS
   data : { } :data
   .data : AT(ADDR(.data) - LOAD_OFFSET)
        {
-#ifdef CONFIG_SMP
-  . = ALIGN(PERCPU_PAGE_SIZE);
-               __cpu0_per_cpu = .;
-  . = . + PERCPU_PAGE_SIZE;    /* cpu0 per-cpu space */
-#endif
                INIT_TASK_DATA(PAGE_SIZE)
                CACHELINE_ALIGNED_DATA(SMP_CACHE_BYTES)
                READ_MOSTLY_DATA(SMP_CACHE_BYTES)
index 2f724d2..54bf540 100644 (file)
@@ -154,38 +154,99 @@ static void *cpu_data;
 void * __cpuinit
 per_cpu_init (void)
 {
-       int cpu;
-       static int first_time=1;
+       static bool first_time = true;
+       void *cpu0_data = __cpu0_per_cpu;
+       unsigned int cpu;
+
+       if (!first_time)
+               goto skip;
+       first_time = false;
 
        /*
-        * get_free_pages() cannot be used before cpu_init() done.  BSP
-        * allocates "NR_CPUS" pages for all CPUs to avoid that AP calls
-        * get_zeroed_page().
+        * get_free_pages() cannot be used before cpu_init() done.
+        * BSP allocates PERCPU_PAGE_SIZE bytes for all possible CPUs
+        * to avoid that AP calls get_zeroed_page().
         */
-       if (first_time) {
-               void *cpu0_data = __cpu0_per_cpu;
+       for_each_possible_cpu(cpu) {
+               void *src = cpu == 0 ? cpu0_data : __phys_per_cpu_start;
 
-               first_time=0;
+               memcpy(cpu_data, src, __per_cpu_end - __per_cpu_start);
+               __per_cpu_offset[cpu] = (char *)cpu_data - __per_cpu_start;
+               per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
 
-               __per_cpu_offset[0] = (char *) cpu0_data - __per_cpu_start;
-               per_cpu(local_per_cpu_offset, 0) = __per_cpu_offset[0];
+               /*
+                * percpu area for cpu0 is moved from the __init area
+                * which is setup by head.S and used till this point.
+                * Update ar.k3.  This move is ensures that percpu
+                * area for cpu0 is on the correct node and its
+                * virtual address isn't insanely far from other
+                * percpu areas which is important for congruent
+                * percpu allocator.
+                */
+               if (cpu == 0)
+                       ia64_set_kr(IA64_KR_PER_CPU_DATA, __pa(cpu_data) -
+                                   (unsigned long)__per_cpu_start);
 
-               for (cpu = 1; cpu < NR_CPUS; cpu++) {
-                       memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
-                       __per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start;
-                       cpu_data += PERCPU_PAGE_SIZE;
-                       per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
-               }
+               cpu_data += PERCPU_PAGE_SIZE;
        }
+skip:
        return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
 }
 
 static inline void
 alloc_per_cpu_data(void)
 {
-       cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS-1,
+       cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * num_possible_cpus(),
                                   PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
 }
+
+/**
+ * setup_per_cpu_areas - setup percpu areas
+ *
+ * Arch code has already allocated and initialized percpu areas.  All
+ * this function has to do is to teach the determined layout to the
+ * dynamic percpu allocator, which happens to be more complex than
+ * creating whole new ones using helpers.
+ */
+void __init
+setup_per_cpu_areas(void)
+{
+       struct pcpu_alloc_info *ai;
+       struct pcpu_group_info *gi;
+       unsigned int cpu;
+       ssize_t static_size, reserved_size, dyn_size;
+       int rc;
+
+       ai = pcpu_alloc_alloc_info(1, num_possible_cpus());
+       if (!ai)
+               panic("failed to allocate pcpu_alloc_info");
+       gi = &ai->groups[0];
+
+       /* units are assigned consecutively to possible cpus */
+       for_each_possible_cpu(cpu)
+               gi->cpu_map[gi->nr_units++] = cpu;
+
+       /* set parameters */
+       static_size = __per_cpu_end - __per_cpu_start;
+       reserved_size = PERCPU_MODULE_RESERVE;
+       dyn_size = PERCPU_PAGE_SIZE - static_size - reserved_size;
+       if (dyn_size < 0)
+               panic("percpu area overflow static=%zd reserved=%zd\n",
+                     static_size, reserved_size);
+
+       ai->static_size         = static_size;
+       ai->reserved_size       = reserved_size;
+       ai->dyn_size            = dyn_size;
+       ai->unit_size           = PERCPU_PAGE_SIZE;
+       ai->atom_size           = PAGE_SIZE;
+       ai->alloc_size          = PERCPU_PAGE_SIZE;
+
+       rc = pcpu_setup_first_chunk(ai, __per_cpu_start + __per_cpu_offset[0]);
+       if (rc)
+               panic("failed to setup percpu area (err=%d)", rc);
+
+       pcpu_free_alloc_info(ai);
+}
 #else
 #define alloc_per_cpu_data() do { } while (0)
 #endif /* CONFIG_SMP */
@@ -270,8 +331,8 @@ paging_init (void)
 
                map_size = PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) *
                        sizeof(struct page));
-               vmalloc_end -= map_size;
-               vmem_map = (struct page *) vmalloc_end;
+               VMALLOC_END -= map_size;
+               vmem_map = (struct page *) VMALLOC_END;
                efi_memmap_walk(create_mem_map_page_table, NULL);
 
                /*
index d85ba98..19c4b21 100644 (file)
@@ -143,22 +143,120 @@ static void *per_cpu_node_setup(void *cpu_data, int node)
        int cpu;
 
        for_each_possible_early_cpu(cpu) {
-               if (cpu == 0) {
-                       void *cpu0_data = __cpu0_per_cpu;
-                       __per_cpu_offset[cpu] = (char*)cpu0_data -
-                               __per_cpu_start;
-               } else if (node == node_cpuid[cpu].nid) {
-                       memcpy(__va(cpu_data), __phys_per_cpu_start,
-                              __per_cpu_end - __per_cpu_start);
-                       __per_cpu_offset[cpu] = (char*)__va(cpu_data) -
-                               __per_cpu_start;
-                       cpu_data += PERCPU_PAGE_SIZE;
-               }
+               void *src = cpu == 0 ? __cpu0_per_cpu : __phys_per_cpu_start;
+
+               if (node != node_cpuid[cpu].nid)
+                       continue;
+
+               memcpy(__va(cpu_data), src, __per_cpu_end - __per_cpu_start);
+               __per_cpu_offset[cpu] = (char *)__va(cpu_data) -
+                       __per_cpu_start;
+
+               /*
+                * percpu area for cpu0 is moved from the __init area
+                * which is setup by head.S and used till this point.
+                * Update ar.k3.  This move is ensures that percpu
+                * area for cpu0 is on the correct node and its
+                * virtual address isn't insanely far from other
+                * percpu areas which is important for congruent
+                * percpu allocator.
+                */
+               if (cpu == 0)
+                       ia64_set_kr(IA64_KR_PER_CPU_DATA,
+                                   (unsigned long)cpu_data -
+                                   (unsigned long)__per_cpu_start);
+
+               cpu_data += PERCPU_PAGE_SIZE;
        }
 #endif
        return cpu_data;
 }
 
+#ifdef CONFIG_SMP
+/**
+ * setup_per_cpu_areas - setup percpu areas
+ *
+ * Arch code has already allocated and initialized percpu areas.  All
+ * this function has to do is to teach the determined layout to the
+ * dynamic percpu allocator, which happens to be more complex than
+ * creating whole new ones using helpers.
+ */
+void __init setup_per_cpu_areas(void)
+{
+       struct pcpu_alloc_info *ai;
+       struct pcpu_group_info *uninitialized_var(gi);
+       unsigned int *cpu_map;
+       void *base;
+       unsigned long base_offset;
+       unsigned int cpu;
+       ssize_t static_size, reserved_size, dyn_size;
+       int node, prev_node, unit, nr_units, rc;
+
+       ai = pcpu_alloc_alloc_info(MAX_NUMNODES, nr_cpu_ids);
+       if (!ai)
+               panic("failed to allocate pcpu_alloc_info");
+       cpu_map = ai->groups[0].cpu_map;
+
+       /* determine base */
+       base = (void *)ULONG_MAX;
+       for_each_possible_cpu(cpu)
+               base = min(base,
+                          (void *)(__per_cpu_offset[cpu] + __per_cpu_start));
+       base_offset = (void *)__per_cpu_start - base;
+
+       /* build cpu_map, units are grouped by node */
+       unit = 0;
+       for_each_node(node)
+               for_each_possible_cpu(cpu)
+                       if (node == node_cpuid[cpu].nid)
+                               cpu_map[unit++] = cpu;
+       nr_units = unit;
+
+       /* set basic parameters */
+       static_size = __per_cpu_end - __per_cpu_start;
+       reserved_size = PERCPU_MODULE_RESERVE;
+       dyn_size = PERCPU_PAGE_SIZE - static_size - reserved_size;
+       if (dyn_size < 0)
+               panic("percpu area overflow static=%zd reserved=%zd\n",
+                     static_size, reserved_size);
+
+       ai->static_size         = static_size;
+       ai->reserved_size       = reserved_size;
+       ai->dyn_size            = dyn_size;
+       ai->unit_size           = PERCPU_PAGE_SIZE;
+       ai->atom_size           = PAGE_SIZE;
+       ai->alloc_size          = PERCPU_PAGE_SIZE;
+
+       /*
+        * CPUs are put into groups according to node.  Walk cpu_map
+        * and create new groups at node boundaries.
+        */
+       prev_node = -1;
+       ai->nr_groups = 0;
+       for (unit = 0; unit < nr_units; unit++) {
+               cpu = cpu_map[unit];
+               node = node_cpuid[cpu].nid;
+
+               if (node == prev_node) {
+                       gi->nr_units++;
+                       continue;
+               }
+               prev_node = node;
+
+               gi = &ai->groups[ai->nr_groups++];
+               gi->nr_units            = 1;
+               gi->base_offset         = __per_cpu_offset[cpu] + base_offset;
+               gi->cpu_map             = &cpu_map[unit];
+       }
+
+       rc = pcpu_setup_first_chunk(ai, base);
+       if (rc)
+               panic("failed to setup percpu area (err=%d)", rc);
+
+       pcpu_free_alloc_info(ai);
+}
+#endif
+
 /**
  * fill_pernode - initialize pernode data.
  * @node: the node id.
@@ -352,7 +450,8 @@ static void __init initialize_pernode_data(void)
        /* Set the node_data pointer for each per-cpu struct */
        for_each_possible_early_cpu(cpu) {
                node = node_cpuid[cpu].nid;
-               per_cpu(cpu_info, cpu).node_data = mem_data[node].node_data;
+               per_cpu(ia64_cpu_info, cpu).node_data =
+                       mem_data[node].node_data;
        }
 #else
        {
@@ -360,7 +459,7 @@ static void __init initialize_pernode_data(void)
                cpu = 0;
                node = node_cpuid[cpu].nid;
                cpu0_cpu_info = (struct cpuinfo_ia64 *)(__phys_per_cpu_start +
-                       ((char *)&per_cpu__cpu_info - __per_cpu_start));
+                       ((char *)&per_cpu__ia64_cpu_info - __per_cpu_start));
                cpu0_cpu_info->node_data = mem_data[node].node_data;
        }
 #endif /* CONFIG_SMP */
@@ -666,9 +765,9 @@ void __init paging_init(void)
        sparse_init();
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
-       vmalloc_end -= PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) *
+       VMALLOC_END -= PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) *
                sizeof(struct page));
-       vmem_map = (struct page *) vmalloc_end;
+       vmem_map = (struct page *) VMALLOC_END;
        efi_memmap_walk(create_mem_map_page_table, NULL);
        printk("Virtual mem_map starts at 0x%p\n", vmem_map);
 #endif
index 1857766..b9609c6 100644 (file)
@@ -44,8 +44,8 @@ extern void ia64_tlb_init (void);
 unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL;
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
-unsigned long vmalloc_end = VMALLOC_END_INIT;
-EXPORT_SYMBOL(vmalloc_end);
+unsigned long VMALLOC_END = VMALLOC_END_INIT;
+EXPORT_SYMBOL(VMALLOC_END);
 struct page *vmem_map;
 EXPORT_SYMBOL(vmem_map);
 #endif
index 1176506..e884ba4 100644 (file)
@@ -496,13 +496,13 @@ static int sn2_ptc_seq_show(struct seq_file *file, void *data)
                seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l,
                                stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed,
                                stat->deadlocks,
-                               1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,
-                               1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,
-                               1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec,
+                               1000 * stat->lock_itc_clocks / per_cpu(ia64_cpu_info, cpu).cyc_per_usec,
+                               1000 * stat->shub_itc_clocks / per_cpu(ia64_cpu_info, cpu).cyc_per_usec,
+                               1000 * stat->shub_itc_clocks_max / per_cpu(ia64_cpu_info, cpu).cyc_per_usec,
                                stat->shub_ptc_flushes_not_my_mm,
                                stat->deadlocks2,
                                stat->shub_ipi_flushes,
-                               1000 * stat->shub_ipi_flushes_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec);
+                               1000 * stat->shub_ipi_flushes_itc_clocks / per_cpu(ia64_cpu_info, cpu).cyc_per_usec);
        }
        return 0;
 }
index f042e19..a3fb7cf 100644 (file)
@@ -63,19 +63,19 @@ xen_free_irq_vector(int vector)
 }
 
 
-static DEFINE_PER_CPU(int, timer_irq) = -1;
-static DEFINE_PER_CPU(int, ipi_irq) = -1;
-static DEFINE_PER_CPU(int, resched_irq) = -1;
-static DEFINE_PER_CPU(int, cmc_irq) = -1;
-static DEFINE_PER_CPU(int, cmcp_irq) = -1;
-static DEFINE_PER_CPU(int, cpep_irq) = -1;
+static DEFINE_PER_CPU(int, xen_timer_irq) = -1;
+static DEFINE_PER_CPU(int, xen_ipi_irq) = -1;
+static DEFINE_PER_CPU(int, xen_resched_irq) = -1;
+static DEFINE_PER_CPU(int, xen_cmc_irq) = -1;
+static DEFINE_PER_CPU(int, xen_cmcp_irq) = -1;
+static DEFINE_PER_CPU(int, xen_cpep_irq) = -1;
 #define NAME_SIZE      15
-static DEFINE_PER_CPU(char[NAME_SIZE], timer_name);
-static DEFINE_PER_CPU(char[NAME_SIZE], ipi_name);
-static DEFINE_PER_CPU(char[NAME_SIZE], resched_name);
-static DEFINE_PER_CPU(char[NAME_SIZE], cmc_name);
-static DEFINE_PER_CPU(char[NAME_SIZE], cmcp_name);
-static DEFINE_PER_CPU(char[NAME_SIZE], cpep_name);
+static DEFINE_PER_CPU(char[NAME_SIZE], xen_timer_name);
+static DEFINE_PER_CPU(char[NAME_SIZE], xen_ipi_name);
+static DEFINE_PER_CPU(char[NAME_SIZE], xen_resched_name);
+static DEFINE_PER_CPU(char[NAME_SIZE], xen_cmc_name);
+static DEFINE_PER_CPU(char[NAME_SIZE], xen_cmcp_name);
+static DEFINE_PER_CPU(char[NAME_SIZE], xen_cpep_name);
 #undef NAME_SIZE
 
 struct saved_irq {
@@ -144,64 +144,64 @@ __xen_register_percpu_irq(unsigned int cpu, unsigned int vec,
        if (xen_slab_ready) {
                switch (vec) {
                case IA64_TIMER_VECTOR:
-                       snprintf(per_cpu(timer_name, cpu),
-                                sizeof(per_cpu(timer_name, cpu)),
+                       snprintf(per_cpu(xen_timer_name, cpu),
+                                sizeof(per_cpu(xen_timer_name, cpu)),
                                 "%s%d", action->name, cpu);
                        irq = bind_virq_to_irqhandler(VIRQ_ITC, cpu,
                                action->handler, action->flags,
-                               per_cpu(timer_name, cpu), action->dev_id);
-                       per_cpu(timer_irq, cpu) = irq;
+                               per_cpu(xen_timer_name, cpu), action->dev_id);
+                       per_cpu(xen_timer_irq, cpu) = irq;
                        break;
                case IA64_IPI_RESCHEDULE:
-                       snprintf(per_cpu(resched_name, cpu),
-                                sizeof(per_cpu(resched_name, cpu)),
+                       snprintf(per_cpu(xen_resched_name, cpu),
+                                sizeof(per_cpu(xen_resched_name, cpu)),
                                 "%s%d", action->name, cpu);
                        irq = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, cpu,
                                action->handler, action->flags,
-                               per_cpu(resched_name, cpu), action->dev_id);
-                       per_cpu(resched_irq, cpu) = irq;
+                               per_cpu(xen_resched_name, cpu), action->dev_id);
+                       per_cpu(xen_resched_irq, cpu) = irq;
                        break;
                case IA64_IPI_VECTOR:
-                       snprintf(per_cpu(ipi_name, cpu),
-                                sizeof(per_cpu(ipi_name, cpu)),
+                       snprintf(per_cpu(xen_ipi_name, cpu),
+                                sizeof(per_cpu(xen_ipi_name, cpu)),
                                 "%s%d", action->name, cpu);
                        irq = bind_ipi_to_irqhandler(XEN_IPI_VECTOR, cpu,
                                action->handler, action->flags,
-                               per_cpu(ipi_name, cpu), action->dev_id);
-                       per_cpu(ipi_irq, cpu) = irq;
+                               per_cpu(xen_ipi_name, cpu), action->dev_id);
+                       per_cpu(xen_ipi_irq, cpu) = irq;
                        break;
                case IA64_CMC_VECTOR:
-                       snprintf(per_cpu(cmc_name, cpu),
-                                sizeof(per_cpu(cmc_name, cpu)),
+                       snprintf(per_cpu(xen_cmc_name, cpu),
+                                sizeof(per_cpu(xen_cmc_name, cpu)),
                                 "%s%d", action->name, cpu);
                        irq = bind_virq_to_irqhandler(VIRQ_MCA_CMC, cpu,
-                                                     action->handler,
-                                                     action->flags,
-                                                     per_cpu(cmc_name, cpu),
-                                                     action->dev_id);
-                       per_cpu(cmc_irq, cpu) = irq;
+                                               action->handler,
+                                               action->flags,
+                                               per_cpu(xen_cmc_name, cpu),
+                                               action->dev_id);
+                       per_cpu(xen_cmc_irq, cpu) = irq;
                        break;
                case IA64_CMCP_VECTOR:
-                       snprintf(per_cpu(cmcp_name, cpu),
-                                sizeof(per_cpu(cmcp_name, cpu)),
+                       snprintf(per_cpu(xen_cmcp_name, cpu),
+                                sizeof(per_cpu(xen_cmcp_name, cpu)),
                                 "%s%d", action->name, cpu);
                        irq = bind_ipi_to_irqhandler(XEN_CMCP_VECTOR, cpu,
-                                                    action->handler,
-                                                    action->flags,
-                                                    per_cpu(cmcp_name, cpu),
-                                                    action->dev_id);
-                       per_cpu(cmcp_irq, cpu) = irq;
+                                               action->handler,
+                                               action->flags,
+                                               per_cpu(xen_cmcp_name, cpu),
+                                               action->dev_id);
+                       per_cpu(xen_cmcp_irq, cpu) = irq;
                        break;
                case IA64_CPEP_VECTOR:
-                       snprintf(per_cpu(cpep_name, cpu),
-                                sizeof(per_cpu(cpep_name, cpu)),
+                       snprintf(per_cpu(xen_cpep_name, cpu),
+                                sizeof(per_cpu(xen_cpep_name, cpu)),
                                 "%s%d", action->name, cpu);
                        irq = bind_ipi_to_irqhandler(XEN_CPEP_VECTOR, cpu,
-                                                    action->handler,
-                                                    action->flags,
-                                                    per_cpu(cpep_name, cpu),
-                                                    action->dev_id);
-                       per_cpu(cpep_irq, cpu) = irq;
+                                               action->handler,
+                                               action->flags,
+                                               per_cpu(xen_cpep_name, cpu),
+                                               action->dev_id);
+                       per_cpu(xen_cpep_irq, cpu) = irq;
                        break;
                case IA64_CPE_VECTOR:
                case IA64_MCA_RENDEZ_VECTOR:
@@ -275,30 +275,33 @@ unbind_evtchn_callback(struct notifier_block *nfb,
 
        if (action == CPU_DEAD) {
                /* Unregister evtchn.  */
-               if (per_cpu(cpep_irq, cpu) >= 0) {
-                       unbind_from_irqhandler(per_cpu(cpep_irq, cpu), NULL);
-                       per_cpu(cpep_irq, cpu) = -1;
+               if (per_cpu(xen_cpep_irq, cpu) >= 0) {
+                       unbind_from_irqhandler(per_cpu(xen_cpep_irq, cpu),
+                                              NULL);
+                       per_cpu(xen_cpep_irq, cpu) = -1;
                }
-               if (per_cpu(cmcp_irq, cpu) >= 0) {
-                       unbind_from_irqhandler(per_cpu(cmcp_irq, cpu), NULL);
-                       per_cpu(cmcp_irq, cpu) = -1;
+               if (per_cpu(xen_cmcp_irq, cpu) >= 0) {
+                       unbind_from_irqhandler(per_cpu(xen_cmcp_irq, cpu),
+                                              NULL);
+                       per_cpu(xen_cmcp_irq, cpu) = -1;
                }
-               if (per_cpu(cmc_irq, cpu) >= 0) {
-                       unbind_from_irqhandler(per_cpu(cmc_irq, cpu), NULL);
-                       per_cpu(cmc_irq, cpu) = -1;
+               if (per_cpu(xen_cmc_irq, cpu) >= 0) {
+                       unbind_from_irqhandler(per_cpu(xen_cmc_irq, cpu), NULL);
+                       per_cpu(xen_cmc_irq, cpu) = -1;
                }
-               if (per_cpu(ipi_irq, cpu) >= 0) {
-                       unbind_from_irqhandler(per_cpu(ipi_irq, cpu), NULL);
-                       per_cpu(ipi_irq, cpu) = -1;
+               if (per_cpu(xen_ipi_irq, cpu) >= 0) {
+                       unbind_from_irqhandler(per_cpu(xen_ipi_irq, cpu), NULL);
+                       per_cpu(xen_ipi_irq, cpu) = -1;
                }
-               if (per_cpu(resched_irq, cpu) >= 0) {
-                       unbind_from_irqhandler(per_cpu(resched_irq, cpu),
-                                               NULL);
-                       per_cpu(resched_irq, cpu) = -1;
+               if (per_cpu(xen_resched_irq, cpu) >= 0) {
+                       unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu),
+                                              NULL);
+                       per_cpu(xen_resched_irq, cpu) = -1;
                }
-               if (per_cpu(timer_irq, cpu) >= 0) {
-                       unbind_from_irqhandler(per_cpu(timer_irq, cpu), NULL);
-                       per_cpu(timer_irq, cpu) = -1;
+               if (per_cpu(xen_timer_irq, cpu) >= 0) {
+                       unbind_from_irqhandler(per_cpu(xen_timer_irq, cpu),
+                                              NULL);
+                       per_cpu(xen_timer_irq, cpu) = -1;
                }
        }
        return NOTIFY_OK;
index dbeadb9..c1c5445 100644 (file)
 
 #include "../kernel/fsyscall_gtod_data.h"
 
-DEFINE_PER_CPU(struct vcpu_runstate_info, runstate);
-DEFINE_PER_CPU(unsigned long, processed_stolen_time);
-DEFINE_PER_CPU(unsigned long, processed_blocked_time);
+static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate);
+static DEFINE_PER_CPU(unsigned long, xen_stolen_time);
+static DEFINE_PER_CPU(unsigned long, xen_blocked_time);
 
 /* taken from i386/kernel/time-xen.c */
 static void xen_init_missing_ticks_accounting(int cpu)
 {
        struct vcpu_register_runstate_memory_area area;
-       struct vcpu_runstate_info *runstate = &per_cpu(runstate, cpu);
+       struct vcpu_runstate_info *runstate = &per_cpu(xen_runstate, cpu);
        int rc;
 
        memset(runstate, 0, sizeof(*runstate));
@@ -52,8 +52,8 @@ static void xen_init_missing_ticks_accounting(int cpu)
                                &area);
        WARN_ON(rc && rc != -ENOSYS);
 
-       per_cpu(processed_blocked_time, cpu) = runstate->time[RUNSTATE_blocked];
-       per_cpu(processed_stolen_time, cpu) = runstate->time[RUNSTATE_runnable]
+       per_cpu(xen_blocked_time, cpu) = runstate->time[RUNSTATE_blocked];
+       per_cpu(xen_stolen_time, cpu) = runstate->time[RUNSTATE_runnable]
                                            + runstate->time[RUNSTATE_offline];
 }
 
@@ -68,7 +68,7 @@ static void get_runstate_snapshot(struct vcpu_runstate_info *res)
 
        BUG_ON(preemptible());
 
-       state = &__get_cpu_var(runstate);
+       state = &__get_cpu_var(xen_runstate);
 
        /*
         * The runstate info is always updated by the hypervisor on
@@ -103,12 +103,12 @@ consider_steal_time(unsigned long new_itm)
         * This function just checks and reject this effect.
         */
        if (!time_after_eq(runstate.time[RUNSTATE_blocked],
-                          per_cpu(processed_blocked_time, cpu)))
+                          per_cpu(xen_blocked_time, cpu)))
                blocked = 0;
 
        if (!time_after_eq(runstate.time[RUNSTATE_runnable] +
                           runstate.time[RUNSTATE_offline],
-                          per_cpu(processed_stolen_time, cpu)))
+                          per_cpu(xen_stolen_time, cpu)))
                stolen = 0;
 
        if (!time_after(delta_itm + new_itm, ia64_get_itc()))
@@ -147,8 +147,8 @@ consider_steal_time(unsigned long new_itm)
                } else {
                        local_cpu_data->itm_next = delta_itm + new_itm;
                }
-               per_cpu(processed_stolen_time, cpu) += NS_PER_TICK * stolen;
-               per_cpu(processed_blocked_time, cpu) += NS_PER_TICK * blocked;
+               per_cpu(xen_stolen_time, cpu) += NS_PER_TICK * stolen;
+               per_cpu(xen_blocked_time, cpu) += NS_PER_TICK * blocked;
        }
        return delta_itm;
 }
index fe60e1a..aca0e28 100644 (file)
@@ -83,9 +83,9 @@
 #define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_END KMAP_START
 #else
-extern unsigned long vmalloc_end;
+extern unsigned long m68k_vmalloc_end;
 #define VMALLOC_START 0x0f800000
-#define VMALLOC_END vmalloc_end
+#define VMALLOC_END m68k_vmalloc_end
 #endif /* CONFIG_SUN3 */
 
 /* zero page used for uninitialized stuff */
index 3cd1939..94f81ec 100644 (file)
@@ -45,8 +45,8 @@
 ** Globals
 */
 
-unsigned long vmalloc_end;
-EXPORT_SYMBOL(vmalloc_end);
+unsigned long m68k_vmalloc_end;
+EXPORT_SYMBOL(m68k_vmalloc_end);
 
 unsigned long pmeg_vaddr[PMEGS_NUM];
 unsigned char pmeg_alloc[PMEGS_NUM];
@@ -172,8 +172,8 @@ void mmu_emu_init(unsigned long bootmem_end)
 #endif
                        // the lowest mapping here is the end of our
                        // vmalloc region
-                       if(!vmalloc_end)
-                               vmalloc_end = seg;
+                       if (!m68k_vmalloc_end)
+                               m68k_vmalloc_end = seg;
 
                        // mark the segmap alloc'd, and reserve any
                        // of the first 0xbff pages the hardware is
index dacafab..67e6389 100644 (file)
@@ -31,13 +31,13 @@ const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist);
 #define KPROBE_HIT_ACTIVE      0x00000001
 #define KPROBE_HIT_SS          0x00000002
 
-static struct kprobe *current_kprobe;
-static unsigned long current_kprobe_orig_pc;
-static unsigned long current_kprobe_next_pc;
-static int current_kprobe_ss_flags;
+static struct kprobe *cur_kprobe;
+static unsigned long cur_kprobe_orig_pc;
+static unsigned long cur_kprobe_next_pc;
+static int cur_kprobe_ss_flags;
 static unsigned long kprobe_status;
-static kprobe_opcode_t current_kprobe_ss_buf[MAX_INSN_SIZE + 2];
-static unsigned long current_kprobe_bp_addr;
+static kprobe_opcode_t cur_kprobe_ss_buf[MAX_INSN_SIZE + 2];
+static unsigned long cur_kprobe_bp_addr;
 
 DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
 
@@ -399,26 +399,25 @@ void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 {
        unsigned long nextpc;
 
-       current_kprobe_orig_pc = regs->pc;
-       memcpy(current_kprobe_ss_buf, &p->ainsn.insn[0], MAX_INSN_SIZE);
-       regs->pc = (unsigned long) current_kprobe_ss_buf;
+       cur_kprobe_orig_pc = regs->pc;
+       memcpy(cur_kprobe_ss_buf, &p->ainsn.insn[0], MAX_INSN_SIZE);
+       regs->pc = (unsigned long) cur_kprobe_ss_buf;
 
-       nextpc = find_nextpc(regs, &current_kprobe_ss_flags);
-       if (current_kprobe_ss_flags & SINGLESTEP_PCREL)
-               current_kprobe_next_pc =
-                       current_kprobe_orig_pc + (nextpc - regs->pc);
+       nextpc = find_nextpc(regs, &cur_kprobe_ss_flags);
+       if (cur_kprobe_ss_flags & SINGLESTEP_PCREL)
+               cur_kprobe_next_pc = cur_kprobe_orig_pc + (nextpc - regs->pc);
        else
-               current_kprobe_next_pc = nextpc;
+               cur_kprobe_next_pc = nextpc;
 
        /* branching instructions need special handling */
-       if (current_kprobe_ss_flags & SINGLESTEP_BRANCH)
+       if (cur_kprobe_ss_flags & SINGLESTEP_BRANCH)
                nextpc = singlestep_branch_setup(regs);
 
-       current_kprobe_bp_addr = nextpc;
+       cur_kprobe_bp_addr = nextpc;
 
        *(u8 *) nextpc = BREAKPOINT_INSTRUCTION;
-       mn10300_dcache_flush_range2((unsigned) current_kprobe_ss_buf,
-                                   sizeof(current_kprobe_ss_buf));
+       mn10300_dcache_flush_range2((unsigned) cur_kprobe_ss_buf,
+                                   sizeof(cur_kprobe_ss_buf));
        mn10300_icache_inv();
 }
 
@@ -440,7 +439,7 @@ static inline int __kprobes kprobe_handler(struct pt_regs *regs)
                        disarm_kprobe(p, regs);
                        ret = 1;
                } else {
-                       p = current_kprobe;
+                       p = cur_kprobe;
                        if (p->break_handler && p->break_handler(p, regs))
                                goto ss_probe;
                }
@@ -464,7 +463,7 @@ static inline int __kprobes kprobe_handler(struct pt_regs *regs)
        }
 
        kprobe_status = KPROBE_HIT_ACTIVE;
-       current_kprobe = p;
+       cur_kprobe = p;
        if (p->pre_handler(p, regs)) {
                /* handler has already set things up, so skip ss setup */
                return 1;
@@ -491,8 +490,8 @@ no_kprobe:
 static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
 {
        /* we may need to fixup regs/stack after singlestepping a call insn */
-       if (current_kprobe_ss_flags & SINGLESTEP_BRANCH) {
-               regs->pc = current_kprobe_orig_pc;
+       if (cur_kprobe_ss_flags & SINGLESTEP_BRANCH) {
+               regs->pc = cur_kprobe_orig_pc;
                switch (p->ainsn.insn[0]) {
                case 0xcd:      /* CALL (d16,PC) */
                        *(unsigned *) regs->sp = regs->mdr = regs->pc + 5;
@@ -523,8 +522,8 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
                }
        }
 
-       regs->pc = current_kprobe_next_pc;
-       current_kprobe_bp_addr = 0;
+       regs->pc = cur_kprobe_next_pc;
+       cur_kprobe_bp_addr = 0;
 }
 
 static inline int __kprobes post_kprobe_handler(struct pt_regs *regs)
@@ -532,10 +531,10 @@ static inline int __kprobes post_kprobe_handler(struct pt_regs *regs)
        if (!kprobe_running())
                return 0;
 
-       if (current_kprobe->post_handler)
-               current_kprobe->post_handler(current_kprobe, regs, 0);
+       if (cur_kprobe->post_handler)
+               cur_kprobe->post_handler(cur_kprobe, regs, 0);
 
-       resume_execution(current_kprobe, regs);
+       resume_execution(cur_kprobe, regs);
        reset_current_kprobe();
        preempt_enable_no_resched();
        return 1;
@@ -545,12 +544,12 @@ static inline int __kprobes post_kprobe_handler(struct pt_regs *regs)
 static inline
 int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
-       if (current_kprobe->fault_handler &&
-           current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+       if (cur_kprobe->fault_handler &&
+           cur_kprobe->fault_handler(cur_kprobe, regs, trapnr))
                return 1;
 
        if (kprobe_status & KPROBE_HIT_SS) {
-               resume_execution(current_kprobe, regs);
+               resume_execution(cur_kprobe, regs);
                reset_current_kprobe();
                preempt_enable_no_resched();
        }
@@ -567,7 +566,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 
        switch (val) {
        case DIE_BREAKPOINT:
-               if (current_kprobe_bp_addr != args->regs->pc) {
+               if (cur_kprobe_bp_addr != args->regs->pc) {
                        if (kprobe_handler(args->regs))
                                return NOTIFY_STOP;
                } else {
index d9ea8d3..1d3b270 100644 (file)
@@ -37,7 +37,7 @@ extern void cpu_die(void);
 extern void smp_send_debugger_break(int cpu);
 extern void smp_message_recv(int);
 
-DECLARE_PER_CPU(unsigned int, pvr);
+DECLARE_PER_CPU(unsigned int, cpu_pvr);
 
 #ifdef CONFIG_HOTPLUG_CPU
 extern void fixup_irqs(cpumask_t map);
index 936f04d..a3c11ca 100644 (file)
@@ -487,11 +487,11 @@ static void perf_callchain_user_32(struct pt_regs *regs,
  * Since we can't get PMU interrupts inside a PMU interrupt handler,
  * we don't need separate irq and nmi entries here.
  */
-static DEFINE_PER_CPU(struct perf_callchain_entry, callchain);
+static DEFINE_PER_CPU(struct perf_callchain_entry, cpu_perf_callchain);
 
 struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
 {
-       struct perf_callchain_entry *entry = &__get_cpu_var(callchain);
+       struct perf_callchain_entry *entry = &__get_cpu_var(cpu_perf_callchain);
 
        entry->nr = 0;
 
index 845c72a..03dd6a2 100644 (file)
@@ -157,7 +157,7 @@ extern u32 cpu_temp_both(unsigned long cpu);
 #endif /* CONFIG_TAU */
 
 #ifdef CONFIG_SMP
-DEFINE_PER_CPU(unsigned int, pvr);
+DEFINE_PER_CPU(unsigned int, cpu_pvr);
 #endif
 
 static int show_cpuinfo(struct seq_file *m, void *v)
@@ -209,7 +209,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        }
 
 #ifdef CONFIG_SMP
-       pvr = per_cpu(pvr, cpu_id);
+       pvr = per_cpu(cpu_pvr, cpu_id);
 #else
        pvr = mfspr(SPRN_PVR);
 #endif
index 97196ee..a521fb8 100644 (file)
@@ -235,7 +235,7 @@ struct thread_info *current_set[NR_CPUS];
 
 static void __devinit smp_store_cpu_info(int id)
 {
-       per_cpu(pvr, id) = mfspr(SPRN_PVR);
+       per_cpu(cpu_pvr, id) = mfspr(SPRN_PVR);
 }
 
 static void __init smp_create_idle(unsigned int cpu)
index f9dbf76..7267eff 100644 (file)
@@ -54,7 +54,7 @@ struct iic {
        struct device_node *node;
 };
 
-static DEFINE_PER_CPU(struct iic, iic);
+static DEFINE_PER_CPU(struct iic, cpu_iic);
 #define IIC_NODE_COUNT 2
 static struct irq_host *iic_host;
 
@@ -82,7 +82,7 @@ static void iic_unmask(unsigned int irq)
 
 static void iic_eoi(unsigned int irq)
 {
-       struct iic *iic = &__get_cpu_var(iic);
+       struct iic *iic = &__get_cpu_var(cpu_iic);
        out_be64(&iic->regs->prio, iic->eoi_stack[--iic->eoi_ptr]);
        BUG_ON(iic->eoi_ptr < 0);
 }
@@ -146,7 +146,7 @@ static unsigned int iic_get_irq(void)
        struct iic *iic;
        unsigned int virq;
 
-       iic = &__get_cpu_var(iic);
+       iic = &__get_cpu_var(cpu_iic);
        *(unsigned long *) &pending =
                in_be64((u64 __iomem *) &iic->regs->pending_destr);
        if (!(pending.flags & CBE_IIC_IRQ_VALID))
@@ -161,12 +161,12 @@ static unsigned int iic_get_irq(void)
 
 void iic_setup_cpu(void)
 {
-       out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
+       out_be64(&__get_cpu_var(cpu_iic).regs->prio, 0xff);
 }
 
 u8 iic_get_target_id(int cpu)
 {
-       return per_cpu(iic, cpu).target_id;
+       return per_cpu(cpu_iic, cpu).target_id;
 }
 
 EXPORT_SYMBOL_GPL(iic_get_target_id);
@@ -181,7 +181,7 @@ static inline int iic_ipi_to_irq(int ipi)
 
 void iic_cause_IPI(int cpu, int mesg)
 {
-       out_be64(&per_cpu(iic, cpu).regs->generate, (0xf - mesg) << 4);
+       out_be64(&per_cpu(cpu_iic, cpu).regs->generate, (0xf - mesg) << 4);
 }
 
 struct irq_host *iic_get_irq_host(int node)
@@ -348,7 +348,7 @@ static void __init init_one_iic(unsigned int hw_cpu, unsigned long addr,
        /* XXX FIXME: should locate the linux CPU number from the HW cpu
         * number properly. We are lucky for now
         */
-       struct iic *iic = &per_cpu(iic, hw_cpu);
+       struct iic *iic = &per_cpu(cpu_iic, hw_cpu);
 
        iic->regs = ioremap(addr, sizeof(struct cbe_iic_thread_regs));
        BUG_ON(iic->regs == NULL);
index 937a544..c5f3116 100644 (file)
@@ -54,7 +54,7 @@ struct dtl {
        int                     buf_entries;
        u64                     last_idx;
 };
-static DEFINE_PER_CPU(struct dtl, dtl);
+static DEFINE_PER_CPU(struct dtl, cpu_dtl);
 
 /*
  * Dispatch trace log event mask:
@@ -261,7 +261,7 @@ static int dtl_init(void)
 
        /* set up the per-cpu log structures */
        for_each_possible_cpu(i) {
-               struct dtl *dtl = &per_cpu(dtl, i);
+               struct dtl *dtl = &per_cpu(cpu_dtl, i);
                dtl->cpu = i;
 
                rc = dtl_setup_file(dtl);
index b129611..f30f4a1 100644 (file)
@@ -47,7 +47,7 @@ static DEFINE_PER_CPU(short, wd_enabled);
 static int endflag __initdata;
 
 static DEFINE_PER_CPU(unsigned int, last_irq_sum);
-static DEFINE_PER_CPU(local_t, alert_counter);
+static DEFINE_PER_CPU(long, alert_counter);
 static DEFINE_PER_CPU(int, nmi_touch);
 
 void touch_nmi_watchdog(void)
@@ -112,13 +112,13 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
                touched = 1;
        }
        if (!touched && __get_cpu_var(last_irq_sum) == sum) {
-               local_inc(&__get_cpu_var(alert_counter));
-               if (local_read(&__get_cpu_var(alert_counter)) == 30 * nmi_hz)
+               __this_cpu_inc(per_cpu_var(alert_counter));
+               if (__this_cpu_read(per_cpu_var(alert_counter)) == 30 * nmi_hz)
                        die_nmi("BUG: NMI Watchdog detected LOCKUP",
                                regs, panic_on_timeout);
        } else {
                __get_cpu_var(last_irq_sum) = sum;
-               local_set(&__get_cpu_var(alert_counter), 0);
+               __this_cpu_write(per_cpu_var(alert_counter), 0);
        }
        if (__get_cpu_var(wd_enabled)) {
                write_pic(picl_value(nmi_hz));
index b65a36d..0c44196 100644 (file)
@@ -74,31 +74,31 @@ extern void __bad_percpu_size(void);
 
 #define percpu_to_op(op, var, val)                     \
 do {                                                   \
-       typedef typeof(var) T__;                        \
+       typedef typeof(var) pto_T__;                    \
        if (0) {                                        \
-               T__ tmp__;                              \
-               tmp__ = (val);                          \
+               pto_T__ pto_tmp__;                      \
+               pto_tmp__ = (val);                      \
        }                                               \
        switch (sizeof(var)) {                          \
        case 1:                                         \
                asm(op "b %1,"__percpu_arg(0)           \
                    : "+m" (var)                        \
-                   : "qi" ((T__)(val)));               \
+                   : "qi" ((pto_T__)(val)));           \
                break;                                  \
        case 2:                                         \
                asm(op "w %1,"__percpu_arg(0)           \
                    : "+m" (var)                        \
-                   : "ri" ((T__)(val)));               \
+                   : "ri" ((pto_T__)(val)));           \
                break;                                  \
        case 4:                                         \
                asm(op "l %1,"__percpu_arg(0)           \
                    : "+m" (var)                        \
-                   : "ri" ((T__)(val)));               \
+                   : "ri" ((pto_T__)(val)));           \
                break;                                  \
        case 8:                                         \
                asm(op "q %1,"__percpu_arg(0)           \
                    : "+m" (var)                        \
-                   : "re" ((T__)(val)));               \
+                   : "re" ((pto_T__)(val)));           \
                break;                                  \
        default: __bad_percpu_size();                   \
        }                                               \
@@ -106,31 +106,31 @@ do {                                                      \
 
 #define percpu_from_op(op, var, constraint)            \
 ({                                                     \
-       typeof(var) ret__;                              \
+       typeof(var) pfo_ret__;                          \
        switch (sizeof(var)) {                          \
        case 1:                                         \
                asm(op "b "__percpu_arg(1)",%0"         \
-                   : "=q" (ret__)                      \
+                   : "=q" (pfo_ret__)                  \
                    : constraint);                      \
                break;                                  \
        case 2:                                         \
                asm(op "w "__percpu_arg(1)",%0"         \
-                   : "=r" (ret__)                      \
+                   : "=r" (pfo_ret__)                  \
                    : constraint);                      \
                break;                                  \
        case 4:                                         \
                asm(op "l "__percpu_arg(1)",%0"         \
-                   : "=r" (ret__)                      \
+                   : "=r" (pfo_ret__)                  \
                    : constraint);                      \
                break;                                  \
        case 8:                                         \
                asm(op "q "__percpu_arg(1)",%0"         \
-                   : "=r" (ret__)                      \
+                   : "=r" (pfo_ret__)                  \
                    : constraint);                      \
                break;                                  \
        default: __bad_percpu_size();                   \
        }                                               \
-       ret__;                                          \
+       pfo_ret__;                                      \
 })
 
 /*
@@ -153,6 +153,84 @@ do {                                                       \
 #define percpu_or(var, val)    percpu_to_op("or", per_cpu__##var, val)
 #define percpu_xor(var, val)   percpu_to_op("xor", per_cpu__##var, val)
 
+#define __this_cpu_read_1(pcp)         percpu_from_op("mov", (pcp), "m"(pcp))
+#define __this_cpu_read_2(pcp)         percpu_from_op("mov", (pcp), "m"(pcp))
+#define __this_cpu_read_4(pcp)         percpu_from_op("mov", (pcp), "m"(pcp))
+
+#define __this_cpu_write_1(pcp, val)   percpu_to_op("mov", (pcp), val)
+#define __this_cpu_write_2(pcp, val)   percpu_to_op("mov", (pcp), val)
+#define __this_cpu_write_4(pcp, val)   percpu_to_op("mov", (pcp), val)
+#define __this_cpu_add_1(pcp, val)     percpu_to_op("add", (pcp), val)
+#define __this_cpu_add_2(pcp, val)     percpu_to_op("add", (pcp), val)
+#define __this_cpu_add_4(pcp, val)     percpu_to_op("add", (pcp), val)
+#define __this_cpu_and_1(pcp, val)     percpu_to_op("and", (pcp), val)
+#define __this_cpu_and_2(pcp, val)     percpu_to_op("and", (pcp), val)
+#define __this_cpu_and_4(pcp, val)     percpu_to_op("and", (pcp), val)
+#define __this_cpu_or_1(pcp, val)      percpu_to_op("or", (pcp), val)
+#define __this_cpu_or_2(pcp, val)      percpu_to_op("or", (pcp), val)
+#define __this_cpu_or_4(pcp, val)      percpu_to_op("or", (pcp), val)
+#define __this_cpu_xor_1(pcp, val)     percpu_to_op("xor", (pcp), val)
+#define __this_cpu_xor_2(pcp, val)     percpu_to_op("xor", (pcp), val)
+#define __this_cpu_xor_4(pcp, val)     percpu_to_op("xor", (pcp), val)
+
+#define this_cpu_read_1(pcp)           percpu_from_op("mov", (pcp), "m"(pcp))
+#define this_cpu_read_2(pcp)           percpu_from_op("mov", (pcp), "m"(pcp))
+#define this_cpu_read_4(pcp)           percpu_from_op("mov", (pcp), "m"(pcp))
+#define this_cpu_write_1(pcp, val)     percpu_to_op("mov", (pcp), val)
+#define this_cpu_write_2(pcp, val)     percpu_to_op("mov", (pcp), val)
+#define this_cpu_write_4(pcp, val)     percpu_to_op("mov", (pcp), val)
+#define this_cpu_add_1(pcp, val)       percpu_to_op("add", (pcp), val)
+#define this_cpu_add_2(pcp, val)       percpu_to_op("add", (pcp), val)
+#define this_cpu_add_4(pcp, val)       percpu_to_op("add", (pcp), val)
+#define this_cpu_and_1(pcp, val)       percpu_to_op("and", (pcp), val)
+#define this_cpu_and_2(pcp, val)       percpu_to_op("and", (pcp), val)
+#define this_cpu_and_4(pcp, val)       percpu_to_op("and", (pcp), val)
+#define this_cpu_or_1(pcp, val)                percpu_to_op("or", (pcp), val)
+#define this_cpu_or_2(pcp, val)                percpu_to_op("or", (pcp), val)
+#define this_cpu_or_4(pcp, val)                percpu_to_op("or", (pcp), val)
+#define this_cpu_xor_1(pcp, val)       percpu_to_op("xor", (pcp), val)
+#define this_cpu_xor_2(pcp, val)       percpu_to_op("xor", (pcp), val)
+#define this_cpu_xor_4(pcp, val)       percpu_to_op("xor", (pcp), val)
+
+#define irqsafe_cpu_add_1(pcp, val)    percpu_to_op("add", (pcp), val)
+#define irqsafe_cpu_add_2(pcp, val)    percpu_to_op("add", (pcp), val)
+#define irqsafe_cpu_add_4(pcp, val)    percpu_to_op("add", (pcp), val)
+#define irqsafe_cpu_and_1(pcp, val)    percpu_to_op("and", (pcp), val)
+#define irqsafe_cpu_and_2(pcp, val)    percpu_to_op("and", (pcp), val)
+#define irqsafe_cpu_and_4(pcp, val)    percpu_to_op("and", (pcp), val)
+#define irqsafe_cpu_or_1(pcp, val)     percpu_to_op("or", (pcp), val)
+#define irqsafe_cpu_or_2(pcp, val)     percpu_to_op("or", (pcp), val)
+#define irqsafe_cpu_or_4(pcp, val)     percpu_to_op("or", (pcp), val)
+#define irqsafe_cpu_xor_1(pcp, val)    percpu_to_op("xor", (pcp), val)
+#define irqsafe_cpu_xor_2(pcp, val)    percpu_to_op("xor", (pcp), val)
+#define irqsafe_cpu_xor_4(pcp, val)    percpu_to_op("xor", (pcp), val)
+
+/*
+ * Per cpu atomic 64 bit operations are only available under 64 bit.
+ * 32 bit must fall back to generic operations.
+ */
+#ifdef CONFIG_X86_64
+#define __this_cpu_read_8(pcp)         percpu_from_op("mov", (pcp), "m"(pcp))
+#define __this_cpu_write_8(pcp, val)   percpu_to_op("mov", (pcp), val)
+#define __this_cpu_add_8(pcp, val)     percpu_to_op("add", (pcp), val)
+#define __this_cpu_and_8(pcp, val)     percpu_to_op("and", (pcp), val)
+#define __this_cpu_or_8(pcp, val)      percpu_to_op("or", (pcp), val)
+#define __this_cpu_xor_8(pcp, val)     percpu_to_op("xor", (pcp), val)
+
+#define this_cpu_read_8(pcp)           percpu_from_op("mov", (pcp), "m"(pcp))
+#define this_cpu_write_8(pcp, val)     percpu_to_op("mov", (pcp), val)
+#define this_cpu_add_8(pcp, val)       percpu_to_op("add", (pcp), val)
+#define this_cpu_and_8(pcp, val)       percpu_to_op("and", (pcp), val)
+#define this_cpu_or_8(pcp, val)                percpu_to_op("or", (pcp), val)
+#define this_cpu_xor_8(pcp, val)       percpu_to_op("xor", (pcp), val)
+
+#define irqsafe_cpu_add_8(pcp, val)    percpu_to_op("add", (pcp), val)
+#define irqsafe_cpu_and_8(pcp, val)    percpu_to_op("and", (pcp), val)
+#define irqsafe_cpu_or_8(pcp, val)     percpu_to_op("or", (pcp), val)
+#define irqsafe_cpu_xor_8(pcp, val)    percpu_to_op("xor", (pcp), val)
+
+#endif
+
 /* This is not atomic against other CPUs -- CPU preemption needs to be off */
 #define x86_test_and_clear_bit_percpu(bit, var)                                \
 ({                                                                     \
index 6389432..0159a69 100644 (file)
@@ -361,7 +361,7 @@ void stop_apic_nmi_watchdog(void *unused)
  */
 
 static DEFINE_PER_CPU(unsigned, last_irq_sum);
-static DEFINE_PER_CPU(local_t, alert_counter);
+static DEFINE_PER_CPU(long, alert_counter);
 static DEFINE_PER_CPU(int, nmi_touch);
 
 void touch_nmi_watchdog(void)
@@ -438,8 +438,8 @@ nmi_watchdog_tick(struct pt_regs *regs, unsigned reason)
                 * Ayiee, looks like this CPU is stuck ...
                 * wait a few IRQs (5 seconds) before doing the oops ...
                 */
-               local_inc(&__get_cpu_var(alert_counter));
-               if (local_read(&__get_cpu_var(alert_counter)) == 5 * nmi_hz)
+               __this_cpu_inc(per_cpu_var(alert_counter));
+               if (__this_cpu_read(per_cpu_var(alert_counter)) == 5 * nmi_hz)
                        /*
                         * die_nmi will return ONLY if NOTIFY_STOP happens..
                         */
@@ -447,7 +447,7 @@ nmi_watchdog_tick(struct pt_regs *regs, unsigned reason)
                                regs, panic_on_timeout);
        } else {
                __get_cpu_var(last_irq_sum) = sum;
-               local_set(&__get_cpu_var(alert_counter), 0);
+               __this_cpu_write(per_cpu_var(alert_counter), 0);
        }
 
        /* see if the nmi watchdog went off */
index c1afa99..20399b7 100644 (file)
@@ -1093,7 +1093,7 @@ static void clear_all_debug_regs(void)
 
 void __cpuinit cpu_init(void)
 {
-       struct orig_ist *orig_ist;
+       struct orig_ist *oist;
        struct task_struct *me;
        struct tss_struct *t;
        unsigned long v;
@@ -1102,7 +1102,7 @@ void __cpuinit cpu_init(void)
 
        cpu = stack_smp_processor_id();
        t = &per_cpu(init_tss, cpu);
-       orig_ist = &per_cpu(orig_ist, cpu);
+       oist = &per_cpu(orig_ist, cpu);
 
 #ifdef CONFIG_NUMA
        if (cpu != 0 && percpu_read(node_number) == 0 &&
@@ -1143,12 +1143,12 @@ void __cpuinit cpu_init(void)
        /*
         * set up and load the per-CPU TSS
         */
-       if (!orig_ist->ist[0]) {
+       if (!oist->ist[0]) {
                char *estacks = per_cpu(exception_stacks, cpu);
 
                for (v = 0; v < N_EXCEPTION_STACKS; v++) {
                        estacks += exception_stack_sizes[v];
-                       orig_ist->ist[v] = t->x86_tss.ist[v] =
+                       oist->ist[v] = t->x86_tss.ist[v] =
                                        (unsigned long)estacks;
                }
        }
index dca325c..b368cd8 100644 (file)
@@ -30,9 +30,9 @@
 #include <asm/apic.h>
 #include <asm/desc.h>
 
-static DEFINE_PER_CPU(struct cpu_cpuX_base [CPU_REG_ALL_BIT], cpu_arr);
-static DEFINE_PER_CPU(struct cpu_private * [MAX_CPU_FILES], priv_arr);
-static DEFINE_PER_CPU(int, cpu_priv_count);
+static DEFINE_PER_CPU(struct cpu_cpuX_base [CPU_REG_ALL_BIT], cpud_arr);
+static DEFINE_PER_CPU(struct cpu_private * [MAX_CPU_FILES], cpud_priv_arr);
+static DEFINE_PER_CPU(int, cpud_priv_count);
 
 static DEFINE_MUTEX(cpu_debug_lock);
 
@@ -531,7 +531,7 @@ static int cpu_create_file(unsigned cpu, unsigned type, unsigned reg,
 
        /* Already intialized */
        if (file == CPU_INDEX_BIT)
-               if (per_cpu(cpu_arr[type].init, cpu))
+               if (per_cpu(cpud_arr[type].init, cpu))
                        return 0;
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -543,8 +543,8 @@ static int cpu_create_file(unsigned cpu, unsigned type, unsigned reg,
        priv->reg = reg;
        priv->file = file;
        mutex_lock(&cpu_debug_lock);
-       per_cpu(priv_arr[type], cpu) = priv;
-       per_cpu(cpu_priv_count, cpu)++;
+       per_cpu(cpud_priv_arr[type], cpu) = priv;
+       per_cpu(cpud_priv_count, cpu)++;
        mutex_unlock(&cpu_debug_lock);
 
        if (file)
@@ -552,10 +552,10 @@ static int cpu_create_file(unsigned cpu, unsigned type, unsigned reg,
                                    dentry, (void *)priv, &cpu_fops);
        else {
                debugfs_create_file(cpu_base[type].name, S_IRUGO,
-                                   per_cpu(cpu_arr[type].dentry, cpu),
+                                   per_cpu(cpud_arr[type].dentry, cpu),
                                    (void *)priv, &cpu_fops);
                mutex_lock(&cpu_debug_lock);
-               per_cpu(cpu_arr[type].init, cpu) = 1;
+               per_cpu(cpud_arr[type].init, cpu) = 1;
                mutex_unlock(&cpu_debug_lock);
        }
 
@@ -615,7 +615,7 @@ static int cpu_init_allreg(unsigned cpu, struct dentry *dentry)
                if (!is_typeflag_valid(cpu, cpu_base[type].flag))
                        continue;
                cpu_dentry = debugfs_create_dir(cpu_base[type].name, dentry);
-               per_cpu(cpu_arr[type].dentry, cpu) = cpu_dentry;
+               per_cpu(cpud_arr[type].dentry, cpu) = cpu_dentry;
 
                if (type < CPU_TSS_BIT)
                        err = cpu_init_msr(cpu, type, cpu_dentry);
@@ -647,11 +647,11 @@ static int cpu_init_cpu(void)
                err = cpu_init_allreg(cpu, cpu_dentry);
 
                pr_info("cpu%d(%d) debug files %d\n",
-                       cpu, nr_cpu_ids, per_cpu(cpu_priv_count, cpu));
-               if (per_cpu(cpu_priv_count, cpu) > MAX_CPU_FILES) {
+                       cpu, nr_cpu_ids, per_cpu(cpud_priv_count, cpu));
+               if (per_cpu(cpud_priv_count, cpu) > MAX_CPU_FILES) {
                        pr_err("Register files count %d exceeds limit %d\n",
-                               per_cpu(cpu_priv_count, cpu), MAX_CPU_FILES);
-                       per_cpu(cpu_priv_count, cpu) = MAX_CPU_FILES;
+                               per_cpu(cpud_priv_count, cpu), MAX_CPU_FILES);
+                       per_cpu(cpud_priv_count, cpu) = MAX_CPU_FILES;
                        err = -ENFILE;
                }
                if (err)
@@ -676,8 +676,8 @@ static void __exit cpu_debug_exit(void)
                debugfs_remove_recursive(cpu_debugfs_dir);
 
        for (cpu = 0; cpu <  nr_cpu_ids; cpu++)
-               for (i = 0; i < per_cpu(cpu_priv_count, cpu); i++)
-                       kfree(per_cpu(priv_arr[i], cpu));
+               for (i = 0; i < per_cpu(cpud_priv_count, cpu); i++)
+                       kfree(per_cpu(cpud_priv_arr[i], cpu));
 }
 
 module_init(cpu_debug_init);
index d2e7c77..f28decf 100644 (file)
@@ -68,9 +68,9 @@ struct acpi_cpufreq_data {
        unsigned int cpu_feature;
 };
 
-static DEFINE_PER_CPU(struct acpi_cpufreq_data *, drv_data);
+static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data);
 
-static DEFINE_PER_CPU(struct aperfmperf, old_perf);
+static DEFINE_PER_CPU(struct aperfmperf, acfreq_old_perf);
 
 /* acpi_perf_data is a pointer to percpu data. */
 static struct acpi_processor_performance *acpi_perf_data;
@@ -214,14 +214,14 @@ static u32 get_cur_val(const struct cpumask *mask)
        if (unlikely(cpumask_empty(mask)))
                return 0;
 
-       switch (per_cpu(drv_data, cpumask_first(mask))->cpu_feature) {
+       switch (per_cpu(acfreq_data, cpumask_first(mask))->cpu_feature) {
        case SYSTEM_INTEL_MSR_CAPABLE:
                cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
                cmd.addr.msr.reg = MSR_IA32_PERF_STATUS;
                break;
        case SYSTEM_IO_CAPABLE:
                cmd.type = SYSTEM_IO_CAPABLE;
-               perf = per_cpu(drv_data, cpumask_first(mask))->acpi_data;
+               perf = per_cpu(acfreq_data, cpumask_first(mask))->acpi_data;
                cmd.addr.io.port = perf->control_register.address;
                cmd.addr.io.bit_width = perf->control_register.bit_width;
                break;
@@ -268,8 +268,8 @@ static unsigned int get_measured_perf(struct cpufreq_policy *policy,
        if (smp_call_function_single(cpu, read_measured_perf_ctrs, &perf, 1))
                return 0;
 
-       ratio = calc_aperfmperf_ratio(&per_cpu(old_perf, cpu), &perf);
-       per_cpu(old_perf, cpu) = perf;
+       ratio = calc_aperfmperf_ratio(&per_cpu(acfreq_old_perf, cpu), &perf);
+       per_cpu(acfreq_old_perf, cpu) = perf;
 
        retval = (policy->cpuinfo.max_freq * ratio) >> APERFMPERF_SHIFT;
 
@@ -278,7 +278,7 @@ static unsigned int get_measured_perf(struct cpufreq_policy *policy,
 
 static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
 {
-       struct acpi_cpufreq_data *data = per_cpu(drv_data, cpu);
+       struct acpi_cpufreq_data *data = per_cpu(acfreq_data, cpu);
        unsigned int freq;
        unsigned int cached_freq;
 
@@ -322,7 +322,7 @@ static unsigned int check_freqs(const struct cpumask *mask, unsigned int freq,
 static int acpi_cpufreq_target(struct cpufreq_policy *policy,
                               unsigned int target_freq, unsigned int relation)
 {
-       struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu);
+       struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
        struct acpi_processor_performance *perf;
        struct cpufreq_freqs freqs;
        struct drv_cmd cmd;
@@ -416,7 +416,7 @@ out:
 
 static int acpi_cpufreq_verify(struct cpufreq_policy *policy)
 {
-       struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu);
+       struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
 
        dprintk("acpi_cpufreq_verify\n");
 
@@ -574,7 +574,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
                return -ENOMEM;
 
        data->acpi_data = per_cpu_ptr(acpi_perf_data, cpu);
-       per_cpu(drv_data, cpu) = data;
+       per_cpu(acfreq_data, cpu) = data;
 
        if (cpu_has(c, X86_FEATURE_CONSTANT_TSC))
                acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
@@ -725,20 +725,20 @@ err_unreg:
        acpi_processor_unregister_performance(perf, cpu);
 err_free:
        kfree(data);
-       per_cpu(drv_data, cpu) = NULL;
+       per_cpu(acfreq_data, cpu) = NULL;
 
        return result;
 }
 
 static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 {
-       struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu);
+       struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
 
        dprintk("acpi_cpufreq_cpu_exit\n");
 
        if (data) {
                cpufreq_frequency_table_put_attr(policy->cpu);
-               per_cpu(drv_data, policy->cpu) = NULL;
+               per_cpu(acfreq_data, policy->cpu) = NULL;
                acpi_processor_unregister_performance(data->acpi_data,
                                                      policy->cpu);
                kfree(data);
@@ -749,7 +749,7 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 
 static int acpi_cpufreq_resume(struct cpufreq_policy *policy)
 {
-       struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu);
+       struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
 
        dprintk("acpi_cpufreq_resume\n");
 
index 6c40f6b..0c06bca 100644 (file)
@@ -499,8 +499,8 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
 #ifdef CONFIG_SYSFS
 
 /* pointer to _cpuid4_info array (for each cache leaf) */
-static DEFINE_PER_CPU(struct _cpuid4_info *, cpuid4_info);
-#define CPUID4_INFO_IDX(x, y)  (&((per_cpu(cpuid4_info, x))[y]))
+static DEFINE_PER_CPU(struct _cpuid4_info *, ici_cpuid4_info);
+#define CPUID4_INFO_IDX(x, y)  (&((per_cpu(ici_cpuid4_info, x))[y]))
 
 #ifdef CONFIG_SMP
 static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
@@ -513,7 +513,7 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
        if ((index == 3) && (c->x86_vendor == X86_VENDOR_AMD)) {
                struct cpuinfo_x86 *d;
                for_each_online_cpu(i) {
-                       if (!per_cpu(cpuid4_info, i))
+                       if (!per_cpu(ici_cpuid4_info, i))
                                continue;
                        d = &cpu_data(i);
                        this_leaf = CPUID4_INFO_IDX(i, index);
@@ -535,7 +535,7 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
                            c->apicid >> index_msb) {
                                cpumask_set_cpu(i,
                                        to_cpumask(this_leaf->shared_cpu_map));
-                               if (i != cpu && per_cpu(cpuid4_info, i))  {
+                               if (i != cpu && per_cpu(ici_cpuid4_info, i))  {
                                        sibling_leaf =
                                                CPUID4_INFO_IDX(i, index);
                                        cpumask_set_cpu(cpu, to_cpumask(
@@ -574,8 +574,8 @@ static void __cpuinit free_cache_attributes(unsigned int cpu)
        for (i = 0; i < num_cache_leaves; i++)
                cache_remove_shared_cpu_map(cpu, i);
 
-       kfree(per_cpu(cpuid4_info, cpu));
-       per_cpu(cpuid4_info, cpu) = NULL;
+       kfree(per_cpu(ici_cpuid4_info, cpu));
+       per_cpu(ici_cpuid4_info, cpu) = NULL;
 }
 
 static int
@@ -614,15 +614,15 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu)
        if (num_cache_leaves == 0)
                return -ENOENT;
 
-       per_cpu(cpuid4_info, cpu) = kzalloc(
+       per_cpu(ici_cpuid4_info, cpu) = kzalloc(
            sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL);
-       if (per_cpu(cpuid4_info, cpu) == NULL)
+       if (per_cpu(ici_cpuid4_info, cpu) == NULL)
                return -ENOMEM;
 
        smp_call_function_single(cpu, get_cpu_leaves, &retval, true);
        if (retval) {
-               kfree(per_cpu(cpuid4_info, cpu));
-               per_cpu(cpuid4_info, cpu) = NULL;
+               kfree(per_cpu(ici_cpuid4_info, cpu));
+               per_cpu(ici_cpuid4_info, cpu) = NULL;
        }
 
        return retval;
@@ -634,7 +634,7 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu)
 extern struct sysdev_class cpu_sysdev_class; /* from drivers/base/cpu.c */
 
 /* pointer to kobject for cpuX/cache */
-static DEFINE_PER_CPU(struct kobject *, cache_kobject);
+static DEFINE_PER_CPU(struct kobject *, ici_cache_kobject);
 
 struct _index_kobject {
        struct kobject kobj;
@@ -643,8 +643,8 @@ struct _index_kobject {
 };
 
 /* pointer to array of kobjects for cpuX/cache/indexY */
-static DEFINE_PER_CPU(struct _index_kobject *, index_kobject);
-#define INDEX_KOBJECT_PTR(x, y)                (&((per_cpu(index_kobject, x))[y]))
+static DEFINE_PER_CPU(struct _index_kobject *, ici_index_kobject);
+#define INDEX_KOBJECT_PTR(x, y)                (&((per_cpu(ici_index_kobject, x))[y]))
 
 #define show_one_plus(file_name, object, val)                          \
 static ssize_t show_##file_name                                                \
@@ -863,10 +863,10 @@ static struct kobj_type ktype_percpu_entry = {
 
 static void __cpuinit cpuid4_cache_sysfs_exit(unsigned int cpu)
 {
-       kfree(per_cpu(cache_kobject, cpu));
-       kfree(per_cpu(index_kobject, cpu));
-       per_cpu(cache_kobject, cpu) = NULL;
-       per_cpu(index_kobject, cpu) = NULL;
+       kfree(per_cpu(ici_cache_kobject, cpu));
+       kfree(per_cpu(ici_index_kobject, cpu));
+       per_cpu(ici_cache_kobject, cpu) = NULL;
+       per_cpu(ici_index_kobject, cpu) = NULL;
        free_cache_attributes(cpu);
 }
 
@@ -882,14 +882,14 @@ static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu)
                return err;
 
        /* Allocate all required memory */
-       per_cpu(cache_kobject, cpu) =
+       per_cpu(ici_cache_kobject, cpu) =
                kzalloc(sizeof(struct kobject), GFP_KERNEL);
-       if (unlikely(per_cpu(cache_kobject, cpu) == NULL))
+       if (unlikely(per_cpu(ici_cache_kobject, cpu) == NULL))
                goto err_out;
 
-       per_cpu(index_kobject, cpu) = kzalloc(
+       per_cpu(ici_index_kobject, cpu) = kzalloc(
            sizeof(struct _index_kobject) * num_cache_leaves, GFP_KERNEL);
-       if (unlikely(per_cpu(index_kobject, cpu) == NULL))
+       if (unlikely(per_cpu(ici_index_kobject, cpu) == NULL))
                goto err_out;
 
        return 0;
@@ -913,7 +913,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
        if (unlikely(retval < 0))
                return retval;
 
-       retval = kobject_init_and_add(per_cpu(cache_kobject, cpu),
+       retval = kobject_init_and_add(per_cpu(ici_cache_kobject, cpu),
                                      &ktype_percpu_entry,
                                      &sys_dev->kobj, "%s", "cache");
        if (retval < 0) {
@@ -927,12 +927,12 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
                this_object->index = i;
                retval = kobject_init_and_add(&(this_object->kobj),
                                              &ktype_cache,
-                                             per_cpu(cache_kobject, cpu),
+                                             per_cpu(ici_cache_kobject, cpu),
                                              "index%1lu", i);
                if (unlikely(retval)) {
                        for (j = 0; j < i; j++)
                                kobject_put(&(INDEX_KOBJECT_PTR(cpu, j)->kobj));
-                       kobject_put(per_cpu(cache_kobject, cpu));
+                       kobject_put(per_cpu(ici_cache_kobject, cpu));
                        cpuid4_cache_sysfs_exit(cpu);
                        return retval;
                }
@@ -940,7 +940,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
        }
        cpumask_set_cpu(cpu, to_cpumask(cache_dev_map));
 
-       kobject_uevent(per_cpu(cache_kobject, cpu), KOBJ_ADD);
+       kobject_uevent(per_cpu(ici_cache_kobject, cpu), KOBJ_ADD);
        return 0;
 }
 
@@ -949,7 +949,7 @@ static void __cpuinit cache_remove_dev(struct sys_device * sys_dev)
        unsigned int cpu = sys_dev->id;
        unsigned long i;
 
-       if (per_cpu(cpuid4_info, cpu) == NULL)
+       if (per_cpu(ici_cpuid4_info, cpu) == NULL)
                return;
        if (!cpumask_test_cpu(cpu, to_cpumask(cache_dev_map)))
                return;
@@ -957,7 +957,7 @@ static void __cpuinit cache_remove_dev(struct sys_device * sys_dev)
 
        for (i = 0; i < num_cache_leaves; i++)
                kobject_put(&(INDEX_KOBJECT_PTR(cpu, i)->kobj));
-       kobject_put(per_cpu(cache_kobject, cpu));
+       kobject_put(per_cpu(ici_cache_kobject, cpu));
        cpuid4_cache_sysfs_exit(cpu);
 }
 
index ef42a03..1c47390 100644 (file)
@@ -265,13 +265,13 @@ struct ds_context {
        int                     cpu;
 };
 
-static DEFINE_PER_CPU(struct ds_context *, cpu_context);
+static DEFINE_PER_CPU(struct ds_context *, cpu_ds_context);
 
 
 static struct ds_context *ds_get_context(struct task_struct *task, int cpu)
 {
        struct ds_context **p_context =
-               (task ? &task->thread.ds_ctx : &per_cpu(cpu_context, cpu));
+               (task ? &task->thread.ds_ctx : &per_cpu(cpu_ds_context, cpu));
        struct ds_context *context = NULL;
        struct ds_context *new_context = NULL;
 
index 3de0b37..1d9b338 100644 (file)
@@ -316,7 +316,7 @@ static void svm_hardware_disable(void *garbage)
 static int svm_hardware_enable(void *garbage)
 {
 
-       struct svm_cpu_data *svm_data;
+       struct svm_cpu_data *sd;
        uint64_t efer;
        struct descriptor_table gdt_descr;
        struct desc_struct *gdt;
@@ -331,63 +331,61 @@ static int svm_hardware_enable(void *garbage)
                       me);
                return -EINVAL;
        }
-       svm_data = per_cpu(svm_data, me);
+       sd = per_cpu(svm_data, me);
 
-       if (!svm_data) {
+       if (!sd) {
                printk(KERN_ERR "svm_hardware_enable: svm_data is NULL on %d\n",
                       me);
                return -EINVAL;
        }
 
-       svm_data->asid_generation = 1;
-       svm_data->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1;
-       svm_data->next_asid = svm_data->max_asid + 1;
+       sd->asid_generation = 1;
+       sd->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1;
+       sd->next_asid = sd->max_asid + 1;
 
        kvm_get_gdt(&gdt_descr);
        gdt = (struct desc_struct *)gdt_descr.base;
-       svm_data->tss_desc = (struct kvm_ldttss_desc *)(gdt + GDT_ENTRY_TSS);
+       sd->tss_desc = (struct kvm_ldttss_desc *)(gdt + GDT_ENTRY_TSS);
 
        wrmsrl(MSR_EFER, efer | EFER_SVME);
 
-       wrmsrl(MSR_VM_HSAVE_PA,
-              page_to_pfn(svm_data->save_area) << PAGE_SHIFT);
+       wrmsrl(MSR_VM_HSAVE_PA, page_to_pfn(sd->save_area) << PAGE_SHIFT);
 
        return 0;
 }
 
 static void svm_cpu_uninit(int cpu)
 {
-       struct svm_cpu_data *svm_data
-               = per_cpu(svm_data, raw_smp_processor_id());
+       struct svm_cpu_data *sd = per_cpu(svm_data, raw_smp_processor_id());
 
-       if (!svm_data)
+       if (!sd)
                return;
 
        per_cpu(svm_data, raw_smp_processor_id()) = NULL;
-       __free_page(svm_data->save_area);
-       kfree(svm_data);
+       __free_page(sd->save_area);
+       kfree(sd);
 }
 
 static int svm_cpu_init(int cpu)
 {
-       struct svm_cpu_data *svm_data;
+       struct svm_cpu_data *sd;
        int r;
 
-       svm_data = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL);
-       if (!svm_data)
+       sd = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL);
+       if (!sd)
                return -ENOMEM;
-       svm_data->cpu = cpu;
-       svm_data->save_area = alloc_page(GFP_KERNEL);
+       sd->cpu = cpu;
+       sd->save_area = alloc_page(GFP_KERNEL);
        r = -ENOMEM;
-       if (!svm_data->save_area)
+       if (!sd->save_area)
                goto err_1;
 
-       per_cpu(svm_data, cpu) = svm_data;
+       per_cpu(svm_data, cpu) = sd;
 
        return 0;
 
 err_1:
-       kfree(svm_data);
+       kfree(sd);
        return r;
 
 }
@@ -1092,16 +1090,16 @@ static void save_host_msrs(struct kvm_vcpu *vcpu)
 #endif
 }
 
-static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *svm_data)
+static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd)
 {
-       if (svm_data->next_asid > svm_data->max_asid) {
-               ++svm_data->asid_generation;
-               svm_data->next_asid = 1;
+       if (sd->next_asid > sd->max_asid) {
+               ++sd->asid_generation;
+               sd->next_asid = 1;
                svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
        }
 
-       svm->asid_generation = svm_data->asid_generation;
-       svm->vmcb->control.asid = svm_data->next_asid++;
+       svm->asid_generation = sd->asid_generation;
+       svm->vmcb->control.asid = sd->next_asid++;
 }
 
 static unsigned long svm_get_dr(struct kvm_vcpu *vcpu, int dr)
@@ -2429,8 +2427,8 @@ static void reload_tss(struct kvm_vcpu *vcpu)
 {
        int cpu = raw_smp_processor_id();
 
-       struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu);
-       svm_data->tss_desc->type = 9; /* available 32/64-bit TSS */
+       struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
+       sd->tss_desc->type = 9; /* available 32/64-bit TSS */
        load_TR_desc();
 }
 
@@ -2438,12 +2436,12 @@ static void pre_svm_run(struct vcpu_svm *svm)
 {
        int cpu = raw_smp_processor_id();
 
-       struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu);
+       struct svm_cpu_data *sd = per_cpu(svm_data, cpu);
 
        svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
        /* FIXME: handle wraparound of asid_generation */
-       if (svm->asid_generation != svm_data->asid_generation)
-               new_asid(svm, svm_data);
+       if (svm->asid_generation != sd->asid_generation)
+               new_asid(svm, sd);
 }
 
 static void svm_inject_nmi(struct kvm_vcpu *vcpu)
index 64757c0..563d205 100644 (file)
 
 cpumask_var_t xen_cpu_initialized_map;
 
-static DEFINE_PER_CPU(int, resched_irq);
-static DEFINE_PER_CPU(int, callfunc_irq);
-static DEFINE_PER_CPU(int, callfuncsingle_irq);
-static DEFINE_PER_CPU(int, debug_irq) = -1;
+static DEFINE_PER_CPU(int, xen_resched_irq);
+static DEFINE_PER_CPU(int, xen_callfunc_irq);
+static DEFINE_PER_CPU(int, xen_callfuncsingle_irq);
+static DEFINE_PER_CPU(int, xen_debug_irq) = -1;
 
 static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id);
 static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id);
@@ -103,7 +103,7 @@ static int xen_smp_intr_init(unsigned int cpu)
                                    NULL);
        if (rc < 0)
                goto fail;
-       per_cpu(resched_irq, cpu) = rc;
+       per_cpu(xen_resched_irq, cpu) = rc;
 
        callfunc_name = kasprintf(GFP_KERNEL, "callfunc%d", cpu);
        rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR,
@@ -114,7 +114,7 @@ static int xen_smp_intr_init(unsigned int cpu)
                                    NULL);
        if (rc < 0)
                goto fail;
-       per_cpu(callfunc_irq, cpu) = rc;
+       per_cpu(xen_callfunc_irq, cpu) = rc;
 
        debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu);
        rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, xen_debug_interrupt,
@@ -122,7 +122,7 @@ static int xen_smp_intr_init(unsigned int cpu)
                                     debug_name, NULL);
        if (rc < 0)
                goto fail;
-       per_cpu(debug_irq, cpu) = rc;
+       per_cpu(xen_debug_irq, cpu) = rc;
 
        callfunc_name = kasprintf(GFP_KERNEL, "callfuncsingle%d", cpu);
        rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_SINGLE_VECTOR,
@@ -133,19 +133,20 @@ static int xen_smp_intr_init(unsigned int cpu)
                                    NULL);
        if (rc < 0)
                goto fail;
-       per_cpu(callfuncsingle_irq, cpu) = rc;
+       per_cpu(xen_callfuncsingle_irq, cpu) = rc;
 
        return 0;
 
  fail:
-       if (per_cpu(resched_irq, cpu) >= 0)
-               unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
-       if (per_cpu(callfunc_irq, cpu) >= 0)
-               unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
-       if (per_cpu(debug_irq, cpu) >= 0)
-               unbind_from_irqhandler(per_cpu(debug_irq, cpu), NULL);
-       if (per_cpu(callfuncsingle_irq, cpu) >= 0)
-               unbind_from_irqhandler(per_cpu(callfuncsingle_irq, cpu), NULL);
+       if (per_cpu(xen_resched_irq, cpu) >= 0)
+               unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu), NULL);
+       if (per_cpu(xen_callfunc_irq, cpu) >= 0)
+               unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL);
+       if (per_cpu(xen_debug_irq, cpu) >= 0)
+               unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL);
+       if (per_cpu(xen_callfuncsingle_irq, cpu) >= 0)
+               unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu),
+                                      NULL);
 
        return rc;
 }
@@ -349,10 +350,10 @@ static void xen_cpu_die(unsigned int cpu)
                current->state = TASK_UNINTERRUPTIBLE;
                schedule_timeout(HZ/10);
        }
-       unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
-       unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
-       unbind_from_irqhandler(per_cpu(debug_irq, cpu), NULL);
-       unbind_from_irqhandler(per_cpu(callfuncsingle_irq, cpu), NULL);
+       unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu), NULL);
+       unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL);
+       unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL);
+       unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL);
        xen_uninit_lock_cpu(cpu);
        xen_teardown_timer(cpu);
 
index 9d1f853..0d3f07c 100644 (file)
 #define NS_PER_TICK    (1000000000LL / HZ)
 
 /* runstate info updated by Xen */
-static DEFINE_PER_CPU(struct vcpu_runstate_info, runstate);
+static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate);
 
 /* snapshots of runstate info */
-static DEFINE_PER_CPU(struct vcpu_runstate_info, runstate_snapshot);
+static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate_snapshot);
 
 /* unused ns of stolen and blocked time */
-static DEFINE_PER_CPU(u64, residual_stolen);
-static DEFINE_PER_CPU(u64, residual_blocked);
+static DEFINE_PER_CPU(u64, xen_residual_stolen);
+static DEFINE_PER_CPU(u64, xen_residual_blocked);
 
 /* return an consistent snapshot of 64-bit time/counter value */
 static u64 get64(const u64 *p)
@@ -79,7 +79,7 @@ static void get_runstate_snapshot(struct vcpu_runstate_info *res)
 
        BUG_ON(preemptible());
 
-       state = &__get_cpu_var(runstate);
+       state = &__get_cpu_var(xen_runstate);
 
        /*
         * The runstate info is always updated by the hypervisor on
@@ -97,14 +97,14 @@ static void get_runstate_snapshot(struct vcpu_runstate_info *res)
 /* return true when a vcpu could run but has no real cpu to run on */
 bool xen_vcpu_stolen(int vcpu)
 {
-       return per_cpu(runstate, vcpu).state == RUNSTATE_runnable;
+       return per_cpu(xen_runstate, vcpu).state == RUNSTATE_runnable;
 }
 
 void xen_setup_runstate_info(int cpu)
 {
        struct vcpu_register_runstate_memory_area area;
 
-       area.addr.v = &per_cpu(runstate, cpu);
+       area.addr.v = &per_cpu(xen_runstate, cpu);
 
        if (HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area,
                               cpu, &area))
@@ -122,7 +122,7 @@ static void do_stolen_accounting(void)
 
        WARN_ON(state.state != RUNSTATE_running);
 
-       snap = &__get_cpu_var(runstate_snapshot);
+       snap = &__get_cpu_var(xen_runstate_snapshot);
 
        /* work out how much time the VCPU has not been runn*ing*  */
        blocked = state.time[RUNSTATE_blocked] - snap->time[RUNSTATE_blocked];
@@ -133,24 +133,24 @@ static void do_stolen_accounting(void)
 
        /* Add the appropriate number of ticks of stolen time,
           including any left-overs from last time. */
-       stolen = runnable + offline + __get_cpu_var(residual_stolen);
+       stolen = runnable + offline + __get_cpu_var(xen_residual_stolen);
 
        if (stolen < 0)
                stolen = 0;
 
        ticks = iter_div_u64_rem(stolen, NS_PER_TICK, &stolen);
-       __get_cpu_var(residual_stolen) = stolen;
+       __get_cpu_var(xen_residual_stolen) = stolen;
        account_steal_ticks(ticks);
 
        /* Add the appropriate number of ticks of blocked time,
           including any left-overs from last time. */
-       blocked += __get_cpu_var(residual_blocked);
+       blocked += __get_cpu_var(xen_residual_blocked);
 
        if (blocked < 0)
                blocked = 0;
 
        ticks = iter_div_u64_rem(blocked, NS_PER_TICK, &blocked);
-       __get_cpu_var(residual_blocked) = blocked;
+       __get_cpu_var(xen_residual_blocked) = blocked;
        account_idle_ticks(ticks);
 }
 
index f8ae0d9..704c141 100644 (file)
@@ -99,7 +99,7 @@ static int cryptd_enqueue_request(struct cryptd_queue *queue,
        struct cryptd_cpu_queue *cpu_queue;
 
        cpu = get_cpu();
-       cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu);
+       cpu_queue = this_cpu_ptr(queue->cpu_queue);
        err = crypto_enqueue_request(&cpu_queue->queue, request);
        queue_work_on(cpu, kcrypto_wq, &cpu_queue->work);
        put_cpu();
index 27fd775..958bd15 100644 (file)
@@ -131,7 +131,7 @@ static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute
         * boot up and this data does not change there after. Hence this
         * operation should be safe. No locking required.
         */
-       addr = __pa(per_cpu_ptr(crash_notes, cpunum));
+       addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpunum));
        rc = sprintf(buf, "%Lx\n", addr);
        return rc;
 }
index f20668c..67bc2ec 100644 (file)
@@ -64,14 +64,14 @@ static DEFINE_SPINLOCK(cpufreq_driver_lock);
  * - Lock should not be held across
  *     __cpufreq_governor(data, CPUFREQ_GOV_STOP);
  */
-static DEFINE_PER_CPU(int, policy_cpu);
+static DEFINE_PER_CPU(int, cpufreq_policy_cpu);
 static DEFINE_PER_CPU(struct rw_semaphore, cpu_policy_rwsem);
 
 #define lock_policy_rwsem(mode, cpu)                                   \
 int lock_policy_rwsem_##mode                                           \
 (int cpu)                                                              \
 {                                                                      \
-       int policy_cpu = per_cpu(policy_cpu, cpu);                      \
+       int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu);              \
        BUG_ON(policy_cpu == -1);                                       \
        down_##mode(&per_cpu(cpu_policy_rwsem, policy_cpu));            \
        if (unlikely(!cpu_online(cpu))) {                               \
@@ -90,7 +90,7 @@ EXPORT_SYMBOL_GPL(lock_policy_rwsem_write);
 
 void unlock_policy_rwsem_read(int cpu)
 {
-       int policy_cpu = per_cpu(policy_cpu, cpu);
+       int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu);
        BUG_ON(policy_cpu == -1);
        up_read(&per_cpu(cpu_policy_rwsem, policy_cpu));
 }
@@ -98,7 +98,7 @@ EXPORT_SYMBOL_GPL(unlock_policy_rwsem_read);
 
 void unlock_policy_rwsem_write(int cpu)
 {
-       int policy_cpu = per_cpu(policy_cpu, cpu);
+       int policy_cpu = per_cpu(cpufreq_policy_cpu, cpu);
        BUG_ON(policy_cpu == -1);
        up_write(&per_cpu(cpu_policy_rwsem, policy_cpu));
 }
@@ -818,7 +818,7 @@ static int cpufreq_add_dev_policy(unsigned int cpu,
 
                        /* Set proper policy_cpu */
                        unlock_policy_rwsem_write(cpu);
-                       per_cpu(policy_cpu, cpu) = managed_policy->cpu;
+                       per_cpu(cpufreq_policy_cpu, cpu) = managed_policy->cpu;
 
                        if (lock_policy_rwsem_write(cpu) < 0) {
                                /* Should not go through policy unlock path */
@@ -932,7 +932,7 @@ static int cpufreq_add_dev_interface(unsigned int cpu,
        if (!cpu_online(j))
                continue;
                per_cpu(cpufreq_cpu_data, j) = policy;
-               per_cpu(policy_cpu, j) = policy->cpu;
+               per_cpu(cpufreq_policy_cpu, j) = policy->cpu;
        }
        spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
@@ -1020,7 +1020,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
        cpumask_copy(policy->cpus, cpumask_of(cpu));
 
        /* Initially set CPU itself as the policy_cpu */
-       per_cpu(policy_cpu, cpu) = cpu;
+       per_cpu(cpufreq_policy_cpu, cpu) = cpu;
        ret = (lock_policy_rwsem_write(cpu) < 0);
        WARN_ON(ret);
 
@@ -2002,7 +2002,7 @@ static int __init cpufreq_core_init(void)
        int cpu;
 
        for_each_possible_cpu(cpu) {
-               per_cpu(policy_cpu, cpu) = -1;
+               per_cpu(cpufreq_policy_cpu, cpu) = -1;
                init_rwsem(&per_cpu(cpu_policy_rwsem, cpu));
        }
 
index a9bd3a0..0543221 100644 (file)
@@ -174,7 +174,7 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
 
-static DEFINE_PER_CPU(struct cpufreq_frequency_table *, show_table);
+static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table);
 /**
  * show_available_freqs - show available frequencies for the specified CPU
  */
@@ -185,10 +185,10 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf)
        ssize_t count = 0;
        struct cpufreq_frequency_table *table;
 
-       if (!per_cpu(show_table, cpu))
+       if (!per_cpu(cpufreq_show_table, cpu))
                return -ENODEV;
 
-       table = per_cpu(show_table, cpu);
+       table = per_cpu(cpufreq_show_table, cpu);
 
        for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
                if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
@@ -217,20 +217,20 @@ void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
                                      unsigned int cpu)
 {
        dprintk("setting show_table for cpu %u to %p\n", cpu, table);
-       per_cpu(show_table, cpu) = table;
+       per_cpu(cpufreq_show_table, cpu) = table;
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);
 
 void cpufreq_frequency_table_put_attr(unsigned int cpu)
 {
        dprintk("clearing show_table for cpu %u\n", cpu);
-       per_cpu(show_table, cpu) = NULL;
+       per_cpu(cpufreq_show_table, cpu) = NULL;
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
 
 struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu)
 {
-       return per_cpu(show_table, cpu);
+       return per_cpu(cpufreq_show_table, cpu);
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table);
 
index 84c51e1..8c2f370 100644 (file)
@@ -64,7 +64,7 @@ struct aes_ctx {
        u32 *D;
 };
 
-static DEFINE_PER_CPU(struct cword *, last_cword);
+static DEFINE_PER_CPU(struct cword *, paes_last_cword);
 
 /* Tells whether the ACE is capable to generate
    the extended key for a given key_len. */
@@ -152,9 +152,9 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
 
 ok:
        for_each_online_cpu(cpu)
-               if (&ctx->cword.encrypt == per_cpu(last_cword, cpu) ||
-                   &ctx->cword.decrypt == per_cpu(last_cword, cpu))
-                       per_cpu(last_cword, cpu) = NULL;
+               if (&ctx->cword.encrypt == per_cpu(paes_last_cword, cpu) ||
+                   &ctx->cword.decrypt == per_cpu(paes_last_cword, cpu))
+                       per_cpu(paes_last_cword, cpu) = NULL;
 
        return 0;
 }
@@ -166,7 +166,7 @@ static inline void padlock_reset_key(struct cword *cword)
 {
        int cpu = raw_smp_processor_id();
 
-       if (cword != per_cpu(last_cword, cpu))
+       if (cword != per_cpu(paes_last_cword, cpu))
 #ifndef CONFIG_X86_64
                asm volatile ("pushfl; popfl");
 #else
@@ -176,7 +176,7 @@ static inline void padlock_reset_key(struct cword *cword)
 
 static inline void padlock_store_cword(struct cword *cword)
 {
-       per_cpu(last_cword, raw_smp_processor_id()) = cword;
+       per_cpu(paes_last_cword, raw_smp_processor_id()) = cword;
 }
 
 /*
index 8f99354..6f51a0a 100644 (file)
@@ -326,14 +326,7 @@ arch_initcall(dma_channel_table_init);
  */
 struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type)
 {
-       struct dma_chan *chan;
-       int cpu;
-
-       cpu = get_cpu();
-       chan = per_cpu_ptr(channel_table[tx_type], cpu)->chan;
-       put_cpu();
-
-       return chan;
+       return this_cpu_read(channel_table[tx_type]->chan);
 }
 EXPORT_SYMBOL(dma_find_channel);
 
@@ -857,7 +850,6 @@ dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest,
        struct dma_async_tx_descriptor *tx;
        dma_addr_t dma_dest, dma_src;
        dma_cookie_t cookie;
-       int cpu;
        unsigned long flags;
 
        dma_src = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE);
@@ -876,10 +868,10 @@ dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest,
        tx->callback = NULL;
        cookie = tx->tx_submit(tx);
 
-       cpu = get_cpu();
-       per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
-       per_cpu_ptr(chan->local, cpu)->memcpy_count++;
-       put_cpu();
+       preempt_disable();
+       __this_cpu_add(chan->local->bytes_transferred, len);
+       __this_cpu_inc(chan->local->memcpy_count);
+       preempt_enable();
 
        return cookie;
 }
@@ -906,7 +898,6 @@ dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page,
        struct dma_async_tx_descriptor *tx;
        dma_addr_t dma_dest, dma_src;
        dma_cookie_t cookie;
-       int cpu;
        unsigned long flags;
 
        dma_src = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE);
@@ -923,10 +914,10 @@ dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page,
        tx->callback = NULL;
        cookie = tx->tx_submit(tx);
 
-       cpu = get_cpu();
-       per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
-       per_cpu_ptr(chan->local, cpu)->memcpy_count++;
-       put_cpu();
+       preempt_disable();
+       __this_cpu_add(chan->local->bytes_transferred, len);
+       __this_cpu_inc(chan->local->memcpy_count);
+       preempt_enable();
 
        return cookie;
 }
@@ -955,7 +946,6 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
        struct dma_async_tx_descriptor *tx;
        dma_addr_t dma_dest, dma_src;
        dma_cookie_t cookie;
-       int cpu;
        unsigned long flags;
 
        dma_src = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE);
@@ -973,10 +963,10 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
        tx->callback = NULL;
        cookie = tx->tx_submit(tx);
 
-       cpu = get_cpu();
-       per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
-       per_cpu_ptr(chan->local, cpu)->memcpy_count++;
-       put_cpu();
+       preempt_disable();
+       __this_cpu_add(chan->local->bytes_transferred, len);
+       __this_cpu_inc(chan->local->memcpy_count);
+       preempt_enable();
 
        return cookie;
 }
index 4b89b79..42be0b1 100644 (file)
@@ -826,8 +826,7 @@ static void __cpuinit take_over_work(struct ehca_comp_pool *pool, int cpu)
                cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
 
                list_del(&cq->entry);
-               __queue_comp_task(cq, per_cpu_ptr(pool->cpu_comp_tasks,
-                                                 smp_processor_id()));
+               __queue_comp_task(cq, this_cpu_ptr(pool->cpu_comp_tasks));
        }
 
        spin_unlock_irqrestore(&cct->task_lock, flags_cct);
index 6ae3888..fb2b7ef 100644 (file)
@@ -69,7 +69,7 @@ static struct lguest_pages *lguest_pages(unsigned int cpu)
                  (SWITCHER_ADDR + SHARED_SWITCHER_PAGES*PAGE_SIZE))[cpu]);
 }
 
-static DEFINE_PER_CPU(struct lg_cpu *, last_cpu);
+static DEFINE_PER_CPU(struct lg_cpu *, lg_last_cpu);
 
 /*S:010
  * We approach the Switcher.
@@ -90,8 +90,8 @@ static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages)
         * meanwhile).  If that's not the case, we pretend everything in the
         * Guest has changed.
         */
-       if (__get_cpu_var(last_cpu) != cpu || cpu->last_pages != pages) {
-               __get_cpu_var(last_cpu) = cpu;
+       if (__get_cpu_var(lg_last_cpu) != cpu || cpu->last_pages != pages) {
+               __get_cpu_var(lg_last_cpu) = cpu;
                cpu->last_pages = pages;
                cpu->changed = CHANGED_ALL;
        }
index 8c658cf..109d278 100644 (file)
@@ -1378,7 +1378,7 @@ static void sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len)
        }
        __skb_pull(skb, sizeof(*p));
 
-       st = per_cpu_ptr(sge->port_stats[p->iff], smp_processor_id());
+       st = this_cpu_ptr(sge->port_stats[p->iff]);
 
        skb->protocol = eth_type_trans(skb, adapter->port[p->iff].dev);
        if ((adapter->flags & RX_CSUM_ENABLED) && p->csum == 0xffff &&
@@ -1780,8 +1780,7 @@ netdev_tx_t t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct adapter *adapter = dev->ml_priv;
        struct sge *sge = adapter->sge;
-       struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port],
-                                               smp_processor_id());
+       struct sge_port_stats *st = this_cpu_ptr(sge->port_stats[dev->if_port]);
        struct cpl_tx_pkt *cpl;
        struct sk_buff *orig_skb = skb;
        int ret;
index eae4ad7..b9fcc98 100644 (file)
@@ -81,7 +81,7 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
 
        /* it's OK to use per_cpu_ptr() because BHs are off */
        pcpu_lstats = dev->ml_priv;
-       lb_stats = per_cpu_ptr(pcpu_lstats, smp_processor_id());
+       lb_stats = this_cpu_ptr(pcpu_lstats);
 
        len = skb->len;
        if (likely(netif_rx(skb) == NET_RX_SUCCESS)) {
index 63099c5..3a15de5 100644 (file)
@@ -153,15 +153,14 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
        struct net_device *rcv = NULL;
        struct veth_priv *priv, *rcv_priv;
        struct veth_net_stats *stats, *rcv_stats;
-       int length, cpu;
+       int length;
 
        priv = netdev_priv(dev);
        rcv = priv->peer;
        rcv_priv = netdev_priv(rcv);
 
-       cpu = smp_processor_id();
-       stats = per_cpu_ptr(priv->stats, cpu);
-       rcv_stats = per_cpu_ptr(rcv_priv->stats, cpu);
+       stats = this_cpu_ptr(priv->stats);
+       rcv_stats = this_cpu_ptr(rcv_priv->stats);
 
        if (!(rcv->flags & IFF_UP))
                goto tx_drop;
index a7aae24..166b67e 100644 (file)
@@ -47,7 +47,7 @@
  */
 static struct ring_buffer *op_ring_buffer_read;
 static struct ring_buffer *op_ring_buffer_write;
-DEFINE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer);
+DEFINE_PER_CPU(struct oprofile_cpu_buffer, op_cpu_buffer);
 
 static void wq_sync_buffer(struct work_struct *work);
 
@@ -61,8 +61,7 @@ unsigned long oprofile_get_cpu_buffer_size(void)
 
 void oprofile_cpu_buffer_inc_smpl_lost(void)
 {
-       struct oprofile_cpu_buffer *cpu_buf
-               = &__get_cpu_var(cpu_buffer);
+       struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer);
 
        cpu_buf->sample_lost_overflow++;
 }
@@ -95,7 +94,7 @@ int alloc_cpu_buffers(void)
                goto fail;
 
        for_each_possible_cpu(i) {
-               struct oprofile_cpu_buffer *b = &per_cpu(cpu_buffer, i);
+               struct oprofile_cpu_buffer *b = &per_cpu(op_cpu_buffer, i);
 
                b->last_task = NULL;
                b->last_is_kernel = -1;
@@ -122,7 +121,7 @@ void start_cpu_work(void)
        work_enabled = 1;
 
        for_each_online_cpu(i) {
-               struct oprofile_cpu_buffer *b = &per_cpu(cpu_buffer, i);
+               struct oprofile_cpu_buffer *b = &per_cpu(op_cpu_buffer, i);
 
                /*
                 * Spread the work by 1 jiffy per cpu so they dont all
@@ -139,7 +138,7 @@ void end_cpu_work(void)
        work_enabled = 0;
 
        for_each_online_cpu(i) {
-               struct oprofile_cpu_buffer *b = &per_cpu(cpu_buffer, i);
+               struct oprofile_cpu_buffer *b = &per_cpu(op_cpu_buffer, i);
 
                cancel_delayed_work(&b->work);
        }
@@ -330,7 +329,7 @@ static inline void
 __oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
                          unsigned long event, int is_kernel)
 {
-       struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
+       struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer);
        unsigned long backtrace = oprofile_backtrace_depth;
 
        /*
@@ -375,7 +374,7 @@ oprofile_write_reserve(struct op_entry *entry, struct pt_regs * const regs,
 {
        struct op_sample *sample;
        int is_kernel = !user_mode(regs);
-       struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
+       struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer);
 
        cpu_buf->sample_received++;
 
@@ -430,13 +429,13 @@ int oprofile_write_commit(struct op_entry *entry)
 
 void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event)
 {
-       struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
+       struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer);
        log_sample(cpu_buf, pc, 0, is_kernel, event);
 }
 
 void oprofile_add_trace(unsigned long pc)
 {
-       struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
+       struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer);
 
        if (!cpu_buf->tracing)
                return;
index 272995d..68ea16a 100644 (file)
@@ -50,7 +50,7 @@ struct oprofile_cpu_buffer {
        struct delayed_work work;
 };
 
-DECLARE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer);
+DECLARE_PER_CPU(struct oprofile_cpu_buffer, op_cpu_buffer);
 
 /*
  * Resets the cpu buffer to a sane state.
@@ -60,7 +60,7 @@ DECLARE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer);
  */
 static inline void op_cpu_buffer_reset(int cpu)
 {
-       struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu);
+       struct oprofile_cpu_buffer *cpu_buf = &per_cpu(op_cpu_buffer, cpu);
 
        cpu_buf->last_is_kernel = -1;
        cpu_buf->last_task = NULL;
index 61689e8..917d28e 100644 (file)
@@ -23,7 +23,7 @@ void oprofile_reset_stats(void)
        int i;
 
        for_each_possible_cpu(i) {
-               cpu_buf = &per_cpu(cpu_buffer, i);
+               cpu_buf = &per_cpu(op_cpu_buffer, i);
                cpu_buf->sample_received = 0;
                cpu_buf->sample_lost_overflow = 0;
                cpu_buf->backtrace_aborted = 0;
@@ -51,7 +51,7 @@ void oprofile_create_stats_files(struct super_block *sb, struct dentry *root)
                return;
 
        for_each_possible_cpu(i) {
-               cpu_buf = &per_cpu(cpu_buffer, i);
+               cpu_buf = &per_cpu(op_cpu_buffer, i);
                snprintf(buf, 10, "cpu%d", i);
                cpudir = oprofilefs_mkdir(sb, dir, buf);
 
index 395c04c..98c04ca 100644 (file)
@@ -113,11 +113,9 @@ static inline int iucv_dbf_passes(debug_info_t *dbf_grp, int level)
 #define IUCV_DBF_TEXT_(name, level, text...) \
        do { \
                if (iucv_dbf_passes(iucv_dbf_##name, level)) { \
-                       char* iucv_dbf_txt_buf = \
-                                       get_cpu_var(iucv_dbf_txt_buf); \
-                       sprintf(iucv_dbf_txt_buf, text); \
-                       debug_text_event(iucv_dbf_##name, level, \
-                                               iucv_dbf_txt_buf); \
+                       char* __buf = get_cpu_var(iucv_dbf_txt_buf); \
+                       sprintf(__buf, text); \
+                       debug_text_event(iucv_dbf_##name, level, __buf); \
                        put_cpu_var(iucv_dbf_txt_buf); \
                } \
        } while (0)
index c1e19d5..b1fd3da 100644 (file)
@@ -3955,7 +3955,7 @@ static void ext4_mb_group_or_file(struct ext4_allocation_context *ac)
         * per cpu locality group is to reduce the contention between block
         * request from multiple CPUs.
         */
-       ac->ac_lg = per_cpu_ptr(sbi->s_locality_groups, raw_smp_processor_id());
+       ac->ac_lg = __this_cpu_ptr(sbi->s_locality_groups);
 
        /* we're going to use group allocation */
        ac->ac_flags |= EXT4_MB_HINT_GROUP_ALLOC;
index 293fa05..73ab220 100644 (file)
@@ -78,11 +78,6 @@ nfs4_callback_svc(void *vrqstp)
 
        set_freezable();
 
-       /*
-        * FIXME: do we really need to run this under the BKL? If so, please
-        * add a comment about what it's intended to protect.
-        */
-       lock_kernel();
        while (!kthread_should_stop()) {
                /*
                 * Listen for a request on the socket
@@ -104,7 +99,6 @@ nfs4_callback_svc(void *vrqstp)
                preverr = err;
                svc_process(rqstp);
        }
-       unlock_kernel();
        return 0;
 }
 
@@ -160,11 +154,6 @@ nfs41_callback_svc(void *vrqstp)
 
        set_freezable();
 
-       /*
-        * FIXME: do we really need to run this under the BKL? If so, please
-        * add a comment about what it's intended to protect.
-        */
-       lock_kernel();
        while (!kthread_should_stop()) {
                prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE);
                spin_lock_bh(&serv->sv_cb_lock);
@@ -183,7 +172,6 @@ nfs41_callback_svc(void *vrqstp)
                }
                finish_wait(&serv->sv_cb_waitq, &wq);
        }
-       unlock_kernel();
        return 0;
 }
 
@@ -397,6 +385,7 @@ static int nfs_callback_authenticate(struct svc_rqst *rqstp)
  */
 static struct svc_version *nfs4_callback_version[] = {
        [1] = &nfs4_callback_version1,
+       [4] = &nfs4_callback_version4,
 };
 
 static struct svc_stat nfs4_callback_stats;
index 07baa82..d4036be 100644 (file)
@@ -106,6 +106,19 @@ struct cb_sequenceres {
 extern unsigned nfs4_callback_sequence(struct cb_sequenceargs *args,
                                       struct cb_sequenceres *res);
 
+extern int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation,
+                                            const nfs4_stateid *stateid);
+
+#define RCA4_TYPE_MASK_RDATA_DLG       0
+#define RCA4_TYPE_MASK_WDATA_DLG       1
+
+struct cb_recallanyargs {
+       struct sockaddr *craa_addr;
+       uint32_t        craa_objs_to_keep;
+       uint32_t        craa_type_mask;
+};
+
+extern unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy);
 #endif /* CONFIG_NFS_V4_1 */
 
 extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res);
@@ -114,8 +127,9 @@ extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy);
 #ifdef CONFIG_NFS_V4
 extern int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt);
 extern void nfs_callback_down(int minorversion);
+extern int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation,
+                                           const nfs4_stateid *stateid);
 #endif /* CONFIG_NFS_V4 */
-
 /*
  * nfs41: Callbacks are expected to not cause substantial latency,
  * so we limit their concurrency to 1 by setting up the maximum number
index b7da1f5..defa9b4 100644 (file)
@@ -61,6 +61,16 @@ out:
        return res->status;
 }
 
+static int (*nfs_validate_delegation_stateid(struct nfs_client *clp))(struct nfs_delegation *, const nfs4_stateid *)
+{
+#if defined(CONFIG_NFS_V4_1)
+       if (clp->cl_minorversion > 0)
+               return nfs41_validate_delegation_stateid;
+#endif
+       return nfs4_validate_delegation_stateid;
+}
+
+
 __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
 {
        struct nfs_client *clp;
@@ -81,7 +91,8 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
                inode = nfs_delegation_find_inode(clp, &args->fh);
                if (inode != NULL) {
                        /* Set up a helper thread to actually return the delegation */
-                       switch(nfs_async_inode_return_delegation(inode, &args->stateid)) {
+                       switch (nfs_async_inode_return_delegation(inode, &args->stateid,
+                                                                 nfs_validate_delegation_stateid(clp))) {
                                case 0:
                                        res = 0;
                                        break;
@@ -102,8 +113,31 @@ out:
        return res;
 }
 
+int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid)
+{
+       if (delegation == NULL || memcmp(delegation->stateid.data, stateid->data,
+                                        sizeof(delegation->stateid.data)) != 0)
+               return 0;
+       return 1;
+}
+
 #if defined(CONFIG_NFS_V4_1)
 
+int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid)
+{
+       if (delegation == NULL)
+               return 0;
+
+       /* seqid is 4-bytes long */
+       if (((u32 *) &stateid->data)[0] != 0)
+               return 0;
+       if (memcmp(&delegation->stateid.data[4], &stateid->data[4],
+                  sizeof(stateid->data)-4))
+               return 0;
+
+       return 1;
+}
+
 /*
  * Validate the sequenceID sent by the server.
  * Return success if the sequenceID is one more than what we last saw on
@@ -227,4 +261,32 @@ out:
        return res->csr_status;
 }
 
+unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy)
+{
+       struct nfs_client *clp;
+       int status;
+       fmode_t flags = 0;
+
+       status = htonl(NFS4ERR_OP_NOT_IN_SESSION);
+       clp = nfs_find_client(args->craa_addr, 4);
+       if (clp == NULL)
+               goto out;
+
+       dprintk("NFS: RECALL_ANY callback request from %s\n",
+               rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR));
+
+       if (test_bit(RCA4_TYPE_MASK_RDATA_DLG, (const unsigned long *)
+                    &args->craa_type_mask))
+               flags = FMODE_READ;
+       if (test_bit(RCA4_TYPE_MASK_WDATA_DLG, (const unsigned long *)
+                    &args->craa_type_mask))
+               flags |= FMODE_WRITE;
+
+       if (flags)
+               nfs_expire_all_delegation_types(clp, flags);
+       status = htonl(NFS4_OK);
+out:
+       dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
+       return status;
+}
 #endif /* CONFIG_NFS_V4_1 */
index 76b0aa0..8e1a251 100644 (file)
@@ -23,6 +23,7 @@
 #if defined(CONFIG_NFS_V4_1)
 #define CB_OP_SEQUENCE_RES_MAXSZ       (CB_OP_HDR_RES_MAXSZ + \
                                        4 + 1 + 3)
+#define CB_OP_RECALLANY_RES_MAXSZ      (CB_OP_HDR_RES_MAXSZ)
 #endif /* CONFIG_NFS_V4_1 */
 
 #define NFSDBG_FACILITY NFSDBG_CALLBACK
@@ -326,6 +327,25 @@ out_free:
        goto out;
 }
 
+static unsigned decode_recallany_args(struct svc_rqst *rqstp,
+                                     struct xdr_stream *xdr,
+                                     struct cb_recallanyargs *args)
+{
+       uint32_t *p;
+
+       args->craa_addr = svc_addr(rqstp);
+       p = read_buf(xdr, 4);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_BADXDR);
+       args->craa_objs_to_keep = ntohl(*p++);
+       p = read_buf(xdr, 4);
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_BADXDR);
+       args->craa_type_mask = ntohl(*p);
+
+       return 0;
+}
+
 #endif /* CONFIG_NFS_V4_1 */
 
 static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
@@ -533,6 +553,7 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
        case OP_CB_GETATTR:
        case OP_CB_RECALL:
        case OP_CB_SEQUENCE:
+       case OP_CB_RECALL_ANY:
                *op = &callback_ops[op_nr];
                break;
 
@@ -540,7 +561,6 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
        case OP_CB_NOTIFY_DEVICEID:
        case OP_CB_NOTIFY:
        case OP_CB_PUSH_DELEG:
-       case OP_CB_RECALL_ANY:
        case OP_CB_RECALLABLE_OBJ_AVAIL:
        case OP_CB_RECALL_SLOT:
        case OP_CB_WANTS_CANCELLED:
@@ -688,6 +708,11 @@ static struct callback_op callback_ops[] = {
                .encode_res = (callback_encode_res_t)encode_cb_sequence_res,
                .res_maxsize = CB_OP_SEQUENCE_RES_MAXSZ,
        },
+       [OP_CB_RECALL_ANY] = {
+               .process_op = (callback_process_op_t)nfs4_callback_recallany,
+               .decode_args = (callback_decode_arg_t)decode_recallany_args,
+               .res_maxsize = CB_OP_RECALLANY_RES_MAXSZ,
+       },
 #endif /* CONFIG_NFS_V4_1 */
 };
 
@@ -718,3 +743,10 @@ struct svc_version nfs4_callback_version1 = {
        .vs_dispatch = NULL,
 };
 
+struct svc_version nfs4_callback_version4 = {
+       .vs_vers = 4,
+       .vs_nproc = ARRAY_SIZE(nfs4_callback_procedures1),
+       .vs_proc = nfs4_callback_procedures1,
+       .vs_xdrsize = NFS4_CALLBACK_XDRSIZE,
+       .vs_dispatch = NULL,
+};
index 99ea196..ee77713 100644 (file)
@@ -1260,10 +1260,20 @@ error:
 static void nfs4_session_set_rwsize(struct nfs_server *server)
 {
 #ifdef CONFIG_NFS_V4_1
+       struct nfs4_session *sess;
+       u32 server_resp_sz;
+       u32 server_rqst_sz;
+
        if (!nfs4_has_session(server->nfs_client))
                return;
-       server->rsize = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
-       server->wsize = server->nfs_client->cl_session->fc_attrs.max_rqst_sz;
+       sess = server->nfs_client->cl_session;
+       server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead;
+       server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead;
+
+       if (server->rsize > server_resp_sz)
+               server->rsize = server_resp_sz;
+       if (server->wsize > server_rqst_sz)
+               server->wsize = server_rqst_sz;
 #endif /* CONFIG_NFS_V4_1 */
 }
 
index 6dd48a4..2563beb 100644 (file)
@@ -92,7 +92,7 @@ out:
        return status;
 }
 
-static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid)
+static int nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid)
 {
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_open_context *ctx;
@@ -116,10 +116,11 @@ again:
                        err = nfs_delegation_claim_locks(ctx, state);
                put_nfs_open_context(ctx);
                if (err != 0)
-                       return;
+                       return err;
                goto again;
        }
        spin_unlock(&inode->i_lock);
+       return 0;
 }
 
 /*
@@ -261,30 +262,34 @@ static void nfs_msync_inode(struct inode *inode)
 /*
  * Basic procedure for returning a delegation to the server
  */
-static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation)
+static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync)
 {
        struct nfs_inode *nfsi = NFS_I(inode);
+       int err;
 
-       nfs_msync_inode(inode);
        /*
         * Guard against new delegated open/lock/unlock calls and against
         * state recovery
         */
        down_write(&nfsi->rwsem);
-       nfs_delegation_claim_opens(inode, &delegation->stateid);
+       err = nfs_delegation_claim_opens(inode, &delegation->stateid);
        up_write(&nfsi->rwsem);
-       nfs_msync_inode(inode);
+       if (err)
+               goto out;
 
-       return nfs_do_return_delegation(inode, delegation, 1);
+       err = nfs_do_return_delegation(inode, delegation, issync);
+out:
+       return err;
 }
 
 /*
  * Return all delegations that have been marked for return
  */
-void nfs_client_return_marked_delegations(struct nfs_client *clp)
+int nfs_client_return_marked_delegations(struct nfs_client *clp)
 {
        struct nfs_delegation *delegation;
        struct inode *inode;
+       int err = 0;
 
 restart:
        rcu_read_lock();
@@ -298,12 +303,18 @@ restart:
                delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
                spin_unlock(&clp->cl_lock);
                rcu_read_unlock();
-               if (delegation != NULL)
-                       __nfs_inode_return_delegation(inode, delegation);
+               if (delegation != NULL) {
+                       filemap_flush(inode->i_mapping);
+                       err = __nfs_inode_return_delegation(inode, delegation, 0);
+               }
                iput(inode);
-               goto restart;
+               if (!err)
+                       goto restart;
+               set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
+               return err;
        }
        rcu_read_unlock();
+       return 0;
 }
 
 /*
@@ -338,8 +349,10 @@ int nfs_inode_return_delegation(struct inode *inode)
                spin_lock(&clp->cl_lock);
                delegation = nfs_detach_delegation_locked(nfsi, NULL);
                spin_unlock(&clp->cl_lock);
-               if (delegation != NULL)
-                       err = __nfs_inode_return_delegation(inode, delegation);
+               if (delegation != NULL) {
+                       nfs_msync_inode(inode);
+                       err = __nfs_inode_return_delegation(inode, delegation, 1);
+               }
        }
        return err;
 }
@@ -368,33 +381,47 @@ void nfs_super_return_all_delegations(struct super_block *sb)
                spin_unlock(&delegation->lock);
        }
        rcu_read_unlock();
-       nfs_client_return_marked_delegations(clp);
+       if (nfs_client_return_marked_delegations(clp) != 0)
+               nfs4_schedule_state_manager(clp);
 }
 
-static void nfs_client_mark_return_all_delegations(struct nfs_client *clp)
+static
+void nfs_client_mark_return_all_delegation_types(struct nfs_client *clp, fmode_t flags)
 {
        struct nfs_delegation *delegation;
 
        rcu_read_lock();
        list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
-               set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
-               set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
+               if ((delegation->type == (FMODE_READ|FMODE_WRITE)) && !(flags & FMODE_WRITE))
+                       continue;
+               if (delegation->type & flags)
+                       nfs_mark_return_delegation(clp, delegation);
        }
        rcu_read_unlock();
 }
 
+static void nfs_client_mark_return_all_delegations(struct nfs_client *clp)
+{
+       nfs_client_mark_return_all_delegation_types(clp, FMODE_READ|FMODE_WRITE);
+}
+
 static void nfs_delegation_run_state_manager(struct nfs_client *clp)
 {
        if (test_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state))
                nfs4_schedule_state_manager(clp);
 }
 
-void nfs_expire_all_delegations(struct nfs_client *clp)
+void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags)
 {
-       nfs_client_mark_return_all_delegations(clp);
+       nfs_client_mark_return_all_delegation_types(clp, flags);
        nfs_delegation_run_state_manager(clp);
 }
 
+void nfs_expire_all_delegations(struct nfs_client *clp)
+{
+       nfs_expire_all_delegation_types(clp, FMODE_READ|FMODE_WRITE);
+}
+
 /*
  * Return all delegations following an NFS4ERR_CB_PATH_DOWN error.
  */
@@ -413,8 +440,7 @@ static void nfs_client_mark_return_unreferenced_delegations(struct nfs_client *c
        list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
                if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags))
                        continue;
-               set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
-               set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
+               nfs_mark_return_delegation(clp, delegation);
        }
        rcu_read_unlock();
 }
@@ -428,18 +454,21 @@ void nfs_expire_unreferenced_delegations(struct nfs_client *clp)
 /*
  * Asynchronous delegation recall!
  */
-int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid)
+int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid,
+                                     int (*validate_stateid)(struct nfs_delegation *delegation,
+                                                             const nfs4_stateid *stateid))
 {
        struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
        struct nfs_delegation *delegation;
 
        rcu_read_lock();
        delegation = rcu_dereference(NFS_I(inode)->delegation);
-       if (delegation == NULL || memcmp(delegation->stateid.data, stateid->data,
-                               sizeof(delegation->stateid.data)) != 0) {
+
+       if (!validate_stateid(delegation, stateid)) {
                rcu_read_unlock();
                return -ENOENT;
        }
+
        nfs_mark_return_delegation(clp, delegation);
        rcu_read_unlock();
        nfs_delegation_run_state_manager(clp);
index 09f3837..944b627 100644 (file)
@@ -34,15 +34,18 @@ enum {
 int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
 void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
 int nfs_inode_return_delegation(struct inode *inode);
-int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid);
+int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid,
+                                     int (*validate_stateid)(struct nfs_delegation *delegation,
+                                                             const nfs4_stateid *stateid));
 void nfs_inode_return_delegation_noreclaim(struct inode *inode);
 
 struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle);
 void nfs_super_return_all_delegations(struct super_block *sb);
 void nfs_expire_all_delegations(struct nfs_client *clp);
+void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags);
 void nfs_expire_unreferenced_delegations(struct nfs_client *clp);
 void nfs_handle_cb_pathdown(struct nfs_client *clp);
-void nfs_client_return_marked_delegations(struct nfs_client *clp);
+int nfs_client_return_marked_delegations(struct nfs_client *clp);
 
 void nfs_delegation_mark_reclaim(struct nfs_client *clp);
 void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
index 7cb2985..2c5ace4 100644 (file)
@@ -1579,55 +1579,46 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct dentry *dentry = NULL, *rehash = NULL;
        int error = -EBUSY;
 
-       /*
-        * To prevent any new references to the target during the rename,
-        * we unhash the dentry and free the inode in advance.
-        */
-       if (!d_unhashed(new_dentry)) {
-               d_drop(new_dentry);
-               rehash = new_dentry;
-       }
-
        dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n",
                 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
                 new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
                 atomic_read(&new_dentry->d_count));
 
        /*
-        * First check whether the target is busy ... we can't
-        * safely do _any_ rename if the target is in use.
-        *
-        * For files, make a copy of the dentry and then do a 
-        * silly-rename. If the silly-rename succeeds, the
-        * copied dentry is hashed and becomes the new target.
+        * For non-directories, check whether the target is busy and if so,
+        * make a copy of the dentry and then do a silly-rename. If the
+        * silly-rename succeeds, the copied dentry is hashed and becomes
+        * the new target.
         */
-       if (!new_inode)
-               goto go_ahead;
-       if (S_ISDIR(new_inode->i_mode)) {
-               error = -EISDIR;
-               if (!S_ISDIR(old_inode->i_mode))
-                       goto out;
-       } else if (atomic_read(&new_dentry->d_count) > 2) {
-               int err;
-               /* copy the target dentry's name */
-               dentry = d_alloc(new_dentry->d_parent,
-                                &new_dentry->d_name);
-               if (!dentry)
-                       goto out;
+       if (new_inode && !S_ISDIR(new_inode->i_mode)) {
+               /*
+                * To prevent any new references to the target during the
+                * rename, we unhash the dentry in advance.
+                */
+               if (!d_unhashed(new_dentry)) {
+                       d_drop(new_dentry);
+                       rehash = new_dentry;
+               }
+
+               if (atomic_read(&new_dentry->d_count) > 2) {
+                       int err;
+
+                       /* copy the target dentry's name */
+                       dentry = d_alloc(new_dentry->d_parent,
+                                        &new_dentry->d_name);
+                       if (!dentry)
+                               goto out;
 
-               /* silly-rename the existing target ... */
-               err = nfs_sillyrename(new_dir, new_dentry);
-               if (!err) {
-                       new_dentry = rehash = dentry;
+                       /* silly-rename the existing target ... */
+                       err = nfs_sillyrename(new_dir, new_dentry);
+                       if (err)
+                               goto out;
+
+                       new_dentry = dentry;
                        new_inode = NULL;
-                       /* instantiate the replacement target */
-                       d_instantiate(new_dentry, NULL);
-               } else if (atomic_read(&new_dentry->d_count) > 1)
-                       /* dentry still busy? */
-                       goto out;
+               }
        }
 
-go_ahead:
        /*
         * ... prune child dentries and writebacks if needed.
         */
index f4d54ba..95e1ca7 100644 (file)
@@ -146,7 +146,7 @@ static int nfs_dns_show(struct seq_file *m, struct cache_detail *cd,
        return 0;
 }
 
-struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd,
+static struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd,
                struct nfs_dns_ent *key)
 {
        struct cache_head *ch;
@@ -159,7 +159,7 @@ struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd,
        return container_of(ch, struct nfs_dns_ent, h);
 }
 
-struct nfs_dns_ent *nfs_dns_update(struct cache_detail *cd,
+static struct nfs_dns_ent *nfs_dns_update(struct cache_detail *cd,
                struct nfs_dns_ent *new,
                struct nfs_dns_ent *key)
 {
index e21b1bb..29e464d 100644 (file)
@@ -30,6 +30,15 @@ static inline int nfs4_has_session(const struct nfs_client *clp)
        return 0;
 }
 
+static inline int nfs4_has_persistent_session(const struct nfs_client *clp)
+{
+#ifdef CONFIG_NFS_V4_1
+       if (nfs4_has_session(clp))
+               return (clp->cl_session->flags & SESSION4_PERSIST);
+#endif /* CONFIG_NFS_V4_1 */
+       return 0;
+}
+
 struct nfs_clone_mount {
        const struct super_block *sb;
        const struct dentry *dentry;
@@ -156,6 +165,7 @@ struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentr
 
 /* callback_xdr.c */
 extern struct svc_version nfs4_callback_version1;
+extern struct svc_version nfs4_callback_version4;
 
 /* pagelist.c */
 extern int __init nfs_init_nfspagecache(void);
@@ -177,24 +187,14 @@ extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int);
 extern struct rpc_procinfo nfs3_procedures[];
 extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int);
 
-/* nfs4proc.c */
-static inline void nfs4_restart_rpc(struct rpc_task *task,
-                                   const struct nfs_client *clp)
-{
-#ifdef CONFIG_NFS_V4_1
-       if (nfs4_has_session(clp) &&
-           test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)) {
-               rpc_restart_call_prepare(task);
-               return;
-       }
-#endif /* CONFIG_NFS_V4_1 */
-       rpc_restart_call(task);
-}
-
 /* nfs4xdr.c */
 #ifdef CONFIG_NFS_V4
 extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
 #endif
+#ifdef CONFIG_NFS_V4_1
+extern const u32 nfs41_maxread_overhead;
+extern const u32 nfs41_maxwrite_overhead;
+#endif
 
 /* nfs4proc.c */
 #ifdef CONFIG_NFS_V4
@@ -273,20 +273,6 @@ extern int _nfs4_call_sync_session(struct nfs_server *server,
                                   struct nfs4_sequence_res *res,
                                   int cache_reply);
 
-#ifdef CONFIG_NFS_V4_1
-extern void nfs41_sequence_free_slot(const struct nfs_client *,
-                                    struct nfs4_sequence_res *res);
-#endif /* CONFIG_NFS_V4_1 */
-
-static inline void nfs4_sequence_free_slot(const struct nfs_client *clp,
-                                          struct nfs4_sequence_res *res)
-{
-#ifdef CONFIG_NFS_V4_1
-       if (nfs4_has_session(clp))
-               nfs41_sequence_free_slot(clp, res);
-#endif /* CONFIG_NFS_V4_1 */
-}
-
 /*
  * Determine the device name as a string
  */
@@ -380,3 +366,15 @@ unsigned int nfs_page_array_len(unsigned int base, size_t len)
        return ((unsigned long)len + (unsigned long)base +
                PAGE_SIZE - 1) >> PAGE_SHIFT;
 }
+
+/*
+ * Helper for restarting RPC calls in the possible presence of NFSv4.1
+ * sessions.
+ */
+static inline void nfs_restart_rpc(struct rpc_task *task, const struct nfs_client *clp)
+{
+       if (nfs4_has_session(clp))
+               rpc_restart_call_prepare(task);
+       else
+               rpc_restart_call(task);
+}
index ceda50a..46d779a 100644 (file)
@@ -25,13 +25,7 @@ struct nfs_iostats {
 static inline void nfs_inc_server_stats(const struct nfs_server *server,
                                        enum nfs_stat_eventcounters stat)
 {
-       struct nfs_iostats *iostats;
-       int cpu;
-
-       cpu = get_cpu();
-       iostats = per_cpu_ptr(server->io_stats, cpu);
-       iostats->events[stat]++;
-       put_cpu();
+       this_cpu_inc(server->io_stats->events[stat]);
 }
 
 static inline void nfs_inc_stats(const struct inode *inode,
@@ -44,13 +38,7 @@ static inline void nfs_add_server_stats(const struct nfs_server *server,
                                        enum nfs_stat_bytecounters stat,
                                        unsigned long addend)
 {
-       struct nfs_iostats *iostats;
-       int cpu;
-
-       cpu = get_cpu();
-       iostats = per_cpu_ptr(server->io_stats, cpu);
-       iostats->bytes[stat] += addend;
-       put_cpu();
+       this_cpu_add(server->io_stats->bytes[stat], addend);
 }
 
 static inline void nfs_add_stats(const struct inode *inode,
@@ -65,13 +53,7 @@ static inline void nfs_add_fscache_stats(struct inode *inode,
                                         enum nfs_stat_fscachecounters stat,
                                         unsigned long addend)
 {
-       struct nfs_iostats *iostats;
-       int cpu;
-
-       cpu = get_cpu();
-       iostats = per_cpu_ptr(NFS_SERVER(inode)->io_stats, cpu);
-       iostats->fscache[stat] += addend;
-       put_cpu();
+       this_cpu_add(NFS_SERVER(inode)->io_stats->fscache[stat], addend);
 }
 #endif
 
index 6ea07a3..7e57b04 100644 (file)
@@ -44,7 +44,8 @@ enum nfs4_client_state {
        NFS4CLNT_RECLAIM_REBOOT,
        NFS4CLNT_RECLAIM_NOGRACE,
        NFS4CLNT_DELEGRETURN,
-       NFS4CLNT_SESSION_SETUP,
+       NFS4CLNT_SESSION_RESET,
+       NFS4CLNT_SESSION_DRAINING,
 };
 
 /*
@@ -180,6 +181,7 @@ struct nfs4_state_recovery_ops {
        int (*recover_lock)(struct nfs4_state *, struct file_lock *);
        int (*establish_clid)(struct nfs_client *, struct rpc_cred *);
        struct rpc_cred * (*get_clid_cred)(struct nfs_client *);
+       int (*reclaim_complete)(struct nfs_client *);
 };
 
 struct nfs4_state_maintenance_ops {
@@ -200,9 +202,11 @@ extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t);
 /* nfs4proc.c */
 extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *);
 extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *);
+extern int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred);
 extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
+extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait);
 extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
 extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
@@ -218,9 +222,11 @@ extern int nfs4_setup_sequence(struct nfs_client *clp,
                int cache_reply, struct rpc_task *task);
 extern void nfs4_destroy_session(struct nfs4_session *session);
 extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp);
-extern int nfs4_proc_create_session(struct nfs_client *, int reset);
+extern int nfs4_proc_create_session(struct nfs_client *);
 extern int nfs4_proc_destroy_session(struct nfs4_session *);
 extern int nfs4_init_session(struct nfs_server *server);
+extern int nfs4_proc_get_lease_time(struct nfs_client *clp,
+               struct nfs_fsinfo *fsinfo);
 #else /* CONFIG_NFS_v4_1 */
 static inline int nfs4_setup_sequence(struct nfs_client *clp,
                struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
@@ -267,6 +273,7 @@ extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t);
 extern void nfs4_schedule_state_recovery(struct nfs_client *);
 extern void nfs4_schedule_state_manager(struct nfs_client *);
 extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state);
+extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
 extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
 extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
 extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
@@ -287,6 +294,7 @@ struct nfs4_mount_data;
 
 /* callback_xdr.c */
 extern struct svc_version nfs4_callback_version1;
+extern struct svc_version nfs4_callback_version4;
 
 #else
 
index 741a562..9f5f11e 100644 (file)
@@ -270,11 +270,18 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
                case -NFS4ERR_SEQ_MISORDERED:
                        dprintk("%s ERROR: %d Reset session\n", __func__,
                                errorcode);
-                       set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
+                       nfs4_schedule_state_recovery(clp);
                        exception->retry = 1;
-                       /* FALLTHROUGH */
+                       break;
 #endif /* !defined(CONFIG_NFS_V4_1) */
                case -NFS4ERR_FILE_OPEN:
+                       if (exception->timeout > HZ) {
+                               /* We have retried a decent amount, time to
+                                * fail
+                                */
+                               ret = -EBUSY;
+                               break;
+                       }
                case -NFS4ERR_GRACE:
                case -NFS4ERR_DELAY:
                        ret = nfs4_delay(server->client, &exception->timeout);
@@ -311,48 +318,54 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp
  * so we need to scan down from highest_used_slotid to 0 looking for the now
  * highest slotid in use.
  * If none found, highest_used_slotid is set to -1.
+ *
+ * Must be called while holding tbl->slot_tbl_lock
  */
 static void
 nfs4_free_slot(struct nfs4_slot_table *tbl, u8 free_slotid)
 {
        int slotid = free_slotid;
 
-       spin_lock(&tbl->slot_tbl_lock);
        /* clear used bit in bitmap */
        __clear_bit(slotid, tbl->used_slots);
 
        /* update highest_used_slotid when it is freed */
        if (slotid == tbl->highest_used_slotid) {
                slotid = find_last_bit(tbl->used_slots, tbl->max_slots);
-               if (slotid >= 0 && slotid < tbl->max_slots)
+               if (slotid < tbl->max_slots)
                        tbl->highest_used_slotid = slotid;
                else
                        tbl->highest_used_slotid = -1;
        }
-       rpc_wake_up_next(&tbl->slot_tbl_waitq);
-       spin_unlock(&tbl->slot_tbl_lock);
        dprintk("%s: free_slotid %u highest_used_slotid %d\n", __func__,
                free_slotid, tbl->highest_used_slotid);
 }
 
-void nfs41_sequence_free_slot(const struct nfs_client *clp,
+static void nfs41_sequence_free_slot(const struct nfs_client *clp,
                              struct nfs4_sequence_res *res)
 {
        struct nfs4_slot_table *tbl;
 
-       if (!nfs4_has_session(clp)) {
-               dprintk("%s: No session\n", __func__);
-               return;
-       }
        tbl = &clp->cl_session->fc_slot_table;
        if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) {
-               dprintk("%s: No slot\n", __func__);
                /* just wake up the next guy waiting since
                 * we may have not consumed a slot after all */
-               rpc_wake_up_next(&tbl->slot_tbl_waitq);
+               dprintk("%s: No slot\n", __func__);
                return;
        }
+
+       spin_lock(&tbl->slot_tbl_lock);
        nfs4_free_slot(tbl, res->sr_slotid);
+
+       /* Signal state manager thread if session is drained */
+       if (test_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state)) {
+               if (tbl->highest_used_slotid == -1) {
+                       dprintk("%s COMPLETE: Session Drained\n", __func__);
+                       complete(&clp->cl_session->complete);
+               }
+       } else
+               rpc_wake_up_next(&tbl->slot_tbl_waitq);
+       spin_unlock(&tbl->slot_tbl_lock);
        res->sr_slotid = NFS4_MAX_SLOT_TABLE;
 }
 
@@ -377,10 +390,10 @@ static void nfs41_sequence_done(struct nfs_client *clp,
        if (res->sr_slotid == NFS4_MAX_SLOT_TABLE)
                goto out;
 
-       tbl = &clp->cl_session->fc_slot_table;
-       slot = tbl->slots + res->sr_slotid;
-
+       /* Check the SEQUENCE operation status */
        if (res->sr_status == 0) {
+               tbl = &clp->cl_session->fc_slot_table;
+               slot = tbl->slots + res->sr_slotid;
                /* Update the slot's sequence and clientid lease timer */
                ++slot->seq_nr;
                timestamp = res->sr_renewal_time;
@@ -388,7 +401,8 @@ static void nfs41_sequence_done(struct nfs_client *clp,
                if (time_before(clp->cl_last_renewal, timestamp))
                        clp->cl_last_renewal = timestamp;
                spin_unlock(&clp->cl_lock);
-               return;
+               /* Check sequence flags */
+               nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
        }
 out:
        /* The session may be reset by one of the error handlers. */
@@ -429,24 +443,6 @@ out:
        return ret_id;
 }
 
-static int nfs4_recover_session(struct nfs4_session *session)
-{
-       struct nfs_client *clp = session->clp;
-       unsigned int loop;
-       int ret;
-
-       for (loop = NFS4_MAX_LOOP_ON_RECOVER; loop != 0; loop--) {
-               ret = nfs4_wait_clnt_recover(clp);
-               if (ret != 0)
-                       break;
-               if (!test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state))
-                       break;
-               nfs4_schedule_state_manager(clp);
-               ret = -EIO;
-       }
-       return ret;
-}
-
 static int nfs41_setup_sequence(struct nfs4_session *session,
                                struct nfs4_sequence_args *args,
                                struct nfs4_sequence_res *res,
@@ -455,7 +451,6 @@ static int nfs41_setup_sequence(struct nfs4_session *session,
 {
        struct nfs4_slot *slot;
        struct nfs4_slot_table *tbl;
-       int status = 0;
        u8 slotid;
 
        dprintk("--> %s\n", __func__);
@@ -468,21 +463,15 @@ static int nfs41_setup_sequence(struct nfs4_session *session,
        tbl = &session->fc_slot_table;
 
        spin_lock(&tbl->slot_tbl_lock);
-       if (test_bit(NFS4CLNT_SESSION_SETUP, &session->clp->cl_state)) {
-               if (tbl->highest_used_slotid != -1) {
-                       rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
-                       spin_unlock(&tbl->slot_tbl_lock);
-                       dprintk("<-- %s: Session reset: draining\n", __func__);
-                       return -EAGAIN;
-               }
-
-               /* The slot table is empty; start the reset thread */
-               dprintk("%s Session Reset\n", __func__);
+       if (test_bit(NFS4CLNT_SESSION_DRAINING, &session->clp->cl_state)) {
+               /*
+                * The state manager will wait until the slot table is empty.
+                * Schedule the reset thread
+                */
+               rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
                spin_unlock(&tbl->slot_tbl_lock);
-               status = nfs4_recover_session(session);
-               if (status)
-                       return status;
-               spin_lock(&tbl->slot_tbl_lock);
+               dprintk("%s Schedule Session Reset\n", __func__);
+               return -EAGAIN;
        }
 
        slotid = nfs4_find_slot(tbl, task);
@@ -527,7 +516,7 @@ int nfs4_setup_sequence(struct nfs_client *clp,
                goto out;
        ret = nfs41_setup_sequence(clp->cl_session, args, res, cache_reply,
                                   task);
-       if (ret != -EAGAIN) {
+       if (ret && ret != -EAGAIN) {
                /* terminate rpc task */
                task->tk_status = ret;
                task->tk_action = NULL;
@@ -561,7 +550,6 @@ static void nfs41_call_sync_done(struct rpc_task *task, void *calldata)
        struct nfs41_call_sync_data *data = calldata;
 
        nfs41_sequence_done(data->clp, data->seq_res, task->tk_status);
-       nfs41_sequence_free_slot(data->clp, data->seq_res);
 }
 
 struct rpc_call_ops nfs41_call_sync_ops = {
@@ -637,15 +625,6 @@ static void nfs4_sequence_done(const struct nfs_server *server,
 #endif /* CONFIG_NFS_V4_1 */
 }
 
-/* no restart, therefore free slot here */
-static void nfs4_sequence_done_free_slot(const struct nfs_server *server,
-                                        struct nfs4_sequence_res *res,
-                                        int rpc_status)
-{
-       nfs4_sequence_done(server, res, rpc_status);
-       nfs4_sequence_free_slot(server->nfs_client, res);
-}
-
 static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
 {
        struct nfs_inode *nfsi = NFS_I(dir);
@@ -720,9 +699,15 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
        p->o_arg.bitmask = server->attr_bitmask;
        p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
        if (flags & O_EXCL) {
-               u32 *s = (u32 *) p->o_arg.u.verifier.data;
-               s[0] = jiffies;
-               s[1] = current->pid;
+               if (nfs4_has_persistent_session(server->nfs_client)) {
+                       /* GUARDED */
+                       p->o_arg.u.attrs = &p->attrs;
+                       memcpy(&p->attrs, attrs, sizeof(p->attrs));
+               } else { /* EXCLUSIVE4_1 */
+                       u32 *s = (u32 *) p->o_arg.u.verifier.data;
+                       s[0] = jiffies;
+                       s[1] = current->pid;
+               }
        } else if (flags & O_CREAT) {
                p->o_arg.u.attrs = &p->attrs;
                memcpy(&p->attrs, attrs, sizeof(p->attrs));
@@ -776,13 +761,16 @@ static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode
                goto out;
        switch (mode & (FMODE_READ|FMODE_WRITE)) {
                case FMODE_READ:
-                       ret |= test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0;
+                       ret |= test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0
+                               && state->n_rdonly != 0;
                        break;
                case FMODE_WRITE:
-                       ret |= test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0;
+                       ret |= test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0
+                               && state->n_wronly != 0;
                        break;
                case FMODE_READ|FMODE_WRITE:
-                       ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0;
+                       ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0
+                               && state->n_rdwr != 0;
        }
 out:
        return ret;
@@ -1183,6 +1171,14 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state
                        case -ENOENT:
                        case -ESTALE:
                                goto out;
+                       case -NFS4ERR_BADSESSION:
+                       case -NFS4ERR_BADSLOT:
+                       case -NFS4ERR_BAD_HIGH_SLOT:
+                       case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+                       case -NFS4ERR_DEADSESSION:
+                               nfs4_schedule_state_recovery(
+                                       server->nfs_client);
+                               goto out;
                        case -NFS4ERR_STALE_CLIENTID:
                        case -NFS4ERR_STALE_STATEID:
                        case -NFS4ERR_EXPIRED:
@@ -1336,8 +1332,8 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)
 
        data->rpc_status = task->tk_status;
 
-       nfs4_sequence_done_free_slot(data->o_arg.server, &data->o_res.seq_res,
-                                    task->tk_status);
+       nfs4_sequence_done(data->o_arg.server, &data->o_res.seq_res,
+                       task->tk_status);
 
        if (RPC_ASSASSINATED(task))
                return;
@@ -1488,7 +1484,7 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s
        return ret;
 }
 
-static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
+static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
 {
        struct nfs_server *server = NFS_SERVER(state->inode);
        struct nfs4_exception exception = { };
@@ -1496,10 +1492,16 @@ static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4
 
        do {
                err = _nfs4_open_expired(ctx, state);
-               if (err != -NFS4ERR_DELAY)
-                       break;
-               nfs4_handle_exception(server, err, &exception);
+               switch (err) {
+               default:
+                       goto out;
+               case -NFS4ERR_GRACE:
+               case -NFS4ERR_DELAY:
+                       nfs4_handle_exception(server, err, &exception);
+                       err = 0;
+               }
        } while (exception.retry);
+out:
        return err;
 }
 
@@ -1712,6 +1714,18 @@ static void nfs4_free_closedata(void *data)
        kfree(calldata);
 }
 
+static void nfs4_close_clear_stateid_flags(struct nfs4_state *state,
+               fmode_t fmode)
+{
+       spin_lock(&state->owner->so_lock);
+       if (!(fmode & FMODE_READ))
+               clear_bit(NFS_O_RDONLY_STATE, &state->flags);
+       if (!(fmode & FMODE_WRITE))
+               clear_bit(NFS_O_WRONLY_STATE, &state->flags);
+       clear_bit(NFS_O_RDWR_STATE, &state->flags);
+       spin_unlock(&state->owner->so_lock);
+}
+
 static void nfs4_close_done(struct rpc_task *task, void *data)
 {
        struct nfs4_closedata *calldata = data;
@@ -1728,6 +1742,8 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
                case 0:
                        nfs_set_open_stateid(state, &calldata->res.stateid, 0);
                        renew_lease(server, calldata->timestamp);
+                       nfs4_close_clear_stateid_flags(state,
+                                       calldata->arg.fmode);
                        break;
                case -NFS4ERR_STALE_STATEID:
                case -NFS4ERR_OLD_STATEID:
@@ -1737,11 +1753,10 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
                                break;
                default:
                        if (nfs4_async_handle_error(task, server, state) == -EAGAIN) {
-                               nfs4_restart_rpc(task, server->nfs_client);
+                               nfs_restart_rpc(task, server->nfs_client);
                                return;
                        }
        }
-       nfs4_sequence_free_slot(server->nfs_client, &calldata->res.seq_res);
        nfs_refresh_inode(calldata->inode, calldata->res.fattr);
 }
 
@@ -1749,38 +1764,39 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
 {
        struct nfs4_closedata *calldata = data;
        struct nfs4_state *state = calldata->state;
-       int clear_rd, clear_wr, clear_rdwr;
+       int call_close = 0;
 
        if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
                return;
 
-       clear_rd = clear_wr = clear_rdwr = 0;
+       task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
+       calldata->arg.fmode = FMODE_READ|FMODE_WRITE;
        spin_lock(&state->owner->so_lock);
        /* Calculate the change in open mode */
        if (state->n_rdwr == 0) {
                if (state->n_rdonly == 0) {
-                       clear_rd |= test_and_clear_bit(NFS_O_RDONLY_STATE, &state->flags);
-                       clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags);
+                       call_close |= test_bit(NFS_O_RDONLY_STATE, &state->flags);
+                       call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
+                       calldata->arg.fmode &= ~FMODE_READ;
                }
                if (state->n_wronly == 0) {
-                       clear_wr |= test_and_clear_bit(NFS_O_WRONLY_STATE, &state->flags);
-                       clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags);
+                       call_close |= test_bit(NFS_O_WRONLY_STATE, &state->flags);
+                       call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
+                       calldata->arg.fmode &= ~FMODE_WRITE;
                }
        }
        spin_unlock(&state->owner->so_lock);
-       if (!clear_rd && !clear_wr && !clear_rdwr) {
+
+       if (!call_close) {
                /* Note: exit _without_ calling nfs4_close_done */
                task->tk_action = NULL;
                return;
        }
+
+       if (calldata->arg.fmode == 0)
+               task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE];
+
        nfs_fattr_init(calldata->res.fattr);
-       if (test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0) {
-               task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
-               calldata->arg.fmode = FMODE_READ;
-       } else if (test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0) {
-               task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
-               calldata->arg.fmode = FMODE_WRITE;
-       }
        calldata->timestamp = jiffies;
        if (nfs4_setup_sequence((NFS_SERVER(calldata->inode))->nfs_client,
                                &calldata->arg.seq_args, &calldata->res.seq_res,
@@ -1981,7 +1997,7 @@ out_drop:
        return 0;
 }
 
-void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
+static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
 {
        if (ctx->state == NULL)
                return;
@@ -2532,7 +2548,6 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
        nfs4_sequence_done(res->server, &res->seq_res, task->tk_status);
        if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
                return 0;
-       nfs4_sequence_free_slot(res->server->nfs_client, &res->seq_res);
        update_changeattr(dir, &res->cinfo);
        nfs_post_op_update_inode(dir, &res->dir_attr);
        return 1;
@@ -2971,11 +2986,10 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
 
        dprintk("--> %s\n", __func__);
 
-       /* nfs4_sequence_free_slot called in the read rpc_call_done */
        nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
 
        if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) {
-               nfs4_restart_rpc(task, server->nfs_client);
+               nfs_restart_rpc(task, server->nfs_client);
                return -EAGAIN;
        }
 
@@ -2995,12 +3009,11 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
 {
        struct inode *inode = data->inode;
        
-       /* slot is freed in nfs_writeback_done */
        nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res,
                           task->tk_status);
 
        if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) {
-               nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
+               nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
                return -EAGAIN;
        }
        if (task->tk_status >= 0) {
@@ -3028,11 +3041,9 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
        nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res,
                           task->tk_status);
        if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) {
-               nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
+               nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
                return -EAGAIN;
        }
-       nfs4_sequence_free_slot(NFS_SERVER(inode)->nfs_client,
-                               &data->res.seq_res);
        nfs_refresh_inode(inode, data->res.fattr);
        return 0;
 }
@@ -3350,7 +3361,7 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
                case -NFS4ERR_SEQ_MISORDERED:
                        dprintk("%s ERROR %d, Reset session\n", __func__,
                                task->tk_status);
-                       set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
+                       nfs4_schedule_state_recovery(clp);
                        task->tk_status = 0;
                        return -EAGAIN;
 #endif /* CONFIG_NFS_V4_1 */
@@ -3483,12 +3494,23 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
 {
        struct nfs4_delegreturndata *data = calldata;
 
-       nfs4_sequence_done_free_slot(data->res.server, &data->res.seq_res,
-                                    task->tk_status);
+       nfs4_sequence_done(data->res.server, &data->res.seq_res,
+                       task->tk_status);
 
-       data->rpc_status = task->tk_status;
-       if (data->rpc_status == 0)
+       switch (task->tk_status) {
+       case -NFS4ERR_STALE_STATEID:
+       case -NFS4ERR_EXPIRED:
+       case 0:
                renew_lease(data->res.server, data->timestamp);
+               break;
+       default:
+               if (nfs4_async_handle_error(task, data->res.server, NULL) ==
+                               -EAGAIN) {
+                       nfs_restart_rpc(task, data->res.server->nfs_client);
+                       return;
+               }
+       }
+       data->rpc_status = task->tk_status;
 }
 
 static void nfs4_delegreturn_release(void *calldata)
@@ -3741,11 +3763,9 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
                        break;
                default:
                        if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN)
-                               nfs4_restart_rpc(task,
-                                               calldata->server->nfs_client);
+                               nfs_restart_rpc(task,
+                                                calldata->server->nfs_client);
        }
-       nfs4_sequence_free_slot(calldata->server->nfs_client,
-                               &calldata->res.seq_res);
 }
 
 static void nfs4_locku_prepare(struct rpc_task *task, void *data)
@@ -3927,8 +3947,8 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
 
        dprintk("%s: begin!\n", __func__);
 
-       nfs4_sequence_done_free_slot(data->server, &data->res.seq_res,
-                                    task->tk_status);
+       nfs4_sequence_done(data->server, &data->res.seq_res,
+                       task->tk_status);
 
        data->rpc_status = task->tk_status;
        if (RPC_ASSASSINATED(task))
@@ -4049,10 +4069,16 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
                if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
                        return 0;
                err = _nfs4_do_setlk(state, F_SETLK, request, 0);
-               if (err != -NFS4ERR_DELAY)
-                       break;
-               nfs4_handle_exception(server, err, &exception);
+               switch (err) {
+               default:
+                       goto out;
+               case -NFS4ERR_GRACE:
+               case -NFS4ERR_DELAY:
+                       nfs4_handle_exception(server, err, &exception);
+                       err = 0;
+               }
        } while (exception.retry);
+out:
        return err;
 }
 
@@ -4172,6 +4198,11 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
                        case -NFS4ERR_EXPIRED:
                        case -NFS4ERR_STALE_CLIENTID:
                        case -NFS4ERR_STALE_STATEID:
+                       case -NFS4ERR_BADSESSION:
+                       case -NFS4ERR_BADSLOT:
+                       case -NFS4ERR_BAD_HIGH_SLOT:
+                       case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+                       case -NFS4ERR_DEADSESSION:
                                nfs4_schedule_state_recovery(server->nfs_client);
                                goto out;
                        case -ERESTARTSYS:
@@ -4296,7 +4327,7 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
  * NFS4ERR_BADSESSION in the sequence operation, and will therefore
  * be in some phase of session reset.
  */
-static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
+int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
 {
        nfs4_verifier verifier;
        struct nfs41_exchange_id_args args = {
@@ -4318,6 +4349,9 @@ static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
        dprintk("--> %s\n", __func__);
        BUG_ON(clp == NULL);
 
+       /* Remove server-only flags */
+       args.flags &= ~EXCHGID4_FLAG_CONFIRMED_R;
+
        p = (u32 *)verifier.data;
        *p++ = htonl((u32)clp->cl_boot_time.tv_sec);
        *p = htonl((u32)clp->cl_boot_time.tv_nsec);
@@ -4389,10 +4423,9 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata)
                dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status);
                rpc_delay(task, NFS4_POLL_RETRY_MIN);
                task->tk_status = 0;
-               nfs4_restart_rpc(task, data->clp);
+               nfs_restart_rpc(task, data->clp);
                return;
        }
-       nfs41_sequence_free_slot(data->clp, &data->res->lr_seq_res);
        dprintk("<-- %s\n", __func__);
 }
 
@@ -4465,7 +4498,6 @@ static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, int max_slots,
        spin_lock(&tbl->slot_tbl_lock);
        for (i = 0; i < max_slots; ++i)
                tbl->slots[i].seq_nr = ivalue;
-       tbl->highest_used_slotid = -1;
        spin_unlock(&tbl->slot_tbl_lock);
        dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
                tbl, tbl->slots, tbl->max_slots);
@@ -4515,7 +4547,6 @@ static void nfs4_destroy_slot_tables(struct nfs4_session *session)
 static int nfs4_init_slot_table(struct nfs4_slot_table *tbl,
                int max_slots, int ivalue)
 {
-       int i;
        struct nfs4_slot *slot;
        int ret = -ENOMEM;
 
@@ -4526,18 +4557,9 @@ static int nfs4_init_slot_table(struct nfs4_slot_table *tbl,
        slot = kcalloc(max_slots, sizeof(struct nfs4_slot), GFP_KERNEL);
        if (!slot)
                goto out;
-       for (i = 0; i < max_slots; ++i)
-               slot[i].seq_nr = ivalue;
        ret = 0;
 
        spin_lock(&tbl->slot_tbl_lock);
-       if (tbl->slots != NULL) {
-               spin_unlock(&tbl->slot_tbl_lock);
-               dprintk("%s: slot table already initialized. tbl=%p slots=%p\n",
-                       __func__, tbl, tbl->slots);
-               WARN_ON(1);
-               goto out_free;
-       }
        tbl->max_slots = max_slots;
        tbl->slots = slot;
        tbl->highest_used_slotid = -1;  /* no slot is currently used */
@@ -4547,10 +4569,6 @@ static int nfs4_init_slot_table(struct nfs4_slot_table *tbl,
 out:
        dprintk("<-- %s: return %d\n", __func__, ret);
        return ret;
-
-out_free:
-       kfree(slot);
-       goto out;
 }
 
 /*
@@ -4558,17 +4576,24 @@ out_free:
  */
 static int nfs4_init_slot_tables(struct nfs4_session *session)
 {
-       int status;
+       struct nfs4_slot_table *tbl;
+       int status = 0;
 
-       status = nfs4_init_slot_table(&session->fc_slot_table,
-                       session->fc_attrs.max_reqs, 1);
-       if (status)
-               return status;
+       tbl = &session->fc_slot_table;
+       if (tbl->slots == NULL) {
+               status = nfs4_init_slot_table(tbl,
+                               session->fc_attrs.max_reqs, 1);
+               if (status)
+                       return status;
+       }
 
-       status = nfs4_init_slot_table(&session->bc_slot_table,
-                       session->bc_attrs.max_reqs, 0);
-       if (status)
-               nfs4_destroy_slot_tables(session);
+       tbl = &session->bc_slot_table;
+       if (tbl->slots == NULL) {
+               status = nfs4_init_slot_table(tbl,
+                               session->bc_attrs.max_reqs, 0);
+               if (status)
+                       nfs4_destroy_slot_tables(session);
+       }
 
        return status;
 }
@@ -4582,7 +4607,6 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp)
        if (!session)
                return NULL;
 
-       set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
        /*
         * The create session reply races with the server back
         * channel probe. Mark the client NFS_CS_SESSION_INITING
@@ -4590,12 +4614,15 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp)
         * nfs_client struct
         */
        clp->cl_cons_state = NFS_CS_SESSION_INITING;
+       init_completion(&session->complete);
 
        tbl = &session->fc_slot_table;
+       tbl->highest_used_slotid = -1;
        spin_lock_init(&tbl->slot_tbl_lock);
        rpc_init_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table");
 
        tbl = &session->bc_slot_table;
+       tbl->highest_used_slotid = -1;
        spin_lock_init(&tbl->slot_tbl_lock);
        rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table");
 
@@ -4747,11 +4774,10 @@ static int _nfs4_proc_create_session(struct nfs_client *clp)
  * It is the responsibility of the caller to verify the session is
  * expired before calling this routine.
  */
-int nfs4_proc_create_session(struct nfs_client *clp, int reset)
+int nfs4_proc_create_session(struct nfs_client *clp)
 {
        int status;
        unsigned *ptr;
-       struct nfs_fsinfo fsinfo;
        struct nfs4_session *session = clp->cl_session;
 
        dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);
@@ -4760,35 +4786,19 @@ int nfs4_proc_create_session(struct nfs_client *clp, int reset)
        if (status)
                goto out;
 
-       /* Init or reset the fore channel */
-       if (reset)
-               status = nfs4_reset_slot_tables(session);
-       else
-               status = nfs4_init_slot_tables(session);
-       dprintk("fore channel slot table initialization returned %d\n", status);
+       /* Init and reset the fore channel */
+       status = nfs4_init_slot_tables(session);
+       dprintk("slot table initialization returned %d\n", status);
+       if (status)
+               goto out;
+       status = nfs4_reset_slot_tables(session);
+       dprintk("slot table reset returned %d\n", status);
        if (status)
                goto out;
 
        ptr = (unsigned *)&session->sess_id.data[0];
        dprintk("%s client>seqid %d sessionid %u:%u:%u:%u\n", __func__,
                clp->cl_seqid, ptr[0], ptr[1], ptr[2], ptr[3]);
-
-       if (reset)
-               /* Lease time is aleady set */
-               goto out;
-
-       /* Get the lease time */
-       status = nfs4_proc_get_lease_time(clp, &fsinfo);
-       if (status == 0) {
-               /* Update lease time and schedule renewal */
-               spin_lock(&clp->cl_lock);
-               clp->cl_lease_time = fsinfo.lease_time * HZ;
-               clp->cl_last_renewal = jiffies;
-               clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
-               spin_unlock(&clp->cl_lock);
-
-               nfs4_schedule_state_renewal(clp);
-       }
 out:
        dprintk("<-- %s\n", __func__);
        return status;
@@ -4827,13 +4837,16 @@ int nfs4_proc_destroy_session(struct nfs4_session *session)
 int nfs4_init_session(struct nfs_server *server)
 {
        struct nfs_client *clp = server->nfs_client;
+       struct nfs4_session *session;
        int ret;
 
        if (!nfs4_has_session(clp))
                return 0;
 
-       clp->cl_session->fc_attrs.max_rqst_sz = server->wsize;
-       clp->cl_session->fc_attrs.max_resp_sz = server->rsize;
+       session = clp->cl_session;
+       session->fc_attrs.max_rqst_sz = server->wsize + nfs41_maxwrite_overhead;
+       session->fc_attrs.max_resp_sz = server->rsize + nfs41_maxread_overhead;
+
        ret = nfs4_recover_expired_lease(server);
        if (!ret)
                ret = nfs4_check_client_ready(clp);
@@ -4872,11 +4885,10 @@ void nfs41_sequence_call_done(struct rpc_task *task, void *data)
 
                if (_nfs4_async_handle_error(task, NULL, clp, NULL)
                                                                == -EAGAIN) {
-                       nfs4_restart_rpc(task, clp);
+                       nfs_restart_rpc(task, clp);
                        return;
                }
        }
-       nfs41_sequence_free_slot(clp, task->tk_msg.rpc_resp);
        dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
 
        kfree(task->tk_msg.rpc_argp);
@@ -4931,6 +4943,109 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp,
                              &nfs41_sequence_ops, (void *)clp);
 }
 
+struct nfs4_reclaim_complete_data {
+       struct nfs_client *clp;
+       struct nfs41_reclaim_complete_args arg;
+       struct nfs41_reclaim_complete_res res;
+};
+
+static void nfs4_reclaim_complete_prepare(struct rpc_task *task, void *data)
+{
+       struct nfs4_reclaim_complete_data *calldata = data;
+
+       if (nfs4_setup_sequence(calldata->clp, &calldata->arg.seq_args,
+                               &calldata->res.seq_res, 0, task))
+               return;
+
+       rpc_call_start(task);
+}
+
+static void nfs4_reclaim_complete_done(struct rpc_task *task, void *data)
+{
+       struct nfs4_reclaim_complete_data *calldata = data;
+       struct nfs_client *clp = calldata->clp;
+       struct nfs4_sequence_res *res = &calldata->res.seq_res;
+
+       dprintk("--> %s\n", __func__);
+       nfs41_sequence_done(clp, res, task->tk_status);
+       switch (task->tk_status) {
+       case 0:
+       case -NFS4ERR_COMPLETE_ALREADY:
+               break;
+       case -NFS4ERR_BADSESSION:
+       case -NFS4ERR_DEADSESSION:
+               /*
+                * Handle the session error, but do not retry the operation, as
+                * we have no way of telling whether the clientid had to be
+                * reset before we got our reply.  If reset, a new wave of
+                * reclaim operations will follow, containing their own reclaim
+                * complete.  We don't want our retry to get on the way of
+                * recovery by incorrectly indicating to the server that we're
+                * done reclaiming state since the process had to be restarted.
+                */
+               _nfs4_async_handle_error(task, NULL, clp, NULL);
+               break;
+       default:
+               if (_nfs4_async_handle_error(
+                               task, NULL, clp, NULL) == -EAGAIN) {
+                       rpc_restart_call_prepare(task);
+                       return;
+               }
+       }
+
+       dprintk("<-- %s\n", __func__);
+}
+
+static void nfs4_free_reclaim_complete_data(void *data)
+{
+       struct nfs4_reclaim_complete_data *calldata = data;
+
+       kfree(calldata);
+}
+
+static const struct rpc_call_ops nfs4_reclaim_complete_call_ops = {
+       .rpc_call_prepare = nfs4_reclaim_complete_prepare,
+       .rpc_call_done = nfs4_reclaim_complete_done,
+       .rpc_release = nfs4_free_reclaim_complete_data,
+};
+
+/*
+ * Issue a global reclaim complete.
+ */
+static int nfs41_proc_reclaim_complete(struct nfs_client *clp)
+{
+       struct nfs4_reclaim_complete_data *calldata;
+       struct rpc_task *task;
+       struct rpc_message msg = {
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RECLAIM_COMPLETE],
+       };
+       struct rpc_task_setup task_setup_data = {
+               .rpc_client = clp->cl_rpcclient,
+               .rpc_message = &msg,
+               .callback_ops = &nfs4_reclaim_complete_call_ops,
+               .flags = RPC_TASK_ASYNC,
+       };
+       int status = -ENOMEM;
+
+       dprintk("--> %s\n", __func__);
+       calldata = kzalloc(sizeof(*calldata), GFP_KERNEL);
+       if (calldata == NULL)
+               goto out;
+       calldata->clp = clp;
+       calldata->arg.one_fs = 0;
+       calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
+
+       msg.rpc_argp = &calldata->arg;
+       msg.rpc_resp = &calldata->res;
+       task_setup_data.callback_data = calldata;
+       task = rpc_run_task(&task_setup_data);
+       if (IS_ERR(task))
+               status = PTR_ERR(task);
+       rpc_put_task(task);
+out:
+       dprintk("<-- %s status=%d\n", __func__, status);
+       return status;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
@@ -4948,8 +5063,9 @@ struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = {
        .state_flag_bit = NFS_STATE_RECLAIM_REBOOT,
        .recover_open   = nfs4_open_reclaim,
        .recover_lock   = nfs4_lock_reclaim,
-       .establish_clid = nfs4_proc_exchange_id,
+       .establish_clid = nfs41_init_clientid,
        .get_clid_cred  = nfs4_get_exchange_id_cred,
+       .reclaim_complete = nfs41_proc_reclaim_complete,
 };
 #endif /* CONFIG_NFS_V4_1 */
 
@@ -4968,7 +5084,7 @@ struct nfs4_state_recovery_ops nfs41_nograce_recovery_ops = {
        .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE,
        .recover_open   = nfs4_open_expired,
        .recover_lock   = nfs4_lock_expired,
-       .establish_clid = nfs4_proc_exchange_id,
+       .establish_clid = nfs41_init_clientid,
        .get_clid_cred  = nfs4_get_exchange_id_cred,
 };
 #endif /* CONFIG_NFS_V4_1 */
index 2ef4fec..e76427e 100644 (file)
@@ -116,6 +116,68 @@ struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp)
 
 #if defined(CONFIG_NFS_V4_1)
 
+static int nfs41_setup_state_renewal(struct nfs_client *clp)
+{
+       int status;
+       struct nfs_fsinfo fsinfo;
+
+       status = nfs4_proc_get_lease_time(clp, &fsinfo);
+       if (status == 0) {
+               /* Update lease time and schedule renewal */
+               spin_lock(&clp->cl_lock);
+               clp->cl_lease_time = fsinfo.lease_time * HZ;
+               clp->cl_last_renewal = jiffies;
+               spin_unlock(&clp->cl_lock);
+
+               nfs4_schedule_state_renewal(clp);
+       }
+
+       return status;
+}
+
+static void nfs41_end_drain_session(struct nfs_client *clp,
+               struct nfs4_session *ses)
+{
+       if (test_and_clear_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state))
+               rpc_wake_up(&ses->fc_slot_table.slot_tbl_waitq);
+}
+
+static int nfs41_begin_drain_session(struct nfs_client *clp,
+               struct nfs4_session *ses)
+{
+       struct nfs4_slot_table *tbl = &ses->fc_slot_table;
+
+       spin_lock(&tbl->slot_tbl_lock);
+       set_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state);
+       if (tbl->highest_used_slotid != -1) {
+               INIT_COMPLETION(ses->complete);
+               spin_unlock(&tbl->slot_tbl_lock);
+               return wait_for_completion_interruptible(&ses->complete);
+       }
+       spin_unlock(&tbl->slot_tbl_lock);
+       return 0;
+}
+
+int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
+{
+       int status;
+
+       status = nfs41_begin_drain_session(clp, clp->cl_session);
+       if (status != 0)
+               goto out;
+       status = nfs4_proc_exchange_id(clp, cred);
+       if (status != 0)
+               goto out;
+       status = nfs4_proc_create_session(clp);
+       if (status != 0)
+               goto out;
+       nfs41_end_drain_session(clp, clp->cl_session);
+       nfs41_setup_state_renewal(clp);
+       nfs_mark_client_ready(clp, NFS_CS_READY);
+out:
+       return status;
+}
+
 struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp)
 {
        struct rpc_cred *cred;
@@ -877,6 +939,10 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
                        case -NFS4ERR_EXPIRED:
                        case -NFS4ERR_NO_GRACE:
                        case -NFS4ERR_STALE_CLIENTID:
+                       case -NFS4ERR_BADSESSION:
+                       case -NFS4ERR_BADSLOT:
+                       case -NFS4ERR_BAD_HIGH_SLOT:
+                       case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
                                goto out;
                        default:
                                printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
@@ -959,6 +1025,10 @@ restart:
                        case -NFS4ERR_NO_GRACE:
                                nfs4_state_mark_reclaim_nograce(sp->so_client, state);
                        case -NFS4ERR_STALE_CLIENTID:
+                       case -NFS4ERR_BADSESSION:
+                       case -NFS4ERR_BADSLOT:
+                       case -NFS4ERR_BAD_HIGH_SLOT:
+                       case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
                                goto out_err;
                }
                nfs4_put_open_state(state);
@@ -1011,6 +1081,14 @@ static void nfs4_state_start_reclaim_reboot(struct nfs_client *clp)
        nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_reboot);
 }
 
+static void nfs4_reclaim_complete(struct nfs_client *clp,
+                                const struct nfs4_state_recovery_ops *ops)
+{
+       /* Notify the server we're done reclaiming our state */
+       if (ops->reclaim_complete)
+               (void)ops->reclaim_complete(clp);
+}
+
 static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
 {
        struct nfs4_state_owner *sp;
@@ -1020,6 +1098,9 @@ static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
        if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
                return;
 
+       nfs4_reclaim_complete(clp,
+               nfs4_reboot_recovery_ops[clp->cl_minorversion]);
+
        for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
                sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
                spin_lock(&sp->so_lock);
@@ -1046,25 +1127,25 @@ static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp)
        nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce);
 }
 
-static void nfs4_state_end_reclaim_nograce(struct nfs_client *clp)
-{
-       clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
-}
-
-static void nfs4_recovery_handle_error(struct nfs_client *clp, int error)
+static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
 {
        switch (error) {
                case -NFS4ERR_CB_PATH_DOWN:
                        nfs_handle_cb_pathdown(clp);
-                       break;
+                       return 0;
+               case -NFS4ERR_NO_GRACE:
+                       nfs4_state_end_reclaim_reboot(clp);
+                       return 0;
                case -NFS4ERR_STALE_CLIENTID:
                case -NFS4ERR_LEASE_MOVED:
                        set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
+                       nfs4_state_end_reclaim_reboot(clp);
                        nfs4_state_start_reclaim_reboot(clp);
                        break;
                case -NFS4ERR_EXPIRED:
                        set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
                        nfs4_state_start_reclaim_nograce(clp);
+                       break;
                case -NFS4ERR_BADSESSION:
                case -NFS4ERR_BADSLOT:
                case -NFS4ERR_BAD_HIGH_SLOT:
@@ -1072,8 +1153,11 @@ static void nfs4_recovery_handle_error(struct nfs_client *clp, int error)
                case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
                case -NFS4ERR_SEQ_FALSE_RETRY:
                case -NFS4ERR_SEQ_MISORDERED:
-                       set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
+                       set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
+                       /* Zero session reset errors */
+                       return 0;
        }
+       return error;
 }
 
 static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops)
@@ -1093,8 +1177,7 @@ restart:
                if (status < 0) {
                        set_bit(ops->owner_flag_bit, &sp->so_flags);
                        nfs4_put_state_owner(sp);
-                       nfs4_recovery_handle_error(clp, status);
-                       return status;
+                       return nfs4_recovery_handle_error(clp, status);
                }
                nfs4_put_state_owner(sp);
                goto restart;
@@ -1124,8 +1207,7 @@ static int nfs4_check_lease(struct nfs_client *clp)
        status = ops->renew_lease(clp, cred);
        put_rpccred(cred);
 out:
-       nfs4_recovery_handle_error(clp, status);
-       return status;
+       return nfs4_recovery_handle_error(clp, status);
 }
 
 static int nfs4_reclaim_lease(struct nfs_client *clp)
@@ -1151,55 +1233,65 @@ static int nfs4_reclaim_lease(struct nfs_client *clp)
 }
 
 #ifdef CONFIG_NFS_V4_1
-static void nfs4_session_recovery_handle_error(struct nfs_client *clp, int err)
+void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags)
 {
-       switch (err) {
-       case -NFS4ERR_STALE_CLIENTID:
+       if (!flags)
+               return;
+       else if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED) {
                set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
-               set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
-       }
+               nfs4_state_start_reclaim_reboot(clp);
+               nfs4_schedule_state_recovery(clp);
+       } else if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED |
+                           SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED |
+                           SEQ4_STATUS_ADMIN_STATE_REVOKED |
+                           SEQ4_STATUS_RECALLABLE_STATE_REVOKED |
+                           SEQ4_STATUS_LEASE_MOVED)) {
+               set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
+               nfs4_state_start_reclaim_nograce(clp);
+               nfs4_schedule_state_recovery(clp);
+       } else if (flags & (SEQ4_STATUS_CB_PATH_DOWN |
+                           SEQ4_STATUS_BACKCHANNEL_FAULT |
+                           SEQ4_STATUS_CB_PATH_DOWN_SESSION))
+               nfs_expire_all_delegations(clp);
 }
 
 static int nfs4_reset_session(struct nfs_client *clp)
 {
+       struct nfs4_session *ses = clp->cl_session;
        int status;
 
+       status = nfs41_begin_drain_session(clp, ses);
+       if (status != 0)
+               return status;
+
        status = nfs4_proc_destroy_session(clp->cl_session);
        if (status && status != -NFS4ERR_BADSESSION &&
            status != -NFS4ERR_DEADSESSION) {
-               nfs4_session_recovery_handle_error(clp, status);
+               status = nfs4_recovery_handle_error(clp, status);
                goto out;
        }
 
        memset(clp->cl_session->sess_id.data, 0, NFS4_MAX_SESSIONID_LEN);
-       status = nfs4_proc_create_session(clp, 1);
+       status = nfs4_proc_create_session(clp);
        if (status)
-               nfs4_session_recovery_handle_error(clp, status);
-               /* fall through*/
-out:
-       /* Wake up the next rpc task even on error */
-       rpc_wake_up_next(&clp->cl_session->fc_slot_table.slot_tbl_waitq);
-       return status;
-}
-
-static int nfs4_initialize_session(struct nfs_client *clp)
-{
-       int status;
+               status = nfs4_recovery_handle_error(clp, status);
 
-       status = nfs4_proc_create_session(clp, 0);
-       if (!status) {
-               nfs_mark_client_ready(clp, NFS_CS_READY);
-       } else if (status == -NFS4ERR_STALE_CLIENTID) {
-               set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
-               set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
-       } else {
-               nfs_mark_client_ready(clp, status);
+out:
+       /*
+        * Let the state manager reestablish state
+        * without waking other tasks yet.
+        */
+       if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) {
+               /* Wake up the next rpc task */
+               nfs41_end_drain_session(clp, ses);
+               if (status == 0)
+                       nfs41_setup_state_renewal(clp);
        }
        return status;
 }
+
 #else /* CONFIG_NFS_V4_1 */
 static int nfs4_reset_session(struct nfs_client *clp) { return 0; }
-static int nfs4_initialize_session(struct nfs_client *clp) { return 0; }
 #endif /* CONFIG_NFS_V4_1 */
 
 /* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors
@@ -1234,7 +1326,8 @@ static void nfs4_state_manager(struct nfs_client *clp)
                        status = nfs4_reclaim_lease(clp);
                        if (status) {
                                nfs4_set_lease_expired(clp, status);
-                               if (status == -EAGAIN)
+                               if (test_bit(NFS4CLNT_LEASE_EXPIRED,
+                                                       &clp->cl_state))
                                        continue;
                                if (clp->cl_cons_state ==
                                                        NFS_CS_SESSION_INITING)
@@ -1242,55 +1335,51 @@ static void nfs4_state_manager(struct nfs_client *clp)
                                goto out_error;
                        }
                        clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
+                       set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state);
                }
 
                if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) {
                        status = nfs4_check_lease(clp);
-                       if (status != 0)
+                       if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
                                continue;
+                       if (status < 0 && status != -NFS4ERR_CB_PATH_DOWN)
+                               goto out_error;
                }
+
                /* Initialize or reset the session */
-               if (test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)
+               if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)
                   && nfs4_has_session(clp)) {
-                       if (clp->cl_cons_state == NFS_CS_SESSION_INITING)
-                               status = nfs4_initialize_session(clp);
-                       else
-                               status = nfs4_reset_session(clp);
-                       if (status) {
-                               if (status == -NFS4ERR_STALE_CLIENTID)
-                                       continue;
+                       status = nfs4_reset_session(clp);
+                       if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
+                               continue;
+                       if (status < 0)
                                goto out_error;
-                       }
                }
+
                /* First recover reboot state... */
-               if (test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) {
+               if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) {
                        status = nfs4_do_reclaim(clp,
                                nfs4_reboot_recovery_ops[clp->cl_minorversion]);
-                       if (status == -NFS4ERR_STALE_CLIENTID)
-                               continue;
-                       if (test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state))
+                       if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) ||
+                           test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state))
                                continue;
                        nfs4_state_end_reclaim_reboot(clp);
-                       continue;
+                       if (test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state))
+                               continue;
+                       if (status < 0)
+                               goto out_error;
                }
 
                /* Now recover expired state... */
                if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
                        status = nfs4_do_reclaim(clp,
                                nfs4_nograce_recovery_ops[clp->cl_minorversion]);
-                       if (status < 0) {
-                               set_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
-                               if (status == -NFS4ERR_STALE_CLIENTID)
-                                       continue;
-                               if (status == -NFS4ERR_EXPIRED)
-                                       continue;
-                               if (test_bit(NFS4CLNT_SESSION_SETUP,
-                                                               &clp->cl_state))
-                                       continue;
+                       if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) ||
+                           test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) ||
+                           test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
+                               continue;
+                       if (status < 0)
                                goto out_error;
-                       } else
-                               nfs4_state_end_reclaim_nograce(clp);
-                       continue;
                }
 
                if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) {
@@ -1309,8 +1398,6 @@ static void nfs4_state_manager(struct nfs_client *clp)
 out_error:
        printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s"
                        " with error %d\n", clp->cl_hostname, -status);
-       if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
-               nfs4_state_end_reclaim_reboot(clp);
        nfs4_clear_state_manager_bit(clp);
 }
 
index 20b4e30..e437fd6 100644 (file)
 #include <linux/proc_fs.h>
 #include <linux/kdev_t.h>
 #include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/msg_prot.h>
 #include <linux/nfs.h>
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_idmap.h>
 #include "nfs4_fs.h"
+#include "internal.h"
 
 #define NFSDBG_FACILITY                NFSDBG_XDR
 
@@ -134,7 +136,7 @@ static int nfs4_stat_to_errno(int);
 #define decode_lookup_maxsz    (op_decode_hdr_maxsz)
 #define encode_share_access_maxsz \
                                (2)
-#define encode_createmode_maxsz        (1 + encode_attrs_maxsz)
+#define encode_createmode_maxsz        (1 + encode_attrs_maxsz + encode_verifier_maxsz)
 #define encode_opentype_maxsz  (1 + encode_createmode_maxsz)
 #define encode_claim_null_maxsz        (1 + nfs4_name_maxsz)
 #define encode_open_maxsz      (op_encode_hdr_maxsz + \
@@ -299,6 +301,8 @@ static int nfs4_stat_to_errno(int);
                                XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4)
 #define decode_sequence_maxsz  (op_decode_hdr_maxsz + \
                                XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5)
+#define encode_reclaim_complete_maxsz  (op_encode_hdr_maxsz + 4)
+#define decode_reclaim_complete_maxsz  (op_decode_hdr_maxsz + 4)
 #else /* CONFIG_NFS_V4_1 */
 #define encode_sequence_maxsz  0
 #define decode_sequence_maxsz  0
@@ -676,6 +680,25 @@ static int nfs4_stat_to_errno(int);
                                         decode_sequence_maxsz + \
                                         decode_putrootfh_maxsz + \
                                         decode_fsinfo_maxsz)
+#define NFS4_enc_reclaim_complete_sz   (compound_encode_hdr_maxsz + \
+                                        encode_sequence_maxsz + \
+                                        encode_reclaim_complete_maxsz)
+#define NFS4_dec_reclaim_complete_sz   (compound_decode_hdr_maxsz + \
+                                        decode_sequence_maxsz + \
+                                        decode_reclaim_complete_maxsz)
+
+const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
+                                     compound_encode_hdr_maxsz +
+                                     encode_sequence_maxsz +
+                                     encode_putfh_maxsz +
+                                     encode_getattr_maxsz) *
+                                    XDR_UNIT);
+
+const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
+                                    compound_decode_hdr_maxsz +
+                                    decode_sequence_maxsz +
+                                    decode_putfh_maxsz) *
+                                   XDR_UNIT);
 #endif /* CONFIG_NFS_V4_1 */
 
 static const umode_t nfs_type2fmt[] = {
@@ -1140,6 +1163,7 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena
 static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
 {
        __be32 *p;
+       struct nfs_client *clp;
 
        p = reserve_space(xdr, 4);
        switch(arg->open_flags & O_EXCL) {
@@ -1148,8 +1172,23 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op
                encode_attrs(xdr, arg->u.attrs, arg->server);
                break;
        default:
-               *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE);
-               encode_nfs4_verifier(xdr, &arg->u.verifier);
+               clp = arg->server->nfs_client;
+               if (clp->cl_minorversion > 0) {
+                       if (nfs4_has_persistent_session(clp)) {
+                               *p = cpu_to_be32(NFS4_CREATE_GUARDED);
+                               encode_attrs(xdr, arg->u.attrs, arg->server);
+                       } else {
+                               struct iattr dummy;
+
+                               *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1);
+                               encode_nfs4_verifier(xdr, &arg->u.verifier);
+                               dummy.ia_valid = 0;
+                               encode_attrs(xdr, &dummy, arg->server);
+                       }
+               } else {
+                       *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE);
+                       encode_nfs4_verifier(xdr, &arg->u.verifier);
+               }
        }
 }
 
@@ -1592,6 +1631,19 @@ static void encode_destroy_session(struct xdr_stream *xdr,
        hdr->nops++;
        hdr->replen += decode_destroy_session_maxsz;
 }
+
+static void encode_reclaim_complete(struct xdr_stream *xdr,
+                                   struct nfs41_reclaim_complete_args *args,
+                                   struct compound_hdr *hdr)
+{
+       __be32 *p;
+
+       p = reserve_space(xdr, 8);
+       *p++ = cpu_to_be32(OP_RECLAIM_COMPLETE);
+       *p++ = cpu_to_be32(args->one_fs);
+       hdr->nops++;
+       hdr->replen += decode_reclaim_complete_maxsz;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 static void encode_sequence(struct xdr_stream *xdr,
@@ -2096,7 +2148,7 @@ nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,
        encode_compound_hdr(&xdr, req, &hdr);
        encode_sequence(&xdr, &args->seq_args, &hdr);
        encode_putfh(&xdr, args->fh, &hdr);
-       replen = hdr.replen + nfs4_fattr_bitmap_maxsz + 1;
+       replen = hdr.replen + op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz + 1;
        encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr);
 
        xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
@@ -2420,6 +2472,26 @@ static int nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, uint32_t *p,
        encode_nops(&hdr);
        return 0;
 }
+
+/*
+ * a RECLAIM_COMPLETE request
+ */
+static int nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req, uint32_t *p,
+                                    struct nfs41_reclaim_complete_args *args)
+{
+       struct xdr_stream xdr;
+       struct compound_hdr hdr = {
+               .minorversion = nfs4_xdr_minorversion(&args->seq_args)
+       };
+
+       xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+       encode_compound_hdr(&xdr, req, &hdr);
+       encode_sequence(&xdr, &args->seq_args, &hdr);
+       encode_reclaim_complete(&xdr, args, &hdr);
+       encode_nops(&hdr);
+       return 0;
+}
+
 #endif /* CONFIG_NFS_V4_1 */
 
 static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
@@ -4528,6 +4600,11 @@ static int decode_destroy_session(struct xdr_stream *xdr, void *dummy)
 {
        return decode_op_hdr(xdr, OP_DESTROY_SESSION);
 }
+
+static int decode_reclaim_complete(struct xdr_stream *xdr, void *dummy)
+{
+       return decode_op_hdr(xdr, OP_RECLAIM_COMPLETE);
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 static int decode_sequence(struct xdr_stream *xdr,
@@ -4583,8 +4660,8 @@ static int decode_sequence(struct xdr_stream *xdr,
        dummy = be32_to_cpup(p++);
        /* target highest slot id - currently not processed */
        dummy = be32_to_cpup(p++);
-       /* result flags - currently not processed */
-       dummy = be32_to_cpup(p);
+       /* result flags */
+       res->sr_status_flags = be32_to_cpup(p);
        status = 0;
 out_err:
        res->sr_status = status;
@@ -5309,7 +5386,7 @@ out:
 }
 
 /*
- * FSINFO request
+ * Decode FSINFO response
  */
 static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p,
                               struct nfs4_fsinfo_res *res)
@@ -5330,7 +5407,7 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p,
 }
 
 /*
- * PATHCONF request
+ * Decode PATHCONF response
  */
 static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p,
                                 struct nfs4_pathconf_res *res)
@@ -5351,7 +5428,7 @@ static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p,
 }
 
 /*
- * STATFS request
+ * Decode STATFS response
  */
 static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p,
                               struct nfs4_statfs_res *res)
@@ -5372,7 +5449,7 @@ static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p,
 }
 
 /*
- * GETATTR_BITMAP request
+ * Decode GETATTR_BITMAP response
  */
 static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, __be32 *p, struct nfs4_server_caps_res *res)
 {
@@ -5411,7 +5488,7 @@ static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, __be32 *p, void *dummy)
 }
 
 /*
- * a SETCLIENTID request
+ * Decode SETCLIENTID response
  */
 static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p,
                struct nfs_client *clp)
@@ -5428,7 +5505,7 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p,
 }
 
 /*
- * a SETCLIENTID_CONFIRM request
+ * Decode SETCLIENTID_CONFIRM response
  */
 static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *fsinfo)
 {
@@ -5448,7 +5525,7 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
 }
 
 /*
- * DELEGRETURN request
+ * Decode DELEGRETURN response
  */
 static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_delegreturnres *res)
 {
@@ -5474,7 +5551,7 @@ out:
 }
 
 /*
- * FS_LOCATIONS request
+ * Decode FS_LOCATIONS response
  */
 static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p,
                                     struct nfs4_fs_locations_res *res)
@@ -5504,7 +5581,7 @@ out:
 
 #if defined(CONFIG_NFS_V4_1)
 /*
- * EXCHANGE_ID request
+ * Decode EXCHANGE_ID response
  */
 static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, uint32_t *p,
                                    void *res)
@@ -5521,7 +5598,7 @@ static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, uint32_t *p,
 }
 
 /*
- * a CREATE_SESSION request
+ * Decode CREATE_SESSION response
  */
 static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, uint32_t *p,
                                       struct nfs41_create_session_res *res)
@@ -5538,7 +5615,7 @@ static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, uint32_t *p,
 }
 
 /*
- * a DESTROY_SESSION request
+ * Decode DESTROY_SESSION response
  */
 static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, uint32_t *p,
                                        void *dummy)
@@ -5555,7 +5632,7 @@ static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, uint32_t *p,
 }
 
 /*
- * a SEQUENCE request
+ * Decode SEQUENCE response
  */
 static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, uint32_t *p,
                                 struct nfs4_sequence_res *res)
@@ -5572,7 +5649,7 @@ static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, uint32_t *p,
 }
 
 /*
- * a GET_LEASE_TIME request
+ * Decode GET_LEASE_TIME response
  */
 static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p,
                                       struct nfs4_get_lease_time_res *res)
@@ -5591,6 +5668,25 @@ static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p,
                status = decode_fsinfo(&xdr, res->lr_fsinfo);
        return status;
 }
+
+/*
+ * Decode RECLAIM_COMPLETE response
+ */
+static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp, uint32_t *p,
+                                        struct nfs41_reclaim_complete_res *res)
+{
+       struct xdr_stream xdr;
+       struct compound_hdr hdr;
+       int status;
+
+       xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+       status = decode_compound_hdr(&xdr, &hdr);
+       if (!status)
+               status = decode_sequence(&xdr, &res->seq_res, rqstp);
+       if (!status)
+               status = decode_reclaim_complete(&xdr, (void *)NULL);
+       return status;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
@@ -5767,6 +5863,7 @@ struct rpc_procinfo       nfs4_procedures[] = {
   PROC(DESTROY_SESSION,        enc_destroy_session,    dec_destroy_session),
   PROC(SEQUENCE,       enc_sequence,   dec_sequence),
   PROC(GET_LEASE_TIME, enc_get_lease_time,     dec_get_lease_time),
+  PROC(RECLAIM_COMPLETE, enc_reclaim_complete,  dec_reclaim_complete),
 #endif /* CONFIG_NFS_V4_1 */
 };
 
index 12c9e66..db9b360 100644 (file)
@@ -356,25 +356,19 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data
        struct nfs_readres *resp = &data->res;
 
        if (resp->eof || resp->count == argp->count)
-               goto out;
+               return;
 
        /* This is a short read! */
        nfs_inc_stats(data->inode, NFSIOS_SHORTREAD);
        /* Has the server at least made some progress? */
        if (resp->count == 0)
-               goto out;
+               return;
 
        /* Yes, so retry the read at the end of the data */
        argp->offset += resp->count;
        argp->pgbase += resp->count;
        argp->count -= resp->count;
-       nfs4_restart_rpc(task, NFS_SERVER(data->inode)->nfs_client);
-       return;
-out:
-       nfs4_sequence_free_slot(NFS_SERVER(data->inode)->nfs_client,
-                               &data->res.seq_res);
-       return;
-
+       nfs_restart_rpc(task, NFS_SERVER(data->inode)->nfs_client);
 }
 
 /*
index 90be551..ce907ef 100644 (file)
@@ -175,14 +175,16 @@ static const match_table_t nfs_mount_option_tokens = {
 };
 
 enum {
-       Opt_xprt_udp, Opt_xprt_tcp, Opt_xprt_rdma,
+       Opt_xprt_udp, Opt_xprt_udp6, Opt_xprt_tcp, Opt_xprt_tcp6, Opt_xprt_rdma,
 
        Opt_xprt_err
 };
 
 static const match_table_t nfs_xprt_protocol_tokens = {
        { Opt_xprt_udp, "udp" },
+       { Opt_xprt_udp6, "udp6" },
        { Opt_xprt_tcp, "tcp" },
+       { Opt_xprt_tcp6, "tcp6" },
        { Opt_xprt_rdma, "rdma" },
 
        { Opt_xprt_err, NULL }
@@ -492,6 +494,45 @@ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
        return sec_flavours[i].str;
 }
 
+static void nfs_show_mountd_netid(struct seq_file *m, struct nfs_server *nfss,
+                                 int showdefaults)
+{
+       struct sockaddr *sap = (struct sockaddr *) &nfss->mountd_address;
+
+       seq_printf(m, ",mountproto=");
+       switch (sap->sa_family) {
+       case AF_INET:
+               switch (nfss->mountd_protocol) {
+               case IPPROTO_UDP:
+                       seq_printf(m, RPCBIND_NETID_UDP);
+                       break;
+               case IPPROTO_TCP:
+                       seq_printf(m, RPCBIND_NETID_TCP);
+                       break;
+               default:
+                       if (showdefaults)
+                               seq_printf(m, "auto");
+               }
+               break;
+       case AF_INET6:
+               switch (nfss->mountd_protocol) {
+               case IPPROTO_UDP:
+                       seq_printf(m, RPCBIND_NETID_UDP6);
+                       break;
+               case IPPROTO_TCP:
+                       seq_printf(m, RPCBIND_NETID_TCP6);
+                       break;
+               default:
+                       if (showdefaults)
+                               seq_printf(m, "auto");
+               }
+               break;
+       default:
+               if (showdefaults)
+                       seq_printf(m, "auto");
+       }
+}
+
 static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
                                    int showdefaults)
 {
@@ -505,7 +546,7 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
        }
        case AF_INET6: {
                struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
-               seq_printf(m, ",mountaddr=%pI6", &sin6->sin6_addr);
+               seq_printf(m, ",mountaddr=%pI6c", &sin6->sin6_addr);
                break;
        }
        default:
@@ -518,17 +559,7 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss,
        if (nfss->mountd_port || showdefaults)
                seq_printf(m, ",mountport=%u", nfss->mountd_port);
 
-       switch (nfss->mountd_protocol) {
-       case IPPROTO_UDP:
-               seq_printf(m, ",mountproto=udp");
-               break;
-       case IPPROTO_TCP:
-               seq_printf(m, ",mountproto=tcp");
-               break;
-       default:
-               if (showdefaults)
-                       seq_printf(m, ",mountproto=auto");
-       }
+       nfs_show_mountd_netid(m, nfss, showdefaults);
 }
 
 /*
@@ -578,7 +609,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
                        seq_puts(m, nfs_infop->nostr);
        }
        seq_printf(m, ",proto=%s",
-                  rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO));
+                  rpc_peeraddr2str(nfss->client, RPC_DISPLAY_NETID));
        if (version == 4) {
                if (nfss->port != NFS_PORT)
                        seq_printf(m, ",port=%u", nfss->port);
@@ -714,8 +745,6 @@ static void nfs_umount_begin(struct super_block *sb)
        struct nfs_server *server;
        struct rpc_clnt *rpc;
 
-       lock_kernel();
-
        server = NFS_SB(sb);
        /* -EIO all pending I/O */
        rpc = server->client_acl;
@@ -724,8 +753,6 @@ static void nfs_umount_begin(struct super_block *sb)
        rpc = server->client;
        if (!IS_ERR(rpc))
                rpc_killall_tasks(rpc);
-
-       unlock_kernel();
 }
 
 static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int version)
@@ -734,8 +761,6 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int ve
 
        data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (data) {
-               data->rsize             = NFS_MAX_FILE_IO_SIZE;
-               data->wsize             = NFS_MAX_FILE_IO_SIZE;
                data->acregmin          = NFS_DEF_ACREGMIN;
                data->acregmax          = NFS_DEF_ACREGMAX;
                data->acdirmin          = NFS_DEF_ACDIRMIN;
@@ -887,6 +912,8 @@ static int nfs_parse_mount_options(char *raw,
 {
        char *p, *string, *secdata;
        int rc, sloppy = 0, invalid_option = 0;
+       unsigned short protofamily = AF_UNSPEC;
+       unsigned short mountfamily = AF_UNSPEC;
 
        if (!raw) {
                dfprintk(MOUNT, "NFS: mount options string was NULL.\n");
@@ -1232,12 +1259,17 @@ static int nfs_parse_mount_options(char *raw,
                        token = match_token(string,
                                            nfs_xprt_protocol_tokens, args);
 
+                       protofamily = AF_INET;
                        switch (token) {
+                       case Opt_xprt_udp6:
+                               protofamily = AF_INET6;
                        case Opt_xprt_udp:
                                mnt->flags &= ~NFS_MOUNT_TCP;
                                mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP;
                                kfree(string);
                                break;
+                       case Opt_xprt_tcp6:
+                               protofamily = AF_INET6;
                        case Opt_xprt_tcp:
                                mnt->flags |= NFS_MOUNT_TCP;
                                mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP;
@@ -1265,10 +1297,15 @@ static int nfs_parse_mount_options(char *raw,
                                            nfs_xprt_protocol_tokens, args);
                        kfree(string);
 
+                       mountfamily = AF_INET;
                        switch (token) {
+                       case Opt_xprt_udp6:
+                               mountfamily = AF_INET6;
                        case Opt_xprt_udp:
                                mnt->mount_server.protocol = XPRT_TRANSPORT_UDP;
                                break;
+                       case Opt_xprt_tcp6:
+                               mountfamily = AF_INET6;
                        case Opt_xprt_tcp:
                                mnt->mount_server.protocol = XPRT_TRANSPORT_TCP;
                                break;
@@ -1367,8 +1404,33 @@ static int nfs_parse_mount_options(char *raw,
        if (!sloppy && invalid_option)
                return 0;
 
+       /*
+        * verify that any proto=/mountproto= options match the address
+        * familiies in the addr=/mountaddr= options.
+        */
+       if (protofamily != AF_UNSPEC &&
+           protofamily != mnt->nfs_server.address.ss_family)
+               goto out_proto_mismatch;
+
+       if (mountfamily != AF_UNSPEC) {
+               if (mnt->mount_server.addrlen) {
+                       if (mountfamily != mnt->mount_server.address.ss_family)
+                               goto out_mountproto_mismatch;
+               } else {
+                       if (mountfamily != mnt->nfs_server.address.ss_family)
+                               goto out_mountproto_mismatch;
+               }
+       }
+
        return 1;
 
+out_mountproto_mismatch:
+       printk(KERN_INFO "NFS: mount server address does not match mountproto= "
+                        "option\n");
+       return 0;
+out_proto_mismatch:
+       printk(KERN_INFO "NFS: server address does not match proto= option\n");
+       return 0;
 out_invalid_address:
        printk(KERN_INFO "NFS: bad IP address specified: %s\n", p);
        return 0;
@@ -1881,7 +1943,6 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
        if (data == NULL)
                return -ENOMEM;
 
-       lock_kernel();
        /* fill out struct with values from existing mount */
        data->flags = nfss->flags;
        data->rsize = nfss->rsize;
@@ -1907,7 +1968,6 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
        error = nfs_compare_remount_data(nfss, data);
 out:
        kfree(data);
-       unlock_kernel();
        return error;
 }
 
index 1064c91..6da3d3f 100644 (file)
@@ -83,7 +83,7 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
        struct inode *dir = data->dir;
 
        if (!NFS_PROTO(dir)->unlink_done(task, dir))
-               nfs4_restart_rpc(task, NFS_SERVER(dir)->nfs_client);
+               nfs_restart_rpc(task, NFS_SERVER(dir)->nfs_client);
 }
 
 /**
index b1ce2ea..d171696 100644 (file)
@@ -1216,7 +1216,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
                                 */
                                argp->stable = NFS_FILE_SYNC;
                        }
-                       nfs4_restart_rpc(task, server->nfs_client);
+                       nfs_restart_rpc(task, server->nfs_client);
                        return -EAGAIN;
                }
                if (time_before(complain, jiffies)) {
@@ -1228,7 +1228,6 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
                /* Can't do anything about it except throw an error. */
                task->tk_status = -EIO;
        }
-       nfs4_sequence_free_slot(server->nfs_client, &data->res.seq_res);
        return 0;
 }
 
@@ -1612,15 +1611,16 @@ int nfs_migrate_page(struct address_space *mapping, struct page *newpage,
        if (ret)
                goto out_unlock;
        page_cache_get(newpage);
+       spin_lock(&mapping->host->i_lock);
        req->wb_page = newpage;
        SetPagePrivate(newpage);
-       set_page_private(newpage, page_private(page));
+       set_page_private(newpage, (unsigned long)req);
        ClearPagePrivate(page);
        set_page_private(page, 0);
+       spin_unlock(&mapping->host->i_lock);
        page_cache_release(page);
 out_unlock:
        nfs_clear_page_tag_locked(req);
-       nfs_release_request(req);
 out:
        return ret;
 }
index 66a888a..bfffd63 100644 (file)
@@ -2389,12 +2389,12 @@ xfs_icsb_modify_counters(
 {
        xfs_icsb_cnts_t *icsbp;
        long long       lcounter;       /* long counter for 64 bit fields */
-       int             cpu, ret = 0;
+       int             ret = 0;
 
        might_sleep();
 again:
-       cpu = get_cpu();
-       icsbp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, cpu);
+       preempt_disable();
+       icsbp = this_cpu_ptr(mp->m_sb_cnts);
 
        /*
         * if the counter is disabled, go to slow path
@@ -2438,11 +2438,11 @@ again:
                break;
        }
        xfs_icsb_unlock_cntr(icsbp);
-       put_cpu();
+       preempt_enable();
        return 0;
 
 slow_path:
-       put_cpu();
+       preempt_enable();
 
        /*
         * serialise with a mutex so we don't burn lots of cpu on
@@ -2490,7 +2490,7 @@ slow_path:
 
 balance_counter:
        xfs_icsb_unlock_cntr(icsbp);
-       put_cpu();
+       preempt_enable();
 
        /*
         * We may have multiple threads here if multiple per-cpu
index 90079c3..8087b90 100644 (file)
@@ -56,6 +56,9 @@ extern unsigned long __per_cpu_offset[NR_CPUS];
 #define __raw_get_cpu_var(var) \
        (*SHIFT_PERCPU_PTR(&per_cpu_var(var), __my_cpu_offset))
 
+#define this_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, my_cpu_offset)
+#define __this_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, __my_cpu_offset)
+
 
 #ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA
 extern void setup_per_cpu_areas(void);
@@ -66,6 +69,8 @@ extern void setup_per_cpu_areas(void);
 #define per_cpu(var, cpu)                      (*((void)(cpu), &per_cpu_var(var)))
 #define __get_cpu_var(var)                     per_cpu_var(var)
 #define __raw_get_cpu_var(var)                 per_cpu_var(var)
+#define this_cpu_ptr(ptr) per_cpu_ptr(ptr, 0)
+#define __this_cpu_ptr(ptr) this_cpu_ptr(ptr)
 
 #endif /* SMP */
 
index c4c0602..9b8299a 100644 (file)
 #define SEQ4_STATUS_RECALLABLE_STATE_REVOKED   0x00000040
 #define SEQ4_STATUS_LEASE_MOVED                        0x00000080
 #define SEQ4_STATUS_RESTART_RECLAIM_NEEDED     0x00000100
+#define SEQ4_STATUS_CB_PATH_DOWN_SESSION       0x00000200
+#define SEQ4_STATUS_BACKCHANNEL_FAULT          0x00000400
 
 #define NFS4_MAX_UINT64        (~(u64)0)
 
@@ -528,6 +530,7 @@ enum {
        NFSPROC4_CLNT_DESTROY_SESSION,
        NFSPROC4_CLNT_SEQUENCE,
        NFSPROC4_CLNT_GET_LEASE_TIME,
+       NFSPROC4_CLNT_RECLAIM_COMPLETE,
 };
 
 /* nfs41 types */
index 320569e..34fc6be 100644 (file)
@@ -209,6 +209,7 @@ struct nfs4_session {
        unsigned long                   session_state;
        u32                             hash_alg;
        u32                             ssv_len;
+       struct completion               complete;
 
        /* The fore and back channel */
        struct nfs4_channel_attrs       fc_attrs;
index 62f63fb..51071b3 100644 (file)
@@ -170,8 +170,9 @@ struct nfs4_sequence_args {
 struct nfs4_sequence_res {
        struct nfs4_session     *sr_session;
        u8                      sr_slotid;      /* slot used to send request */
-       unsigned long           sr_renewal_time;
        int                     sr_status;      /* sequence operation status */
+       unsigned long           sr_renewal_time;
+       u32                     sr_status_flags;
 };
 
 struct nfs4_get_lease_time_args {
@@ -938,6 +939,16 @@ struct nfs41_create_session_args {
 struct nfs41_create_session_res {
        struct nfs_client              *client;
 };
+
+struct nfs41_reclaim_complete_args {
+       /* In the future extend to include curr_fh for use with migration */
+       unsigned char                   one_fs:1;
+       struct nfs4_sequence_args       seq_args;
+};
+
+struct nfs41_reclaim_complete_res {
+       struct nfs4_sequence_res        seq_res;
+};
 #endif /* CONFIG_NFS_V4_1 */
 
 struct nfs_page;
index 9bd0319..5a5d6ce 100644 (file)
@@ -60,6 +60,7 @@
 
 #define DEFINE_PER_CPU_SECTION(type, name, sec)                                \
        __PCPU_DUMMY_ATTRS char __pcpu_scope_##name;                    \
+       extern __PCPU_DUMMY_ATTRS char __pcpu_unique_##name;            \
        __PCPU_DUMMY_ATTRS char __pcpu_unique_##name;                   \
        __PCPU_ATTRS(sec) PER_CPU_DEF_ATTRIBUTES __weak                 \
        __typeof__(type) per_cpu__##name
index 878836c..cf5efbc 100644 (file)
@@ -34,8 +34,6 @@
 
 #ifdef CONFIG_SMP
 
-#ifndef CONFIG_HAVE_LEGACY_PER_CPU_AREA
-
 /* minimum unit size, also is the maximum supported allocation size */
 #define PCPU_MIN_UNIT_SIZE             PFN_ALIGN(64 << 10)
 
@@ -130,30 +128,9 @@ extern int __init pcpu_page_first_chunk(size_t reserved_size,
 #define per_cpu_ptr(ptr, cpu)  SHIFT_PERCPU_PTR((ptr), per_cpu_offset((cpu)))
 
 extern void *__alloc_reserved_percpu(size_t size, size_t align);
-
-#else /* CONFIG_HAVE_LEGACY_PER_CPU_AREA */
-
-struct percpu_data {
-       void *ptrs[1];
-};
-
-/* pointer disguising messes up the kmemleak objects tracking */
-#ifndef CONFIG_DEBUG_KMEMLEAK
-#define __percpu_disguise(pdata) (struct percpu_data *)~(unsigned long)(pdata)
-#else
-#define __percpu_disguise(pdata) (struct percpu_data *)(pdata)
-#endif
-
-#define per_cpu_ptr(ptr, cpu)                                          \
-({                                                                     \
-        struct percpu_data *__p = __percpu_disguise(ptr);              \
-        (__typeof__(ptr))__p->ptrs[(cpu)];                             \
-})
-
-#endif /* CONFIG_HAVE_LEGACY_PER_CPU_AREA */
-
 extern void *__alloc_percpu(size_t size, size_t align);
 extern void free_percpu(void *__pdata);
+extern phys_addr_t per_cpu_ptr_to_phys(void *addr);
 
 #ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA
 extern void __init setup_per_cpu_areas(void);
@@ -179,6 +156,11 @@ static inline void free_percpu(void *p)
        kfree(p);
 }
 
+static inline phys_addr_t per_cpu_ptr_to_phys(void *addr)
+{
+       return __pa(addr);
+}
+
 static inline void __init setup_per_cpu_areas(void) { }
 
 static inline void *pcpu_lpage_remapped(void *kaddr)
@@ -188,8 +170,8 @@ static inline void *pcpu_lpage_remapped(void *kaddr)
 
 #endif /* CONFIG_SMP */
 
-#define alloc_percpu(type)     (type *)__alloc_percpu(sizeof(type), \
-                                                      __alignof__(type))
+#define alloc_percpu(type)     \
+       (typeof(type) *)__alloc_percpu(sizeof(type), __alignof__(type))
 
 /*
  * Optional methods for optimized non-lvalue per-cpu variable access.
@@ -243,4 +225,404 @@ do {                                                                      \
 # define percpu_xor(var, val)          __percpu_generic_to_op(var, (val), ^=)
 #endif
 
+/*
+ * Branching function to split up a function into a set of functions that
+ * are called for different scalar sizes of the objects handled.
+ */
+
+extern void __bad_size_call_parameter(void);
+
+#define __pcpu_size_call_return(stem, variable)                                \
+({     typeof(variable) pscr_ret__;                                    \
+       switch(sizeof(variable)) {                                      \
+       case 1: pscr_ret__ = stem##1(variable);break;                   \
+       case 2: pscr_ret__ = stem##2(variable);break;                   \
+       case 4: pscr_ret__ = stem##4(variable);break;                   \
+       case 8: pscr_ret__ = stem##8(variable);break;                   \
+       default:                                                        \
+               __bad_size_call_parameter();break;                      \
+       }                                                               \
+       pscr_ret__;                                                     \
+})
+
+#define __pcpu_size_call(stem, variable, ...)                          \
+do {                                                                   \
+       switch(sizeof(variable)) {                                      \
+               case 1: stem##1(variable, __VA_ARGS__);break;           \
+               case 2: stem##2(variable, __VA_ARGS__);break;           \
+               case 4: stem##4(variable, __VA_ARGS__);break;           \
+               case 8: stem##8(variable, __VA_ARGS__);break;           \
+               default:                                                \
+                       __bad_size_call_parameter();break;              \
+       }                                                               \
+} while (0)
+
+/*
+ * Optimized manipulation for memory allocated through the per cpu
+ * allocator or for addresses of per cpu variables (can be determined
+ * using per_cpu_var(xx).
+ *
+ * These operation guarantee exclusivity of access for other operations
+ * on the *same* processor. The assumption is that per cpu data is only
+ * accessed by a single processor instance (the current one).
+ *
+ * The first group is used for accesses that must be done in a
+ * preemption safe way since we know that the context is not preempt
+ * safe. Interrupts may occur. If the interrupt modifies the variable
+ * too then RMW actions will not be reliable.
+ *
+ * The arch code can provide optimized functions in two ways:
+ *
+ * 1. Override the function completely. F.e. define this_cpu_add().
+ *    The arch must then ensure that the various scalar format passed
+ *    are handled correctly.
+ *
+ * 2. Provide functions for certain scalar sizes. F.e. provide
+ *    this_cpu_add_2() to provide per cpu atomic operations for 2 byte
+ *    sized RMW actions. If arch code does not provide operations for
+ *    a scalar size then the fallback in the generic code will be
+ *    used.
+ */
+
+#define _this_cpu_generic_read(pcp)                                    \
+({     typeof(pcp) ret__;                                              \
+       preempt_disable();                                              \
+       ret__ = *this_cpu_ptr(&(pcp));                                  \
+       preempt_enable();                                               \
+       ret__;                                                          \
+})
+
+#ifndef this_cpu_read
+# ifndef this_cpu_read_1
+#  define this_cpu_read_1(pcp) _this_cpu_generic_read(pcp)
+# endif
+# ifndef this_cpu_read_2
+#  define this_cpu_read_2(pcp) _this_cpu_generic_read(pcp)
+# endif
+# ifndef this_cpu_read_4
+#  define this_cpu_read_4(pcp) _this_cpu_generic_read(pcp)
+# endif
+# ifndef this_cpu_read_8
+#  define this_cpu_read_8(pcp) _this_cpu_generic_read(pcp)
+# endif
+# define this_cpu_read(pcp)    __pcpu_size_call_return(this_cpu_read_, (pcp))
+#endif
+
+#define _this_cpu_generic_to_op(pcp, val, op)                          \
+do {                                                                   \
+       preempt_disable();                                              \
+       *__this_cpu_ptr(&pcp) op val;                                   \
+       preempt_enable();                                               \
+} while (0)
+
+#ifndef this_cpu_write
+# ifndef this_cpu_write_1
+#  define this_cpu_write_1(pcp, val)   _this_cpu_generic_to_op((pcp), (val), =)
+# endif
+# ifndef this_cpu_write_2
+#  define this_cpu_write_2(pcp, val)   _this_cpu_generic_to_op((pcp), (val), =)
+# endif
+# ifndef this_cpu_write_4
+#  define this_cpu_write_4(pcp, val)   _this_cpu_generic_to_op((pcp), (val), =)
+# endif
+# ifndef this_cpu_write_8
+#  define this_cpu_write_8(pcp, val)   _this_cpu_generic_to_op((pcp), (val), =)
+# endif
+# define this_cpu_write(pcp, val)      __pcpu_size_call(this_cpu_write_, (pcp), (val))
+#endif
+
+#ifndef this_cpu_add
+# ifndef this_cpu_add_1
+#  define this_cpu_add_1(pcp, val)     _this_cpu_generic_to_op((pcp), (val), +=)
+# endif
+# ifndef this_cpu_add_2
+#  define this_cpu_add_2(pcp, val)     _this_cpu_generic_to_op((pcp), (val), +=)
+# endif
+# ifndef this_cpu_add_4
+#  define this_cpu_add_4(pcp, val)     _this_cpu_generic_to_op((pcp), (val), +=)
+# endif
+# ifndef this_cpu_add_8
+#  define this_cpu_add_8(pcp, val)     _this_cpu_generic_to_op((pcp), (val), +=)
+# endif
+# define this_cpu_add(pcp, val)                __pcpu_size_call(this_cpu_add_, (pcp), (val))
+#endif
+
+#ifndef this_cpu_sub
+# define this_cpu_sub(pcp, val)                this_cpu_add((pcp), -(val))
+#endif
+
+#ifndef this_cpu_inc
+# define this_cpu_inc(pcp)             this_cpu_add((pcp), 1)
+#endif
+
+#ifndef this_cpu_dec
+# define this_cpu_dec(pcp)             this_cpu_sub((pcp), 1)
+#endif
+
+#ifndef this_cpu_and
+# ifndef this_cpu_and_1
+#  define this_cpu_and_1(pcp, val)     _this_cpu_generic_to_op((pcp), (val), &=)
+# endif
+# ifndef this_cpu_and_2
+#  define this_cpu_and_2(pcp, val)     _this_cpu_generic_to_op((pcp), (val), &=)
+# endif
+# ifndef this_cpu_and_4
+#  define this_cpu_and_4(pcp, val)     _this_cpu_generic_to_op((pcp), (val), &=)
+# endif
+# ifndef this_cpu_and_8
+#  define this_cpu_and_8(pcp, val)     _this_cpu_generic_to_op((pcp), (val), &=)
+# endif
+# define this_cpu_and(pcp, val)                __pcpu_size_call(this_cpu_and_, (pcp), (val))
+#endif
+
+#ifndef this_cpu_or
+# ifndef this_cpu_or_1
+#  define this_cpu_or_1(pcp, val)      _this_cpu_generic_to_op((pcp), (val), |=)
+# endif
+# ifndef this_cpu_or_2
+#  define this_cpu_or_2(pcp, val)      _this_cpu_generic_to_op((pcp), (val), |=)
+# endif
+# ifndef this_cpu_or_4
+#  define this_cpu_or_4(pcp, val)      _this_cpu_generic_to_op((pcp), (val), |=)
+# endif
+# ifndef this_cpu_or_8
+#  define this_cpu_or_8(pcp, val)      _this_cpu_generic_to_op((pcp), (val), |=)
+# endif
+# define this_cpu_or(pcp, val)         __pcpu_size_call(this_cpu_or_, (pcp), (val))
+#endif
+
+#ifndef this_cpu_xor
+# ifndef this_cpu_xor_1
+#  define this_cpu_xor_1(pcp, val)     _this_cpu_generic_to_op((pcp), (val), ^=)
+# endif
+# ifndef this_cpu_xor_2
+#  define this_cpu_xor_2(pcp, val)     _this_cpu_generic_to_op((pcp), (val), ^=)
+# endif
+# ifndef this_cpu_xor_4
+#  define this_cpu_xor_4(pcp, val)     _this_cpu_generic_to_op((pcp), (val), ^=)
+# endif
+# ifndef this_cpu_xor_8
+#  define this_cpu_xor_8(pcp, val)     _this_cpu_generic_to_op((pcp), (val), ^=)
+# endif
+# define this_cpu_xor(pcp, val)                __pcpu_size_call(this_cpu_or_,