@cryptotaxi247 / netdata-1 / commits / 3bcd59a23

Improve storage collector by using dictionary delete callbacks (#21500)

* Add dictionary delete callbacks Ensure proper deallocation of disk-related strings and reset pointers to NULL. Add metadata reset (`collected_metadata = false`) during cleanup to prevent stale data usage. * Reset `st_disk_space` pointer to NULL during cleanup in perflib-storage.

Stelios Fragkakis committed Jan 8, 2026 at 19:17 UTC 3bcd59a2346c4b626cf74315877802b641430679
1 file changed +33 -8
src/collectors/windows.plugin/perflib-storage.c
+33 -8
@@ -97,7 +97,13 @@ dict_logical_disk_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, void *va
97
98 static void logical_disk_cleanup(struct logical_disk *d)
99 {
100 + string_freez(d->filesystem);
101 + d->filesystem = NULL;
102 +
103 + d->collected_metadata = false;
104 +
105 rrdset_is_obsolete___safe_from_collector_thread(d->st_disk_space);
106 + d->st_disk_space = NULL;
107 }
108
109 static void physical_disk_initialize(struct physical_disk *d)
@@ -128,12 +134,21 @@ static void physical_disk_initialize(struct physical_disk *d)
134 static void physical_disk_cleanup(struct physical_disk *d)
135 {
136 string_freez(d->device);
137 + d->device = NULL;
138 string_freez(d->mount_point);
139 + d->mount_point = NULL;
140 string_freez(d->manufacturer);
141 + d->manufacturer = NULL;
142 string_freez(d->model);
143 + d->model = NULL;
144 string_freez(d->media_type);
145 + d->media_type = NULL;
146 string_freez(d->name);
147 + d->name = NULL;
148 string_freez(d->device_id);
149 + d->device_id = NULL;
150 +
151 + d->collected_metadata = false;
152
153 rrdset_is_obsolete___safe_from_collector_thread(d->disk_io.st_io);
154 rrdset_is_obsolete___safe_from_collector_thread(d->disk_ops.st_ops);
@@ -153,6 +168,18 @@ void dict_physical_disk_insert_cb(const DICTIONARY_ITEM *item __maybe_unused, vo
168 physical_disk_initialize(pd);
169 }
170
171 +static void dict_logical_disk_delete_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
172 +{
173 + struct logical_disk *d = value;
174 + logical_disk_cleanup(d);
175 +}
176 +
177 +static void dict_physical_disk_delete_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
178 +{
179 + struct physical_disk *d = value;
180 + physical_disk_cleanup(d);
181 +}
182 +
183 static DICTIONARY *logicalDisks = NULL, *physicalDisks = NULL;
184 static void initialize(void)
185 {
@@ -162,11 +189,13 @@ static void initialize(void)
189 DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct logical_disk));
190
191 dictionary_register_insert_callback(logicalDisks, dict_logical_disk_insert_cb, NULL);
192 + dictionary_register_delete_callback(logicalDisks, dict_logical_disk_delete_cb, NULL);
193
194 physicalDisks = dictionary_create_advanced(
195 DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct physical_disk));
196
197 dictionary_register_insert_callback(physicalDisks, dict_physical_disk_insert_cb, NULL);
198 + dictionary_register_delete_callback(physicalDisks, dict_physical_disk_delete_cb, NULL);
199 }
200
201 static STRING *getFileSystemType(struct logical_disk *d, const char *diskName)
@@ -347,15 +376,13 @@ static bool do_logical_disk(PERF_DATA_BLOCK *pDataBlock, int update_every, usec_
376 rrdset_done(d->st_disk_space);
377 }
378
350 - // cleanup
379 + // cleanup - delete callback will handle resource cleanup
380 {
381 struct logical_disk *d;
382 dfe_start_write(dict, d)
383 {
355 - if (d->last_collected < now_ut) {
356 - logical_disk_cleanup(d);
384 + if (d->last_collected < now_ut)
385 dictionary_del(dict, d_dfe.name);
358 - }
386 }
387 dfe_done(d);
388 dictionary_garbage_collect(dict);
@@ -661,15 +688,13 @@ static bool do_physical_disk(PERF_DATA_BLOCK *pDataBlock, int update_every, usec
688 }
689 }
690
664 - // cleanup
691 + // cleanup - delete callback will handle resource cleanup
692 {
693 struct physical_disk *d;
694 dfe_start_write(dict, d)
695 {
669 - if (d->last_collected < now_ut) {
670 - physical_disk_cleanup(d);
696 + if (d->last_collected < now_ut)
697 dictionary_del(dict, d_dfe.name);
672 - }
698 }
699 dfe_done(d);
700 dictionary_garbage_collect(dict);