gfs2: Clean up delete work processing
authorAndreas Gruenbacher <agruenba@redhat.com>
Thu, 12 Sep 2024 21:29:41 +0000 (23:29 +0200)
committerAndreas Gruenbacher <agruenba@redhat.com>
Tue, 5 Nov 2024 11:39:29 +0000 (12:39 +0100)
Function delete_work_func() was previously assuming that the
GLF_TRY_TO_EVICT and GLF_VERIFY_DELETE flags won't both be set at the
same time, but there probably are races in which that can happen, so
handle that case correctly.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
fs/gfs2/glock.c

index 9ec305b..95f082f 100644 (file)
@@ -1028,6 +1028,7 @@ static void delete_work_func(struct work_struct *work)
        struct delayed_work *dwork = to_delayed_work(work);
        struct gfs2_glock *gl = container_of(dwork, struct gfs2_glock, gl_delete);
        struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
+       bool verify_delete = test_and_clear_bit(GLF_VERIFY_DELETE, &gl->gl_flags);
 
        if (test_and_clear_bit(GLF_TRY_TO_EVICT, &gl->gl_flags)) {
                /*
@@ -1048,15 +1049,15 @@ static void delete_work_func(struct work_struct *work)
                 * step entirely.
                 */
                if (gfs2_try_evict(gl)) {
-                       if (test_bit(SDF_KILL, &sdp->sd_flags))
-                               goto out;
-                       if (gfs2_queue_verify_delete(gl, true))
-                               return;
+                       if (!test_bit(SDF_KILL, &sdp->sd_flags)) {
+                               gfs2_glock_hold(gl);
+                               if (!gfs2_queue_verify_delete(gl, true))
+                                       gfs2_glock_put(gl);
+                       }
                }
-               goto out;
        }
 
-       if (test_and_clear_bit(GLF_VERIFY_DELETE, &gl->gl_flags)) {
+       if (verify_delete) {
                u64 no_addr = gl->gl_name.ln_number;
                struct inode *inode;
 
@@ -1073,7 +1074,6 @@ static void delete_work_func(struct work_struct *work)
                }
        }
 
-out:
        gfs2_glock_put(gl);
 }