summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKen Chen2007-11-15 01:59:44 +0100
committerLinus Torvalds2007-11-15 03:45:40 +0100
commit45c682a68a87251d9a01383ce076ab21ee09812e (patch)
treed9fa6a02263c50ef97e1c525b91b29b6aedf9e40
parentmm/hugetlb.c: make a function static (diff)
downloadkernel-qcow2-linux-45c682a68a87251d9a01383ce076ab21ee09812e.tar.gz
kernel-qcow2-linux-45c682a68a87251d9a01383ce076ab21ee09812e.tar.xz
kernel-qcow2-linux-45c682a68a87251d9a01383ce076ab21ee09812e.zip
hugetlb: fix i_blocks accounting
For administrative purpose, we want to query actual block usage for hugetlbfs file via fstat. Currently, hugetlbfs always return 0. Fix that up since kernel already has all the information to track it properly. Signed-off-by: Ken Chen <kenchen@google.com> Acked-by: Adam Litke <agl@us.ibm.com> Cc: Badari Pulavarty <pbadari@us.ibm.com> Cc: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/hugetlb.h2
-rw-r--r--mm/hugetlb.c10
2 files changed, 12 insertions, 0 deletions
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 8104e5af75ab..24968790bc3e 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -168,6 +168,8 @@ struct file *hugetlb_file_setup(const char *name, size_t);
int hugetlb_get_quota(struct address_space *mapping, long delta);
void hugetlb_put_quota(struct address_space *mapping, long delta);
+#define BLOCKS_PER_HUGEPAGE (HPAGE_SIZE / 512)
+
static inline int is_file_hugepages(struct file *file)
{
if (file->f_op == &hugetlbfs_file_operations)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index abe1e9f2a942..6121b57bbe96 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -801,6 +801,7 @@ retry:
if (vma->vm_flags & VM_SHARED) {
int err;
+ struct inode *inode = mapping->host;
err = add_to_page_cache(page, mapping, idx, GFP_KERNEL);
if (err) {
@@ -809,6 +810,10 @@ retry:
goto retry;
goto out;
}
+
+ spin_lock(&inode->i_lock);
+ inode->i_blocks += BLOCKS_PER_HUGEPAGE;
+ spin_unlock(&inode->i_lock);
} else
lock_page(page);
}
@@ -1160,6 +1165,11 @@ int hugetlb_reserve_pages(struct inode *inode, long from, long to)
void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed)
{
long chg = region_truncate(&inode->i_mapping->private_list, offset);
+
+ spin_lock(&inode->i_lock);
+ inode->i_blocks -= BLOCKS_PER_HUGEPAGE * freed;
+ spin_unlock(&inode->i_lock);
+
hugetlb_put_quota(inode->i_mapping, (chg - freed));
hugetlb_acct_memory(-(chg - freed));
}