
From: Zwane Mwaikambo <zwane@linuxpower.ca>

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;



 25-akpm/fs/hugetlbfs/inode.c |   13 ++++++-------
 1 files changed, 6 insertions(+), 7 deletions(-)

diff -puN fs/hugetlbfs/inode.c~hugetlbfs-free_blocks-accounting-fix fs/hugetlbfs/inode.c
--- 25/fs/hugetlbfs/inode.c~hugetlbfs-free_blocks-accounting-fix	Mon Aug 11 13:59:00 2003
+++ 25-akpm/fs/hugetlbfs/inode.c	Mon Aug 11 13:59:00 2003
@@ -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);
 	}
 

_
