]> git.karo-electronics.de Git - linux-beck.git/blobdiff - drivers/char/mem.c
shmem: get_unmapped_area align huge page
[linux-beck.git] / drivers / char / mem.c
index d633974e7f8b1d82914743e0a27bda495e1ff5af..a33163dbb913541ad6649de8e9a43f8256e1742a 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/device.h>
 #include <linux/highmem.h>
 #include <linux/backing-dev.h>
+#include <linux/shmem_fs.h>
 #include <linux/splice.h>
 #include <linux/pfn.h>
 #include <linux/export.h>
@@ -657,6 +658,28 @@ static int mmap_zero(struct file *file, struct vm_area_struct *vma)
        return 0;
 }
 
+static unsigned long get_unmapped_area_zero(struct file *file,
+                               unsigned long addr, unsigned long len,
+                               unsigned long pgoff, unsigned long flags)
+{
+#ifdef CONFIG_MMU
+       if (flags & MAP_SHARED) {
+               /*
+                * mmap_zero() will call shmem_zero_setup() to create a file,
+                * so use shmem's get_unmapped_area in case it can be huge;
+                * and pass NULL for file as in mmap.c's get_unmapped_area(),
+                * so as not to confuse shmem with our handle on "/dev/zero".
+                */
+               return shmem_get_unmapped_area(NULL, addr, len, pgoff, flags);
+       }
+
+       /* Otherwise flags & MAP_PRIVATE: with no shmem object beneath it */
+       return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
+#else
+       return -ENOSYS;
+#endif
+}
+
 static ssize_t write_full(struct file *file, const char __user *buf,
                          size_t count, loff_t *ppos)
 {
@@ -764,6 +787,7 @@ static const struct file_operations zero_fops = {
        .read_iter      = read_iter_zero,
        .write_iter     = write_iter_zero,
        .mmap           = mmap_zero,
+       .get_unmapped_area = get_unmapped_area_zero,
 #ifndef CONFIG_MMU
        .mmap_capabilities = zero_mmap_capabilities,
 #endif