X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fhugetlbfs%2Finode.c;h=6e7aeff355afe50685269b23b5b1a7574ba3639f;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=4ec4283159ea111d097e592de6f36f71b8b86c50;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 4ec428315..6e7aeff35 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -52,6 +52,9 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) loff_t len, vma_len; int ret; + if ((vma->vm_flags & (VM_MAYSHARE | VM_WRITE)) == VM_WRITE) + return -EINVAL; + if (vma->vm_pgoff & (HPAGE_SIZE / PAGE_SIZE - 1)) return -EINVAL; @@ -70,10 +73,19 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) file_accessed(file); vma->vm_flags |= VM_HUGETLB | VM_RESERVED; vma->vm_ops = &hugetlb_vm_ops; + + ret = -ENOMEM; + len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); + if (!(vma->vm_flags & VM_WRITE) && len > inode->i_size) + goto out; + ret = hugetlb_prefault(mapping, vma); - len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); - if (ret == 0 && inode->i_size < len) + if (ret) + goto out; + + if (inode->i_size < len) inode->i_size = len; +out: up(&inode->i_sem); return ret; @@ -272,11 +284,10 @@ static void hugetlbfs_drop_inode(struct inode *inode) static inline void hugetlb_vmtruncate_list(struct prio_tree_root *root, unsigned long h_pgoff) { - struct vm_area_struct *vma = NULL; + struct vm_area_struct *vma; struct prio_tree_iter iter; - while ((vma = vma_prio_tree_next(vma, root, &iter, - h_pgoff, ULONG_MAX)) != NULL) { + vma_prio_tree_foreach(vma, &iter, root, h_pgoff, ULONG_MAX) { unsigned long h_vm_pgoff; unsigned long v_length; unsigned long v_offset; @@ -640,6 +651,7 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent) sbinfo->free_blocks = config.nr_blocks; sbinfo->max_inodes = config.nr_inodes; sbinfo->free_inodes = config.nr_inodes; + sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_blocksize = HPAGE_SIZE; sb->s_blocksize_bits = HPAGE_SHIFT; sb->s_magic = HUGETLBFS_MAGIC; @@ -721,12 +733,13 @@ static unsigned long hugetlbfs_counter(void) static int can_do_hugetlb_shm(void) { return likely(capable(CAP_IPC_LOCK) || - in_group_p(sysctl_hugetlb_shm_group)); + in_group_p(sysctl_hugetlb_shm_group) || + can_do_mlock()); } struct file *hugetlb_zero_setup(size_t size) { - int error; + int error = -ENOMEM; struct file *file; struct inode *inode; struct dentry *dentry, *root; @@ -739,6 +752,9 @@ struct file *hugetlb_zero_setup(size_t size) if (!is_hugepage_mem_enough(size)) return ERR_PTR(-ENOMEM); + if (!user_shm_lock(size, current->user)) + return ERR_PTR(-ENOMEM); + root = hugetlbfs_vfsmount->mnt_root; snprintf(buf, 16, "%lu", hugetlbfs_counter()); quick_string.name = buf; @@ -746,7 +762,7 @@ struct file *hugetlb_zero_setup(size_t size) quick_string.hash = 0; dentry = d_alloc(root, &quick_string); if (!dentry) - return ERR_PTR(-ENOMEM); + goto out_shm_unlock; error = -ENFILE; file = get_empty_filp(); @@ -773,6 +789,8 @@ out_file: put_filp(file); out_dentry: dput(dentry); +out_shm_unlock: + user_shm_unlock(size, current->user); return ERR_PTR(error); } @@ -783,8 +801,7 @@ static int __init init_hugetlbfs_fs(void) hugetlbfs_inode_cachep = kmem_cache_create("hugetlbfs_inode_cache", sizeof(struct hugetlbfs_inode_info), - 0, SLAB_RECLAIM_ACCOUNT, - init_once, NULL); + 0, 0, init_once, NULL); if (hugetlbfs_inode_cachep == NULL) return -ENOMEM;