summaryrefslogtreecommitdiff
path: root/fs/gfs2/glock.c
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruenba@redhat.com>2024-09-12 23:29:41 +0200
committerAndreas Gruenbacher <agruenba@redhat.com>2024-11-05 12:39:29 +0100
commit0baa10b60cddb587a1a252a8db76b0cea439d1be (patch)
treea5a608b5687d798a8a15f3f65386c95efcea5cbc /fs/gfs2/glock.c
parentb4100457d02d90149129ba2230130954a03fdf0b (diff)
gfs2: Clean up delete work processing
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>
Diffstat (limited to 'fs/gfs2/glock.c')
-rw-r--r--fs/gfs2/glock.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 9ec305b8d4d4..95f082f13a8c 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -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);
}