Skip to content

Commit 9947a06

Browse files
author
Andreas Gruenbacher
committed
gfs2: do_xmote fixes
Function do_xmote() is called with the glock spinlock held. Commit 8693419 added a 'goto skip_inval' statement at the beginning of the function to further below where the glock spinlock is expected not to be held anymore. Then it added code there that requires the glock spinlock to be held. This doesn't make sense; fix this up by dropping and retaking the spinlock where needed. In addition, when ->lm_lock() returned an error, do_xmote() didn't fail the locking operation, and simply left the glock hanging; fix that as well. (This is a much older error.) Fixes: 8693419 ("gfs2: Clear flags when withdraw prevents xmote") Signed-off-by: Andreas Gruenbacher <[email protected]>
1 parent 1cd28e1 commit 9947a06

File tree

1 file changed

+25
-19
lines changed

1 file changed

+25
-19
lines changed

fs/gfs2/glock.c

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@ __acquires(&gl->gl_lockref.lock)
721721
{
722722
const struct gfs2_glock_operations *glops = gl->gl_ops;
723723
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
724+
struct lm_lockstruct *ls = &sdp->sd_lockstruct;
724725
unsigned int lck_flags = (unsigned int)(gh ? gh->gh_flags : 0);
725726
int ret;
726727

@@ -749,6 +750,9 @@ __acquires(&gl->gl_lockref.lock)
749750
(gl->gl_state == LM_ST_EXCLUSIVE) ||
750751
(lck_flags & (LM_FLAG_TRY|LM_FLAG_TRY_1CB)))
751752
clear_bit(GLF_BLOCKING, &gl->gl_flags);
753+
if (!glops->go_inval && !glops->go_sync)
754+
goto skip_inval;
755+
752756
spin_unlock(&gl->gl_lockref.lock);
753757
if (glops->go_sync) {
754758
ret = glops->go_sync(gl);
@@ -761,6 +765,7 @@ __acquires(&gl->gl_lockref.lock)
761765
fs_err(sdp, "Error %d syncing glock \n", ret);
762766
gfs2_dump_glock(NULL, gl, true);
763767
}
768+
spin_lock(&gl->gl_lockref.lock);
764769
goto skip_inval;
765770
}
766771
}
@@ -781,9 +786,10 @@ __acquires(&gl->gl_lockref.lock)
781786
glops->go_inval(gl, target == LM_ST_DEFERRED ? 0 : DIO_METADATA);
782787
clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags);
783788
}
789+
spin_lock(&gl->gl_lockref.lock);
784790

785791
skip_inval:
786-
gfs2_glock_hold(gl);
792+
gl->gl_lockref.count++;
787793
/*
788794
* Check for an error encountered since we called go_sync and go_inval.
789795
* If so, we can't withdraw from the glock code because the withdraw
@@ -825,37 +831,37 @@ __acquires(&gl->gl_lockref.lock)
825831
*/
826832
clear_bit(GLF_LOCK, &gl->gl_flags);
827833
clear_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags);
828-
gfs2_glock_queue_work(gl, GL_GLOCK_DFT_HOLD);
829-
goto out;
834+
__gfs2_glock_queue_work(gl, GL_GLOCK_DFT_HOLD);
835+
return;
830836
} else {
831837
clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags);
832838
}
833839
}
834840

835-
if (sdp->sd_lockstruct.ls_ops->lm_lock) {
836-
struct lm_lockstruct *ls = &sdp->sd_lockstruct;
841+
if (ls->ls_ops->lm_lock) {
842+
spin_unlock(&gl->gl_lockref.lock);
843+
ret = ls->ls_ops->lm_lock(gl, target, lck_flags);
844+
spin_lock(&gl->gl_lockref.lock);
837845

838-
/* lock_dlm */
839-
ret = sdp->sd_lockstruct.ls_ops->lm_lock(gl, target, lck_flags);
840846
if (ret == -EINVAL && gl->gl_target == LM_ST_UNLOCKED &&
841847
target == LM_ST_UNLOCKED &&
842848
test_bit(DFL_UNMOUNT, &ls->ls_recover_flags)) {
843-
spin_lock(&gl->gl_lockref.lock);
844-
finish_xmote(gl, target);
845-
__gfs2_glock_queue_work(gl, 0);
846-
spin_unlock(&gl->gl_lockref.lock);
849+
/*
850+
* The lockspace has been released and the lock has
851+
* been unlocked implicitly.
852+
*/
847853
} else if (ret) {
848854
fs_err(sdp, "lm_lock ret %d\n", ret);
849-
GLOCK_BUG_ON(gl, !gfs2_withdrawing_or_withdrawn(sdp));
855+
target = gl->gl_state | LM_OUT_ERROR;
856+
} else {
857+
/* The operation will be completed asynchronously. */
858+
return;
850859
}
851-
} else { /* lock_nolock */
852-
spin_lock(&gl->gl_lockref.lock);
853-
finish_xmote(gl, target);
854-
__gfs2_glock_queue_work(gl, 0);
855-
spin_unlock(&gl->gl_lockref.lock);
856860
}
857-
out:
858-
spin_lock(&gl->gl_lockref.lock);
861+
862+
/* Complete the operation now. */
863+
finish_xmote(gl, target);
864+
__gfs2_glock_queue_work(gl, 0);
859865
}
860866

861867
/**

0 commit comments

Comments
 (0)