Commit 8a1335e9 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[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.
parent a20d5200
......@@ -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);
}
}
......
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