X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=fs%2Fdquot.c;h=41b9dbd68b0e88e4a466685e1150e262e5d03c59;hb=d692abd92f22a81b38d52c39601871003262841c;hp=cee7c6f428f0fa518e80bda281eb92421a5ac295;hpb=c1f3ee120bb61045b1c0a3ead620d1d65af47130;p=karo-tx-linux.git diff --git a/fs/dquot.c b/fs/dquot.c index cee7c6f428f0..41b9dbd68b0e 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -696,9 +696,8 @@ static int dqinit_needed(struct inode *inode, int type) /* This routine is guarded by dqonoff_mutex mutex */ static void add_dquot_ref(struct super_block *sb, int type) { - struct inode *inode; + struct inode *inode, *old_inode = NULL; -restart: spin_lock(&inode_lock); list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { if (!atomic_read(&inode->i_writecount)) @@ -711,12 +710,18 @@ restart: __iget(inode); spin_unlock(&inode_lock); + iput(old_inode); sb->dq_op->initialize(inode, type); - iput(inode); - /* As we may have blocked we had better restart... */ - goto restart; + /* We hold a reference to 'inode' so it couldn't have been + * removed from s_inodes list while we dropped the inode_lock. + * We cannot iput the inode now as we can be holding the last + * reference and we cannot iput it under inode_lock. So we + * keep the reference and iput it later. */ + old_inode = inode; + spin_lock(&inode_lock); } spin_unlock(&inode_lock); + iput(old_inode); } /* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */ @@ -1517,8 +1522,8 @@ int vfs_quota_off(struct super_block *sb, int type) truncate_inode_pages(&toputinode[cnt]->i_data, 0); mutex_unlock(&toputinode[cnt]->i_mutex); mark_inode_dirty(toputinode[cnt]); - iput(toputinode[cnt]); } + iput(toputinode[cnt]); mutex_unlock(&dqopt->dqonoff_mutex); } if (sb->s_bdev) @@ -1628,16 +1633,17 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path) error = path_lookup(path, LOOKUP_FOLLOW, &nd); if (error < 0) return error; - error = security_quota_on(nd.dentry); + error = security_quota_on(nd.path.dentry); if (error) goto out_path; /* Quota file not on the same filesystem? */ - if (nd.mnt->mnt_sb != sb) + if (nd.path.mnt->mnt_sb != sb) error = -EXDEV; else - error = vfs_quota_on_inode(nd.dentry->d_inode, type, format_id); + error = vfs_quota_on_inode(nd.path.dentry->d_inode, type, + format_id); out_path: - path_release(&nd); + path_put(&nd.path); return error; }