gfs2: Clean up inode initialization and teardown

When allocating a new inode, mark the iopen glock holder as uninitialized to
make sure gfs2_evict_inode won't fail after an incomplete create or lookup.  In
gfs2_evict_inode, allow the inode glock to be NULL and remove the duplicate
iopen glock teardown code.  In gfs2_inode_lookup, don't tear down things that
gfs2_evict_inode will already tear down.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
This commit is contained in:
Andreas Gruenbacher 2020-01-24 14:14:46 +01:00 committed by Bob Peterson
parent 490031281d
commit 40e7e86ef1
2 changed files with 19 additions and 27 deletions

View File

@ -144,7 +144,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl); error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
if (unlikely(error)) if (unlikely(error))
goto fail_put; goto fail;
if (type == DT_UNKNOWN || blktype != GFS2_BLKST_FREE) { if (type == DT_UNKNOWN || blktype != GFS2_BLKST_FREE) {
/* /*
@ -155,13 +155,13 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE,
GL_SKIP, &i_gh); GL_SKIP, &i_gh);
if (error) if (error)
goto fail_put; goto fail;
if (blktype != GFS2_BLKST_FREE) { if (blktype != GFS2_BLKST_FREE) {
error = gfs2_check_blk_type(sdp, no_addr, error = gfs2_check_blk_type(sdp, no_addr,
blktype); blktype);
if (error) if (error)
goto fail_put; goto fail;
} }
} }
@ -169,7 +169,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
set_bit(GIF_INVALID, &ip->i_flags); set_bit(GIF_INVALID, &ip->i_flags);
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh); error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
if (unlikely(error)) if (unlikely(error))
goto fail_put; goto fail;
glock_set_object(ip->i_iopen_gh.gh_gl, ip); glock_set_object(ip->i_iopen_gh.gh_gl, ip);
gfs2_glock_put(io_gl); gfs2_glock_put(io_gl);
io_gl = NULL; io_gl = NULL;
@ -182,7 +182,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
/* Inode glock must be locked already */ /* Inode glock must be locked already */
error = gfs2_inode_refresh(GFS2_I(inode)); error = gfs2_inode_refresh(GFS2_I(inode));
if (error) if (error)
goto fail_refresh; goto fail;
} else { } else {
ip->i_no_formal_ino = no_formal_ino; ip->i_no_formal_ino = no_formal_ino;
inode->i_mode = DT2IF(type); inode->i_mode = DT2IF(type);
@ -197,17 +197,11 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
gfs2_glock_dq_uninit(&i_gh); gfs2_glock_dq_uninit(&i_gh);
return inode; return inode;
fail_refresh: fail:
ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
glock_clear_object(ip->i_iopen_gh.gh_gl, ip);
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
fail_put:
if (io_gl) if (io_gl)
gfs2_glock_put(io_gl); gfs2_glock_put(io_gl);
glock_clear_object(ip->i_gl, ip);
if (gfs2_holder_initialized(&i_gh)) if (gfs2_holder_initialized(&i_gh))
gfs2_glock_dq_uninit(&i_gh); gfs2_glock_dq_uninit(&i_gh);
fail:
iget_failed(inode); iget_failed(inode);
return ERR_PTR(error); return ERR_PTR(error);
} }

View File

@ -1393,14 +1393,6 @@ static void gfs2_evict_inode(struct inode *inode)
if (gfs2_rs_active(&ip->i_res)) if (gfs2_rs_active(&ip->i_res))
gfs2_rs_deltree(&ip->i_res); gfs2_rs_deltree(&ip->i_res);
if (gfs2_holder_initialized(&ip->i_iopen_gh)) {
glock_clear_object(ip->i_iopen_gh.gh_gl, ip);
if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) {
ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
gfs2_glock_dq(&ip->i_iopen_gh);
}
gfs2_holder_uninit(&ip->i_iopen_gh);
}
if (gfs2_holder_initialized(&gh)) { if (gfs2_holder_initialized(&gh)) {
glock_clear_object(ip->i_gl, ip); glock_clear_object(ip->i_gl, ip);
gfs2_glock_dq_uninit(&gh); gfs2_glock_dq_uninit(&gh);
@ -1413,18 +1405,23 @@ static void gfs2_evict_inode(struct inode *inode)
gfs2_ordered_del_inode(ip); gfs2_ordered_del_inode(ip);
clear_inode(inode); clear_inode(inode);
gfs2_dir_hash_inval(ip); gfs2_dir_hash_inval(ip);
glock_clear_object(ip->i_gl, ip); if (ip->i_gl) {
wait_on_bit_io(&ip->i_flags, GIF_GLOP_PENDING, TASK_UNINTERRUPTIBLE); glock_clear_object(ip->i_gl, ip);
gfs2_glock_add_to_lru(ip->i_gl); wait_on_bit_io(&ip->i_flags, GIF_GLOP_PENDING, TASK_UNINTERRUPTIBLE);
gfs2_glock_put_eventually(ip->i_gl); gfs2_glock_add_to_lru(ip->i_gl);
ip->i_gl = NULL; gfs2_glock_put_eventually(ip->i_gl);
ip->i_gl = NULL;
}
if (gfs2_holder_initialized(&ip->i_iopen_gh)) { if (gfs2_holder_initialized(&ip->i_iopen_gh)) {
struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl;
glock_clear_object(gl, ip); glock_clear_object(gl, ip);
ip->i_iopen_gh.gh_flags |= GL_NOCACHE; if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) {
ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
gfs2_glock_dq(&ip->i_iopen_gh);
}
gfs2_glock_hold(gl); gfs2_glock_hold(gl);
gfs2_glock_dq_uninit(&ip->i_iopen_gh); gfs2_holder_uninit(&ip->i_iopen_gh);
gfs2_glock_put_eventually(gl); gfs2_glock_put_eventually(gl);
} }
} }
@ -1438,6 +1435,7 @@ static struct inode *gfs2_alloc_inode(struct super_block *sb)
return NULL; return NULL;
ip->i_flags = 0; ip->i_flags = 0;
ip->i_gl = NULL; ip->i_gl = NULL;
gfs2_holder_mark_uninitialized(&ip->i_iopen_gh);
memset(&ip->i_res, 0, sizeof(ip->i_res)); memset(&ip->i_res, 0, sizeof(ip->i_res));
RB_CLEAR_NODE(&ip->i_res.rs_node); RB_CLEAR_NODE(&ip->i_res.rs_node);
ip->i_rahead = 0; ip->i_rahead = 0;