title: Protecting shared memory segment between kernel and user space
body: <p>I have shared memory segment created in kernel using mmap. I need to access this mapped memory from both kernel and user space. What mechanism should I use to protect the memory from concurrent access ? 
  I want to have something like:</p>
  
  <p>Kernel module:</p>
  
  <pre><code>#include &lt;linux/module.h&gt;
  #include &lt;linux/kernel.h&gt;
  #include &lt;linux/init.h&gt;
  #include &lt;linux/fs.h&gt;
  #include &lt;linux/debugfs.h&gt;
  #include &lt;linux/slab.h&gt;
  #include &lt;linux/mm.h&gt; 
  
  #ifndef VM_RESERVED
  # define  VM_RESERVED   (VM_DONTEXPAND | VM_DONTDUMP)
  #endif
  
  struct dentry  *file;
  
  struct mmap_info
  {
      char *data;            
      int reference;      
  };
  
  void mmap_open(struct vm_area_struct *vma)
  {
      struct mmap_info *info = (struct mmap_info *)vma-&gt;vm_private_data;
      info-&gt;reference++;
  }
  
  void mmap_close(struct vm_area_struct *vma)
  {
      struct mmap_info *info = (struct mmap_info *)vma-&gt;vm_private_data;
      info-&gt;reference--;
  }
  
  static int mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
  {
      struct page *page;
      struct mmap_info *info;    
  
      info = (struct mmap_info *)vma-&gt;vm_private_data;
      if (!info-&gt;data)
      {
          printk("No data\n");
          return 0;    
      }
      page = virt_to_page(info-&gt;data);    
      get_page(page);
      vmf-&gt;page = page;            
      return 0;
  }
  
  struct vm_operations_struct mmap_vm_ops =
  {
      .open =     mmap_open,
      .close =    mmap_close,
      .fault =    mmap_fault,    
  };
  
  int op_mmap(struct file *filp, struct vm_area_struct *vma)
  {
      vma-&gt;vm_ops = &amp;mmap_vm_ops;
      vma-&gt;vm_flags |= VM_RESERVED;    
      vma-&gt;vm_private_data = filp-&gt;private_data;
      mmap_open(vma);
      return 0;
  }
  
  int mmapfop_close(struct inode *inode, struct file *filp)
  {
      struct mmap_info *info = filp-&gt;private_data;
      free_page((unsigned long)info-&gt;data);
      kfree(info);
      filp-&gt;private_data = NULL;
      return 0;
  }
  
  int mmapfop_open(struct inode *inode, struct file *filp)
  {
      struct mmap_info *info = kmalloc(sizeof(struct mmap_info), GFP_KERNEL);    
      info-&gt;data = (char *)get_zeroed_page(GFP_KERNEL);
      memcpy(info-&gt;data, "hello from kernel this is file: ", 32);
      memcpy(info-&gt;data + 32, filp-&gt;f_dentry-&gt;d_name.name, strlen(filp-&gt;f_dentry-&gt;d_name.name));
      /* assign this info struct to the file */
      filp-&gt;private_data = info;
      return 0;
  }
  
  static const struct file_operations mmap_fops = {
      .open = mmapfop_open,
      .release = mmapfop_close,
      .mmap = op_mmap,
  };
  
   static int __init mmapexample_module_init(void)
  {
      file = debugfs_create_file("mmap_example", 0644, NULL, NULL, &amp;mmap_fops);
      return 0;
  }
  
  static void __exit mmapexample_module_exit(void)
  {
      debugfs_remove(file);
  }
  
  module_init(mmapexample_module_init);
  module_exit(mmapexample_module_exit);
  MODULE_LICENSE("GPL");
  </code></pre>
  
  <p>User space:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;string.h&gt;
  #include &lt;fcntl.h&gt;
  #include &lt;sys/mman.h&gt;
  
  #define PAGE_SIZE     4096
  
  int main ( int argc, char **argv )
  {
      int configfd;
      char * address = NULL;
  
      configfd = open("/sys/kernel/debug/mmap_example", O_RDWR);
      if(configfd &lt; 0)
      {
          perror("Open call failed");
          return -1;
      }
  
      address = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, configfd, 0);
      if (address == MAP_FAILED)
      {
          perror("mmap operation failed");
          return -1;
      }
      printf("Initial message: %s\n", address);
      memcpy(address + 11 , "*user*", 6);
      printf("Changed message: %s\n", address);
      close(configfd);    
      return 0;
  }
  </code></pre>
  
  <p>but with locks.</p>