Skip to content

Commit acf1f42

Browse files
author
Andreas Gruenbacher
committed
gfs2: Fix "Make glock lru list scanning safer"
Commit 228804a tried to add a refcount check to gfs2_scan_glock_lru() to make sure that glocks that are still referenced cannot be freed. It failed to account for the bias state_change() adds to the refcount for held glocks, so held glocks are no longer removed from the glock cache, which can lead to out-of-memory problems. Fix that. (The inodes those glocks are associated with do get shrunk and do get pushed out of memory.) In addition, use the same eligibility check in gfs2_scan_glock_lru() and gfs2_dispose_glock_lru(). Signed-off-by: Andreas Gruenbacher <[email protected]>
1 parent c9a0a4b commit acf1f42

File tree

1 file changed

+13
-11
lines changed

1 file changed

+13
-11
lines changed

fs/gfs2/glock.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1987,6 +1987,14 @@ static int glock_cmp(void *priv, const struct list_head *a,
19871987
return 0;
19881988
}
19891989

1990+
static bool can_free_glock(struct gfs2_glock *gl)
1991+
{
1992+
bool held = gl->gl_state != LM_ST_UNLOCKED;
1993+
1994+
return !test_bit(GLF_LOCK, &gl->gl_flags) &&
1995+
gl->gl_lockref.count == held;
1996+
}
1997+
19901998
/**
19911999
* gfs2_dispose_glock_lru - Demote a list of glocks
19922000
* @list: The list to dispose of
@@ -2020,7 +2028,7 @@ __acquires(&lru_lock)
20202028
atomic_inc(&lru_count);
20212029
continue;
20222030
}
2023-
if (test_bit(GLF_LOCK, &gl->gl_flags)) {
2031+
if (!can_free_glock(gl)) {
20242032
spin_unlock(&gl->gl_lockref.lock);
20252033
goto add_back_to_lru;
20262034
}
@@ -2052,16 +2060,10 @@ static long gfs2_scan_glock_lru(int nr)
20522060
list_for_each_entry_safe(gl, next, &lru_list, gl_lru) {
20532061
if (nr-- <= 0)
20542062
break;
2055-
/* Test for being demotable */
2056-
if (!test_bit(GLF_LOCK, &gl->gl_flags)) {
2057-
if (!spin_trylock(&gl->gl_lockref.lock))
2058-
continue;
2059-
if (!gl->gl_lockref.count) {
2060-
list_move(&gl->gl_lru, &dispose);
2061-
atomic_dec(&lru_count);
2062-
freed++;
2063-
}
2064-
spin_unlock(&gl->gl_lockref.lock);
2063+
if (can_free_glock(gl)) {
2064+
list_move(&gl->gl_lru, &dispose);
2065+
atomic_dec(&lru_count);
2066+
freed++;
20652067
}
20662068
}
20672069
if (!list_empty(&dispose))

0 commit comments

Comments
 (0)