mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-27 03:19:35 +03:00
arc_evict, arc_evict_ghost: reduce stack usage using kmem_zalloc
With debugging enabled and depending on your kernel config, the size of arc_buf_hdr_t can blow out the stack of arc_evict() and arc_evict_ghost() to greater than 1024 bytes. Let's avoid this. Signed-off-by: Chris Dunlop <chris@onthe.net.au> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #3377
This commit is contained in:
parent
63e3a8616b
commit
16fcdea363
@ -1825,13 +1825,15 @@ arc_evict(arc_state_t *state, uint64_t spa, int64_t bytes, boolean_t recycle,
|
|||||||
kmutex_t *hash_lock;
|
kmutex_t *hash_lock;
|
||||||
boolean_t have_lock;
|
boolean_t have_lock;
|
||||||
void *stolen = NULL;
|
void *stolen = NULL;
|
||||||
arc_buf_hdr_t marker = {{{ 0 }}};
|
arc_buf_hdr_t *marker;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
ASSERT(state == arc_mru || state == arc_mfu);
|
ASSERT(state == arc_mru || state == arc_mfu);
|
||||||
|
|
||||||
evicted_state = (state == arc_mru) ? arc_mru_ghost : arc_mfu_ghost;
|
evicted_state = (state == arc_mru) ? arc_mru_ghost : arc_mfu_ghost;
|
||||||
|
|
||||||
|
marker = kmem_zalloc(sizeof (arc_buf_hdr_t), KM_SLEEP);
|
||||||
|
|
||||||
top:
|
top:
|
||||||
mutex_enter(&state->arcs_mtx);
|
mutex_enter(&state->arcs_mtx);
|
||||||
mutex_enter(&evicted_state->arcs_mtx);
|
mutex_enter(&evicted_state->arcs_mtx);
|
||||||
@ -1866,14 +1868,14 @@ top:
|
|||||||
* the hot code path, so don't sleep.
|
* the hot code path, so don't sleep.
|
||||||
*/
|
*/
|
||||||
if (!recycle && count++ > arc_evict_iterations) {
|
if (!recycle && count++ > arc_evict_iterations) {
|
||||||
list_insert_after(list, ab, &marker);
|
list_insert_after(list, ab, marker);
|
||||||
mutex_exit(&evicted_state->arcs_mtx);
|
mutex_exit(&evicted_state->arcs_mtx);
|
||||||
mutex_exit(&state->arcs_mtx);
|
mutex_exit(&state->arcs_mtx);
|
||||||
kpreempt(KPREEMPT_SYNC);
|
kpreempt(KPREEMPT_SYNC);
|
||||||
mutex_enter(&state->arcs_mtx);
|
mutex_enter(&state->arcs_mtx);
|
||||||
mutex_enter(&evicted_state->arcs_mtx);
|
mutex_enter(&evicted_state->arcs_mtx);
|
||||||
ab_prev = list_prev(list, &marker);
|
ab_prev = list_prev(list, marker);
|
||||||
list_remove(list, &marker);
|
list_remove(list, marker);
|
||||||
count = 0;
|
count = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1957,6 +1959,8 @@ top:
|
|||||||
goto top;
|
goto top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kmem_free(marker, sizeof (arc_buf_hdr_t));
|
||||||
|
|
||||||
if (bytes_evicted < bytes)
|
if (bytes_evicted < bytes)
|
||||||
dprintf("only evicted %lld bytes from %x\n",
|
dprintf("only evicted %lld bytes from %x\n",
|
||||||
(longlong_t)bytes_evicted, state->arcs_state);
|
(longlong_t)bytes_evicted, state->arcs_state);
|
||||||
@ -1986,7 +1990,7 @@ arc_evict_ghost(arc_state_t *state, uint64_t spa, int64_t bytes,
|
|||||||
arc_buf_contents_t type)
|
arc_buf_contents_t type)
|
||||||
{
|
{
|
||||||
arc_buf_hdr_t *ab, *ab_prev;
|
arc_buf_hdr_t *ab, *ab_prev;
|
||||||
arc_buf_hdr_t marker;
|
arc_buf_hdr_t *marker;
|
||||||
list_t *list = &state->arcs_list[type];
|
list_t *list = &state->arcs_list[type];
|
||||||
kmutex_t *hash_lock;
|
kmutex_t *hash_lock;
|
||||||
uint64_t bytes_deleted = 0;
|
uint64_t bytes_deleted = 0;
|
||||||
@ -1994,7 +1998,9 @@ arc_evict_ghost(arc_state_t *state, uint64_t spa, int64_t bytes,
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
ASSERT(GHOST_STATE(state));
|
ASSERT(GHOST_STATE(state));
|
||||||
bzero(&marker, sizeof (marker));
|
|
||||||
|
marker = kmem_zalloc(sizeof (arc_buf_hdr_t), KM_SLEEP);
|
||||||
|
|
||||||
top:
|
top:
|
||||||
mutex_enter(&state->arcs_mtx);
|
mutex_enter(&state->arcs_mtx);
|
||||||
for (ab = list_tail(list); ab; ab = ab_prev) {
|
for (ab = list_tail(list); ab; ab = ab_prev) {
|
||||||
@ -2020,12 +2026,12 @@ top:
|
|||||||
* before reacquiring the lock.
|
* before reacquiring the lock.
|
||||||
*/
|
*/
|
||||||
if (count++ > arc_evict_iterations) {
|
if (count++ > arc_evict_iterations) {
|
||||||
list_insert_after(list, ab, &marker);
|
list_insert_after(list, ab, marker);
|
||||||
mutex_exit(&state->arcs_mtx);
|
mutex_exit(&state->arcs_mtx);
|
||||||
kpreempt(KPREEMPT_SYNC);
|
kpreempt(KPREEMPT_SYNC);
|
||||||
mutex_enter(&state->arcs_mtx);
|
mutex_enter(&state->arcs_mtx);
|
||||||
ab_prev = list_prev(list, &marker);
|
ab_prev = list_prev(list, marker);
|
||||||
list_remove(list, &marker);
|
list_remove(list, marker);
|
||||||
count = 0;
|
count = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2057,13 +2063,13 @@ top:
|
|||||||
* hash lock to become available. Once its
|
* hash lock to become available. Once its
|
||||||
* available, restart from where we left off.
|
* available, restart from where we left off.
|
||||||
*/
|
*/
|
||||||
list_insert_after(list, ab, &marker);
|
list_insert_after(list, ab, marker);
|
||||||
mutex_exit(&state->arcs_mtx);
|
mutex_exit(&state->arcs_mtx);
|
||||||
mutex_enter(hash_lock);
|
mutex_enter(hash_lock);
|
||||||
mutex_exit(hash_lock);
|
mutex_exit(hash_lock);
|
||||||
mutex_enter(&state->arcs_mtx);
|
mutex_enter(&state->arcs_mtx);
|
||||||
ab_prev = list_prev(list, &marker);
|
ab_prev = list_prev(list, marker);
|
||||||
list_remove(list, &marker);
|
list_remove(list, marker);
|
||||||
} else {
|
} else {
|
||||||
bufs_skipped += 1;
|
bufs_skipped += 1;
|
||||||
}
|
}
|
||||||
@ -2076,6 +2082,8 @@ top:
|
|||||||
goto top;
|
goto top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kmem_free(marker, sizeof (arc_buf_hdr_t));
|
||||||
|
|
||||||
if (bufs_skipped) {
|
if (bufs_skipped) {
|
||||||
ARCSTAT_INCR(arcstat_mutex_miss, bufs_skipped);
|
ARCSTAT_INCR(arcstat_mutex_miss, bufs_skipped);
|
||||||
ASSERT(bytes >= 0);
|
ASSERT(bytes >= 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user