[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: hugepage patches
7/4
hugetlbfs i_size fixes
We're expanding hugetlbfs i_size in the wrong place. If someone attempts to
mmap more pages than are available, i_size is updated to reflect the
attempted mapping size.
So set i_size only when pages are successfully added to the mapping.
i_size handling at truncate time is still a bit wrong - if the mapping has
pages at (say) page offset 100-200 and the mappng is truncated to (say_ page
offset 50, i_size should be set to zero. But it is instead set to
50*HPAGE_SIZE. That's harmless.
i386/mm/hugetlbpage.c | 5 +++++
ia64/mm/hugetlbpage.c | 0
sparc64/mm/hugetlbpage.c | 0
x86_64/mm/hugetlbpage.c | 6 ++++++
hugetlbfs/inode.c | 5 -----
5 files changed, 11 insertions(+), 5 deletions(-)
diff -puN fs/hugetlbfs/inode.c~hugetlbfs-i_size-fix fs/hugetlbfs/inode.c
--- 25/fs/hugetlbfs/inode.c~hugetlbfs-i_size-fix 2003-02-01 02:07:22.000000000 -0800
+++ 25-akpm/fs/hugetlbfs/inode.c 2003-02-01 02:07:22.000000000 -0800
@@ -45,7 +45,6 @@ static int hugetlbfs_file_mmap(struct fi
{
struct inode *inode =file->f_dentry->d_inode;
struct address_space *mapping = inode->i_mapping;
- size_t len;
int ret;
if (!capable(CAP_IPC_LOCK))
@@ -66,10 +65,6 @@ 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 = (vma->vm_end - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
- if (inode->i_size < len)
- inode->i_size = len;
-
up(&inode->i_sem);
return ret;
}
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 2003-02-01 02:07:22.000000000 -0800
+++ 25-akpm/arch/i386/mm/hugetlbpage.c 2003-02-01 02:07:22.000000000 -0800
@@ -284,6 +284,7 @@ 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 *inode = mapping->host;
unsigned long addr;
int ret = 0;
@@ -307,6 +308,7 @@ 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;
@@ -318,6 +320,9 @@ 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/ia64/mm/hugetlbpage.c~hugetlbfs-i_size-fix arch/ia64/mm/hugetlbpage.c
diff -puN arch/sparc64/mm/hugetlbpage.c~hugetlbfs-i_size-fix arch/sparc64/mm/hugetlbpage.c
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 2003-02-01 02:07:22.000000000 -0800
+++ 25-akpm/arch/x86_64/mm/hugetlbpage.c 2003-02-01 02:07:22.000000000 -0800
@@ -205,6 +205,7 @@ 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;
@@ -228,6 +229,8 @@ 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;
@@ -239,6 +242,9 @@ 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);
}
_
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/