diff options
author | Jan Kara <jack@suse.cz> | 2008-08-19 08:51:22 -0400 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 11:36:55 -0500 |
commit | 74f783af95c982aef6d3a1415275650dcf511666 (patch) | |
tree | 594e978641d31e05e170a56ec68f8c65b37bb649 | |
parent | 9f868f16e40e9ad8e39aebff94a4be0d96520734 (diff) |
quota: Add callbacks for allocating and destroying dquot structures
Some filesystems would like to keep private information together with each
dquot. Add callbacks alloc_dquot and destroy_dquot allowing filesystem to
allocate larger dquots from their private slab in a similar fashion we
currently allocate inodes.
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
-rw-r--r-- | fs/dquot.c | 27 | ||||
-rw-r--r-- | include/linux/quota.h | 2 |
2 files changed, 24 insertions, 5 deletions
diff --git a/fs/dquot.c b/fs/dquot.c index c237ccc8581c..1b5fc4b7fbeb 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
@@ -415,6 +415,16 @@ out_dqlock: | |||
415 | return ret; | 415 | return ret; |
416 | } | 416 | } |
417 | 417 | ||
418 | static void dquot_destroy(struct dquot *dquot) | ||
419 | { | ||
420 | kmem_cache_free(dquot_cachep, dquot); | ||
421 | } | ||
422 | |||
423 | static inline void do_destroy_dquot(struct dquot *dquot) | ||
424 | { | ||
425 | dquot->dq_sb->dq_op->destroy_dquot(dquot); | ||
426 | } | ||
427 | |||
418 | /* Invalidate all dquots on the list. Note that this function is called after | 428 | /* Invalidate all dquots on the list. Note that this function is called after |
419 | * quota is disabled and pointers from inodes removed so there cannot be new | 429 | * quota is disabled and pointers from inodes removed so there cannot be new |
420 | * quota users. There can still be some users of quotas due to inodes being | 430 | * quota users. There can still be some users of quotas due to inodes being |
@@ -463,7 +473,7 @@ restart: | |||
463 | remove_dquot_hash(dquot); | 473 | remove_dquot_hash(dquot); |
464 | remove_free_dquot(dquot); | 474 | remove_free_dquot(dquot); |
465 | remove_inuse(dquot); | 475 | remove_inuse(dquot); |
466 | kmem_cache_free(dquot_cachep, dquot); | 476 | do_destroy_dquot(dquot); |
467 | } | 477 | } |
468 | spin_unlock(&dq_list_lock); | 478 | spin_unlock(&dq_list_lock); |
469 | } | 479 | } |
@@ -527,7 +537,7 @@ static void prune_dqcache(int count) | |||
527 | remove_dquot_hash(dquot); | 537 | remove_dquot_hash(dquot); |
528 | remove_free_dquot(dquot); | 538 | remove_free_dquot(dquot); |
529 | remove_inuse(dquot); | 539 | remove_inuse(dquot); |
530 | kmem_cache_free(dquot_cachep, dquot); | 540 | do_destroy_dquot(dquot); |
531 | count--; | 541 | count--; |
532 | head = free_dquots.prev; | 542 | head = free_dquots.prev; |
533 | } | 543 | } |
@@ -625,11 +635,16 @@ we_slept: | |||
625 | spin_unlock(&dq_list_lock); | 635 | spin_unlock(&dq_list_lock); |
626 | } | 636 | } |
627 | 637 | ||
638 | static struct dquot *dquot_alloc(struct super_block *sb, int type) | ||
639 | { | ||
640 | return kmem_cache_zalloc(dquot_cachep, GFP_NOFS); | ||
641 | } | ||
642 | |||
628 | static struct dquot *get_empty_dquot(struct super_block *sb, int type) | 643 | static struct dquot *get_empty_dquot(struct super_block *sb, int type) |
629 | { | 644 | { |
630 | struct dquot *dquot; | 645 | struct dquot *dquot; |
631 | 646 | ||
632 | dquot = kmem_cache_zalloc(dquot_cachep, GFP_NOFS); | 647 | dquot = sb->dq_op->alloc_dquot(sb, type); |
633 | if(!dquot) | 648 | if(!dquot) |
634 | return NODQUOT; | 649 | return NODQUOT; |
635 | 650 | ||
@@ -682,7 +697,7 @@ we_slept: | |||
682 | dqstats.lookups++; | 697 | dqstats.lookups++; |
683 | spin_unlock(&dq_list_lock); | 698 | spin_unlock(&dq_list_lock); |
684 | if (empty) | 699 | if (empty) |
685 | kmem_cache_free(dquot_cachep, empty); | 700 | do_destroy_dquot(empty); |
686 | } | 701 | } |
687 | /* Wait for dq_lock - after this we know that either dquot_release() is already | 702 | /* Wait for dq_lock - after this we know that either dquot_release() is already |
688 | * finished or it will be canceled due to dq_count > 1 test */ | 703 | * finished or it will be canceled due to dq_count > 1 test */ |
@@ -1533,7 +1548,9 @@ struct dquot_operations dquot_operations = { | |||
1533 | .acquire_dquot = dquot_acquire, | 1548 | .acquire_dquot = dquot_acquire, |
1534 | .release_dquot = dquot_release, | 1549 | .release_dquot = dquot_release, |
1535 | .mark_dirty = dquot_mark_dquot_dirty, | 1550 | .mark_dirty = dquot_mark_dquot_dirty, |
1536 | .write_info = dquot_commit_info | 1551 | .write_info = dquot_commit_info, |
1552 | .alloc_dquot = dquot_alloc, | ||
1553 | .destroy_dquot = dquot_destroy, | ||
1537 | }; | 1554 | }; |
1538 | 1555 | ||
1539 | static inline void set_enable_flags(struct quota_info *dqopt, int type) | 1556 | static inline void set_enable_flags(struct quota_info *dqopt, int type) |
diff --git a/include/linux/quota.h b/include/linux/quota.h index 40401b554484..3ce708c2cb3c 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h | |||
@@ -292,6 +292,8 @@ struct dquot_operations { | |||
292 | int (*free_inode) (const struct inode *, unsigned long); | 292 | int (*free_inode) (const struct inode *, unsigned long); |
293 | int (*transfer) (struct inode *, struct iattr *); | 293 | int (*transfer) (struct inode *, struct iattr *); |
294 | int (*write_dquot) (struct dquot *); /* Ordinary dquot write */ | 294 | int (*write_dquot) (struct dquot *); /* Ordinary dquot write */ |
295 | struct dquot *(*alloc_dquot)(struct super_block *, int); /* Allocate memory for new dquot */ | ||
296 | void (*destroy_dquot)(struct dquot *); /* Free memory for dquot */ | ||
295 | int (*acquire_dquot) (struct dquot *); /* Quota is going to be created on disk */ | 297 | int (*acquire_dquot) (struct dquot *); /* Quota is going to be created on disk */ |
296 | int (*release_dquot) (struct dquot *); /* Quota is going to be deleted from disk */ | 298 | int (*release_dquot) (struct dquot *); /* Quota is going to be deleted from disk */ |
297 | int (*mark_dirty) (struct dquot *); /* Dquot is marked dirty */ | 299 | int (*mark_dirty) (struct dquot *); /* Dquot is marked dirty */ |