mirror of
https://github.com/systemd/systemd.git
synced 2026-08-09 17:38:42 +00:00
network: implement refcounting for SR-IOV objects
link_request_sr_iov_vfs() queued each request with a raw SRIOV* as
userdata and a NULL free_func, so the request did not own the object.
The SRIOV is owned by link->network->sr_iov_by_section, which is freed
by network_free() on reload while the RTM_SETLINK reply may still be in
flight (the floating netlink slot keeps the request alive but does not
keep the userdata alive). A later reply, or the 25s netlink timeout,
then dispatches sr_iov_handler() which reads the freed SRIOV.
Follow-up for cb8453cc51
This commit is contained in:
@@ -98,11 +98,12 @@ int link_request_sr_iov_vfs(Link *link) {
|
||||
if (!sr_iov_has_config(sr_iov, attr))
|
||||
continue;
|
||||
|
||||
/* The request takes a reference on the configuration. */
|
||||
r = link_queue_request_safe(
|
||||
link,
|
||||
_REQUEST_TYPE_SRIOV_BASE + attr,
|
||||
sr_iov,
|
||||
NULL,
|
||||
sr_iov_unref,
|
||||
sr_iov_hash_func,
|
||||
sr_iov_compare_func,
|
||||
sr_iov_process_request,
|
||||
@@ -113,6 +114,8 @@ int link_request_sr_iov_vfs(Link *link) {
|
||||
return log_link_warning_errno(link, r,
|
||||
"Failed to request to set up %s for SR-IOV virtual function %"PRIu32": %m",
|
||||
sr_iov_attribute_to_string(attr), sr_iov->vf);
|
||||
if (r > 0)
|
||||
sr_iov_ref(sr_iov);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,24 +16,42 @@
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
|
||||
static SRIOV* sr_iov_detach_impl(SRIOV *sr_iov) {
|
||||
assert(sr_iov);
|
||||
|
||||
if (!sr_iov->sr_iov_by_section)
|
||||
return NULL;
|
||||
|
||||
assert(sr_iov->section);
|
||||
ordered_hashmap_remove(sr_iov->sr_iov_by_section, sr_iov->section);
|
||||
sr_iov->sr_iov_by_section = NULL;
|
||||
|
||||
return sr_iov;
|
||||
}
|
||||
|
||||
static SRIOV* sr_iov_free(SRIOV *sr_iov) {
|
||||
if (!sr_iov)
|
||||
return NULL;
|
||||
|
||||
if (sr_iov->sr_iov_by_section && sr_iov->section)
|
||||
ordered_hashmap_remove(sr_iov->sr_iov_by_section, sr_iov->section);
|
||||
sr_iov_detach_impl(sr_iov);
|
||||
|
||||
config_section_free(sr_iov->section);
|
||||
|
||||
return mfree(sr_iov);
|
||||
}
|
||||
|
||||
DEFINE_SECTION_CLEANUP_FUNCTIONS(SRIOV, sr_iov_free);
|
||||
DEFINE_TRIVIAL_REF_UNREF_FUNC(SRIOV, sr_iov, sr_iov_free);
|
||||
DEFINE_SECTION_CLEANUP_FUNCTIONS(SRIOV, sr_iov_unref);
|
||||
|
||||
static void sr_iov_detach(SRIOV *sr_iov) {
|
||||
assert(sr_iov);
|
||||
sr_iov_unref(sr_iov_detach_impl(sr_iov));
|
||||
}
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
sr_iov_hash_ops_by_section,
|
||||
ConfigSection, config_section_hash_func, config_section_compare_func,
|
||||
SRIOV, sr_iov_free);
|
||||
SRIOV, sr_iov_detach);
|
||||
|
||||
static int sr_iov_new(SRIOV **ret) {
|
||||
SRIOV *sr_iov;
|
||||
@@ -45,6 +63,7 @@ static int sr_iov_new(SRIOV **ret) {
|
||||
return -ENOMEM;
|
||||
|
||||
*sr_iov = (SRIOV) {
|
||||
.n_ref = 1,
|
||||
.vf = UINT32_MAX,
|
||||
.vlan_proto = ETH_P_8021Q,
|
||||
.vf_spoof_check_setting = -1,
|
||||
@@ -60,7 +79,7 @@ static int sr_iov_new(SRIOV **ret) {
|
||||
|
||||
static int sr_iov_new_static(OrderedHashmap **sr_iov_by_section, const char *filename, unsigned section_line, SRIOV **ret) {
|
||||
_cleanup_(config_section_freep) ConfigSection *n = NULL;
|
||||
_cleanup_(sr_iov_freep) SRIOV *sr_iov = NULL;
|
||||
_cleanup_(sr_iov_unrefp) SRIOV *sr_iov = NULL;
|
||||
SRIOV *existing = NULL;
|
||||
int r;
|
||||
|
||||
@@ -368,7 +387,7 @@ int sr_iov_drop_invalid_sections(uint32_t num_vfs, OrderedHashmap *sr_iov_by_sec
|
||||
SRIOV *dup;
|
||||
|
||||
if (sr_iov_section_verify(num_vfs, sr_iov) < 0) {
|
||||
sr_iov_free(sr_iov);
|
||||
sr_iov_detach(sr_iov);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -378,7 +397,7 @@ int sr_iov_drop_invalid_sections(uint32_t num_vfs, OrderedHashmap *sr_iov_by_sec
|
||||
"dropping the [SR-IOV] section specified at line %u.",
|
||||
dup->section->filename, sr_iov->section->line,
|
||||
dup->section->line, dup->section->line);
|
||||
sr_iov_free(dup);
|
||||
sr_iov_detach(dup);
|
||||
}
|
||||
|
||||
r = set_ensure_put(&set, &sr_iov_hash_ops, sr_iov);
|
||||
@@ -402,7 +421,7 @@ int config_parse_sr_iov_uint32(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
|
||||
_cleanup_(sr_iov_unref_or_set_invalidp) SRIOV *sr_iov = NULL;
|
||||
OrderedHashmap **sr_iov_by_section = ASSERT_PTR(data);
|
||||
uint32_t k;
|
||||
int r;
|
||||
@@ -469,7 +488,7 @@ int config_parse_sr_iov_vlan_proto(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
|
||||
_cleanup_(sr_iov_unref_or_set_invalidp) SRIOV *sr_iov = NULL;
|
||||
OrderedHashmap **sr_iov_by_section = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
@@ -507,7 +526,7 @@ int config_parse_sr_iov_link_state(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
|
||||
_cleanup_(sr_iov_unref_or_set_invalidp) SRIOV *sr_iov = NULL;
|
||||
OrderedHashmap **sr_iov_by_section = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
@@ -558,7 +577,7 @@ int config_parse_sr_iov_boolean(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
|
||||
_cleanup_(sr_iov_unref_or_set_invalidp) SRIOV *sr_iov = NULL;
|
||||
OrderedHashmap **sr_iov_by_section = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
@@ -615,7 +634,7 @@ int config_parse_sr_iov_mac(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_(sr_iov_free_or_set_invalidp) SRIOV *sr_iov = NULL;
|
||||
_cleanup_(sr_iov_unref_or_set_invalidp) SRIOV *sr_iov = NULL;
|
||||
OrderedHashmap **sr_iov_by_section = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ typedef enum SRIOVLinkState {
|
||||
} SRIOVLinkState;
|
||||
|
||||
typedef struct SRIOV {
|
||||
unsigned n_ref;
|
||||
|
||||
ConfigSection *section;
|
||||
OrderedHashmap *sr_iov_by_section;
|
||||
|
||||
@@ -43,6 +45,8 @@ typedef struct SRIOV {
|
||||
|
||||
DECLARE_STRING_TABLE_LOOKUP_TO_STRING(sr_iov_attribute, SRIOVAttribute);
|
||||
|
||||
DECLARE_TRIVIAL_REF_UNREF_FUNC(SRIOV, sr_iov);
|
||||
|
||||
void sr_iov_hash_func(const SRIOV *sr_iov, struct siphash *state);
|
||||
int sr_iov_compare_func(const SRIOV *s1, const SRIOV *s2);
|
||||
bool sr_iov_has_config(SRIOV *sr_iov, SRIOVAttribute attr);
|
||||
|
||||
Reference in New Issue
Block a user