mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-26 19:19:32 +03:00
997f85b4d3
Previous code held ARC state sublist lock throughout all L2ARC write process, which included number of allocations and even ZIO issues. Being blocked in any of those places the code could also block ARC eviction, that could cause OOM activation or even dead- lock if system is low on memory or one is too fragmented. Fix it by dropping the lock as soon as we see a block eligible for L2ARC writing and pick it up later using earlier inserted marker. While there, also reduce scope of hash lock, moving ZIO allocation and other operations not requiring header access out of it. All operations requiring header access move under hash lock, since L2_WRITING flag does not prevent header eviction only transition to arc_l2c_only state with L1 header. To be able to manipulate sublist lock and marker as needed add few more multilist functions and modify one. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored by: iXsystems, Inc. Closes #16040
112 lines
3.5 KiB
C
112 lines
3.5 KiB
C
/*
|
|
* CDDL HEADER START
|
|
*
|
|
* This file and its contents are supplied under the terms of the
|
|
* Common Development and Distribution License ("CDDL"), version 1.0.
|
|
* You may only use this file in accordance with the terms of version
|
|
* 1.0 of the CDDL.
|
|
*
|
|
* A full copy of the text of the CDDL should have accompanied this
|
|
* source. A copy of the CDDL is also available via the Internet at
|
|
* http://www.illumos.org/license/CDDL.
|
|
*
|
|
* CDDL HEADER END
|
|
*/
|
|
/*
|
|
* Copyright (c) 2013, 2017 by Delphix. All rights reserved.
|
|
*/
|
|
|
|
#ifndef _SYS_MULTILIST_H
|
|
#define _SYS_MULTILIST_H
|
|
|
|
#include <sys/zfs_context.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
typedef list_node_t multilist_node_t;
|
|
typedef struct multilist multilist_t;
|
|
typedef struct multilist_sublist multilist_sublist_t;
|
|
typedef unsigned int multilist_sublist_index_func_t(multilist_t *, void *);
|
|
|
|
struct multilist_sublist {
|
|
/*
|
|
* The mutex used internally to implement thread safe insertions
|
|
* and removals to this individual sublist. It can also be locked
|
|
* by a consumer using multilist_sublist_{lock,unlock}, which is
|
|
* useful if a consumer needs to traverse the list in a thread
|
|
* safe manner.
|
|
*/
|
|
kmutex_t mls_lock;
|
|
/*
|
|
* The actual list object containing all objects in this sublist.
|
|
*/
|
|
list_t mls_list;
|
|
/*
|
|
* Pad to cache line, in an effort to try and prevent cache line
|
|
* contention.
|
|
*/
|
|
} ____cacheline_aligned;
|
|
|
|
struct multilist {
|
|
/*
|
|
* This is used to get to the multilist_node_t structure given
|
|
* the void *object contained on the list.
|
|
*/
|
|
size_t ml_offset;
|
|
/*
|
|
* The number of sublists used internally by this multilist.
|
|
*/
|
|
uint64_t ml_num_sublists;
|
|
/*
|
|
* The array of pointers to the actual sublists.
|
|
*/
|
|
multilist_sublist_t *ml_sublists;
|
|
/*
|
|
* Pointer to function which determines the sublist to use
|
|
* when inserting and removing objects from this multilist.
|
|
* Please see the comment above multilist_create for details.
|
|
*/
|
|
multilist_sublist_index_func_t *ml_index_func;
|
|
};
|
|
|
|
void multilist_create(multilist_t *, size_t, size_t,
|
|
multilist_sublist_index_func_t *);
|
|
void multilist_destroy(multilist_t *);
|
|
|
|
void multilist_insert(multilist_t *, void *);
|
|
void multilist_remove(multilist_t *, void *);
|
|
int multilist_is_empty(multilist_t *);
|
|
|
|
unsigned int multilist_get_num_sublists(multilist_t *);
|
|
unsigned int multilist_get_random_index(multilist_t *);
|
|
|
|
void multilist_sublist_lock(multilist_sublist_t *);
|
|
multilist_sublist_t *multilist_sublist_lock_idx(multilist_t *, unsigned int);
|
|
multilist_sublist_t *multilist_sublist_lock_obj(multilist_t *, void *);
|
|
void multilist_sublist_unlock(multilist_sublist_t *);
|
|
|
|
void multilist_sublist_insert_head(multilist_sublist_t *, void *);
|
|
void multilist_sublist_insert_tail(multilist_sublist_t *, void *);
|
|
void multilist_sublist_insert_after(multilist_sublist_t *, void *, void *);
|
|
void multilist_sublist_insert_before(multilist_sublist_t *, void *, void *);
|
|
void multilist_sublist_move_forward(multilist_sublist_t *mls, void *obj);
|
|
void multilist_sublist_remove(multilist_sublist_t *, void *);
|
|
int multilist_sublist_is_empty(multilist_sublist_t *);
|
|
int multilist_sublist_is_empty_idx(multilist_t *, unsigned int);
|
|
|
|
void *multilist_sublist_head(multilist_sublist_t *);
|
|
void *multilist_sublist_tail(multilist_sublist_t *);
|
|
void *multilist_sublist_next(multilist_sublist_t *, void *);
|
|
void *multilist_sublist_prev(multilist_sublist_t *, void *);
|
|
|
|
void multilist_link_init(multilist_node_t *);
|
|
int multilist_link_active(multilist_node_t *);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* _SYS_MULTILIST_H */
|