From 864174f976474bfa7b787ec654733febe3b03f84 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Tue, 7 May 2024 13:48:59 +0200 Subject: [PATCH] gfs2: Don't cache unreferenced glocks Currently, gfs2 caches unreferenced glocks until memory pressure sets in or the filesystem is unmounted. This was supposedly done to avoid excessive log flushing: when a glock still has outstanding revokes, freeing it requires an extra log flush, and we want to avoid too many of those extra log flushes. Since commit 9287c6452d2b1 ("gfs2: Fix occasional glock use-after-free"), outstanding revokes are accounted for in the glock reference count and glocks with outstanding revokes will never be freed anymore, so this is no longer an issue. This also means that we won't need a glock LRU list anymore, but we leave removing that list to a later patch for better readability. It might seem that glocks that are not referenced anymore can be dropped immediately without unlocking them first, but that isn't true for inode glocks that have an address space attached (the "gfs2_glock(aspace)" slab cache): that address space is only truncated when the associated glock is unlocked. So unlock those glocks when they become unreferenced. Signed-off-by: Andreas Gruenbacher --- fs/gfs2/glock.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 0a93824424d5..f00dcae426c5 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -258,8 +258,8 @@ static bool __gfs2_glock_put_or_lock(struct gfs2_glock *gl) return true; GLOCK_BUG_ON(gl, gl->gl_lockref.count != 1); if (gl->gl_state != LM_ST_UNLOCKED) { - gl->gl_lockref.count--; - gfs2_glock_add_to_lru(gl); + request_demote(gl, LM_ST_UNLOCKED, 0, false); + gfs2_glock_queue_work(gl, 0); spin_unlock(&gl->gl_lockref.lock); return true; } @@ -983,16 +983,19 @@ static void delete_work_func(struct work_struct *work) static void glock_work_func(struct work_struct *work) { - unsigned long delay = 0; struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_work.work); - unsigned int drop_refs = 1; + unsigned int drop_refs; + unsigned long delay; spin_lock(&gl->gl_lockref.lock); +again: + drop_refs = 1; if (test_bit(GLF_HAVE_REPLY, &gl->gl_flags)) { clear_bit(GLF_HAVE_REPLY, &gl->gl_flags); finish_xmote(gl, gl->gl_reply); drop_refs++; } + delay = 0; if (test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && gl->gl_state != LM_ST_UNLOCKED && gl->gl_demote_state != LM_ST_EXCLUSIVE) { @@ -1020,11 +1023,13 @@ static void glock_work_func(struct work_struct *work) GLOCK_BUG_ON(gl, gl->gl_lockref.count < drop_refs); gl->gl_lockref.count -= drop_refs; if (!gl->gl_lockref.count) { - if (gl->gl_state == LM_ST_UNLOCKED) { - __gfs2_glock_put(gl); - return; + if (gl->gl_state != LM_ST_UNLOCKED) { + gl->gl_lockref.count++; + request_demote(gl, LM_ST_UNLOCKED, 0, false); + goto again; } - gfs2_glock_add_to_lru(gl); + __gfs2_glock_put(gl); + return; } spin_unlock(&gl->gl_lockref.lock); }