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;
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;
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;
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;
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;
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;
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();
put_filp(file);
out_dentry:
dput(dentry);
+out_shm_unlock:
+ user_shm_unlock(size, current->user);
return ERR_PTR(error);
}
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;