mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 13:41:51 +00:00
gfs2: Switch lock order of inode and iopen glock
This patch tries to fix the continual ABBA deadlocks we keep having between the iopen and inode glocks. This switches the lock order in gfs2_inode_lookup and gfs2_create_inode so the iopen glock is always locked first. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Signed-off-by: Bob Peterson <rpeterso@redhat.com>
This commit is contained in:
parent
1fc05c8d84
commit
29464ee36b
@ -131,7 +131,21 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
struct gfs2_glock *io_gl;
|
||||
|
||||
error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
|
||||
error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE,
|
||||
&ip->i_gl);
|
||||
if (unlikely(error))
|
||||
goto fail;
|
||||
|
||||
error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE,
|
||||
&io_gl);
|
||||
if (unlikely(error))
|
||||
goto fail;
|
||||
|
||||
if (blktype != GFS2_BLKST_UNLINKED)
|
||||
gfs2_cancel_delete_work(io_gl);
|
||||
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT,
|
||||
&ip->i_iopen_gh);
|
||||
gfs2_glock_put(io_gl);
|
||||
if (unlikely(error))
|
||||
goto fail;
|
||||
|
||||
@ -161,16 +175,6 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
|
||||
|
||||
set_bit(GLF_INSTANTIATE_NEEDED, &ip->i_gl->gl_flags);
|
||||
|
||||
error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
|
||||
if (unlikely(error))
|
||||
goto fail;
|
||||
if (blktype != GFS2_BLKST_UNLINKED)
|
||||
gfs2_cancel_delete_work(io_gl);
|
||||
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
|
||||
gfs2_glock_put(io_gl);
|
||||
if (unlikely(error))
|
||||
goto fail;
|
||||
|
||||
/* Lowest possible timestamp; will be overwritten in gfs2_dinode_in. */
|
||||
inode->i_atime.tv_sec = 1LL << (8 * sizeof(inode->i_atime.tv_sec) - 1);
|
||||
inode->i_atime.tv_nsec = 0;
|
||||
@ -716,13 +720,17 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
||||
error = insert_inode_locked4(inode, ip->i_no_addr, iget_test, &ip->i_no_addr);
|
||||
BUG_ON(error);
|
||||
|
||||
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1);
|
||||
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
|
||||
if (error)
|
||||
goto fail_gunlock2;
|
||||
|
||||
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1);
|
||||
if (error)
|
||||
goto fail_gunlock3;
|
||||
|
||||
error = gfs2_trans_begin(sdp, blocks, 0);
|
||||
if (error)
|
||||
goto fail_gunlock2;
|
||||
goto fail_gunlock3;
|
||||
|
||||
if (blocks > 1) {
|
||||
ip->i_eattr = ip->i_no_addr + 1;
|
||||
@ -731,10 +739,6 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
||||
init_dinode(dip, ip, symname);
|
||||
gfs2_trans_end(sdp);
|
||||
|
||||
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
|
||||
if (error)
|
||||
goto fail_gunlock2;
|
||||
|
||||
glock_set_object(ip->i_gl, ip);
|
||||
glock_set_object(io_gl, ip);
|
||||
gfs2_set_iop(inode);
|
||||
@ -745,14 +749,14 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
||||
if (default_acl) {
|
||||
error = __gfs2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
|
||||
if (error)
|
||||
goto fail_gunlock3;
|
||||
goto fail_gunlock4;
|
||||
posix_acl_release(default_acl);
|
||||
default_acl = NULL;
|
||||
}
|
||||
if (acl) {
|
||||
error = __gfs2_set_acl(inode, acl, ACL_TYPE_ACCESS);
|
||||
if (error)
|
||||
goto fail_gunlock3;
|
||||
goto fail_gunlock4;
|
||||
posix_acl_release(acl);
|
||||
acl = NULL;
|
||||
}
|
||||
@ -760,11 +764,11 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
||||
error = security_inode_init_security(&ip->i_inode, &dip->i_inode, name,
|
||||
&gfs2_initxattrs, NULL);
|
||||
if (error)
|
||||
goto fail_gunlock3;
|
||||
goto fail_gunlock4;
|
||||
|
||||
error = link_dinode(dip, name, ip, &da);
|
||||
if (error)
|
||||
goto fail_gunlock3;
|
||||
goto fail_gunlock4;
|
||||
|
||||
mark_inode_dirty(inode);
|
||||
d_instantiate(dentry, inode);
|
||||
@ -782,9 +786,10 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
||||
unlock_new_inode(inode);
|
||||
return error;
|
||||
|
||||
fail_gunlock3:
|
||||
fail_gunlock4:
|
||||
glock_clear_object(ip->i_gl, ip);
|
||||
glock_clear_object(io_gl, ip);
|
||||
fail_gunlock3:
|
||||
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
|
||||
fail_gunlock2:
|
||||
gfs2_glock_put(io_gl);
|
||||
|
Loading…
Reference in New Issue
Block a user