diff options
author | Hugh Dickins <hughd@google.com> | 2016-07-26 18:26:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-26 19:19:19 -0400 |
commit | c01d5b300774d130a24d787825b01eb24e6e20cb (patch) | |
tree | e56b92aa5cf8f25ab812da30db5b36a6126e877b /ipc/shm.c | |
parent | 5a6e75f8110c97e2a5488894d4e922187e6cb343 (diff) |
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 <hughd@google.com>
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc/shm.c')
-rw-r--r-- | ipc/shm.c | 6 |
1 files changed, 4 insertions, 2 deletions
@@ -476,13 +476,15 @@ static const struct file_operations shm_file_operations = { | |||
476 | .mmap = shm_mmap, | 476 | .mmap = shm_mmap, |
477 | .fsync = shm_fsync, | 477 | .fsync = shm_fsync, |
478 | .release = shm_release, | 478 | .release = shm_release, |
479 | #ifndef CONFIG_MMU | ||
480 | .get_unmapped_area = shm_get_unmapped_area, | 479 | .get_unmapped_area = shm_get_unmapped_area, |
481 | #endif | ||
482 | .llseek = noop_llseek, | 480 | .llseek = noop_llseek, |
483 | .fallocate = shm_fallocate, | 481 | .fallocate = shm_fallocate, |
484 | }; | 482 | }; |
485 | 483 | ||
484 | /* | ||
485 | * shm_file_operations_huge is now identical to shm_file_operations, | ||
486 | * but we keep it distinct for the sake of is_file_shm_hugepages(). | ||
487 | */ | ||
486 | static const struct file_operations shm_file_operations_huge = { | 488 | static const struct file_operations shm_file_operations_huge = { |
487 | .mmap = shm_mmap, | 489 | .mmap = shm_mmap, |
488 | .fsync = shm_fsync, | 490 | .fsync = shm_fsync, |