diff options
| author | Andrew Morton <akpm@digeo.com> | 2003-02-05 16:58:51 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-02-05 16:58:51 -0800 |
| commit | 8a1335e97ac2598f8f5ea8f18c7d8eeb4906e841 (patch) | |
| tree | 83d14cf913e02dcae8b527f0adcea102401173b6 | |
| parent | a20d5200d36f3b1604b91c1a73a9f31f91a1bc2c (diff) | |
[PATCH] Fix hugetlb_vmtruncate_list()
This function is quite wrong - has an "=" where it should have a "-" and
confuses PAGE_SIZE and HPAGE_SIZE in its address and file offset arithmetic.
| -rw-r--r-- | fs/hugetlbfs/inode.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 698cb1ff85ef..5ce105bd3d1e 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -238,29 +238,47 @@ static void hugetlbfs_drop_inode(struct inode *inode) hugetlbfs_forget_inode(inode); } -static void hugetlb_vmtruncate_list(struct list_head *list, unsigned long pgoff) +/* + * h_pgoff is in HPAGE_SIZE units. + * vma->vm_pgoff is in PAGE_SIZE units. + */ +static void +hugetlb_vmtruncate_list(struct list_head *list, unsigned long h_pgoff) { - unsigned long start, end, length, delta; struct vm_area_struct *vma; list_for_each_entry(vma, list, shared) { - start = vma->vm_start; - end = vma->vm_end; - length = end - start; - - if (vma->vm_pgoff >= pgoff) { - zap_hugepage_range(vma, start, length); + unsigned long h_vm_pgoff; + unsigned long v_length; + unsigned long h_length; + unsigned long v_offset; + + h_vm_pgoff = vma->vm_pgoff << (HPAGE_SHIFT - PAGE_SHIFT); + v_length = vma->vm_end - vma->vm_start; + h_length = v_length >> HPAGE_SHIFT; + v_offset = (h_pgoff - h_vm_pgoff) << HPAGE_SHIFT; + + /* + * Is this VMA fully outside the truncation point? + */ + if (h_vm_pgoff >= h_pgoff) { + zap_hugepage_range(vma, vma->vm_start, v_length); continue; } - length >>= PAGE_SHIFT; - delta = pgoff = vma->vm_pgoff; - if (delta >= length) + /* + * Is this VMA fully inside the truncaton point? + */ + if (h_vm_pgoff + (v_length >> HPAGE_SHIFT) <= h_pgoff) continue; - start += delta << PAGE_SHIFT; - length = (length - delta) << PAGE_SHIFT; - zap_hugepage_range(vma, start, length); + /* + * The VMA straddles the truncation point. v_offset is the + * offset (in bytes) into the VMA where the point lies. + */ + zap_hugepage_range(vma, + vma->vm_start + v_offset, + v_length - v_offset); } } |
