diff options
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/lock_dlm.c | 20 | ||||
-rw-r--r-- | fs/gfs2/recovery.c | 7 | ||||
-rw-r--r-- | fs/gfs2/sys.c | 11 |
3 files changed, 30 insertions, 8 deletions
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c index 006c6164f759..ac7caa267ed6 100644 --- a/fs/gfs2/lock_dlm.c +++ b/fs/gfs2/lock_dlm.c @@ -821,6 +821,13 @@ restart: goto fail; } + /** + * If we're a spectator, we don't want to take the lock in EX because + * we cannot do the first-mount responsibility it implies: recovery. + */ + if (sdp->sd_args.ar_spectator) + goto locks_done; + error = mounted_lock(sdp, DLM_LOCK_EX, DLM_LKF_CONVERT|DLM_LKF_NOQUEUE); if (!error) { mounted_mode = DLM_LOCK_EX; @@ -896,9 +903,16 @@ locks_done: if (lvb_gen < mount_gen) { /* wait for mounted nodes to update control_lock lvb to our generation, which might include new recovery bits set */ - fs_info(sdp, "control_mount wait1 block %u start %u mount %u " - "lvb %u flags %lx\n", block_gen, start_gen, mount_gen, - lvb_gen, ls->ls_recover_flags); + if (sdp->sd_args.ar_spectator) { + fs_info(sdp, "Recovery is required. Waiting for a " + "non-spectator to mount.\n"); + msleep_interruptible(1000); + } else { + fs_info(sdp, "control_mount wait1 block %u start %u " + "mount %u lvb %u flags %lx\n", block_gen, + start_gen, mount_gen, lvb_gen, + ls->ls_recover_flags); + } spin_unlock(&ls->ls_recover_spin); goto restart; } diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index d8b622c375ab..0f501f938d1c 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c @@ -413,12 +413,13 @@ void gfs2_recover_func(struct work_struct *work) ktime_t t_start, t_jlck, t_jhd, t_tlck, t_rep; int ro = 0; unsigned int pass; - int error; + int error = 0; int jlocked = 0; t_start = ktime_get(); - if (sdp->sd_args.ar_spectator || - (jd->jd_jid != sdp->sd_lockstruct.ls_jid)) { + if (sdp->sd_args.ar_spectator) + goto fail; + if (jd->jd_jid != sdp->sd_lockstruct.ls_jid) { fs_info(sdp, "jid=%u: Trying to acquire journal lock...\n", jd->jd_jid); jlocked = 1; diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index c191fa58a1df..1787d295834e 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c @@ -429,11 +429,18 @@ int gfs2_recover_set(struct gfs2_sbd *sdp, unsigned jid) spin_lock(&sdp->sd_jindex_spin); rv = -EBUSY; - if (sdp->sd_jdesc->jd_jid == jid) + /** + * If we're a spectator, we use journal0, but it's not really ours. + * So we need to wait for its recovery too. If we skip it we'd never + * queue work to the recovery workqueue, and so its completion would + * never clear the DFL_BLOCK_LOCKS flag, so all our locks would + * permanently stop working. + */ + if (sdp->sd_jdesc->jd_jid == jid && !sdp->sd_args.ar_spectator) goto out; rv = -ENOENT; list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) { - if (jd->jd_jid != jid) + if (jd->jd_jid != jid && !sdp->sd_args.ar_spectator) continue; rv = gfs2_recover_journal(jd, false); break; |