aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/dquot.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/fs/dquot.c b/fs/dquot.c
index cee7c6f428f0..def4e969df77 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -696,9 +696,8 @@ static int dqinit_needed(struct inode *inode, int type)
696/* This routine is guarded by dqonoff_mutex mutex */ 696/* This routine is guarded by dqonoff_mutex mutex */
697static void add_dquot_ref(struct super_block *sb, int type) 697static void add_dquot_ref(struct super_block *sb, int type)
698{ 698{
699 struct inode *inode; 699 struct inode *inode, *old_inode = NULL;
700 700
701restart:
702 spin_lock(&inode_lock); 701 spin_lock(&inode_lock);
703 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { 702 list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
704 if (!atomic_read(&inode->i_writecount)) 703 if (!atomic_read(&inode->i_writecount))
@@ -711,12 +710,18 @@ restart:
711 __iget(inode); 710 __iget(inode);
712 spin_unlock(&inode_lock); 711 spin_unlock(&inode_lock);
713 712
713 iput(old_inode);
714 sb->dq_op->initialize(inode, type); 714 sb->dq_op->initialize(inode, type);
715 iput(inode); 715 /* We hold a reference to 'inode' so it couldn't have been
716 /* As we may have blocked we had better restart... */ 716 * removed from s_inodes list while we dropped the inode_lock.
717 goto restart; 717 * We cannot iput the inode now as we can be holding the last
718 * reference and we cannot iput it under inode_lock. So we
719 * keep the reference and iput it later. */
720 old_inode = inode;
721 spin_lock(&inode_lock);
718 } 722 }
719 spin_unlock(&inode_lock); 723 spin_unlock(&inode_lock);
724 iput(old_inode);
720} 725}
721 726
722/* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */ 727/* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */