aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/inode.c
diff options
context:
space:
mode:
authorBob Peterson <rpeterso@redhat.com>2017-07-18 13:15:01 -0400
committerBob Peterson <rpeterso@redhat.com>2017-07-21 09:20:42 -0400
commit4d7c18c7df89ef549f2de79b0faf873b49dea57a (patch)
treed1ae15098ea5fa6eeaaa03ec0e3a8c1d44c20455 /fs/gfs2/inode.c
parentdf3d87bde121213560fde0edb71bc46f0f75692c (diff)
GFS2: Set gl_object in inode lookup only after block type check
Before this patch, the inode glock's gl_object was set after a reference was acquired, but before the block type was verified. In cases where the block was unlinked, then freed and reused on another node, a residule delete callback (delete_work) would try to look up the inode, eventually failing the block check, but only after it overwrites gl_object with a pointer to the wrong inode. This patch moves the assignment of gl_object after the block check so it won't be improperly overwritten. Likewise, at the end of the function, gfs2_inode_lookup was clearing gl_object after it unlocked the glock, which meant another process might free the glock in the meantime. This patch guards against that case. Signed-off-by: Bob Peterson <rpeterso@redhat.com> Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com>
Diffstat (limited to 'fs/gfs2/inode.c')
-rw-r--r--fs/gfs2/inode.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 2578bd824e34..fd6e1da3c5ab 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -145,7 +145,6 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
145 if (unlikely(error)) 145 if (unlikely(error))
146 goto fail; 146 goto fail;
147 flush_delayed_work(&ip->i_gl->gl_work); 147 flush_delayed_work(&ip->i_gl->gl_work);
148 glock_set_object(ip->i_gl, ip);
149 148
150 error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl); 149 error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
151 if (unlikely(error)) 150 if (unlikely(error))
@@ -170,6 +169,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
170 } 169 }
171 } 170 }
172 171
172 glock_set_object(ip->i_gl, ip);
173 set_bit(GIF_INVALID, &ip->i_flags); 173 set_bit(GIF_INVALID, &ip->i_flags);
174 error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh); 174 error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
175 if (unlikely(error)) 175 if (unlikely(error))
@@ -206,9 +206,9 @@ fail_refresh:
206fail_put: 206fail_put:
207 if (io_gl) 207 if (io_gl)
208 gfs2_glock_put(io_gl); 208 gfs2_glock_put(io_gl);
209 glock_clear_object(ip->i_gl, ip);
209 if (gfs2_holder_initialized(&i_gh)) 210 if (gfs2_holder_initialized(&i_gh))
210 gfs2_glock_dq_uninit(&i_gh); 211 gfs2_glock_dq_uninit(&i_gh);
211 glock_clear_object(ip->i_gl, ip);
212fail: 212fail:
213 iget_failed(inode); 213 iget_failed(inode);
214 return ERR_PTR(error); 214 return ERR_PTR(error);