diff -Nurp 2.4.23-pre5/arch/ia64/mm/hugetlbpage.c 2.4.23-pre5.ken/arch/ia64/mm/hugetlbpage.c --- 2.4.23-pre5/arch/ia64/mm/hugetlbpage.c Fri Sep 26 14:28:21 2003 +++ 2.4.23-pre5.ken/arch/ia64/mm/hugetlbpage.c Fri Sep 26 14:29:05 2003 @@ -262,18 +262,19 @@ 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; + /* charge the fs quota first */ + if (hugetlb_get_quota(mapping)) { + ret = -ENOMEM; + goto out; + } page = alloc_hugetlb_page(); if (!page) { + hugetlb_put_quota(mapping); ret = -ENOMEM; goto out; } add_to_page_cache(page, mapping, idx); unlock_page(page); - 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 -Nurp 2.4.23-pre5/fs/hugetlbfs/inode.c 2.4.23-pre5.ken/fs/hugetlbfs/inode.c --- 2.4.23-pre5/fs/hugetlbfs/inode.c Fri Sep 26 14:28:21 2003 +++ 2.4.23-pre5.ken/fs/hugetlbfs/inode.c Fri Sep 26 14:29:05 2003 @@ -139,8 +139,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) @@ -155,17 +154,7 @@ static int hugetlbfs_file_mmap(struct fi if (vma->vm_start < (REGION_HPAGE << REGION_SHIFT)) return -EINVAL; #endif - 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); - spin_unlock(&sbinfo->stat_lock); - } else { - spin_unlock(&sbinfo->stat_lock); - return -ENOMEM; - } - } + vma_len = (loff_t)(vma->vm_end - vma->vm_start); down(&inode->i_sem); @@ -173,15 +162,11 @@ 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_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); + if (ret == 0 && inode->i_size < len) + inode->i_size = len; up(&inode->i_sem); - /* If the huge page allocation has failed then increment the free_blocks. */ - if ((ret != 0) && (sbinfo->free_blocks >= 0)) { - spin_lock(&sbinfo->stat_lock); - sbinfo->free_blocks += (len >> HPAGE_SHIFT); - spin_unlock(&sbinfo->stat_lock); - } - return ret; } @@ -261,7 +246,6 @@ void truncate_huge_page(struct address_s void truncate_hugepages(struct inode *inode, struct address_space *mapping, loff_t lstart) { - struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(mapping->host->i_sb); unsigned long start = lstart >> HPAGE_SHIFT; unsigned long next; unsigned long max_idx; @@ -277,13 +261,8 @@ void truncate_hugepages(struct inode *in page_cache_release(page); truncate_huge_page(mapping, page); unlock_page(page); - if (sbinfo->free_blocks >= 0) { - spin_lock(&sbinfo->stat_lock); - sbinfo->free_blocks ++; - spin_unlock(&sbinfo->stat_lock); - } + hugetlb_put_quota(mapping); } - } static void hugetlbfs_delete_inode(struct inode *inode) @@ -720,6 +699,36 @@ out_dentry: return ERR_PTR(error); } +int hugetlb_get_quota(struct address_space * mapping) +{ + int ret = 0; + struct hugetlbfs_sb_info *sbinfo = + HUGETLBFS_SB(mapping->host->i_sb); + + if (sbinfo->free_blocks > -1) { + spin_lock(&sbinfo->stat_lock); + if (sbinfo->free_blocks > 0) + sbinfo->free_blocks--; + else + ret = -ENOMEM; + spin_unlock(&sbinfo->stat_lock); + } + + return ret; +} + +void hugetlb_put_quota(struct address_space *mapping) +{ + struct hugetlbfs_sb_info *sbinfo = + HUGETLBFS_SB(mapping->host->i_sb); + + if (sbinfo->free_blocks > -1) { + spin_lock(&sbinfo->stat_lock); + sbinfo->free_blocks++; + spin_unlock(&sbinfo->stat_lock); + } +} + static int __init init_hugetlbfs_fs(void) { int error; diff -Nurp 2.4.23-pre5/include/linux/hugetlb.h 2.4.23-pre5.ken/include/linux/hugetlb.h --- 2.4.23-pre5/include/linux/hugetlb.h Fri Sep 26 14:28:21 2003 +++ 2.4.23-pre5.ken/include/linux/hugetlb.h Fri Sep 26 14:29:05 2003 @@ -74,6 +74,8 @@ static inline struct hugetlbfs_sb_info * extern struct file_operations hugetlbfs_file_operations; extern struct vm_operations_struct hugetlb_vm_ops; struct file *hugetlb_zero_setup(size_t); +int hugetlb_get_quota(struct address_space *mapping); +void hugetlb_put_quota(struct address_space *mapping); static inline int is_file_hugepages(struct file *file) { @@ -89,6 +91,8 @@ static inline void set_file_hugepages(st #define is_file_hugepages(file) 0 #define set_file_hugepages(file) BUG() #define hugetlb_zero_setup(size) ERR_PTR(-ENOSYS) +#define hugetlb_get_quota(mapping) 0 +#define hugetlb_put_quota(mapping) 0 #endif /* !CONFIG_HUGETLBFS */