aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorNaoya Horiguchi2013-05-07 18:18:13 -0500
committerGreg Kroah-Hartman2013-05-11 15:53:51 -0500
commitffeae73e9f2780c7711b12b78ade0a447665117c (patch)
tree37f0b5f56b41a7e08ae1592a1c2a0bbfd1216d18 /fs
parent7f9bc00875dd46bc964b37825ba6bb2024a365e4 (diff)
downloadkernel-omap-ffeae73e9f2780c7711b12b78ade0a447665117c.tar.gz
kernel-omap-ffeae73e9f2780c7711b12b78ade0a447665117c.tar.xz
kernel-omap-ffeae73e9f2780c7711b12b78ade0a447665117c.zip
hugetlbfs: fix mmap failure in unaligned size request
commit af73e4d9506d3b797509f3c030e7dcd554f7d9c4 upstream. The current kernel returns -EINVAL unless a given mmap length is "almost" hugepage aligned. This is because in sys_mmap_pgoff() the given length is passed to vm_mmap_pgoff() as it is without being aligned with hugepage boundary. This is a regression introduced in commit 40716e29243d ("hugetlbfs: fix alignment of huge page requests"), where alignment code is pushed into hugetlb_file_setup() and the variable len in caller side is not changed. To fix this, this patch partially reverts that commit, and adds alignment code in caller side. And it also introduces hstate_sizelog() in order to get proper hstate to specified hugepage size. Addresses https://bugzilla.kernel.org/show_bug.cgi?id=56881 [akpm@linux-foundation.org: fix warning when CONFIG_HUGETLB_PAGE=n] Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Reported-by: <iceman_dvd@yahoo.com> Cc: Steven Truelove <steven.truelove@utoronto.ca> Cc: Jianguo Wu <wujianguo@huawei.com> Cc: Hugh Dickins <hughd@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/hugetlbfs/inode.c24
1 files changed, 10 insertions, 14 deletions
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index ccee8cce172c..d0de769bcf20 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -908,19 +908,19 @@ static int can_do_hugetlb_shm(void)
908 908
909static int get_hstate_idx(int page_size_log) 909static int get_hstate_idx(int page_size_log)
910{ 910{
911 struct hstate *h; 911 struct hstate *h = hstate_sizelog(page_size_log);
912 912
913 if (!page_size_log)
914 return default_hstate_idx;
915 h = size_to_hstate(1 << page_size_log);
916 if (!h) 913 if (!h)
917 return -1; 914 return -1;
918 return h - hstates; 915 return h - hstates;
919} 916}
920 917
921struct file *hugetlb_file_setup(const char *name, unsigned long addr, 918/*
922 size_t size, vm_flags_t acctflag, 919 * Note that size should be aligned to proper hugepage size in caller side,
923 struct user_struct **user, 920 * otherwise hugetlb_reserve_pages reserves one less hugepages than intended.
921 */
922struct file *hugetlb_file_setup(const char *name, size_t size,
923 vm_flags_t acctflag, struct user_struct **user,
924 int creat_flags, int page_size_log) 924 int creat_flags, int page_size_log)
925{ 925{
926 int error = -ENOMEM; 926 int error = -ENOMEM;
@@ -929,8 +929,6 @@ struct file *hugetlb_file_setup(const char *name, unsigned long addr,
929 struct path path; 929 struct path path;
930 struct dentry *root; 930 struct dentry *root;
931 struct qstr quick_string; 931 struct qstr quick_string;
932 struct hstate *hstate;
933 unsigned long num_pages;
934 int hstate_idx; 932 int hstate_idx;
935 933
936 hstate_idx = get_hstate_idx(page_size_log); 934 hstate_idx = get_hstate_idx(page_size_log);
@@ -969,12 +967,10 @@ struct file *hugetlb_file_setup(const char *name, unsigned long addr,
969 if (!inode) 967 if (!inode)
970 goto out_dentry; 968 goto out_dentry;
971 969
972 hstate = hstate_inode(inode);
973 size += addr & ~huge_page_mask(hstate);
974 num_pages = ALIGN(size, huge_page_size(hstate)) >>
975 huge_page_shift(hstate);
976 error = -ENOMEM; 970 error = -ENOMEM;
977 if (hugetlb_reserve_pages(inode, 0, num_pages, NULL, acctflag)) 971 if (hugetlb_reserve_pages(inode, 0,
972 size >> huge_page_shift(hstate_inode(inode)), NULL,
973 acctflag))
978 goto out_inode; 974 goto out_inode;
979 975
980 d_instantiate(path.dentry, inode); 976 d_instantiate(path.dentry, inode);