aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hugetlbfs/inode.c
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2008-07-24 00:27:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-24 13:47:17 -0400
commita5516438959d90b071ff0a484ce4f3f523dc3152 (patch)
treee356ba9364c76b93c176b4d4a262b7aca3ee8f91 /fs/hugetlbfs/inode.c
parentb7ba30c679ed1eb7ed3ed8f281f6493282042bd4 (diff)
hugetlb: modular state for hugetlb page size
The goal of this patchset is to support multiple hugetlb page sizes. This is achieved by introducing a new struct hstate structure, which encapsulates the important hugetlb state and constants (eg. huge page size, number of huge pages currently allocated, etc). The hstate structure is then passed around the code which requires these fields, they will do the right thing regardless of the exact hstate they are operating on. This patch adds the hstate structure, with a single global instance of it (default_hstate), and does the basic work of converting hugetlb to use the hstate. Future patches will add more hstate structures to allow for different hugetlbfs mounts to have different page sizes. [akpm@linux-foundation.org: coding-style fixes] Acked-by: Adam Litke <agl@us.ibm.com> Acked-by: Nishanth Aravamudan <nacc@us.ibm.com> Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Nick Piggin <npiggin@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/hugetlbfs/inode.c')
-rw-r--r--fs/hugetlbfs/inode.c52
1 files changed, 30 insertions, 22 deletions
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 428eff5b73f3..516c581b5371 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -80,6 +80,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
80 struct inode *inode = file->f_path.dentry->d_inode; 80 struct inode *inode = file->f_path.dentry->d_inode;
81 loff_t len, vma_len; 81 loff_t len, vma_len;
82 int ret; 82 int ret;
83 struct hstate *h = hstate_file(file);
83 84
84 /* 85 /*
85 * vma address alignment (but not the pgoff alignment) has 86 * vma address alignment (but not the pgoff alignment) has
@@ -92,7 +93,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
92 vma->vm_flags |= VM_HUGETLB | VM_RESERVED; 93 vma->vm_flags |= VM_HUGETLB | VM_RESERVED;
93 vma->vm_ops = &hugetlb_vm_ops; 94 vma->vm_ops = &hugetlb_vm_ops;
94 95
95 if (vma->vm_pgoff & ~(HPAGE_MASK >> PAGE_SHIFT)) 96 if (vma->vm_pgoff & ~(huge_page_mask(h) >> PAGE_SHIFT))
96 return -EINVAL; 97 return -EINVAL;
97 98
98 vma_len = (loff_t)(vma->vm_end - vma->vm_start); 99 vma_len = (loff_t)(vma->vm_end - vma->vm_start);
@@ -104,8 +105,8 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
104 len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); 105 len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
105 106
106 if (hugetlb_reserve_pages(inode, 107 if (hugetlb_reserve_pages(inode,
107 vma->vm_pgoff >> (HPAGE_SHIFT-PAGE_SHIFT), 108 vma->vm_pgoff >> huge_page_order(h),
108 len >> HPAGE_SHIFT, vma)) 109 len >> huge_page_shift(h), vma))
109 goto out; 110 goto out;
110 111
111 ret = 0; 112 ret = 0;
@@ -130,20 +131,21 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
130 struct mm_struct *mm = current->mm; 131 struct mm_struct *mm = current->mm;
131 struct vm_area_struct *vma; 132 struct vm_area_struct *vma;
132 unsigned long start_addr; 133 unsigned long start_addr;
134 struct hstate *h = hstate_file(file);
133 135
134 if (len & ~HPAGE_MASK) 136 if (len & ~huge_page_mask(h))
135 return -EINVAL; 137 return -EINVAL;
136 if (len > TASK_SIZE) 138 if (len > TASK_SIZE)
137 return -ENOMEM; 139 return -ENOMEM;
138 140
139 if (flags & MAP_FIXED) { 141 if (flags & MAP_FIXED) {
140 if (prepare_hugepage_range(addr, len)) 142 if (prepare_hugepage_range(file, addr, len))
141 return -EINVAL; 143 return -EINVAL;
142 return addr; 144 return addr;
143 } 145 }
144 146
145 if (addr) { 147 if (addr) {
146 addr = ALIGN(addr, HPAGE_SIZE); 148 addr = ALIGN(addr, huge_page_size(h));
147 vma = find_vma(mm, addr); 149 vma = find_vma(mm, addr);
148 if (TASK_SIZE - len >= addr && 150 if (TASK_SIZE - len >= addr &&
149 (!vma || addr + len <= vma->vm_start)) 151 (!vma || addr + len <= vma->vm_start))
@@ -156,7 +158,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
156 start_addr = TASK_UNMAPPED_BASE; 158 start_addr = TASK_UNMAPPED_BASE;
157 159
158full_search: 160full_search:
159 addr = ALIGN(start_addr, HPAGE_SIZE); 161 addr = ALIGN(start_addr, huge_page_size(h));
160 162
161 for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { 163 for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
162 /* At this point: (!vma || addr < vma->vm_end). */ 164 /* At this point: (!vma || addr < vma->vm_end). */
@@ -174,7 +176,7 @@ full_search:
174 176
175 if (!vma || addr + len <= vma->vm_start) 177 if (!vma || addr + len <= vma->vm_start)
176 return addr; 178 return addr;
177 addr = ALIGN(vma->vm_end, HPAGE_SIZE); 179 addr = ALIGN(vma->vm_end, huge_page_size(h));
178 } 180 }
179} 181}
180#endif 182#endif
@@ -225,10 +227,11 @@ hugetlbfs_read_actor(struct page *page, unsigned long offset,
225static ssize_t hugetlbfs_read(struct file *filp, char __user *buf, 227static ssize_t hugetlbfs_read(struct file *filp, char __user *buf,
226 size_t len, loff_t *ppos) 228 size_t len, loff_t *ppos)
227{ 229{
230 struct hstate *h = hstate_file(filp);
228 struct address_space *mapping = filp->f_mapping; 231 struct address_space *mapping = filp->f_mapping;
229 struct inode *inode = mapping->host; 232 struct inode *inode = mapping->host;
230 unsigned long index = *ppos >> HPAGE_SHIFT; 233 unsigned long index = *ppos >> huge_page_shift(h);
231 unsigned long offset = *ppos & ~HPAGE_MASK; 234 unsigned long offset = *ppos & ~huge_page_mask(h);
232 unsigned long end_index; 235 unsigned long end_index;
233 loff_t isize; 236 loff_t isize;
234 ssize_t retval = 0; 237 ssize_t retval = 0;
@@ -243,17 +246,17 @@ static ssize_t hugetlbfs_read(struct file *filp, char __user *buf,
243 if (!isize) 246 if (!isize)
244 goto out; 247 goto out;
245 248
246 end_index = (isize - 1) >> HPAGE_SHIFT; 249 end_index = (isize - 1) >> huge_page_shift(h);
247 for (;;) { 250 for (;;) {
248 struct page *page; 251 struct page *page;
249 int nr, ret; 252 unsigned long nr, ret;
250 253
251 /* nr is the maximum number of bytes to copy from this page */ 254 /* nr is the maximum number of bytes to copy from this page */
252 nr = HPAGE_SIZE; 255 nr = huge_page_size(h);
253 if (index >= end_index) { 256 if (index >= end_index) {
254 if (index > end_index) 257 if (index > end_index)
255 goto out; 258 goto out;
256 nr = ((isize - 1) & ~HPAGE_MASK) + 1; 259 nr = ((isize - 1) & ~huge_page_mask(h)) + 1;
257 if (nr <= offset) { 260 if (nr <= offset) {
258 goto out; 261 goto out;
259 } 262 }
@@ -287,8 +290,8 @@ static ssize_t hugetlbfs_read(struct file *filp, char __user *buf,
287 offset += ret; 290 offset += ret;
288 retval += ret; 291 retval += ret;
289 len -= ret; 292 len -= ret;
290 index += offset >> HPAGE_SHIFT; 293 index += offset >> huge_page_shift(h);
291 offset &= ~HPAGE_MASK; 294 offset &= ~huge_page_mask(h);
292 295
293 if (page) 296 if (page)
294 page_cache_release(page); 297 page_cache_release(page);
@@ -298,7 +301,7 @@ static ssize_t hugetlbfs_read(struct file *filp, char __user *buf,
298 break; 301 break;
299 } 302 }
300out: 303out:
301 *ppos = ((loff_t)index << HPAGE_SHIFT) + offset; 304 *ppos = ((loff_t)index << huge_page_shift(h)) + offset;
302 mutex_unlock(&inode->i_mutex); 305 mutex_unlock(&inode->i_mutex);
303 return retval; 306 return retval;
304} 307}
@@ -339,8 +342,9 @@ static void truncate_huge_page(struct page *page)
339 342
340static void truncate_hugepages(struct inode *inode, loff_t lstart) 343static void truncate_hugepages(struct inode *inode, loff_t lstart)
341{ 344{
345 struct hstate *h = hstate_inode(inode);
342 struct address_space *mapping = &inode->i_data; 346 struct address_space *mapping = &inode->i_data;
343 const pgoff_t start = lstart >> HPAGE_SHIFT; 347 const pgoff_t start = lstart >> huge_page_shift(h);
344 struct pagevec pvec; 348 struct pagevec pvec;
345 pgoff_t next; 349 pgoff_t next;
346 int i, freed = 0; 350 int i, freed = 0;
@@ -449,8 +453,9 @@ static int hugetlb_vmtruncate(struct inode *inode, loff_t offset)
449{ 453{
450 pgoff_t pgoff; 454 pgoff_t pgoff;
451 struct address_space *mapping = inode->i_mapping; 455 struct address_space *mapping = inode->i_mapping;
456 struct hstate *h = hstate_inode(inode);
452 457
453 BUG_ON(offset & ~HPAGE_MASK); 458 BUG_ON(offset & ~huge_page_mask(h));
454 pgoff = offset >> PAGE_SHIFT; 459 pgoff = offset >> PAGE_SHIFT;
455 460
456 i_size_write(inode, offset); 461 i_size_write(inode, offset);
@@ -465,6 +470,7 @@ static int hugetlb_vmtruncate(struct inode *inode, loff_t offset)
465static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr) 470static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr)
466{ 471{
467 struct inode *inode = dentry->d_inode; 472 struct inode *inode = dentry->d_inode;
473 struct hstate *h = hstate_inode(inode);
468 int error; 474 int error;
469 unsigned int ia_valid = attr->ia_valid; 475 unsigned int ia_valid = attr->ia_valid;
470 476
@@ -476,7 +482,7 @@ static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr)
476 482
477 if (ia_valid & ATTR_SIZE) { 483 if (ia_valid & ATTR_SIZE) {
478 error = -EINVAL; 484 error = -EINVAL;
479 if (!(attr->ia_size & ~HPAGE_MASK)) 485 if (!(attr->ia_size & ~huge_page_mask(h)))
480 error = hugetlb_vmtruncate(inode, attr->ia_size); 486 error = hugetlb_vmtruncate(inode, attr->ia_size);
481 if (error) 487 if (error)
482 goto out; 488 goto out;
@@ -610,9 +616,10 @@ static int hugetlbfs_set_page_dirty(struct page *page)
610static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf) 616static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf)
611{ 617{
612 struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb); 618 struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb);
619 struct hstate *h = hstate_inode(dentry->d_inode);
613 620
614 buf->f_type = HUGETLBFS_MAGIC; 621 buf->f_type = HUGETLBFS_MAGIC;
615 buf->f_bsize = HPAGE_SIZE; 622 buf->f_bsize = huge_page_size(h);
616 if (sbinfo) { 623 if (sbinfo) {
617 spin_lock(&sbinfo->stat_lock); 624 spin_lock(&sbinfo->stat_lock);
618 /* If no limits set, just report 0 for max/free/used 625 /* If no limits set, just report 0 for max/free/used
@@ -942,7 +949,8 @@ struct file *hugetlb_file_setup(const char *name, size_t size)
942 goto out_dentry; 949 goto out_dentry;
943 950
944 error = -ENOMEM; 951 error = -ENOMEM;
945 if (hugetlb_reserve_pages(inode, 0, size >> HPAGE_SHIFT, NULL)) 952 if (hugetlb_reserve_pages(inode, 0,
953 size >> huge_page_shift(hstate_inode(inode)), NULL))
946 goto out_inode; 954 goto out_inode;
947 955
948 d_instantiate(dentry, inode); 956 d_instantiate(dentry, inode);