skge: default WOL should be magic only (rev2)
[powerpc.git] / mm / slub.c
index ae28310..bd2efae 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1577,37 +1577,75 @@ static int slub_nomerge;
  * requested a higher mininum order then we start with that one instead of
  * the smallest order which will fit the object.
  */
-static int calculate_order(int size)
+static inline int slab_order(int size, int min_objects,
+                               int max_order, int fract_leftover)
 {
        int order;
        int rem;
 
-       for (order = max(slub_min_order, fls(size - 1) - PAGE_SHIFT);
-                       order < MAX_ORDER; order++) {
-               unsigned long slab_size = PAGE_SIZE << order;
+       for (order = max(slub_min_order,
+                               fls(min_objects * size - 1) - PAGE_SHIFT);
+                       order <= max_order; order++) {
 
-               if (order < slub_max_order &&
-                               slab_size < slub_min_objects * size)
-                       continue;
+               unsigned long slab_size = PAGE_SIZE << order;
 
-               if (slab_size < size)
+               if (slab_size < min_objects * size)
                        continue;
 
-               if (order >= slub_max_order)
-                       break;
-
                rem = slab_size % size;
 
-               if (rem <= slab_size / 8)
+               if (rem <= slab_size / fract_leftover)
                        break;
 
        }
-       if (order >= MAX_ORDER)
-               return -E2BIG;
 
        return order;
 }
 
+static inline int calculate_order(int size)
+{
+       int order;
+       int min_objects;
+       int fraction;
+
+       /*
+        * Attempt to find best configuration for a slab. This
+        * works by first attempting to generate a layout with
+        * the best configuration and backing off gradually.
+        *
+        * First we reduce the acceptable waste in a slab. Then
+        * we reduce the minimum objects required in a slab.
+        */
+       min_objects = slub_min_objects;
+       while (min_objects > 1) {
+               fraction = 8;
+               while (fraction >= 4) {
+                       order = slab_order(size, min_objects,
+                                               slub_max_order, fraction);
+                       if (order <= slub_max_order)
+                               return order;
+                       fraction /= 2;
+               }
+               min_objects /= 2;
+       }
+
+       /*
+        * We were unable to place multiple objects in a slab. Now
+        * lets see if we can place a single object there.
+        */
+       order = slab_order(size, 1, slub_max_order, 1);
+       if (order <= slub_max_order)
+               return order;
+
+       /*
+        * Doh this slab cannot be placed using slub_max_order.
+        */
+       order = slab_order(size, 1, MAX_ORDER, 1);
+       if (order <= MAX_ORDER)
+               return order;
+       return -ENOSYS;
+}
+
 /*
  * Figure out what the alignment of the objects will be.
  */
@@ -2248,7 +2286,6 @@ EXPORT_SYMBOL(kmem_cache_shrink);
 
 /**
  * krealloc - reallocate memory. The contents will remain unchanged.
- *
  * @p: object to reallocate memory for.
  * @new_size: how many bytes of memory are required.
  * @flags: the type of memory to allocate.
@@ -2477,7 +2514,9 @@ static int __cpuinit slab_cpuup_callback(struct notifier_block *nfb,
 
        switch (action) {
        case CPU_UP_CANCELED:
+       case CPU_UP_CANCELED_FROZEN:
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                for_all_slabs(__flush_cpu_slab, cpu);
                break;
        default:
@@ -2491,91 +2530,6 @@ static struct notifier_block __cpuinitdata slab_notifier =
 
 #endif
 
-#ifdef CONFIG_NUMA
-
-/*****************************************************************
- * Generic reaper used to support the page allocator
- * (the cpu slabs are reaped by a per slab workqueue).
- *
- * Maybe move this to the page allocator?
- ****************************************************************/
-
-static DEFINE_PER_CPU(unsigned long, reap_node);
-
-static void init_reap_node(int cpu)
-{
-       int node;
-
-       node = next_node(cpu_to_node(cpu), node_online_map);
-       if (node == MAX_NUMNODES)
-               node = first_node(node_online_map);
-
-       __get_cpu_var(reap_node) = node;
-}
-
-static void next_reap_node(void)
-{
-       int node = __get_cpu_var(reap_node);
-
-       /*
-        * Also drain per cpu pages on remote zones
-        */
-       if (node != numa_node_id())
-               drain_node_pages(node);
-
-       node = next_node(node, node_online_map);
-       if (unlikely(node >= MAX_NUMNODES))
-               node = first_node(node_online_map);
-       __get_cpu_var(reap_node) = node;
-}
-#else
-#define init_reap_node(cpu) do { } while (0)
-#define next_reap_node(void) do { } while (0)
-#endif
-
-#define REAPTIMEOUT_CPUC       (2*HZ)
-
-#ifdef CONFIG_SMP
-static DEFINE_PER_CPU(struct delayed_work, reap_work);
-
-static void cache_reap(struct work_struct *unused)
-{
-       next_reap_node();
-       refresh_cpu_vm_stats(smp_processor_id());
-       schedule_delayed_work(&__get_cpu_var(reap_work),
-                                     REAPTIMEOUT_CPUC);
-}
-
-static void __devinit start_cpu_timer(int cpu)
-{
-       struct delayed_work *reap_work = &per_cpu(reap_work, cpu);
-
-       /*
-        * When this gets called from do_initcalls via cpucache_init(),
-        * init_workqueues() has already run, so keventd will be setup
-        * at that time.
-        */
-       if (keventd_up() && reap_work->work.func == NULL) {
-               init_reap_node(cpu);
-               INIT_DELAYED_WORK(reap_work, cache_reap);
-               schedule_delayed_work_on(cpu, reap_work, HZ + 3 * cpu);
-       }
-}
-
-static int __init cpucache_init(void)
-{
-       int cpu;
-
-       /*
-        * Register the timers that drain pcp pages and update vm statistics
-        */
-       for_each_online_cpu(cpu)
-               start_cpu_timer(cpu);
-       return 0;
-}
-__initcall(cpucache_init);
-#endif
-
 void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, void *caller)
 {
        struct kmem_cache *s = get_slab(size, gfpflags);