Skip to content

Commit

Permalink
[PATCH] tightening hugetlb strict accounting
Browse files Browse the repository at this point in the history
Current hugetlb strict accounting for shared mapping always assume mapping
starts at zero file offset and reserves pages between zero and size of the
file.  This assumption often reserves (or lock down) a lot more pages then
necessary if application maps at none zero file offset.  libhugetlbfs is
one example that requires proper reservation on shared mapping starts at
none zero offset.

This patch extends the reservation and hugetlb strict accounting to support
any arbitrary pair of (offset, len), resulting a much more robust and
accurate scheme.  More importantly, it won't lock down any hugetlb pages
outside file mapping.

Signed-off-by: Ken Chen <kenneth.w.chen@intel.com>
Acked-by: Adam Litke <agl@us.ibm.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Cc: William Lee Irwin III <wli@holomorphy.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Chen, Kenneth W authored and Linus Torvalds committed Jun 23, 2006
1 parent e8f03d0 commit a43a8c3
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 138 deletions.
21 changes: 9 additions & 12 deletions fs/hugetlbfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ static void huge_pagevec_release(struct pagevec *pvec)
static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
{
struct inode *inode = file->f_dentry->d_inode;
struct hugetlbfs_inode_info *info = HUGETLBFS_I(inode);
loff_t len, vma_len;
int ret;

Expand Down Expand Up @@ -87,9 +86,10 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
if (!(vma->vm_flags & VM_WRITE) && len > inode->i_size)
goto out;

if (vma->vm_flags & VM_MAYSHARE)
if (hugetlb_extend_reservation(info, len >> HPAGE_SHIFT) != 0)
goto out;
if (vma->vm_flags & VM_MAYSHARE &&
hugetlb_reserve_pages(inode, vma->vm_pgoff >> (HPAGE_SHIFT-PAGE_SHIFT),
len >> HPAGE_SHIFT))
goto out;

ret = 0;
hugetlb_prefault_arch_hook(vma->vm_mm);
Expand Down Expand Up @@ -195,12 +195,8 @@ static void truncate_hugepages(struct inode *inode, loff_t lstart)
const pgoff_t start = lstart >> HPAGE_SHIFT;
struct pagevec pvec;
pgoff_t next;
int i;
int i, freed = 0;

hugetlb_truncate_reservation(HUGETLBFS_I(inode),
lstart >> HPAGE_SHIFT);
if (!mapping->nrpages)
return;
pagevec_init(&pvec, 0);
next = start;
while (1) {
Expand All @@ -221,10 +217,12 @@ static void truncate_hugepages(struct inode *inode, loff_t lstart)
truncate_huge_page(page);
unlock_page(page);
hugetlb_put_quota(mapping);
freed++;
}
huge_pagevec_release(&pvec);
}
BUG_ON(!lstart && mapping->nrpages);
hugetlb_unreserve_pages(inode, start, freed);
}

static void hugetlbfs_delete_inode(struct inode *inode)
Expand Down Expand Up @@ -366,6 +364,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid,
inode->i_mapping->a_ops = &hugetlbfs_aops;
inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
INIT_LIST_HEAD(&inode->i_mapping->private_list);
info = HUGETLBFS_I(inode);
mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, NULL);
switch (mode & S_IFMT) {
Expand Down Expand Up @@ -538,7 +537,6 @@ static struct inode *hugetlbfs_alloc_inode(struct super_block *sb)
hugetlbfs_inc_free_inodes(sbinfo);
return NULL;
}
p->prereserved_hpages = 0;
return &p->vfs_inode;
}

Expand Down Expand Up @@ -781,8 +779,7 @@ struct file *hugetlb_zero_setup(size_t size)
goto out_file;

error = -ENOMEM;
if (hugetlb_extend_reservation(HUGETLBFS_I(inode),
size >> HPAGE_SHIFT) != 0)
if (hugetlb_reserve_pages(inode, 0, size >> HPAGE_SHIFT))
goto out_inode;

d_instantiate(dentry, inode);
Expand Down
8 changes: 2 additions & 6 deletions include/linux/hugetlb.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ int hugetlb_report_node_meminfo(int, char *);
unsigned long hugetlb_total_pages(void);
int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
unsigned long address, int write_access);
int hugetlb_reserve_pages(struct inode *inode, long from, long to);
void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed);

extern unsigned long max_huge_pages;
extern const unsigned long hugetlb_zero, hugetlb_infinity;
Expand Down Expand Up @@ -139,8 +141,6 @@ struct hugetlbfs_sb_info {

struct hugetlbfs_inode_info {
struct shared_policy policy;
/* Protected by the (global) hugetlb_lock */
unsigned long prereserved_hpages;
struct inode vfs_inode;
};

Expand All @@ -157,10 +157,6 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb)
extern const struct file_operations hugetlbfs_file_operations;
extern struct vm_operations_struct hugetlb_vm_ops;
struct file *hugetlb_zero_setup(size_t);
int hugetlb_extend_reservation(struct hugetlbfs_inode_info *info,
unsigned long atleast_hpages);
void hugetlb_truncate_reservation(struct hugetlbfs_inode_info *info,
unsigned long atmost_hpages);
int hugetlb_get_quota(struct address_space *mapping);
void hugetlb_put_quota(struct address_space *mapping);

Expand Down
Loading

0 comments on commit a43a8c3

Please sign in to comment.