aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dquot.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dquot.c')
-rw-r--r--fs/dquot.c59
1 files changed, 39 insertions, 20 deletions
diff --git a/fs/dquot.c b/fs/dquot.c
index 0952cc474d9a..9eb166f91489 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -79,6 +79,7 @@
79#include <linux/buffer_head.h> 79#include <linux/buffer_head.h>
80#include <linux/capability.h> 80#include <linux/capability.h>
81#include <linux/quotaops.h> 81#include <linux/quotaops.h>
82#include <linux/writeback.h> /* for inode_lock, oddly enough.. */
82 83
83#include <asm/uaccess.h> 84#include <asm/uaccess.h>
84 85
@@ -600,11 +601,10 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type)
600{ 601{
601 struct dquot *dquot; 602 struct dquot *dquot;
602 603
603 dquot = kmem_cache_alloc(dquot_cachep, GFP_NOFS); 604 dquot = kmem_cache_zalloc(dquot_cachep, GFP_NOFS);
604 if(!dquot) 605 if(!dquot)
605 return NODQUOT; 606 return NODQUOT;
606 607
607 memset((caddr_t)dquot, 0, sizeof(struct dquot));
608 mutex_init(&dquot->dq_lock); 608 mutex_init(&dquot->dq_lock);
609 INIT_LIST_HEAD(&dquot->dq_free); 609 INIT_LIST_HEAD(&dquot->dq_free);
610 INIT_LIST_HEAD(&dquot->dq_inuse); 610 INIT_LIST_HEAD(&dquot->dq_inuse);
@@ -688,23 +688,27 @@ static int dqinit_needed(struct inode *inode, int type)
688/* This routine is guarded by dqonoff_mutex mutex */ 688/* This routine is guarded by dqonoff_mutex mutex */
689static void add_dquot_ref(struct super_block *sb, int type) 689static void add_dquot_ref(struct super_block *sb, int type)
690{ 690{
691 struct list_head *p; 691 struct inode *inode;
692 692
693restart: 693restart:
694 file_list_lock(); 694 spin_lock(&inode_lock);
695 list_for_each(p, &sb->s_files) { 695 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
696 struct file *filp = list_entry(p, struct file, f_u.fu_list); 696 if (!atomic_read(&inode->i_writecount))
697 struct inode *inode = filp->f_path.dentry->d_inode; 697 continue;
698 if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) { 698 if (!dqinit_needed(inode, type))
699 struct dentry *dentry = dget(filp->f_path.dentry); 699 continue;
700 file_list_unlock(); 700 if (inode->i_state & (I_FREEING|I_WILL_FREE))
701 sb->dq_op->initialize(inode, type); 701 continue;
702 dput(dentry); 702
703 /* As we may have blocked we had better restart... */ 703 __iget(inode);
704 goto restart; 704 spin_unlock(&inode_lock);
705 } 705
706 sb->dq_op->initialize(inode, type);
707 iput(inode);
708 /* As we may have blocked we had better restart... */
709 goto restart;
706 } 710 }
707 file_list_unlock(); 711 spin_unlock(&inode_lock);
708} 712}
709 713
710/* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */ 714/* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */
@@ -756,15 +760,30 @@ static void put_dquot_list(struct list_head *tofree_head)
756 } 760 }
757} 761}
758 762
763static void remove_dquot_ref(struct super_block *sb, int type,
764 struct list_head *tofree_head)
765{
766 struct inode *inode;
767
768 spin_lock(&inode_lock);
769 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
770 if (!IS_NOQUOTA(inode))
771 remove_inode_dquot_ref(inode, type, tofree_head);
772 }
773 spin_unlock(&inode_lock);
774}
775
759/* Gather all references from inodes and drop them */ 776/* Gather all references from inodes and drop them */
760static void drop_dquot_ref(struct super_block *sb, int type) 777static void drop_dquot_ref(struct super_block *sb, int type)
761{ 778{
762 LIST_HEAD(tofree_head); 779 LIST_HEAD(tofree_head);
763 780
764 down_write(&sb_dqopt(sb)->dqptr_sem); 781 if (sb->dq_op) {
765 remove_dquot_ref(sb, type, &tofree_head); 782 down_write(&sb_dqopt(sb)->dqptr_sem);
766 up_write(&sb_dqopt(sb)->dqptr_sem); 783 remove_dquot_ref(sb, type, &tofree_head);
767 put_dquot_list(&tofree_head); 784 up_write(&sb_dqopt(sb)->dqptr_sem);
785 put_dquot_list(&tofree_head);
786 }
768} 787}
769 788
770static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number) 789static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)