[PATCH][2.6] hugetlbfs - 'recovering' too many blocks on failure

From: Zwane Mwaikambo
Date: Mon Aug 11 2003 - 14:01:08 EST


The code appears to be able to add too many blocks back to
sbinfo->free_blocks in the failure path. We first do;

len = vma->vm_end - vma->vm_start;
sbinfo->free_blocks -= len;

but then later do;
len = (vma->vm_end - vma->vma_start) + (vma->vm_pgoff << HPAGE_SHIFT)

error:
sbinfo->free_blocks += len;

Index: linux-2.6.0-test3-mm1/fs/hugetlbfs/inode.c
===================================================================
RCS file: /build/cvsroot/linux-2.6.0-test3/fs/hugetlbfs/inode.c,v
retrieving revision 1.2
diff -u -p -B -r1.2 inode.c
--- linux-2.6.0-test3-mm1/fs/hugetlbfs/inode.c 11 Aug 2003 03:01:07 -0000 1.2
+++ linux-2.6.0-test3-mm1/fs/hugetlbfs/inode.c 11 Aug 2003 17:44:31 -0000
@@ -48,7 +48,7 @@ static int hugetlbfs_file_mmap(struct fi
struct inode *inode = file->f_dentry->d_inode;
struct address_space *mapping = inode->i_mapping;
struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(inode->i_sb);
- loff_t len;
+ loff_t len, vma_len;
int ret;

if (vma->vm_start & ~HPAGE_MASK)
@@ -60,11 +60,11 @@ static int hugetlbfs_file_mmap(struct fi
if (vma->vm_end - vma->vm_start < HPAGE_SIZE)
return -EINVAL;

- len = (loff_t)(vma->vm_end - vma->vm_start);
+ vma_len = (loff_t)(vma->vm_end - vma->vm_start);
if (sbinfo->free_blocks >= 0) { /* Check if there is any size limit. */
spin_lock(&sbinfo->stat_lock);
- if ((len >> HPAGE_SHIFT) <= sbinfo->free_blocks) {
- sbinfo->free_blocks -= (len >> HPAGE_SHIFT);
+ if ((vma_len >> HPAGE_SHIFT) <= sbinfo->free_blocks) {
+ sbinfo->free_blocks -= (vma_len >> HPAGE_SHIFT);
spin_unlock(&sbinfo->stat_lock);
} else {
spin_unlock(&sbinfo->stat_lock);
@@ -78,8 +78,7 @@ 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);
+ len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
if (ret == 0 && inode->i_size < len)
inode->i_size = len;
up(&inode->i_sem);
@@ -89,7 +88,7 @@ static int hugetlbfs_file_mmap(struct fi
*/
if ((ret != 0) && (sbinfo->free_blocks >= 0)) {
spin_lock(&sbinfo->stat_lock);
- sbinfo->free_blocks += (len >> HPAGE_SHIFT);
+ sbinfo->free_blocks += (vma_len >> HPAGE_SHIFT);
spin_unlock(&sbinfo->stat_lock);
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/