gfs2: use i_lock spin_lock for inode qadata
Before this patch, functions gfs2_qa_get and _put used the i_rw_mutex to prevent simultaneous access to its i_qadata. But i_rw_mutex is now used for many other things, including iomap_begin and end, which causes a conflict according to lockdep. We cannot just remove the lock since simultaneous opens (gfs2_open -> gfs2_open_common -> gfs2_qa_get) can then stomp on each others values for i_qadata. This patch solves the conflict by using the i_lock spin_lock in the inode to prevent simultaneous access. Signed-off-by: Bob Peterson <rpeterso@redhat.com> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
This commit is contained in:
parent
f4a47561fc
commit
5fcff61eea
@ -528,34 +528,42 @@ static void qdsb_put(struct gfs2_quota_data *qd)
|
|||||||
*/
|
*/
|
||||||
int gfs2_qa_get(struct gfs2_inode *ip)
|
int gfs2_qa_get(struct gfs2_inode *ip)
|
||||||
{
|
{
|
||||||
int error = 0;
|
|
||||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||||
|
struct inode *inode = &ip->i_inode;
|
||||||
|
|
||||||
if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
|
if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
down_write(&ip->i_rw_mutex);
|
spin_lock(&inode->i_lock);
|
||||||
if (ip->i_qadata == NULL) {
|
if (ip->i_qadata == NULL) {
|
||||||
ip->i_qadata = kmem_cache_zalloc(gfs2_qadata_cachep, GFP_NOFS);
|
struct gfs2_qadata *tmp;
|
||||||
if (!ip->i_qadata) {
|
|
||||||
error = -ENOMEM;
|
spin_unlock(&inode->i_lock);
|
||||||
goto out;
|
tmp = kmem_cache_zalloc(gfs2_qadata_cachep, GFP_NOFS);
|
||||||
}
|
if (!tmp)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
spin_lock(&inode->i_lock);
|
||||||
|
if (ip->i_qadata == NULL)
|
||||||
|
ip->i_qadata = tmp;
|
||||||
|
else
|
||||||
|
kmem_cache_free(gfs2_qadata_cachep, tmp);
|
||||||
}
|
}
|
||||||
ip->i_qadata->qa_ref++;
|
ip->i_qadata->qa_ref++;
|
||||||
out:
|
spin_unlock(&inode->i_lock);
|
||||||
up_write(&ip->i_rw_mutex);
|
return 0;
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gfs2_qa_put(struct gfs2_inode *ip)
|
void gfs2_qa_put(struct gfs2_inode *ip)
|
||||||
{
|
{
|
||||||
down_write(&ip->i_rw_mutex);
|
struct inode *inode = &ip->i_inode;
|
||||||
|
|
||||||
|
spin_lock(&inode->i_lock);
|
||||||
if (ip->i_qadata && --ip->i_qadata->qa_ref == 0) {
|
if (ip->i_qadata && --ip->i_qadata->qa_ref == 0) {
|
||||||
kmem_cache_free(gfs2_qadata_cachep, ip->i_qadata);
|
kmem_cache_free(gfs2_qadata_cachep, ip->i_qadata);
|
||||||
ip->i_qadata = NULL;
|
ip->i_qadata = NULL;
|
||||||
}
|
}
|
||||||
up_write(&ip->i_rw_mutex);
|
spin_unlock(&inode->i_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
|
int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user