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. arch/i386/mm/hugetlbpage.c | 5 ----- arch/x86_64/mm/hugetlbpage.c | 5 ----- fs/hugetlbfs/inode.c | 5 +++++ 3 files changed, 5 insertions(+), 10 deletions(-) diff -puN arch/i386/mm/hugetlbpage.c~hugetlbfs-i_size-fix arch/i386/mm/hugetlbpage.c --- 25/arch/i386/mm/hugetlbpage.c~hugetlbfs-i_size-fix Mon Feb 10 16:55:34 2003 +++ 25-akpm/arch/i386/mm/hugetlbpage.c Mon Feb 10 16:55:34 2003 @@ -296,7 +296,6 @@ zap_hugepage_range(struct vm_area_struct 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_spac + (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_spac 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); } diff -puN arch/x86_64/mm/hugetlbpage.c~hugetlbfs-i_size-fix arch/x86_64/mm/hugetlbpage.c --- 25/arch/x86_64/mm/hugetlbpage.c~hugetlbfs-i_size-fix Mon Feb 10 16:55:34 2003 +++ 25-akpm/arch/x86_64/mm/hugetlbpage.c Mon Feb 10 16:55:34 2003 @@ -216,7 +216,6 @@ void zap_hugepage_range(struct vm_area_s int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma) { struct mm_struct *mm = current->mm; - struct inode = mapping->host; unsigned long addr; int ret = 0; @@ -240,7 +239,6 @@ int hugetlb_prefault(struct address_spac + (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) { @@ -253,9 +251,6 @@ int hugetlb_prefault(struct address_spac 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); } diff -puN fs/hugetlbfs/inode.c~hugetlbfs-i_size-fix fs/hugetlbfs/inode.c --- 25/fs/hugetlbfs/inode.c~hugetlbfs-i_size-fix Mon Feb 10 16:55:34 2003 +++ 25-akpm/fs/hugetlbfs/inode.c Mon Feb 10 16:55:34 2003 @@ -45,6 +45,7 @@ static int hugetlbfs_file_mmap(struct fi { 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 fi 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; } _