Skip to content

Commit 865cc3e

Browse files
AstralBobAndreas Gruenbacher
authored andcommitted
gfs2: fix a deadlock on withdraw-during-mount
Before this patch, gfs2 would deadlock because of the following sequence during mount: mount gfs2_fill_super gfs2_make_fs_rw <--- Detects IO error with glock kthread_stop(sdp->sd_quotad_process); <--- Blocked waiting for quotad to finish logd Detects IO error and the need to withdraw calls gfs2_withdraw gfs2_make_fs_ro kthread_stop(sdp->sd_quotad_process); <--- Blocked waiting for quotad to finish gfs2_quotad gfs2_statfs_sync gfs2_glock_wait <---- Blocked waiting for statfs glock to be granted glock_work_func do_xmote <---Detects IO error, can't release glock: blocked on withdraw glops->go_inval glock_blocked_by_withdraw requeue glock work & exit <--- work requeued, blocked by withdraw This patch makes a special exception for the statfs system inode glock, which allows the statfs glock UNLOCK to proceed normally. That allows the quotad daemon to exit during the withdraw, which allows the logd daemon to exit during the withdraw, which allows the mount to exit. Signed-off-by: Bob Peterson <[email protected]> Signed-off-by: Andreas Gruenbacher <[email protected]>
1 parent 20265d9 commit 865cc3e

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

fs/gfs2/glock.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,16 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
582582
spin_unlock(&gl->gl_lockref.lock);
583583
}
584584

585+
static bool is_system_glock(struct gfs2_glock *gl)
586+
{
587+
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
588+
struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
589+
590+
if (gl == m_ip->i_gl)
591+
return true;
592+
return false;
593+
}
594+
585595
/**
586596
* do_xmote - Calls the DLM to change the state of a lock
587597
* @gl: The lock state
@@ -671,17 +681,25 @@ __acquires(&gl->gl_lockref.lock)
671681
* to see sd_log_error and withdraw, and in the meantime, requeue the
672682
* work for later.
673683
*
684+
* We make a special exception for some system glocks, such as the
685+
* system statfs inode glock, which needs to be granted before the
686+
* gfs2_quotad daemon can exit, and that exit needs to finish before
687+
* we can unmount the withdrawn file system.
688+
*
674689
* However, if we're just unlocking the lock (say, for unmount, when
675690
* gfs2_gl_hash_clear calls clear_glock) and recovery is complete
676691
* then it's okay to tell dlm to unlock it.
677692
*/
678693
if (unlikely(sdp->sd_log_error && !gfs2_withdrawn(sdp)))
679694
gfs2_withdraw_delayed(sdp);
680-
if (glock_blocked_by_withdraw(gl)) {
681-
if (target != LM_ST_UNLOCKED ||
682-
test_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags)) {
695+
if (glock_blocked_by_withdraw(gl) &&
696+
(target != LM_ST_UNLOCKED ||
697+
test_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags))) {
698+
if (!is_system_glock(gl)) {
683699
gfs2_glock_queue_work(gl, GL_GLOCK_DFT_HOLD);
684700
goto out;
701+
} else {
702+
clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags);
685703
}
686704
}
687705

0 commit comments

Comments
 (0)