Commit 5fcff61e authored by Bob Peterson's avatar Bob Peterson Committed by Andreas Gruenbacher

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: default avatarBob Peterson <rpeterso@redhat.com>
Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
parent f4a47561
...@@ -528,34 +528,42 @@ static void qdsb_put(struct gfs2_quota_data *qd) ...@@ -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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment