Commit 40716e29 authored by Steven Truelove's avatar Steven Truelove Committed by Linus Torvalds

hugetlbfs: fix alignment of huge page requests

When calling shmget() with SHM_HUGETLB, shmget aligns the request size to
PAGE_SIZE, but this is not sufficient.

Modify hugetlb_file_setup() to align requests to the huge page size, and
to accept an address argument so that all alignment checks can be
performed in hugetlb_file_setup(), rather than in its callers.  Change
newseg() and mmap_pgoff() to match the new prototype and eliminate a now
redundant alignment check.

[akpm@linux-foundation.org: fix build]
Signed-off-by: default avatarSteven Truelove <steven.truelove@utoronto.ca>
Cc: Hugh Dickins <hughd@google.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 21a3c273
...@@ -935,8 +935,8 @@ static int can_do_hugetlb_shm(void) ...@@ -935,8 +935,8 @@ static int can_do_hugetlb_shm(void)
return capable(CAP_IPC_LOCK) || in_group_p(sysctl_hugetlb_shm_group); return capable(CAP_IPC_LOCK) || in_group_p(sysctl_hugetlb_shm_group);
} }
struct file *hugetlb_file_setup(const char *name, size_t size, struct file *hugetlb_file_setup(const char *name, unsigned long addr,
vm_flags_t acctflag, size_t size, vm_flags_t acctflag,
struct user_struct **user, int creat_flags) struct user_struct **user, int creat_flags)
{ {
int error = -ENOMEM; int error = -ENOMEM;
...@@ -945,6 +945,8 @@ struct file *hugetlb_file_setup(const char *name, size_t size, ...@@ -945,6 +945,8 @@ struct file *hugetlb_file_setup(const char *name, size_t size,
struct path path; struct path path;
struct dentry *root; struct dentry *root;
struct qstr quick_string; struct qstr quick_string;
struct hstate *hstate;
unsigned long num_pages;
*user = NULL; *user = NULL;
if (!hugetlbfs_vfsmount) if (!hugetlbfs_vfsmount)
...@@ -978,10 +980,12 @@ struct file *hugetlb_file_setup(const char *name, size_t size, ...@@ -978,10 +980,12 @@ struct file *hugetlb_file_setup(const char *name, size_t size,
if (!inode) if (!inode)
goto out_dentry; goto out_dentry;
hstate = hstate_inode(inode);
size += addr & ~huge_page_mask(hstate);
num_pages = ALIGN(size, huge_page_size(hstate)) >>
huge_page_shift(hstate);
error = -ENOMEM; error = -ENOMEM;
if (hugetlb_reserve_pages(inode, 0, if (hugetlb_reserve_pages(inode, 0, num_pages, NULL, acctflag))
size >> huge_page_shift(hstate_inode(inode)), NULL,
acctflag))
goto out_inode; goto out_inode;
d_instantiate(path.dentry, inode); d_instantiate(path.dentry, inode);
......
...@@ -152,7 +152,8 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb) ...@@ -152,7 +152,8 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb)
extern const struct file_operations hugetlbfs_file_operations; extern const struct file_operations hugetlbfs_file_operations;
extern const struct vm_operations_struct hugetlb_vm_ops; extern const struct vm_operations_struct hugetlb_vm_ops;
struct file *hugetlb_file_setup(const char *name, size_t size, vm_flags_t acct, struct file *hugetlb_file_setup(const char *name, unsigned long addr,
size_t size, vm_flags_t acct,
struct user_struct **user, int creat_flags); struct user_struct **user, int creat_flags);
static inline int is_file_hugepages(struct file *file) static inline int is_file_hugepages(struct file *file)
...@@ -168,7 +169,8 @@ static inline int is_file_hugepages(struct file *file) ...@@ -168,7 +169,8 @@ static inline int is_file_hugepages(struct file *file)
#else /* !CONFIG_HUGETLBFS */ #else /* !CONFIG_HUGETLBFS */
#define is_file_hugepages(file) 0 #define is_file_hugepages(file) 0
static inline struct file *hugetlb_file_setup(const char *name, size_t size, static inline struct file *
hugetlb_file_setup(const char *name, unsigned long addr, size_t size,
vm_flags_t acctflag, struct user_struct **user, int creat_flags) vm_flags_t acctflag, struct user_struct **user, int creat_flags)
{ {
return ERR_PTR(-ENOSYS); return ERR_PTR(-ENOSYS);
......
...@@ -482,7 +482,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) ...@@ -482,7 +482,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
/* hugetlb_file_setup applies strict accounting */ /* hugetlb_file_setup applies strict accounting */
if (shmflg & SHM_NORESERVE) if (shmflg & SHM_NORESERVE)
acctflag = VM_NORESERVE; acctflag = VM_NORESERVE;
file = hugetlb_file_setup(name, size, acctflag, file = hugetlb_file_setup(name, 0, size, acctflag,
&shp->mlock_user, HUGETLB_SHMFS_INODE); &shp->mlock_user, HUGETLB_SHMFS_INODE);
} else { } else {
/* /*
......
...@@ -1099,9 +1099,9 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, ...@@ -1099,9 +1099,9 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
* A dummy user value is used because we are not locking * A dummy user value is used because we are not locking
* memory so no accounting is necessary * memory so no accounting is necessary
*/ */
len = ALIGN(len, huge_page_size(&default_hstate)); file = hugetlb_file_setup(HUGETLB_ANON_FILE, addr, len,
file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE, VM_NORESERVE, &user,
&user, HUGETLB_ANONHUGE_INODE); HUGETLB_ANONHUGE_INODE);
if (IS_ERR(file)) if (IS_ERR(file))
return PTR_ERR(file); return PTR_ERR(file);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment