GFS2: Check if iopen is held when deleting inode
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/1 GFS2: Check if iopen is held when deleting inode
Hi,
This patch fixes an error condition in which an inode is partially created in gfs2_create_inode() but then some error is discovered, which causes it to fail and call iput() before the iopen glock is created or held. In that case, gfs2_delete_inode would try to unlock an iopen glock that doesn't yet exist. Therefore, we test its holder (which must exist) for the HIF_HOLDER bit before trying to dq it.
fs/gfs2/super.c +9 -6
@@ -1551,12 +1551,15 @@ static void gfs2_evict_inode(struct inode *inode) goto out_truncate; } - ip->i_iopen_gh.gh_flags |=GL_NOCACHE ; -gfs2_glock_dq_wait (&ip->i_iopen_gh); -gfs2_holder_reinit (LM_ST_EXCLUSIVE ,LM_FLAG_TRY_1CB |GL_NOCACHE , &ip->i_iopen_gh); - error =gfs2_glock_nq (&ip->i_iopen_gh); -if (error) - goto out_truncate; +if (test_bit (HIF_HOLDER , &ip->i_iopen_gh.gh_iflags)) { + ip->i_iopen_gh.gh_flags |=GL_NOCACHE ; +gfs2_glock_dq_wait (&ip->i_iopen_gh); +gfs2_holder_reinit (LM_ST_EXCLUSIVE ,LM_FLAG_TRY_1CB |GL_NOCACHE , + &ip->i_iopen_gh); + error =gfs2_glock_nq (&ip->i_iopen_gh); +if (error) + goto out_truncate; + }/* Case 1 starts here */
PATCH v2 1/1 GFS2: Check if iopen is held when deleting inode
Hi,
On 18 December 2015, I posted this upstream GFS2 patch. Since that time, I discovered a bug that warrants expanding the scope of the patch. This is the revised patch.
Patch description:
GFS2: Check if iopen is held when deleting inode
This patch fixes an error condition in which an inode is partially created in gfs2_create_inode() but then some error is discovered, which causes it to fail and call iput() before the iopen glock is created or held. In that case, gfs2_delete_inode would try to unlock an iopen glock that doesn't yet exist. Therefore, we test its holder (which must exist) for the HIF_HOLDER bit before trying to dq it.
fs/gfs2/glock.c +1 -0
@@ -1015,6 +1015,7 @@ void gfs2_glock_dq(struct gfs2_holder *gh)handle_callback (gl,LM_ST_UNLOCKED ,0 , false);list_del_init (&gh->gh_list); +clear_bit (HIF_HOLDER , &gh->gh_iflags);if (find_first_holder (gl) ==NULL ) {if (glops->go_unlock) {GLOCK_BUG_ON (gl,test_and_set_bit (GLF_LOCK , &gl->gl_flags));
fs/gfs2/super.c +16 -10
@@ -1551,12 +1551,16 @@ static void gfs2_evict_inode(struct inode *inode) goto out_truncate; } - ip->i_iopen_gh.gh_flags |=GL_NOCACHE ; -gfs2_glock_dq_wait (&ip->i_iopen_gh); -gfs2_holder_reinit (LM_ST_EXCLUSIVE ,LM_FLAG_TRY_1CB |GL_NOCACHE , &ip->i_iopen_gh); - error =gfs2_glock_nq (&ip->i_iopen_gh); -if (error) - goto out_truncate; +if (ip->i_iopen_gh.gh_gl && +test_bit (HIF_HOLDER , &ip->i_iopen_gh.gh_iflags)) { + ip->i_iopen_gh.gh_flags |=GL_NOCACHE ; +gfs2_glock_dq_wait (&ip->i_iopen_gh); +gfs2_holder_reinit (LM_ST_EXCLUSIVE ,LM_FLAG_TRY_1CB |GL_NOCACHE , + &ip->i_iopen_gh); + error =gfs2_glock_nq (&ip->i_iopen_gh); +if (error) + goto out_truncate; + }/* Case 1 starts here */
@@ -1606,11 +1610,13 @@ out_unlock:if (gfs2_rs_active (&ip->i_res))gfs2_rs_deltree (&ip->i_res); -if (test_bit (HIF_HOLDER , &ip->i_iopen_gh.gh_iflags)) { - ip->i_iopen_gh.gh_flags |=GL_NOCACHE ; -gfs2_glock_dq_wait (&ip->i_iopen_gh); +if (ip->i_iopen_gh.gh_gl) { +if (test_bit (HIF_HOLDER , &ip->i_iopen_gh.gh_iflags)) { + ip->i_iopen_gh.gh_flags |=GL_NOCACHE ; +gfs2_glock_dq_wait (&ip->i_iopen_gh); + } +gfs2_holder_uninit (&ip->i_iopen_gh); } -gfs2_holder_uninit (&ip->i_iopen_gh);gfs2_glock_dq_uninit (&gh);if (error && error !=GLR_TRYFAILED && error != -EROFS )fs_warn (sdp,"gfs2_evict_inode: %d\n" , error);
PATCH v2 1/1 GFS2: Check if iopen is held when deleting inode
Hi,
Steve.
Quoted 78 lines · Bob Peterson
Hi,
On 18 December 2015, I posted this upstream GFS2 patch. Since that time, I discovered a bug that warrants expanding the scope of the patch. This is the revised patch.
Patch description:
GFS2: Check if iopen is held when deleting inode
This patch fixes an error condition in which an inode is partially created in
gfs2_create_inode()but then some error is discovered, which causes it to fail and calliput()before the iopen glock is created or held. In that case,gfs2_delete_inodewould try to unlock an iopen glock that doesn't yet exist. Therefore, we test its holder (which must exist) for theHIF_HOLDERbit before trying to dq it.Signed-off-by Bob Peterson <[email protected]>fs/gfs2/glock.c +1
-0@@ -1015,6 +1015,7 @@ void gfs2_glock_dq(struct gfs2_holder *gh)handle_callback (gl,LM_ST_UNLOCKED ,0 , false);list_del_init (&gh->gh_list); +clear_bit (HIF_HOLDER , &gh->gh_iflags);if (find_first_holder (gl) ==NULL ) {if (glops->go_unlock) {GLOCK_BUG_ON (gl,test_and_set_bit (GLF_LOCK , &gl->gl_flags));fs/gfs2/super.c +16
-10@@ -1551,12 +1551,16 @@ static void gfs2_evict_inode(struct inode *inode) goto out_truncate; } - ip->i_iopen_gh.gh_flags |=GL_NOCACHE ; -gfs2_glock_dq_wait (&ip->i_iopen_gh); -gfs2_holder_reinit (LM_ST_EXCLUSIVE ,LM_FLAG_TRY_1CB |GL_NOCACHE , &ip->i_iopen_gh); - error =gfs2_glock_nq (&ip->i_iopen_gh); -if (error) - goto out_truncate; +if (ip->i_iopen_gh.gh_gl && +test_bit (HIF_HOLDER , &ip->i_iopen_gh.gh_iflags)) { + ip->i_iopen_gh.gh_flags |=GL_NOCACHE ; +gfs2_glock_dq_wait (&ip->i_iopen_gh); +gfs2_holder_reinit (LM_ST_EXCLUSIVE ,LM_FLAG_TRY_1CB |GL_NOCACHE , + &ip->i_iopen_gh); + error =gfs2_glock_nq (&ip->i_iopen_gh); +if (error) + goto out_truncate; + }/* Case 1 starts here */ @@ -1606,11 +1610,13 @@ out_unlock:if (gfs2_rs_active (&ip->i_res))gfs2_rs_deltree (&ip->i_res); -if (test_bit (HIF_HOLDER , &ip->i_iopen_gh.gh_iflags)) { - ip->i_iopen_gh.gh_flags |=GL_NOCACHE ; -gfs2_glock_dq_wait (&ip->i_iopen_gh); +if (ip->i_iopen_gh.gh_gl) { +if (test_bit (HIF_HOLDER , &ip->i_iopen_gh.gh_iflags)) { + ip->i_iopen_gh.gh_flags |=GL_NOCACHE ; +gfs2_glock_dq_wait (&ip->i_iopen_gh); + } +gfs2_holder_uninit (&ip->i_iopen_gh); } -gfs2_holder_uninit (&ip->i_iopen_gh);gfs2_glock_dq_uninit (&gh);if (error && error !=GLR_TRYFAILED && error != -EROFS )fs_warn (sdp,"gfs2_evict_inode: %d\n" , error);
PATCH 1/1 GFS2: Check if iopen is held when deleting inode
In reply to Bob PetersonHi,
Steve.
Quoted 39 lines · Bob Peterson
Hi,
This patch fixes an error condition in which an inode is partially created in
gfs2_create_inode()but then some error is discovered, which causes it to fail and calliput()before the iopen glock is created or held. In that case,gfs2_delete_inodewould try to unlock an iopen glock that doesn't yet exist. Therefore, we test its holder (which must exist) for theHIF_HOLDERbit before trying to dq it.Signed-off-by Bob Peterson <[email protected]>fs/gfs2/super.c +9
-6@@ -1551,12 +1551,15 @@ static void gfs2_evict_inode(struct inode *inode) goto out_truncate; } - ip->i_iopen_gh.gh_flags |=GL_NOCACHE ; -gfs2_glock_dq_wait (&ip->i_iopen_gh); -gfs2_holder_reinit (LM_ST_EXCLUSIVE ,LM_FLAG_TRY_1CB |GL_NOCACHE , &ip->i_iopen_gh); - error =gfs2_glock_nq (&ip->i_iopen_gh); -if (error) - goto out_truncate; +if (test_bit (HIF_HOLDER , &ip->i_iopen_gh.gh_iflags)) { + ip->i_iopen_gh.gh_flags |=GL_NOCACHE ; +gfs2_glock_dq_wait (&ip->i_iopen_gh); +gfs2_holder_reinit (LM_ST_EXCLUSIVE ,LM_FLAG_TRY_1CB |GL_NOCACHE , + &ip->i_iopen_gh); + error =gfs2_glock_nq (&ip->i_iopen_gh); +if (error) + goto out_truncate; + }/* Case 1 starts here */