gfs2: Fix another freeze/thaw hang
authorAndreas Gruenbacher <agruenba@redhat.com>
Mon, 11 Sep 2023 18:00:28 +0000 (20:00 +0200)
committerAndreas Gruenbacher <agruenba@redhat.com>
Mon, 18 Sep 2023 14:00:49 +0000 (16:00 +0200)
On a thawed filesystem, the freeze glock is held in shared mode.  In
order to initiate a cluster-wide freeze, the node initiating the freeze
drops the freeze glock and grabs it in exclusive mode.  The other nodes
recognize this as contention on the freeze glock; function
freeze_go_callback is invoked.  This indicates to them that they must
freeze the filesystem locally, drop the freeze glock, and then
re-acquire it in shared mode before being able to unfreeze the
filesystem locally.

While a node is trying to re-acquire the freeze glock in shared mode,
additional contention can occur.  In that case, the node must behave in
the same way as above.

Unfortunately, freeze_go_callback() contains a check that causes it to
bail out when the freeze glock isn't held in shared mode.  Fix that to
allow the glock to be unlocked or held in shared mode.

In addition, update a reference to trylock_super() which has been
renamed to super_trylock_shared() in the meantime.

Fixes: b77b4a4815a9 ("gfs2: Rework freeze / thaw logic")
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
fs/gfs2/glops.c

index d26759a..f41ca89 100644 (file)
@@ -567,15 +567,16 @@ static void freeze_go_callback(struct gfs2_glock *gl, bool remote)
        struct super_block *sb = sdp->sd_vfs;
 
        if (!remote ||
-           gl->gl_state != LM_ST_SHARED ||
+           (gl->gl_state != LM_ST_SHARED &&
+            gl->gl_state != LM_ST_UNLOCKED) ||
            gl->gl_demote_state != LM_ST_UNLOCKED)
                return;
 
        /*
         * Try to get an active super block reference to prevent racing with
-        * unmount (see trylock_super()).  But note that unmount isn't the only
-        * place where a write lock on s_umount is taken, and we can fail here
-        * because of things like remount as well.
+        * unmount (see super_trylock_shared()).  But note that unmount isn't
+        * the only place where a write lock on s_umount is taken, and we can
+        * fail here because of things like remount as well.
         */
        if (down_read_trylock(&sb->s_umount)) {
                atomic_inc(&sb->s_active);