fix cgroup netdev renames (#20050)
* fix cgroup netdev renames when multiple renames exist for the same device * remove obsolete members and functions
Costa Tsaousis committed
Apr 3, 2025 at 20:28 UTC
bead8823cc7ed4b4f5b1698605adefb46f0a5041
3 files changed
+37
-36
src/collectors/proc.plugin/proc_net_dev.c
+4
-4
@@ -383,9 +383,7 @@ static netdata_mutex_t netdev_mutex = NETDATA_MUTEX_INITIALIZER;
383
384
// ----------------------------------------------------------------------------
385
386
-static inline void netdev_rename(struct netdev *d, struct rename_task *r) {
387
- rename_task_verify_checksum(r);
388
-
386
+static inline void netdev_rename_unsafe(struct netdev *d, struct rename_task *r) {
387
collector_info("CGROUP: renaming network interface '%s' as '%s' under '%s'", d->name, r->container_device, r->container_name);
388
389
netdev_charts_release(d);
@@ -474,7 +472,9 @@ static void netdev_rename_this_device(struct netdev *d) {
472
const DICTIONARY_ITEM *item = dictionary_get_and_acquire_item(netdev_renames, d->name);
473
if(item) {
474
struct rename_task *r = dictionary_acquired_item_value(item);
477
- netdev_rename(d, r);
475
+ spinlock_lock(&r->spinlock);
476
+ netdev_rename_unsafe(d, r);
477
+ spinlock_unlock(&r->spinlock);
478
dictionary_acquired_item_release(netdev_renames, item);
479
}
480
}
src/collectors/proc.plugin/proc_net_dev_renames.c
+27
-29
@@ -4,40 +4,41 @@
4
5
DICTIONARY *netdev_renames = NULL;
6
7
-static XXH64_hash_t rename_task_hash(struct rename_task *r) {
8
- struct rename_task local_copy = *r;
9
- local_copy.checksum = 0;
10
- return XXH3_64bits(&local_copy, sizeof(local_copy));
11
-}
7
+static void netdev_rename_task_cleanup_unsafe(struct rename_task *r) {
8
+ cgroup_netdev_release(r->cgroup_netdev_link);
9
+ r->cgroup_netdev_link = NULL;
10
13
-// Set the checksum for a rename_task
14
-static void rename_task_set_checksum(struct rename_task *r) {
15
- r->checksum = rename_task_hash(r);
16
-}
11
+ rrdlabels_destroy(r->chart_labels);
12
+ r->chart_labels = NULL;
13
18
-// Verify the checksum for a rename_task
19
-void rename_task_verify_checksum(struct rename_task *r) {
20
- if(r->checksum != rename_task_hash(r))
21
- fatal("MEMORY CORRUPTION DETECTED in rename_task structure. "
22
- "Expected checksum: 0x%016" PRIx64 ", "
23
- "Calculated checksum: 0x%016" PRIx64,
24
- r->checksum, rename_task_hash(r));
14
+ freez_and_set_to_null(r->container_name);
15
+ freez_and_set_to_null(r->container_device);
16
+ freez_and_set_to_null(r->ctx_prefix);
17
}
18
19
static void dictionary_netdev_rename_delete_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
20
struct rename_task *r = value;
21
30
- rename_task_verify_checksum(r);
22
+ spinlock_lock(&r->spinlock);
23
+ netdev_rename_task_cleanup_unsafe(r);
24
+ spinlock_unlock(&r->spinlock);
25
+}
26
32
- cgroup_netdev_release(r->cgroup_netdev_link);
33
- r->cgroup_netdev_link = NULL;
27
+static bool dictionary_netdev_rename_conflict_cb(const DICTIONARY_ITEM *item __maybe_unused, void *old_value, void *new_value, void *data __maybe_unused) {
28
+ struct rename_task *old_r = old_value;
29
+ struct rename_task *new_r = new_value;
30
35
- rrdlabels_destroy(r->chart_labels);
36
- r->chart_labels = NULL;
31
+ spinlock_lock(&old_r->spinlock);
32
+ SWAP(old_r->cgroup_netdev_link, new_r->cgroup_netdev_link);
33
+ SWAP(old_r->chart_labels, new_r->chart_labels);
34
+ SWAP(old_r->container_device, new_r->container_device);
35
+ SWAP(old_r->container_name, new_r->container_name);
36
+ SWAP(old_r->ctx_prefix, new_r->ctx_prefix);
37
+ spinlock_unlock(&old_r->spinlock);
38
38
- freez_and_set_to_null(r->container_name);
39
- freez_and_set_to_null(r->container_device);
40
- freez_and_set_to_null(r->ctx_prefix);
39
+ netdev_rename_task_cleanup_unsafe(new_r);
40
+
41
+ return true;
42
}
43
44
void netdev_renames_init(void) {
@@ -45,7 +46,8 @@ void netdev_renames_init(void) {
46
47
spinlock_lock(&spinlock);
48
if(!netdev_renames) {
48
- netdev_renames = dictionary_create_advanced(DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct rename_task));
49
+ netdev_renames = dictionary_create_advanced(DICT_OPTION_FIXED_SIZE | DICT_OPTION_DONT_OVERWRITE_VALUE, NULL, sizeof(struct rename_task));
50
+ dictionary_register_conflict_callback(netdev_renames, dictionary_netdev_rename_conflict_cb, NULL);
51
dictionary_register_delete_callback(netdev_renames, dictionary_netdev_rename_delete_cb, NULL);
52
}
53
spinlock_unlock(&spinlock);
@@ -67,12 +69,8 @@ void cgroup_rename_task_add(
69
.ctx_prefix = strdupz(ctx_prefix),
70
.chart_labels = rrdlabels_create(),
71
.cgroup_netdev_link = cgroup_netdev_link,
70
- .checksum = 0, // Will be set below
72
};
73
rrdlabels_migrate_to_these(tmp.chart_labels, labels);
73
-
74
- // Set the checksum after all fields are initialized
75
- rename_task_set_checksum(&tmp);
74
75
dictionary_set(netdev_renames, host_device, &tmp, sizeof(tmp));
76
}
src/collectors/proc.plugin/proc_net_dev_renames.h
+6
-3
@@ -13,17 +13,20 @@
13
extern DICTIONARY *netdev_renames;
14
15
struct rename_task {
16
+ SPINLOCK spinlock;
17
const char *container_device;
18
const char *container_name;
19
const char *ctx_prefix;
20
RRDLABELS *chart_labels;
21
const DICTIONARY_ITEM *cgroup_netdev_link;
21
- XXH64_hash_t checksum;
22
};
23
24
-void netdev_renames_init(void);
24
+#define freez_and_set_to_null(p) do { \
25
+ freez((void *)p); \
26
+ p = NULL; \
27
+} while(0)
28
26
-void rename_task_verify_checksum(struct rename_task *r);
29
+void netdev_renames_init(void);
30
31
void cgroup_netdev_reset_all(void);
32
void cgroup_netdev_release(const DICTIONARY_ITEM *link);