Skip to content

Commit bead882

Browse files
authored
fix cgroup netdev renames (netdata#20050)
* fix cgroup netdev renames when multiple renames exist for the same device * remove obsolete members and functions
1 parent 02fcff8 commit bead882

3 files changed

Lines changed: 37 additions & 36 deletions

File tree

src/collectors/proc.plugin/proc_net_dev.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -383,9 +383,7 @@ static netdata_mutex_t netdev_mutex = NETDATA_MUTEX_INITIALIZER;
383383

384384
// ----------------------------------------------------------------------------
385385

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) {
389387
collector_info("CGROUP: renaming network interface '%s' as '%s' under '%s'", d->name, r->container_device, r->container_name);
390388

391389
netdev_charts_release(d);
@@ -474,7 +472,9 @@ static void netdev_rename_this_device(struct netdev *d) {
474472
const DICTIONARY_ITEM *item = dictionary_get_and_acquire_item(netdev_renames, d->name);
475473
if(item) {
476474
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);
478478
dictionary_acquired_item_release(netdev_renames, item);
479479
}
480480
}

src/collectors/proc.plugin/proc_net_dev_renames.c

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,50 @@
44

55
DICTIONARY *netdev_renames = NULL;
66

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;
1210

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;
1713

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);
2517
}
2618

2719
static void dictionary_netdev_rename_delete_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
2820
struct rename_task *r = value;
2921

30-
rename_task_verify_checksum(r);
22+
spinlock_lock(&r->spinlock);
23+
netdev_rename_task_cleanup_unsafe(r);
24+
spinlock_unlock(&r->spinlock);
25+
}
3126

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;
3430

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);
3738

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;
4142
}
4243

4344
void netdev_renames_init(void) {
4445
static SPINLOCK spinlock = SPINLOCK_INITIALIZER;
4546

4647
spinlock_lock(&spinlock);
4748
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);
4951
dictionary_register_delete_callback(netdev_renames, dictionary_netdev_rename_delete_cb, NULL);
5052
}
5153
spinlock_unlock(&spinlock);
@@ -67,12 +69,8 @@ void cgroup_rename_task_add(
6769
.ctx_prefix = strdupz(ctx_prefix),
6870
.chart_labels = rrdlabels_create(),
6971
.cgroup_netdev_link = cgroup_netdev_link,
70-
.checksum = 0, // Will be set below
7172
};
7273
rrdlabels_migrate_to_these(tmp.chart_labels, labels);
73-
74-
// Set the checksum after all fields are initialized
75-
rename_task_set_checksum(&tmp);
7674

7775
dictionary_set(netdev_renames, host_device, &tmp, sizeof(tmp));
7876
}

src/collectors/proc.plugin/proc_net_dev_renames.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,20 @@
1313
extern DICTIONARY *netdev_renames;
1414

1515
struct rename_task {
16+
SPINLOCK spinlock;
1617
const char *container_device;
1718
const char *container_name;
1819
const char *ctx_prefix;
1920
RRDLABELS *chart_labels;
2021
const DICTIONARY_ITEM *cgroup_netdev_link;
21-
XXH64_hash_t checksum;
2222
};
2323

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)
2528

26-
void rename_task_verify_checksum(struct rename_task *r);
29+
void netdev_renames_init(void);
2730

2831
void cgroup_netdev_reset_all(void);
2932
void cgroup_netdev_release(const DICTIONARY_ITEM *link);

0 commit comments

Comments
 (0)