hugetlbfs: fix mmap failure in unaligned size request
[linux-3.10.git] / fs / hugetlbfs / inode.c
index 523464e..a3f868a 100644 (file)
@@ -909,11 +909,8 @@ static int can_do_hugetlb_shm(void)
 
 static int get_hstate_idx(int page_size_log)
 {
-       struct hstate *h;
+       struct hstate *h = hstate_sizelog(page_size_log);
 
-       if (!page_size_log)
-               return default_hstate_idx;
-       h = size_to_hstate(1 << page_size_log);
        if (!h)
                return -1;
        return h - hstates;
@@ -929,9 +926,12 @@ static struct dentry_operations anon_ops = {
        .d_dname = hugetlb_dname
 };
 
-struct file *hugetlb_file_setup(const char *name, unsigned long addr,
-                               size_t size, vm_flags_t acctflag,
-                               struct user_struct **user,
+/*
+ * Note that size should be aligned to proper hugepage size in caller side,
+ * otherwise hugetlb_reserve_pages reserves one less hugepages than intended.
+ */
+struct file *hugetlb_file_setup(const char *name, size_t size,
+                               vm_flags_t acctflag, struct user_struct **user,
                                int creat_flags, int page_size_log)
 {
        struct file *file = ERR_PTR(-ENOMEM);
@@ -939,8 +939,6 @@ struct file *hugetlb_file_setup(const char *name, unsigned long addr,
        struct path path;
        struct super_block *sb;
        struct qstr quick_string;
-       struct hstate *hstate;
-       unsigned long num_pages;
        int hstate_idx;
 
        hstate_idx = get_hstate_idx(page_size_log);
@@ -980,12 +978,10 @@ struct file *hugetlb_file_setup(const char *name, unsigned long addr,
        if (!inode)
                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);
        file = ERR_PTR(-ENOMEM);
-       if (hugetlb_reserve_pages(inode, 0, num_pages, NULL, acctflag))
+       if (hugetlb_reserve_pages(inode, 0,
+                       size >> huge_page_shift(hstate_inode(inode)), NULL,
+                       acctflag))
                goto out_inode;
 
        d_instantiate(path.dentry, inode);