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: Steven Truelove <steven.truelove@utoronto.ca> Cc: Hugh Dickins <hughd@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
21a3c273f8
commit
40716e2924
@ -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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
#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)
|
|||||||
/* 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,
|
|||||||
* 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);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user