title: PERCPU: allocation failed, size=256 align=256, failed to allocate new chunk
body: <blockquote>
    <p>PERCPU: allocation failed, size=256 align=256, failed to allocate new chunk.</p>
  </blockquote>
  
  <p>Is The amount of space for per CPU allocations limited?</p>
  
  <p>How much percpu-space can I use in Linux kernel module programming?</p>
  
  <hr>
  
  <p>Now I'm trying to create as many <code>workqueue_struct</code> as possible. My kernel is 3.10.</p>
  
  <p>My result: I can create about 100000 <code>workqueue_struct</code>s, then I find error info (same as in the title) when I use the <code>dmesg</code> command.</p>
  
  <p>My code:</p>
  
  <pre class="lang-c prettyprint-override"><code>#include &lt;linux/module.h&gt;
  #include &lt;linux/kernel.h&gt;
  #include &lt;linux/init.h&gt;
  #include &lt;linux/kthread.h&gt;//kthread_create is_err
  #include &lt;linux/slab.h&gt;//kfree
  #include &lt;linux/sched.h&gt;//schedule
  #include &lt;linux/delay.h&gt;
  #include &lt;linux/list.h&gt;
  #include &lt;linux/workqueue.h&gt;
  
  u64 i = 0;
  static LIST_HEAD(myworkqueuehead);
  static struct task_struct *task;
  
  struct MyworkqueueType {
      struct list_head entry;
      struct workqueue_struct *wq;
      u64 number;
  };
  
  void myfree(void)
  {
      struct MyworkqueueType *tempwqtype,*n;
      list_for_each_entry_safe(tempwqtype, n, &amp;myworkqueuehead, entry)
      {
          if(tempwqtype)
          {
              if(tempwqtype-&gt;wq){
                  //printk("myfree():number=%lld\n",tempwqtype-&gt;number);
                  //printk("list_del()\n");
                  list_del(&amp;(tempwqtype-&gt;entry));
                  //printk("destroy_workqueue()\n");
                  destroy_workqueue(tempwqtype-&gt;wq);
                  //printk("free tempwqtypetype:kfree(tempwqtype)\n");
                  kfree(tempwqtype);
                  //printk("after free tempwqtypetype\n");
              }else{  
                  printk("tempwqtype-&gt;wq is null\n");
              }
          }else{
              printk("tempwqtype is null\n");
          }
      }
      printk("has freed all the workqueue space...\n");
  }
  
  
  static int test(void *data)
  {
      printk("kthread  create_wq start to run test()...\n");
      while(1)
      {
          struct MyworkqueueType *myworkqueue;
          if(kthread_should_stop())
          {
              printk("create_wq kthread begin to do myfree()...\n");
              myfree();
              printk("create_wq kthread stop...\n");
              return 0;
          }
          myworkqueue = kzalloc(sizeof(*myworkqueue), GFP_KERNEL);
          if(myworkqueue){
              struct workqueue_struct *wq = alloc_workqueue("myworkqueue",0,0);
              //struct workqueue_struct *wq = create_workqueue("myworkqueue");
              if(!wq)
              {
                  struct MyworkqueueType *mytype;
                  kfree(myworkqueue);
                  printk("\ncreate workqueue fail...\n");
                  mytype = list_entry(myworkqueuehead.prev, struct MyworkqueueType, entry);
                  printk("current workqueue number=%lld.start to sleep...\n",mytype-&gt;number);
                  msleep(5000);
                  schedule();
                  continue;
              }
              ++i;
              myworkqueue-&gt;number = i;
              myworkqueue-&gt;wq = wq;
              INIT_LIST_HEAD(&amp;myworkqueue-&gt;entry);
              list_add_tail(&amp;myworkqueue-&gt;entry,&amp;myworkqueuehead);
              printk("%lld ",i);
          }
          else
          {
              printk("\nalloc struct MyworkqueueType fail...\n");
              printk("current workqueuenum = %lld",i);
              kfree(myworkqueue);
              msleep(5000);
              schedule();
              continue;
          }
  
      }
  }
  
  static int __init maxwqnum_init(void)
  {
      printk("-----------maxwqnum-------------\n");
      task=kthread_create(test,NULL,"create_wq");
      if(IS_ERR(task))
      {
          printk("create task_struct create_wq fail...\n");
          kfree(task);
          return 0;
      }
      printk("create task_struct create_wq success...\n");
      wake_up_process(task);
      return 0;
  }
  
  static void __exit maxwqnum_cleanup(void)
  {
      kthread_stop(task);
      printk("-----------leaving maxwqnum-------------\n");
  }
  
  module_init(maxwqnum_init);
  module_exit(maxwqnum_cleanup);
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("mjq");
  MODULE_DESCRIPTION("just a test!");
  MODULE_SUPPORTED_DEVICE("WORKQUEUE");
  </code></pre>