diff options
Diffstat (limited to 'fs/hugetlbfs/inode.c')
-rw-r--r-- | fs/hugetlbfs/inode.c | 40 |
1 files changed, 24 insertions, 16 deletions
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 8f96461236f6..dde861387a40 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -136,17 +136,26 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) | |||
136 | vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND; | 136 | vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND; |
137 | vma->vm_ops = &hugetlb_vm_ops; | 137 | vma->vm_ops = &hugetlb_vm_ops; |
138 | 138 | ||
139 | /* | ||
140 | * Offset passed to mmap (before page shift) could have been | ||
141 | * negative when represented as a (l)off_t. | ||
142 | */ | ||
143 | if (((loff_t)vma->vm_pgoff << PAGE_SHIFT) < 0) | ||
144 | return -EINVAL; | ||
145 | |||
139 | if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT)) | 146 | if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT)) |
140 | return -EINVAL; | 147 | return -EINVAL; |
141 | 148 | ||
142 | vma_len = (loff_t)(vma->vm_end - vma->vm_start); | 149 | vma_len = (loff_t)(vma->vm_end - vma->vm_start); |
150 | len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); | ||
151 | /* check for overflow */ | ||
152 | if (len < vma_len) | ||
153 | return -EINVAL; | ||
143 | 154 | ||
144 | inode_lock(inode); | 155 | inode_lock(inode); |
145 | file_accessed(file); | 156 | file_accessed(file); |
146 | 157 | ||
147 | ret = -ENOMEM; | 158 | ret = -ENOMEM; |
148 | len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); | ||
149 | |||
150 | if (hugetlb_reserve_pages(inode, | 159 | if (hugetlb_reserve_pages(inode, |
151 | vma->vm_pgoff >> huge_page_order(h), | 160 | vma->vm_pgoff >> huge_page_order(h), |
152 | len >> huge_page_shift(h), vma, | 161 | len >> huge_page_shift(h), vma, |
@@ -155,7 +164,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) | |||
155 | 164 | ||
156 | ret = 0; | 165 | ret = 0; |
157 | if (vma->vm_flags & VM_WRITE && inode->i_size < len) | 166 | if (vma->vm_flags & VM_WRITE && inode->i_size < len) |
158 | inode->i_size = len; | 167 | i_size_write(inode, len); |
159 | out: | 168 | out: |
160 | inode_unlock(inode); | 169 | inode_unlock(inode); |
161 | 170 | ||
@@ -695,14 +704,11 @@ static struct inode *hugetlbfs_get_root(struct super_block *sb, | |||
695 | 704 | ||
696 | inode = new_inode(sb); | 705 | inode = new_inode(sb); |
697 | if (inode) { | 706 | if (inode) { |
698 | struct hugetlbfs_inode_info *info; | ||
699 | inode->i_ino = get_next_ino(); | 707 | inode->i_ino = get_next_ino(); |
700 | inode->i_mode = S_IFDIR | config->mode; | 708 | inode->i_mode = S_IFDIR | config->mode; |
701 | inode->i_uid = config->uid; | 709 | inode->i_uid = config->uid; |
702 | inode->i_gid = config->gid; | 710 | inode->i_gid = config->gid; |
703 | inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); | 711 | inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); |
704 | info = HUGETLBFS_I(inode); | ||
705 | mpol_shared_policy_init(&info->policy, NULL); | ||
706 | inode->i_op = &hugetlbfs_dir_inode_operations; | 712 | inode->i_op = &hugetlbfs_dir_inode_operations; |
707 | inode->i_fop = &simple_dir_operations; | 713 | inode->i_fop = &simple_dir_operations; |
708 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ | 714 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ |
@@ -733,7 +739,6 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, | |||
733 | 739 | ||
734 | inode = new_inode(sb); | 740 | inode = new_inode(sb); |
735 | if (inode) { | 741 | if (inode) { |
736 | struct hugetlbfs_inode_info *info; | ||
737 | inode->i_ino = get_next_ino(); | 742 | inode->i_ino = get_next_ino(); |
738 | inode_init_owner(inode, dir, mode); | 743 | inode_init_owner(inode, dir, mode); |
739 | lockdep_set_class(&inode->i_mapping->i_mmap_rwsem, | 744 | lockdep_set_class(&inode->i_mapping->i_mmap_rwsem, |
@@ -741,15 +746,6 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, | |||
741 | inode->i_mapping->a_ops = &hugetlbfs_aops; | 746 | inode->i_mapping->a_ops = &hugetlbfs_aops; |
742 | inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); | 747 | inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); |
743 | inode->i_mapping->private_data = resv_map; | 748 | inode->i_mapping->private_data = resv_map; |
744 | info = HUGETLBFS_I(inode); | ||
745 | /* | ||
746 | * The policy is initialized here even if we are creating a | ||
747 | * private inode because initialization simply creates an | ||
748 | * an empty rb tree and calls rwlock_init(), later when we | ||
749 | * call mpol_free_shared_policy() it will just return because | ||
750 | * the rb tree will still be empty. | ||
751 | */ | ||
752 | mpol_shared_policy_init(&info->policy, NULL); | ||
753 | switch (mode & S_IFMT) { | 749 | switch (mode & S_IFMT) { |
754 | default: | 750 | default: |
755 | init_special_inode(inode, mode, dev); | 751 | init_special_inode(inode, mode, dev); |
@@ -937,6 +933,18 @@ static struct inode *hugetlbfs_alloc_inode(struct super_block *sb) | |||
937 | hugetlbfs_inc_free_inodes(sbinfo); | 933 | hugetlbfs_inc_free_inodes(sbinfo); |
938 | return NULL; | 934 | return NULL; |
939 | } | 935 | } |
936 | |||
937 | /* | ||
938 | * Any time after allocation, hugetlbfs_destroy_inode can be called | ||
939 | * for the inode. mpol_free_shared_policy is unconditionally called | ||
940 | * as part of hugetlbfs_destroy_inode. So, initialize policy here | ||
941 | * in case of a quick call to destroy. | ||
942 | * | ||
943 | * Note that the policy is initialized even if we are creating a | ||
944 | * private inode. This simplifies hugetlbfs_destroy_inode. | ||
945 | */ | ||
946 | mpol_shared_policy_init(&p->policy, NULL); | ||
947 | |||
940 | return &p->vfs_inode; | 948 | return &p->vfs_inode; |
941 | } | 949 | } |
942 | 950 | ||