Skip to content

Commit

Permalink
mm: add MAP_HUGETLB support to vm_mmap
Browse files Browse the repository at this point in the history
vm_mmap is exported, which means kernel modules can use it. In particular,
for testing XPFO support, we want to use it with the MAP_HUGETLB flag, so
let's support it via vm_mmap.

Signed-off-by: Tycho Andersen <[email protected]>
Tested-by: Marco Benatto <[email protected]>
  • Loading branch information
Tycho Andersen committed Sep 7, 2017
1 parent 569dbb8 commit 923e915
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 18 deletions.
2 changes: 2 additions & 0 deletions include/linux/mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -2141,6 +2141,8 @@ struct vm_unmapped_area_info {
extern unsigned long unmapped_area(struct vm_unmapped_area_info *info);
extern unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info);

struct file *map_hugetlb_setup(unsigned long *len, unsigned long flags);

/*
* Search for an unmapped address range.
*
Expand Down
19 changes: 1 addition & 18 deletions mm/mmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1490,24 +1490,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
if (unlikely(flags & MAP_HUGETLB && !is_file_hugepages(file)))
goto out_fput;
} else if (flags & MAP_HUGETLB) {
struct user_struct *user = NULL;
struct hstate *hs;

hs = hstate_sizelog((flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK);
if (!hs)
return -EINVAL;

len = ALIGN(len, huge_page_size(hs));
/*
* VM_NORESERVE is used because the reservations will be
* taken when vm_ops->mmap() is called
* A dummy user value is used because we are not locking
* memory so no accounting is necessary
*/
file = hugetlb_file_setup(HUGETLB_ANON_FILE, len,
VM_NORESERVE,
&user, HUGETLB_ANONHUGE_INODE,
(flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK);
file = map_hugetlb_setup(&len, flags);
if (IS_ERR(file))
return PTR_ERR(file);
}
Expand Down
32 changes: 32 additions & 0 deletions mm/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,29 @@ unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr,
return ret;
}

struct file *map_hugetlb_setup(unsigned long *len, unsigned long flags)
{
struct user_struct *user = NULL;
struct hstate *hs;

hs = hstate_sizelog((flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK);
if (!hs)
return ERR_PTR(-EINVAL);

*len = ALIGN(*len, huge_page_size(hs));

/*
* VM_NORESERVE is used because the reservations will be
* taken when vm_ops->mmap() is called
* A dummy user value is used because we are not locking
* memory so no accounting is necessary
*/
return hugetlb_file_setup(HUGETLB_ANON_FILE, *len,
VM_NORESERVE,
&user, HUGETLB_ANONHUGE_INODE,
(flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK);
}

unsigned long vm_mmap(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flag, unsigned long offset)
Expand All @@ -349,6 +372,15 @@ unsigned long vm_mmap(struct file *file, unsigned long addr,
if (unlikely(offset_in_page(offset)))
return -EINVAL;

if (flag & MAP_HUGETLB) {
if (file)
return -EINVAL;

file = map_hugetlb_setup(&len, flag);
if (IS_ERR(file))
return PTR_ERR(file);
}

return vm_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
}
EXPORT_SYMBOL(vm_mmap);
Expand Down

0 comments on commit 923e915

Please sign in to comment.