summaryrefslogtreecommitdiffstats
path: root/fs/hugetlbfs
diff options
context:
space:
mode:
authorNaoya Horiguchi <n-horiguchi@ah.jp.nec.com>2013-05-07 19:18:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-07 21:38:27 -0400
commitaf73e4d9506d3b797509f3c030e7dcd554f7d9c4 (patch)
treef9f1bf7483495b66b6cf2cfb3c676791133733b1 /fs/hugetlbfs
parent1ab4ce762370b82870834899e49c08129d7ae271 (diff)
hugetlbfs: fix mmap failure in unaligned size request
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> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/hugetlbfs')
-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 523464e62849..a3f868ae3fd4 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -909,11 +909,8 @@ static int can_do_hugetlb_shm(void)
909 909
910static int get_hstate_idx(int page_size_log) 910static int get_hstate_idx(int page_size_log)
911{ 911{
912 struct hstate *h; 912 struct hstate *h = hstate_sizelog(page_size_log);
913 913
914 if (!page_size_log)
915 return default_hstate_idx;
916 h = size_to_hstate(1 << page_size_log);
917 if (!h) 914 if (!h)
918 return -1; 915 return -1;
919 return h - hstates; 916 return h - hstates;
@@ -929,9 +926,12 @@ static struct dentry_operations anon_ops = {
929 .d_dname = hugetlb_dname 926 .d_dname = hugetlb_dname
930}; 927};
931 928
932struct file *hugetlb_file_setup(const char *name, unsigned long addr, 929/*
933 size_t size, vm_flags_t acctflag, 930 * Note that size should be aligned to proper hugepage size in caller side,
934 struct user_struct **user, 931 * otherwise hugetlb_reserve_pages reserves one less hugepages than intended.
932 */
933struct file *hugetlb_file_setup(const char *name, size_t size,
934 vm_flags_t acctflag, struct user_struct **user,
935 int creat_flags, int page_size_log) 935 int creat_flags, int page_size_log)
936{ 936{
937 struct file *file = ERR_PTR(-ENOMEM); 937 struct file *file = ERR_PTR(-ENOMEM);
@@ -939,8 +939,6 @@ struct file *hugetlb_file_setup(const char *name, unsigned long addr,
939 struct path path; 939 struct path path;
940 struct super_block *sb; 940 struct super_block *sb;
941 struct qstr quick_string; 941 struct qstr quick_string;
942 struct hstate *hstate;
943 unsigned long num_pages;
944 int hstate_idx; 942 int hstate_idx;
945 943
946 hstate_idx = get_hstate_idx(page_size_log); 944 hstate_idx = get_hstate_idx(page_size_log);
@@ -980,12 +978,10 @@ struct file *hugetlb_file_setup(const char *name, unsigned long addr,
980 if (!inode) 978 if (!inode)
981 goto out_dentry; 979 goto out_dentry;
982 980
983 hstate = hstate_inode(inode);
984 size += addr & ~huge_page_mask(hstate);
985 num_pages = ALIGN(size, huge_page_size(hstate)) >>
986 huge_page_shift(hstate);
987 file = ERR_PTR(-ENOMEM); 981 file = ERR_PTR(-ENOMEM);
988 if (hugetlb_reserve_pages(inode, 0, num_pages, NULL, acctflag)) 982 if (hugetlb_reserve_pages(inode, 0,
983 size >> huge_page_shift(hstate_inode(inode)), NULL,
984 acctflag))
989 goto out_inode; 985 goto out_inode;
990 986
991 d_instantiate(path.dentry, inode); 987 d_instantiate(path.dentry, inode);