Commit 2743f6fe authored by Andrew Morton's avatar Andrew Morton Committed by Vojtech Pavlik

[PATCH] hugetlbfs i_size fix

Growing i_size in hugetlbfs_prefault() isn't right - if we run out of pages,
do_mmap_pgoff() will chop the partially-instantiated pages off again.

So update i_size in hugetlbfs_file_mmap() if the whole mmap attempt was
successful.
parent e4ddca77
......@@ -296,7 +296,6 @@ zap_hugepage_range(struct vm_area_struct *vma,
int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
{
struct mm_struct *mm = current->mm;
struct inode *inode = mapping->host;
unsigned long addr;
int ret = 0;
......@@ -320,7 +319,6 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
+ (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
page = find_get_page(mapping, idx);
if (!page) {
loff_t i_size;
page = alloc_hugetlb_page();
if (!page) {
ret = -ENOMEM;
......@@ -332,9 +330,6 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
free_huge_page(page);
goto out;
}
i_size = (loff_t)(idx + 1) * HPAGE_SIZE;
if (i_size > inode->i_size)
inode->i_size = i_size;
}
set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
}
......
......@@ -245,7 +245,6 @@ void zap_hugepage_range(struct vm_area_struct *vma, unsigned long start, unsigne
int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
{
struct mm_struct *mm = current->mm;
struct inode *inode = mapping->host;
unsigned long addr;
int ret = 0;
......@@ -269,7 +268,6 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
+ (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
page = find_get_page(mapping, idx);
if (!page) {
loff_t i_size;
page = alloc_hugetlb_page();
if (!page) {
......@@ -282,9 +280,6 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
free_huge_page(page);
goto out;
}
i_size = (loff_t)(idx + 1) * HPAGE_SIZE;
if (i_size > inode->i_size)
inode->i_size = i_size;
}
set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
}
......
......@@ -45,6 +45,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
{
struct inode *inode =file->f_dentry->d_inode;
struct address_space *mapping = inode->i_mapping;
loff_t len;
int ret;
if (!capable(CAP_IPC_LOCK))
......@@ -65,6 +66,10 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
vma->vm_flags |= VM_HUGETLB | VM_RESERVED;
vma->vm_ops = &hugetlb_vm_ops;
ret = hugetlb_prefault(mapping, vma);
len = (loff_t)(vma->vm_end - vma->vm_start) +
((loff_t)vma->vm_pgoff << PAGE_SHIFT);
if (ret == 0 && inode->i_size < len)
inode->i_size = len;
up(&inode->i_sem);
return ret;
}
......
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