diff options
author | Christoph Hellwig <hch@lst.de> | 2005-10-29 21:16:42 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-30 00:40:43 -0400 |
commit | 96527980d4cb8f65fe49efdbc4ab92c0837d42f6 (patch) | |
tree | 93b6b438cee41d62e562ae277e67c9b6cad288a7 | |
parent | b8072f099b7829a6ff3eba618e1d079a81f753f8 (diff) |
[PATCH] hugetlbfs: move free_inodes accounting
Move hugetlbfs accounting into ->alloc_inode / ->destroy_inode. This keeps
the code simpler, fixes a loeak where a failing inode allocation wouldn't
decrement the counter and moves hugetlbfs_delete_inode and
hugetlbfs_forget_inode closer to their generic counterparts.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/hugetlbfs/inode.c | 78 |
1 files changed, 42 insertions, 36 deletions
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index a826a8add5e3..8e9d43633365 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -224,8 +224,6 @@ static void truncate_hugepages(struct address_space *mapping, loff_t lstart) | |||
224 | 224 | ||
225 | static void hugetlbfs_delete_inode(struct inode *inode) | 225 | static void hugetlbfs_delete_inode(struct inode *inode) |
226 | { | 226 | { |
227 | struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(inode->i_sb); | ||
228 | |||
229 | hlist_del_init(&inode->i_hash); | 227 | hlist_del_init(&inode->i_hash); |
230 | list_del_init(&inode->i_list); | 228 | list_del_init(&inode->i_list); |
231 | list_del_init(&inode->i_sb_list); | 229 | list_del_init(&inode->i_sb_list); |
@@ -238,12 +236,6 @@ static void hugetlbfs_delete_inode(struct inode *inode) | |||
238 | 236 | ||
239 | security_inode_delete(inode); | 237 | security_inode_delete(inode); |
240 | 238 | ||
241 | if (sbinfo->free_inodes >= 0) { | ||
242 | spin_lock(&sbinfo->stat_lock); | ||
243 | sbinfo->free_inodes++; | ||
244 | spin_unlock(&sbinfo->stat_lock); | ||
245 | } | ||
246 | |||
247 | clear_inode(inode); | 239 | clear_inode(inode); |
248 | destroy_inode(inode); | 240 | destroy_inode(inode); |
249 | } | 241 | } |
@@ -251,7 +243,6 @@ static void hugetlbfs_delete_inode(struct inode *inode) | |||
251 | static void hugetlbfs_forget_inode(struct inode *inode) | 243 | static void hugetlbfs_forget_inode(struct inode *inode) |
252 | { | 244 | { |
253 | struct super_block *super_block = inode->i_sb; | 245 | struct super_block *super_block = inode->i_sb; |
254 | struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(super_block); | ||
255 | 246 | ||
256 | if (hlist_unhashed(&inode->i_hash)) | 247 | if (hlist_unhashed(&inode->i_hash)) |
257 | goto out_truncate; | 248 | goto out_truncate; |
@@ -278,12 +269,6 @@ out_truncate: | |||
278 | if (inode->i_data.nrpages) | 269 | if (inode->i_data.nrpages) |
279 | truncate_hugepages(&inode->i_data, 0); | 270 | truncate_hugepages(&inode->i_data, 0); |
280 | 271 | ||
281 | if (sbinfo->free_inodes >= 0) { | ||
282 | spin_lock(&sbinfo->stat_lock); | ||
283 | sbinfo->free_inodes++; | ||
284 | spin_unlock(&sbinfo->stat_lock); | ||
285 | } | ||
286 | |||
287 | clear_inode(inode); | 272 | clear_inode(inode); |
288 | destroy_inode(inode); | 273 | destroy_inode(inode); |
289 | } | 274 | } |
@@ -375,17 +360,6 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid, | |||
375 | gid_t gid, int mode, dev_t dev) | 360 | gid_t gid, int mode, dev_t dev) |
376 | { | 361 | { |
377 | struct inode *inode; | 362 | struct inode *inode; |
378 | struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(sb); | ||
379 | |||
380 | if (sbinfo->free_inodes >= 0) { | ||
381 | spin_lock(&sbinfo->stat_lock); | ||
382 | if (!sbinfo->free_inodes) { | ||
383 | spin_unlock(&sbinfo->stat_lock); | ||
384 | return NULL; | ||
385 | } | ||
386 | sbinfo->free_inodes--; | ||
387 | spin_unlock(&sbinfo->stat_lock); | ||
388 | } | ||
389 | 363 | ||
390 | inode = new_inode(sb); | 364 | inode = new_inode(sb); |
391 | if (inode) { | 365 | if (inode) { |
@@ -527,29 +501,51 @@ static void hugetlbfs_put_super(struct super_block *sb) | |||
527 | } | 501 | } |
528 | } | 502 | } |
529 | 503 | ||
504 | static inline int hugetlbfs_dec_free_inodes(struct hugetlbfs_sb_info *sbinfo) | ||
505 | { | ||
506 | if (sbinfo->free_inodes >= 0) { | ||
507 | spin_lock(&sbinfo->stat_lock); | ||
508 | if (unlikely(!sbinfo->free_inodes)) { | ||
509 | spin_unlock(&sbinfo->stat_lock); | ||
510 | return 0; | ||
511 | } | ||
512 | sbinfo->free_inodes--; | ||
513 | spin_unlock(&sbinfo->stat_lock); | ||
514 | } | ||
515 | |||
516 | return 1; | ||
517 | } | ||
518 | |||
519 | static void hugetlbfs_inc_free_inodes(struct hugetlbfs_sb_info *sbinfo) | ||
520 | { | ||
521 | if (sbinfo->free_inodes >= 0) { | ||
522 | spin_lock(&sbinfo->stat_lock); | ||
523 | sbinfo->free_inodes++; | ||
524 | spin_unlock(&sbinfo->stat_lock); | ||
525 | } | ||
526 | } | ||
527 | |||
528 | |||
530 | static kmem_cache_t *hugetlbfs_inode_cachep; | 529 | static kmem_cache_t *hugetlbfs_inode_cachep; |
531 | 530 | ||
532 | static struct inode *hugetlbfs_alloc_inode(struct super_block *sb) | 531 | static struct inode *hugetlbfs_alloc_inode(struct super_block *sb) |
533 | { | 532 | { |
533 | struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(sb); | ||
534 | struct hugetlbfs_inode_info *p; | 534 | struct hugetlbfs_inode_info *p; |
535 | 535 | ||
536 | if (unlikely(!hugetlbfs_dec_free_inodes(sbinfo))) | ||
537 | return NULL; | ||
536 | p = kmem_cache_alloc(hugetlbfs_inode_cachep, SLAB_KERNEL); | 538 | p = kmem_cache_alloc(hugetlbfs_inode_cachep, SLAB_KERNEL); |
537 | if (!p) | 539 | if (unlikely(!p)) { |
540 | hugetlbfs_inc_free_inodes(sbinfo); | ||
538 | return NULL; | 541 | return NULL; |
542 | } | ||
539 | return &p->vfs_inode; | 543 | return &p->vfs_inode; |
540 | } | 544 | } |
541 | 545 | ||
542 | static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) | ||
543 | { | ||
544 | struct hugetlbfs_inode_info *ei = (struct hugetlbfs_inode_info *)foo; | ||
545 | |||
546 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == | ||
547 | SLAB_CTOR_CONSTRUCTOR) | ||
548 | inode_init_once(&ei->vfs_inode); | ||
549 | } | ||
550 | |||
551 | static void hugetlbfs_destroy_inode(struct inode *inode) | 546 | static void hugetlbfs_destroy_inode(struct inode *inode) |
552 | { | 547 | { |
548 | hugetlbfs_inc_free_inodes(HUGETLBFS_SB(inode->i_sb)); | ||
553 | mpol_free_shared_policy(&HUGETLBFS_I(inode)->policy); | 549 | mpol_free_shared_policy(&HUGETLBFS_I(inode)->policy); |
554 | kmem_cache_free(hugetlbfs_inode_cachep, HUGETLBFS_I(inode)); | 550 | kmem_cache_free(hugetlbfs_inode_cachep, HUGETLBFS_I(inode)); |
555 | } | 551 | } |
@@ -561,6 +557,16 @@ static struct address_space_operations hugetlbfs_aops = { | |||
561 | .set_page_dirty = hugetlbfs_set_page_dirty, | 557 | .set_page_dirty = hugetlbfs_set_page_dirty, |
562 | }; | 558 | }; |
563 | 559 | ||
560 | |||
561 | static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) | ||
562 | { | ||
563 | struct hugetlbfs_inode_info *ei = (struct hugetlbfs_inode_info *)foo; | ||
564 | |||
565 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == | ||
566 | SLAB_CTOR_CONSTRUCTOR) | ||
567 | inode_init_once(&ei->vfs_inode); | ||
568 | } | ||
569 | |||
564 | struct file_operations hugetlbfs_file_operations = { | 570 | struct file_operations hugetlbfs_file_operations = { |
565 | .mmap = hugetlbfs_file_mmap, | 571 | .mmap = hugetlbfs_file_mmap, |
566 | .fsync = simple_sync_file, | 572 | .fsync = simple_sync_file, |