If gfs2 withdraws the file system due to errors, such as being unable
to write to the journals, we withdraw. When we withdraw, we try to
change the file system to read-only by calling gfs2_make_fs_ro so
that the appropriate items are synced and flushed. However, if the
withdraw occurs while we're mounting the file system, i.e., trying to
make the file system rw (from gfs2_make_fs_rw) we're already holding
the freeze glock, we'd have a recursive glock error.

This patch introduces checks for withdraw in gfs2_make_fs_rw and also
checks for already holding the freeze glock in gfs2_make_fs_ro.

Signed-off-by: Bob Peterson <rpete...@redhat.com>
---
 fs/gfs2/super.c | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 1253fcf35910..d3f6e9a61c13 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -426,9 +426,13 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp)
                goto fail_threads;
 
        j_gl->gl_ops->go_inval(j_gl, DIO_METADATA);
+       if (gfs2_withdrawn(sdp)) {
+               error = -EIO;
+               goto fail;
+       }
 
        error = gfs2_find_jhead(sdp->sd_jdesc, &head, false);
-       if (error)
+       if (error || gfs2_withdrawn(sdp))
                goto fail;
 
        if (!(head.lh_flags & GFS2_LOG_HEAD_UNMOUNT)) {
@@ -442,7 +446,7 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp)
        gfs2_log_pointers_init(sdp, head.lh_blkno);
 
        error = gfs2_quota_init(sdp);
-       if (error)
+       if (error || gfs2_withdrawn(sdp))
                goto fail;
 
        set_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
@@ -854,19 +858,20 @@ int gfs2_make_fs_ro(struct gfs2_sbd *sdp, int withdrawing)
 {
        struct gfs2_holder freeze_gh;
        int flags = GL_NOCACHE;
-       int error;
+       int error = 0;
 
        if (withdrawing)
                flags |= LM_FLAG_TRY;
        gfs2_holder_mark_uninitialized(&freeze_gh);
-       error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, flags,
-                                  &freeze_gh);
-       if (error == GLR_TRYFAILED)
-               error = 0;
-
-       if (error && !gfs2_withdrawn(sdp))
-               return error;
-
+       if (!withdrawing || !gfs2_glock_is_locked_by_me(sdp->sd_freeze_gl)) {
+               error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED,
+                                          flags, &freeze_gh);
+               if (error == GLR_TRYFAILED)
+                       error = 0;
+
+               if (error && !gfs2_withdrawn(sdp))
+                       return error;
+       }
        flush_workqueue(gfs2_delete_workqueue);
 
        if (current == sdp->sd_quotad_process)
-- 
2.20.1

Reply via email to