git://git.onelab.eu
/
linux-2.6.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
vserver 1.9.5.x5
[linux-2.6.git]
/
fs
/
hugetlbfs
/
inode.c
diff --git
a/fs/hugetlbfs/inode.c
b/fs/hugetlbfs/inode.c
index
f2893bb
..
7a006cc
100644
(file)
--- a/
fs/hugetlbfs/inode.c
+++ b/
fs/hugetlbfs/inode.c
@@
-52,6
+52,12
@@
static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
loff_t len, vma_len;
int ret;
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;
+
if (vma->vm_start & ~HPAGE_MASK)
return -EINVAL;
if (vma->vm_start & ~HPAGE_MASK)
return -EINVAL;
@@
-67,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;
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);
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;
inode->i_size = len;
+out:
up(&inode->i_sem);
return ret;
up(&inode->i_sem);
return ret;
@@
-90,6
+105,7
@@
hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
{
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
{
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
+ unsigned long start_addr;
if (len & ~HPAGE_MASK)
return -EINVAL;
if (len & ~HPAGE_MASK)
return -EINVAL;
@@
-104,12
+120,25
@@
hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
return addr;
}
return addr;
}
- addr = ALIGN(mm->free_area_cache, HPAGE_SIZE);
+ start_addr = mm->free_area_cache;
+
+full_search:
+ addr = ALIGN(start_addr, HPAGE_SIZE);
for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
/* At this point: (!vma || addr < vma->vm_end). */
for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
/* At this point: (!vma || addr < vma->vm_end). */
- if (TASK_SIZE - len < addr)
+ if (TASK_SIZE - len < addr) {
+ /*
+ * Start a new search - just in case we missed
+ * some holes.
+ */
+ if (start_addr != TASK_UNMAPPED_BASE) {
+ start_addr = TASK_UNMAPPED_BASE;
+ goto full_search;
+ }
return -ENOMEM;
return -ENOMEM;
+ }
+
if (!vma || addr + len <= vma->vm_start)
return addr;
addr = ALIGN(vma->vm_end, HPAGE_SIZE);
if (!vma || addr + len <= vma->vm_start)
return addr;
addr = ALIGN(vma->vm_end, HPAGE_SIZE);
@@
-139,7
+168,7
@@
static int hugetlbfs_commit_write(struct file *file,
return -EINVAL;
}
return -EINVAL;
}
-void huge_pagevec_release(struct pagevec *pvec)
+
static
void huge_pagevec_release(struct pagevec *pvec)
{
int i;
{
int i;
@@
-149,7
+178,7
@@
void huge_pagevec_release(struct pagevec *pvec)
pagevec_reinit(pvec);
}
pagevec_reinit(pvec);
}
-void truncate_huge_page(struct page *page)
+
static
void truncate_huge_page(struct page *page)
{
clear_page_dirty(page);
ClearPageUptodate(page);
{
clear_page_dirty(page);
ClearPageUptodate(page);
@@
-157,7
+186,7
@@
void truncate_huge_page(struct page *page)
put_page(page);
}
put_page(page);
}
-void truncate_hugepages(struct address_space *mapping, loff_t lstart)
+
static
void truncate_hugepages(struct address_space *mapping, loff_t lstart)
{
const pgoff_t start = lstart >> HPAGE_SHIFT;
struct pagevec pvec;
{
const pgoff_t start = lstart >> HPAGE_SHIFT;
struct pagevec pvec;
@@
-196,6
+225,7
@@
static void hugetlbfs_delete_inode(struct inode *inode)
hlist_del_init(&inode->i_hash);
list_del_init(&inode->i_list);
hlist_del_init(&inode->i_hash);
list_del_init(&inode->i_list);
+ list_del_init(&inode->i_sb_list);
inode->i_state |= I_FREEING;
inodes_stat.nr_inodes--;
spin_unlock(&inode_lock);
inode->i_state |= I_FREEING;
inodes_stat.nr_inodes--;
spin_unlock(&inode_lock);
@@
-238,6
+268,7
@@
static void hugetlbfs_forget_inode(struct inode *inode)
hlist_del_init(&inode->i_hash);
out_truncate:
list_del_init(&inode->i_list);
hlist_del_init(&inode->i_hash);
out_truncate:
list_del_init(&inode->i_list);
+ list_del_init(&inode->i_sb_list);
inode->i_state |= I_FREEING;
inodes_stat.nr_inodes--;
spin_unlock(&inode_lock);
inode->i_state |= I_FREEING;
inodes_stat.nr_inodes--;
spin_unlock(&inode_lock);
@@
-269,25
+300,24
@@
static void hugetlbfs_drop_inode(struct inode *inode)
static inline void
hugetlb_vmtruncate_list(struct prio_tree_root *root, unsigned long h_pgoff)
{
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;
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;
unsigned long h_vm_pgoff;
unsigned long v_length;
unsigned long v_offset;
- h_vm_pgoff = vma->vm_pgoff << (HPAGE_SHIFT - PAGE_SHIFT);
- v_length = vma->vm_end - vma->vm_start;
+ h_vm_pgoff = vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT);
v_offset = (h_pgoff - h_vm_pgoff) << HPAGE_SHIFT;
v_offset = (h_pgoff - h_vm_pgoff) << HPAGE_SHIFT;
-
/*
* Is this VMA fully outside the truncation point?
*/
if (h_vm_pgoff >= h_pgoff)
v_offset = 0;
/*
* Is this VMA fully outside the truncation point?
*/
if (h_vm_pgoff >= h_pgoff)
v_offset = 0;
+ v_length = vma->vm_end - vma->vm_start;
+
zap_hugepage_range(vma,
vma->vm_start + v_offset,
v_length - v_offset);
zap_hugepage_range(vma,
vma->vm_start + v_offset,
v_length - v_offset);
@@
-329,9
+359,6
@@
static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr)
if (error)
goto out;
if (error)
goto out;
- error = security_inode_setattr(dentry, attr);
- if (error)
- goto out;
if (ia_valid & ATTR_SIZE) {
error = -EINVAL;
if (!(attr->ia_size & ~HPAGE_MASK))
if (ia_valid & ATTR_SIZE) {
error = -EINVAL;
if (!(attr->ia_size & ~HPAGE_MASK))
@@
-468,7
+495,7
@@
static int hugetlbfs_symlink(struct inode *dir,
/*
* For direct-IO reads into hugetlb pages
*/
/*
* For direct-IO reads into hugetlb pages
*/
-int hugetlbfs_set_page_dirty(struct page *page)
+
static
int hugetlbfs_set_page_dirty(struct page *page)
{
return 0;
}
{
return 0;
}
@@
-640,10
+667,12
@@
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;
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;
sb->s_op = &hugetlbfs_ops;
sb->s_blocksize = HPAGE_SIZE;
sb->s_blocksize_bits = HPAGE_SHIFT;
sb->s_magic = HUGETLBFS_MAGIC;
sb->s_op = &hugetlbfs_ops;
+ sb->s_time_gran = 1;
inode = hugetlbfs_get_inode(sb, config.uid, config.gid,
S_IFDIR | config.mode, 0);
if (!inode)
inode = hugetlbfs_get_inode(sb, config.uid, config.gid,
S_IFDIR | config.mode, 0);
if (!inode)
@@
-708,7
+737,7
@@
static struct vfsmount *hugetlbfs_vfsmount;
*/
static unsigned long hugetlbfs_counter(void)
{
*/
static unsigned long hugetlbfs_counter(void)
{
- static
spinlock_t lock = SPIN_LOCK_UNLOCKED
;
+ static
DEFINE_SPINLOCK(lock)
;
static unsigned long counter;
unsigned long ret;
static unsigned long counter;
unsigned long ret;
@@
-721,12
+750,13
@@
static unsigned long hugetlbfs_counter(void)
static int can_do_hugetlb_shm(void)
{
return likely(capable(CAP_IPC_LOCK) ||
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)
{
}
struct file *hugetlb_zero_setup(size_t size)
{
- int error;
+ int error
= -ENOMEM
;
struct file *file;
struct inode *inode;
struct dentry *dentry, *root;
struct file *file;
struct inode *inode;
struct dentry *dentry, *root;
@@
-739,6
+769,9
@@
struct file *hugetlb_zero_setup(size_t size)
if (!is_hugepage_mem_enough(size))
return ERR_PTR(-ENOMEM);
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;
root = hugetlbfs_vfsmount->mnt_root;
snprintf(buf, 16, "%lu", hugetlbfs_counter());
quick_string.name = buf;
@@
-746,7
+779,7
@@
struct file *hugetlb_zero_setup(size_t size)
quick_string.hash = 0;
dentry = d_alloc(root, &quick_string);
if (!dentry)
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();
error = -ENFILE;
file = get_empty_filp();
@@
-773,6
+806,8
@@
out_file:
put_filp(file);
out_dentry:
dput(dentry);
put_filp(file);
out_dentry:
dput(dentry);
+out_shm_unlock:
+ user_shm_unlock(size, current->user);
return ERR_PTR(error);
}
return ERR_PTR(error);
}
@@
-783,8
+818,7
@@
static int __init init_hugetlbfs_fs(void)
hugetlbfs_inode_cachep = kmem_cache_create("hugetlbfs_inode_cache",
sizeof(struct hugetlbfs_inode_info),
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;
if (hugetlbfs_inode_cachep == NULL)
return -ENOMEM;