mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
shmem: get_unmapped_area align huge page
Provide a shmem_get_unmapped_area method in file_operations, called at mmap time to decide the mapping address. It could be conditional on CONFIG_TRANSPARENT_HUGEPAGE, but save #ifdefs in other places by making it unconditional. shmem_get_unmapped_area() first calls the usual mm->get_unmapped_area (which we treat as a black box, highly dependent on architecture and config and executable layout). Lots of conditions, and in most cases it just goes with the address that chose; but when our huge stars are rightly aligned, yet that did not provide a suitable address, go back to ask for a larger arena, within which to align the mapping suitably. There have to be some direct calls to shmem_get_unmapped_area(), not via the file_operations: because of the way shmem_zero_setup() is called to create a shmem object late in the mmap sequence, when MAP_SHARED is requested with MAP_ANONYMOUS or /dev/zero. Though this only matters when /proc/sys/vm/shmem_huge has been set. Link: http://lkml.kernel.org/r/1466021202-61880-29-git-send-email-kirill.shutemov@linux.intel.com Signed-off-by: Hugh Dickins <[email protected]> Signed-off-by: Kirill A. Shutemov <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
parent
5a6e75f811
commit
c01d5b3007
5 changed files with 142 additions and 4 deletions
16
mm/mmap.c
16
mm/mmap.c
|
|
@ -25,6 +25,7 @@
|
|||
#include <linux/personality.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/hugetlb.h>
|
||||
#include <linux/shmem_fs.h>
|
||||
#include <linux/profile.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/mount.h>
|
||||
|
|
@ -1897,8 +1898,19 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
|
|||
return -ENOMEM;
|
||||
|
||||
get_area = current->mm->get_unmapped_area;
|
||||
if (file && file->f_op->get_unmapped_area)
|
||||
get_area = file->f_op->get_unmapped_area;
|
||||
if (file) {
|
||||
if (file->f_op->get_unmapped_area)
|
||||
get_area = file->f_op->get_unmapped_area;
|
||||
} else if (flags & MAP_SHARED) {
|
||||
/*
|
||||
* mmap_region() will call shmem_zero_setup() to create a file,
|
||||
* so use shmem's get_unmapped_area in case it can be huge.
|
||||
* do_mmap_pgoff() will clear pgoff, so match alignment.
|
||||
*/
|
||||
pgoff = 0;
|
||||
get_area = shmem_get_unmapped_area;
|
||||
}
|
||||
|
||||
addr = get_area(file, addr, len, pgoff, flags);
|
||||
if (IS_ERR_VALUE(addr))
|
||||
return addr;
|
||||
|
|
|
|||
Loading…
Reference in a new issue