Commit 5f6e13ba authored by Andreas Gruenbacher's avatar Andreas Gruenbacher

gfs2: gfs2_inode_lookup rework

Rework gfs2_inode_lookup() to only set up the new inode's glocks after
verifying that the new inode is valid.

There is no need for flushing the inode glock work queue anymore now,
so remove that as well.

While at it, get rid of the useless wrapper around iget5_locked() and
its unnecessary is_bad_inode() check.
Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
parent b8e12e35
...@@ -40,37 +40,6 @@ static const struct inode_operations gfs2_file_iops; ...@@ -40,37 +40,6 @@ static const struct inode_operations gfs2_file_iops;
static const struct inode_operations gfs2_dir_iops; static const struct inode_operations gfs2_dir_iops;
static const struct inode_operations gfs2_symlink_iops; static const struct inode_operations gfs2_symlink_iops;
static int iget_test(struct inode *inode, void *opaque)
{
u64 no_addr = *(u64 *)opaque;
return GFS2_I(inode)->i_no_addr == no_addr;
}
static int iget_set(struct inode *inode, void *opaque)
{
u64 no_addr = *(u64 *)opaque;
GFS2_I(inode)->i_no_addr = no_addr;
inode->i_ino = no_addr;
return 0;
}
static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr)
{
struct inode *inode;
repeat:
inode = iget5_locked(sb, no_addr, iget_test, iget_set, &no_addr);
if (!inode)
return inode;
if (is_bad_inode(inode)) {
iput(inode);
goto repeat;
}
return inode;
}
/** /**
* gfs2_set_iop - Sets inode operations * gfs2_set_iop - Sets inode operations
* @inode: The inode with correct i_mode filled in * @inode: The inode with correct i_mode filled in
...@@ -104,6 +73,22 @@ static void gfs2_set_iop(struct inode *inode) ...@@ -104,6 +73,22 @@ static void gfs2_set_iop(struct inode *inode)
} }
} }
static int iget_test(struct inode *inode, void *opaque)
{
u64 no_addr = *(u64 *)opaque;
return GFS2_I(inode)->i_no_addr == no_addr;
}
static int iget_set(struct inode *inode, void *opaque)
{
u64 no_addr = *(u64 *)opaque;
GFS2_I(inode)->i_no_addr = no_addr;
inode->i_ino = no_addr;
return 0;
}
/** /**
* gfs2_inode_lookup - Lookup an inode * gfs2_inode_lookup - Lookup an inode
* @sb: The super block * @sb: The super block
...@@ -132,12 +117,11 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, ...@@ -132,12 +117,11 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
{ {
struct inode *inode; struct inode *inode;
struct gfs2_inode *ip; struct gfs2_inode *ip;
struct gfs2_glock *io_gl = NULL;
struct gfs2_holder i_gh; struct gfs2_holder i_gh;
int error; int error;
gfs2_holder_mark_uninitialized(&i_gh); gfs2_holder_mark_uninitialized(&i_gh);
inode = gfs2_iget(sb, no_addr); inode = iget5_locked(sb, no_addr, iget_test, iget_set, &no_addr);
if (!inode) if (!inode)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
...@@ -145,22 +129,16 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, ...@@ -145,22 +129,16 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
if (inode->i_state & I_NEW) { if (inode->i_state & I_NEW) {
struct gfs2_sbd *sdp = GFS2_SB(inode); 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)) if (unlikely(error))
goto fail; goto fail;
flush_delayed_work(&ip->i_gl->gl_work);
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);
if (type == DT_UNKNOWN || blktype != GFS2_BLKST_FREE) { if (type == DT_UNKNOWN || blktype != GFS2_BLKST_FREE) {
/* /*
* The GL_SKIP flag indicates to skip reading the inode * The GL_SKIP flag indicates to skip reading the inode
* block. We read the inode with gfs2_inode_refresh * block. We read the inode when instantiating it
* after possibly checking the block type. * after possibly checking the block type.
*/ */
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE,
...@@ -181,24 +159,31 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, ...@@ -181,24 +159,31 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
} }
} }
glock_set_object(ip->i_gl, ip);
set_bit(GLF_INSTANTIATE_NEEDED, &ip->i_gl->gl_flags); set_bit(GLF_INSTANTIATE_NEEDED, &ip->i_gl->gl_flags);
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
if (unlikely(error)) if (unlikely(error))
goto fail; goto fail;
glock_set_object(ip->i_iopen_gh.gh_gl, ip); 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); gfs2_glock_put(io_gl);
io_gl = NULL; if (unlikely(error))
goto fail;
/* Lowest possible timestamp; will be overwritten in gfs2_dinode_in. */ /* 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_sec = 1LL << (8 * sizeof(inode->i_atime.tv_sec) - 1);
inode->i_atime.tv_nsec = 0; inode->i_atime.tv_nsec = 0;
glock_set_object(ip->i_gl, ip);
if (type == DT_UNKNOWN) { if (type == DT_UNKNOWN) {
/* Inode glock must be locked already */ /* Inode glock must be locked already */
error = gfs2_instantiate(&i_gh); error = gfs2_instantiate(&i_gh);
if (error) if (error) {
glock_clear_object(ip->i_gl, ip);
goto fail; 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);
...@@ -206,6 +191,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, ...@@ -206,6 +191,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
if (gfs2_holder_initialized(&i_gh)) if (gfs2_holder_initialized(&i_gh))
gfs2_glock_dq_uninit(&i_gh); gfs2_glock_dq_uninit(&i_gh);
glock_set_object(ip->i_iopen_gh.gh_gl, ip);
gfs2_set_iop(inode); gfs2_set_iop(inode);
unlock_new_inode(inode); unlock_new_inode(inode);
...@@ -220,12 +206,8 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, ...@@ -220,12 +206,8 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
return inode; return inode;
fail: fail:
if (gfs2_holder_initialized(&ip->i_iopen_gh)) { if (gfs2_holder_initialized(&ip->i_iopen_gh))
glock_clear_object(ip->i_iopen_gh.gh_gl, ip);
gfs2_glock_dq_uninit(&ip->i_iopen_gh); gfs2_glock_dq_uninit(&ip->i_iopen_gh);
}
if (io_gl)
gfs2_glock_put(io_gl);
if (gfs2_holder_initialized(&i_gh)) if (gfs2_holder_initialized(&i_gh))
gfs2_glock_dq_uninit(&i_gh); gfs2_glock_dq_uninit(&i_gh);
iget_failed(inode); iget_failed(inode);
......
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