Add pseudo-anonymous huge page mappings
Subsystems (6)
cover Add pseudo-anonymous huge page mappings
This patch set adds a flag to mmap that allows the user to request a mapping to be backed with huge pages. This mapping will borrow functionality from the huge page shm code to create a file on the kernel internal mount and uses it to approximate an anonymous mapping. The MAP_LARGEPAGE flag is a modifier to MAP_ANONYMOUS and will not work without both flags being preset.
A new flag is necessary because there is no other way to hook into huge pages without creating a file on a hugetlbfs mount which wouldn't be MAP_ANONYMOUS.
To userspace, this mapping will behave just like an anonymous mapping because the file is not accessible outside of the kernel.
Eric B Munson (3):
hugetlbfs: Allow the creation of files suitable for MAP_PRIVATE on
the vfs internal mount
Add MAP_LARGEPAGE for mmaping pseudo-anonymous huge page regions Add MAP_LARGEPAGE example to vm/hugetlbpage.txt
Documentation/vm/hugetlbpage.txt | 80 +++++++++++++++++++++++++++++++++++++ fs/hugetlbfs/inode.c | 22 ++++++++-- include/asm-generic/mman-common.h | 1 + include/linux/hugetlb.h | 17 +++++++- ipc/shm.c | 3 +- mm/mmap.c | 16 +++++++ 6 files changed, 133 insertions(+), 6 deletions(-)
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 1/3 hugetlbfs: Allow the creation of files suitable for MAP_PRIVATE on the vfs internal mount
There are two means of creating mappings backed by huge pages:
1. mmap() a file created on hugetlbfs
2. Use shm which creates a file on an internal mount which essentially maps it MAP_SHARED
The internal mount is only used for shared mappings but there is very little that stops it being used for private mappings. This patch extends hugetlbfs_file_setup() to deal with the creation of files that will be mapped MAP_PRIVATE on the internal hugetlbfs mount. This extended API is used in a subsequent patch to implement the MAP_LARGEPAGE mmap() flag.
--- fs/hugetlbfs/inode.c | 22 ++++++++++++++++++---- include/linux/hugetlb.h | 10 +++++++++- ipc/shm.c | 3 ++- 3 files changed, 29 insertions(+), 6 deletions(-)
fs/hugetlbfs/inode.c +18 -4
@@ -506,6 +506,13 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid, inode->i_atime = inode->i_mtime = inode->i_ctime =CURRENT_TIME ;INIT_LIST_HEAD (&inode->i_mapping->private_list); info =HUGETLBFS_I (inode); +/* +* The policy is initialized here even if we are creating a +* private inode because initialization simply creates an +* an empty rb tree and calls spin_lock_init(), later when we +* call mpol_free_shared_policy() it will just return because +* the rb tree will still be empty. +*/ mpol_shared_policy_init (&info->policy,NULL );switch (mode &S_IFMT ) {default :
@@ -930,12 +937,19 @@ static struct file_system_type hugetlbfs_fs_type = {static struct vfsmount *hugetlbfs_vfsmount; -static int can_do_hugetlb_shm (void ) +static int can_do_hugetlb_shm (int creat_flags) { -return capable (CAP_IPC_LOCK ) ||in_group_p (sysctl_hugetlb_shm_group); +if (!(creat_flags &HUGETLB_SHMFS_INODE )) +return 0 ; +if (capable (CAP_IPC_LOCK )) +return 1 ; +if (in_group_p (sysctl_hugetlb_shm_group)) +return 1 ; +return 0 ; } -struct file *hugetlb_file_setup (const char *name,size_t size,int acctflag) +struct file *hugetlb_file_setup (const char *name,size_t size,int acctflag, +int creat_flags) {int error = -ENOMEM ;int unlock_shm =0 ;
@@ -948,7 +962,7 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag)if (!hugetlbfs_vfsmount)return ERR_PTR (-ENOENT ); -if (!can_do_hugetlb_shm ()) { +if (!can_do_hugetlb_shm (creat_flags)) {if (user_shm_lock (size, user)) { unlock_shm =1 ; WARN_ONCE(1,
include/linux/hugetlb.h +9 -1
@@ -109,6 +109,14 @@ static inline void hugetlb_report_meminfo(struct seq_file *m)#endif /* !CONFIG_HUGETLB_PAGE */ +enum { +/* +* The file will be used as an shm file so shmfs accounting rules +* apply +*/ +HUGETLB_SHMFS_INODE =0x01 , +}; + #ifdef CONFIG_HUGETLBFS struct hugetlbfs_config { uid_t uid;
@@ -146,7 +154,7 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb)extern const struct file_operations hugetlbfs_file_operations;extern struct vm_operations_struct hugetlb_vm_ops; -struct file *hugetlb_file_setup (const char *name,size_t ,int ); +struct file *hugetlb_file_setup (const char *name,size_t ,int ,int );int hugetlb_get_quota (struct address_space *mapping,long delta);void hugetlb_put_quota (struct address_space *mapping,long delta);
ipc/shm.c +2 -1
@@ -369,7 +369,8 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)/* hugetlb_file_setup applies strict accounting */ if (shmflg &SHM_NORESERVE ) acctflag =VM_NORESERVE ; - file =hugetlb_file_setup (name, size, acctflag); + file =hugetlb_file_setup (name, size, acctflag, +HUGETLB_SHMFS_INODE ); shp->mlock_user =current_user (); }else {/*
Signature · 7 lines
1.6.3.2 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 2/3 Add MAP_LARGEPAGE for mmaping pseudo-anonymous huge page regions
This patch adds a flag for mmap that will be used to request a huge page region that will look like anonymous memory to user space. This is accomplished by using a file on the internal vfsmount. MAP_LARGEPAGE is a modifier of MAP_ANONYMOUS and so must be specified with it. The region will behave the same as a MAP_ANONYMOUS region using small pages.
--- include/asm-generic/mman-common.h | 1 + include/linux/hugetlb.h | 7 +++++++ mm/mmap.c | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 0 deletions(-)
include/asm-generic/mman-common.h +1 -0
@@ -19,6 +19,7 @@#define MAP_TYPE 0x0f/* Mask for type of mapping */ #define MAP_FIXED 0x10/* Interpret addr exactly */ #define MAP_ANONYMOUS 0x20/* don't use a file */ +#define MAP_LARGEPAGE 0x40/* create a large page mapping */ #define MS_ASYNC 1/* sync memory asynchronously */ #define MS_INVALIDATE 2/* invalidate the caches */
include/linux/hugetlb.h +7 -0
@@ -109,12 +109,19 @@ static inline void hugetlb_report_meminfo(struct seq_file *m)#endif /* !CONFIG_HUGETLB_PAGE */ +#define HUGETLB_ANON_FILE "anon_hugepage" +enum {/* * The file will be used as an shm file so shmfs accounting rules * apply */ HUGETLB_SHMFS_INODE =0x01 , +/* +* The file is being created on the internal vfs mount and shmfs +* accounting rules do not apply +*/ +HUGETLB_ANONHUGE_INODE =0x02 , };#ifdef CONFIG_HUGETLBFS
mm/mmap.c +16 -0
@@ -29,6 +29,7 @@#include <linux/rmap.h> #include <linux/mmu_notifier.h> #include <linux/perf_counter.h> +#include <linux/hugetlb.h> #include <asm/uaccess.h> #include <asm/cacheflush.h>
@@ -954,6 +955,21 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,if (mm->map_count > sysctl_max_map_count)return -ENOMEM ; +if (flags &MAP_LARGEPAGE ) { +if (file) +return -EINVAL ; + +/* +* VM_NORESERVE is used because the reservations will be +* taken when vm_ops->mmap() is called +*/ + len =ALIGN (len,huge_page_size (&default_hstate)); + file =hugetlb_file_setup (HUGETLB_ANON_FILE , len,VM_NORESERVE , +HUGETLB_ANONHUGE_INODE ); +if (IS_ERR (file)) +return -ENOMEM ; + } +/* Obtain the address to map to. we verify (or select) it and ensure * that it represents a valid section of the address space. */
Signature · 7 lines
1.6.3.2 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 3/3 Add MAP_LARGEPAGE example to vm/hugetlbpage.txt
This patch adds an example of how to use the MAP_LARGEPAGE flag to the vm documentation.
--- Documentation/vm/hugetlbpage.txt | 80 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 80 insertions(+), 0 deletions(-)
Documentation/vm/hugetlbpage.txt +80 -0
@@ -337,3 +337,83 @@ int main(void) return 0; } + +******************************************************************* + +/* + * Example of using hugepage memory in a user application using the mmap + * system call with MAP_LARGEPAGE flag. Before running this program make + * sure the administrator has allocated enough default sized huge pages + * to cover the 256 MB allocation. + * + * For ia64 architecture, Linux kernel reserves Region number 4 for hugepages. + * That means the addresses starting with 0x800000... will need to be + * specified. Specifying a fixed address is not required on ppc64, i386 + * or x86_64. + */ +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/mman.h> +#include <fcntl.h> + +#define LENGTH (256UL*1024*1024) +#define PROTECTION (PROT_READ | PROT_WRITE) + +#ifndef MAP_LARGEPAGE +#define MAP_LARGEPAGE 0x40 +#endif + +/* Only ia64 requires this */ +#ifdef __ia64__ +#define ADDR (void *)(0x8000000000000000UL) +#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_LARGEPAGE | MAP_FIXED) +#else +#define ADDR (void *)(0x0UL) +#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_LARGEPAGE) +#endif + +void check_bytes(char *addr) +{ + printf("First hex is %x\n", *((unsigned int *)addr)); +} + +void write_bytes(char *addr) +{ + unsigned long i; + + for (i = 0; i < LENGTH; i++) + *(addr + i) = (char)i; +} + +void read_bytes(char *addr) +{ + unsigned long i; + + check_bytes(addr); + for (i = 0; i < LENGTH; i++) + if (*(addr + i) != (char)i) { + printf("Mismatch at %lu\n", i); + break; + } +} + +int main(void) +{ + void *addr; + + addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, 0, 0); + if (addr == MAP_FAILED) { + perror("mmap"); + exit(1); + } + + printf("Returned address is %p\n", addr); + check_bytes(addr); + write_bytes(addr); + read_bytes(addr); + + munmap(addr, LENGTH); + + return 0; +}
Signature · 7 lines
1.6.3.2 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 2/3] Add MAP_LARGEPAGE for mmaping pseudo-anonymous huge page regions
In reply to Eric B MunsonEric,
Quoted 5 lines · Eric B Munson
This patch adds a flag for mmap that will be used to request a huge page region that will look like anonymous memory to user space. This is accomplished by using a file on the internal vfsmount. MAP_LARGEPAGE is a modifier of
MAP_ANONYMOUSand so must be specified with it. The region will behave the same as aMAP_ANONYMOUSregion using small pages.
Does this flag provide functionality analogous to shmget(SHM_HUGETLB)? If so, would iot not make sense to name it similarly (i.e., MAP_HUGETLB)?
Cheers,
Michael
Signature · 10 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Watch my Linux system programming book progress to publication! http://blog.man7.org/ -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 2/3] Add MAP_LARGEPAGE for mmaping pseudo-anonymous huge page regions
Quoted 9 lines · Michael Kerrisk
Eric,
Quoted 5 lines · Eric B Munson
This patch adds a flag for mmap that will be used to request a huge page region that will look like anonymous memory to user space. This is accomplished by using a file on the internal vfsmount. MAP_LARGEPAGE is a modifier of
MAP_ANONYMOUSand so must be specified with it. The region will behave the same as aMAP_ANONYMOUSregion using small pages.
Quoted 14 lines
Does this flag provide functionality analogous to
shmget(SHM_HUGETLB)? If so, would iot not make sense to name it similarly (i.e.,MAP_HUGETLB)?Cheers,
Michael
Signature · 4 lines
Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ Watch my Linux system programming book progress to publication! http://blog.man7.org/
I have no particular attachment to MAP_LARGEPAGE, I will make this chage for V2.
Signature · 3 lines
Eric B Munson IBM Linux Technology Center [email protected]
Re: [PATCH 2/3] Add MAP_LARGEPAGE for mmaping pseudo-anonymous huge page regions
In reply to Eric B MunsonHi Eric,
Quoted 7 lines · Eric B Munson
This patch adds a flag for mmap that will be used to request a huge page region that will look like anonymous memory to user space. This is accomplished by using a file on the internal vfsmount. MAP_LARGEPAGE is a modifier of
MAP_ANONYMOUSand so must be specified with it. The region will behave the same as aMAP_ANONYMOUSregion using small pages.Signed-off-by Eric B Munson <[email protected]>
I would love to see something like this in the kernel. Huge pages are useful for garbage collection and JIT text in the userspace but unfortunately obtaining them is a real PITA at the moment.
Is there any way to drop the CAP_IPC_LOCK/in_group_p(hugetlbfs_shm_group) requirement, btw? That would make huge pages even more accessible to user-space virtual machines.
Pekka
Quoted 79 lines
---
include/asm-generic/mman-common.h | 1 +include/linux/hugetlb.h| 7 +++++++mm/mmap.c| 16 ++++++++++++++++3 files changed, 24 insertions(+), 0 deletions(-)include/asm-generic/mman-common.h +1
-0@@ -19,6 +19,7 @@ #define MAP_TYPE 0x0f /* Mask for type of mapping */ #define MAP_FIXED 0x10 /* Interpret addr exactly */ #define MAP_ANONYMOUS 0x20 /* don't use a file */ +#define MAP_LARGEPAGE 0x40/* create a large page mapping */ #define MS_ASYNC 1 /* sync memory asynchronously */ #define MS_INVALIDATE 2 /* invalidate the caches */include/linux/hugetlb.h +7
-0@@ -109,12 +109,19 @@ static inline void hugetlb_report_meminfo(struct seq_file *m) #endif /* !CONFIG_HUGETLB_PAGE */ +#define HUGETLB_ANON_FILE "anon_hugepage" + enum { /* * The file will be used as an shm file so shmfs accounting rules * apply */ HUGETLB_SHMFS_INODE = 0x01, + /* + * The file is being created on the internal vfs mount and shmfs + * accounting rules do not apply + */ + HUGETLB_ANONHUGE_INODE = 0x02, }; #ifdef CONFIG_HUGETLBFSmm/mmap.c +16
-1@@ -29,6 +29,7 @@ #include <linux/rmap.h> #include <linux/mmu_notifier.h> #include <linux/perf_counter.h> +#include <linux/hugetlb.h> #include <asm/uaccess.h> #include <asm/cacheflush.h>@@ -954,6 +955,21 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, if (mm->map_count > sysctl_max_map_count) return -ENOMEM; + if (flags & MAP_LARGEPAGE) { + if (file) + return -EINVAL; + + /* + * VM_NORESERVE is used because the reservations will be + * taken when vm_ops->mmap() is called + */ + len = ALIGN(len, huge_page_size(&default_hstate)); + file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE, + HUGETLB_ANONHUGE_INODE); + if (IS_ERR(file)) + return -ENOMEM; + } + /* Obtain the address to map to. we verify (or select) it and ensure* that it represents a valid section of the address space. */ --1.6.3.2
Quoted 6 lines
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>