}
 
        gfs2_glock_hold(gl);
+       /*
+        * Check for an error encountered since we called go_sync and go_inval.
+        * If so, we can't withdraw from the glock code because the withdraw
+        * code itself uses glocks (see function signal_our_withdraw) to
+        * change the mount to read-only. Most importantly, we must not call
+        * dlm to unlock the glock until the journal is in a known good state
+        * (after journal replay) otherwise other nodes may use the object
+        * (rgrp or dinode) and then later, journal replay will corrupt the
+        * file system. The best we can do here is wait for the logd daemon
+        * to see sd_log_error and withdraw, and in the meantime, requeue the
+        * work for later.
+        *
+        * However, if we're just unlocking the lock (say, for unmount, when
+        * gfs2_gl_hash_clear calls clear_glock) and recovery is complete
+        * then it's okay to tell dlm to unlock it.
+        */
+       if (unlikely(sdp->sd_log_error && !gfs2_withdrawn(sdp)))
+               gfs2_withdraw_delayed(sdp);
+       if (glock_blocked_by_withdraw(gl)) {
+               if (target != LM_ST_UNLOCKED ||
+                   test_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags)) {
+                       gfs2_glock_queue_work(gl, GL_GLOCK_DFT_HOLD);
+                       goto out;
+               }
+       }
+
        if (sdp->sd_lockstruct.ls_ops->lm_lock) {
                /* lock_dlm */
                ret = sdp->sd_lockstruct.ls_ops->lm_lock(gl, target, lck_flags);
                    test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags)) {
                        finish_xmote(gl, target);
                        gfs2_glock_queue_work(gl, 0);
-               }
-               else if (ret) {
+               } else if (ret) {
                        fs_err(sdp, "lm_lock ret %d\n", ret);
                        GLOCK_BUG_ON(gl, !gfs2_withdrawn(sdp));
                }
                finish_xmote(gl, target);
                gfs2_glock_queue_work(gl, 0);
        }
-
+out:
        spin_lock(&gl->gl_lockref.lock);
 }