diff options
Diffstat (limited to 'fs/dquot.c')
-rw-r--r-- | fs/dquot.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/fs/dquot.c b/fs/dquot.c index cee7c6f428f0..9c7feb62eed1 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 */ |
697 | static void add_dquot_ref(struct super_block *sb, int type) | 697 | static 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 | ||
701 | restart: | ||
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) */ |
@@ -1628,16 +1633,17 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path) | |||
1628 | error = path_lookup(path, LOOKUP_FOLLOW, &nd); | 1633 | error = path_lookup(path, LOOKUP_FOLLOW, &nd); |
1629 | if (error < 0) | 1634 | if (error < 0) |
1630 | return error; | 1635 | return error; |
1631 | error = security_quota_on(nd.dentry); | 1636 | error = security_quota_on(nd.path.dentry); |
1632 | if (error) | 1637 | if (error) |
1633 | goto out_path; | 1638 | goto out_path; |
1634 | /* Quota file not on the same filesystem? */ | 1639 | /* Quota file not on the same filesystem? */ |
1635 | if (nd.mnt->mnt_sb != sb) | 1640 | if (nd.path.mnt->mnt_sb != sb) |
1636 | error = -EXDEV; | 1641 | error = -EXDEV; |
1637 | else | 1642 | else |
1638 | error = vfs_quota_on_inode(nd.dentry->d_inode, type, format_id); | 1643 | error = vfs_quota_on_inode(nd.path.dentry->d_inode, type, |
1644 | format_id); | ||
1639 | out_path: | 1645 | out_path: |
1640 | path_release(&nd); | 1646 | path_put(&nd.path); |
1641 | return error; | 1647 | return error; |
1642 | } | 1648 | } |
1643 | 1649 | ||