summaryrefslogtreecommitdiffstats
path: root/src/collectors/diskspace.plugin/plugin_diskspace.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/collectors/diskspace.plugin/plugin_diskspace.c (renamed from collectors/diskspace.plugin/plugin_diskspace.c)291
1 files changed, 134 insertions, 157 deletions
diff --git a/collectors/diskspace.plugin/plugin_diskspace.c b/src/collectors/diskspace.plugin/plugin_diskspace.c
index 94257810c..10e07586c 100644
--- a/collectors/diskspace.plugin/plugin_diskspace.c
+++ b/src/collectors/diskspace.plugin/plugin_diskspace.c
@@ -14,7 +14,7 @@
#define MAX_STAT_USEC 10000LU
#define SLOW_UPDATE_EVERY 5
-static netdata_thread_t *diskspace_slow_thread = NULL;
+static ND_THREAD *diskspace_slow_thread = NULL;
static struct mountinfo *disk_mountinfo_root = NULL;
static int check_for_new_mountpoints_every = 15;
@@ -40,11 +40,10 @@ static inline void mountinfo_reload(int force) {
struct mount_point_metadata {
int do_space;
int do_inodes;
- int shown_error;
- int updated;
- int slow;
- bool function_ready;
+ bool shown_error;
+ bool updated;
+ bool slow;
STRING *filesystem;
STRING *mountroot;
@@ -68,54 +67,51 @@ static DICTIONARY *dict_mountpoints = NULL;
#define rrdset_obsolete_and_pointer_null(st) do { if(st) { rrdset_is_obsolete___safe_from_collector_thread(st); (st) = NULL; } } while(st)
-int mount_point_cleanup(const char *name, void *entry, int slow) {
- (void)name;
-
- struct mount_point_metadata *mp = (struct mount_point_metadata *)entry;
- if(!mp) return 0;
-
- if (slow != mp->slow)
- return 0;
+static void mount_points_cleanup(bool slow) {
+ struct mount_point_metadata *mp;
+ dfe_start_write(dict_mountpoints, mp) {
+ if(mp->slow != slow) continue;
- if(likely(mp->updated)) {
- mp->updated = 0;
- return 0;
+ if(mp->updated)
+ mp->updated = false;
+ else if(cleanup_mount_points)
+ dictionary_del(dict_mountpoints, mp_dfe.name);
}
+ dfe_done(mp);
- if(likely(cleanup_mount_points && mp->collected)) {
- mp->function_ready = false;
- mp->collected = 0;
- mp->updated = 0;
- mp->shown_error = 0;
+ dictionary_garbage_collect(dict_mountpoints);
+}
- string_freez(mp->filesystem);
- string_freez(mp->mountroot);
+void mountpoint_delete_cb(const DICTIONARY_ITEM *item __maybe_unused, void *entry, void *data __maybe_unused) {
+ struct mount_point_metadata *mp = (struct mount_point_metadata *)entry;
- rrdset_obsolete_and_pointer_null(mp->st_space);
- rrdset_obsolete_and_pointer_null(mp->st_inodes);
+ mp->collected = 0;
+ mp->updated = false;
+ mp->shown_error = false;
- mp->rd_space_avail = NULL;
- mp->rd_space_used = NULL;
- mp->rd_space_reserved = NULL;
+ string_freez(mp->filesystem);
+ mp->filesystem = NULL;
- mp->rd_inodes_avail = NULL;
- mp->rd_inodes_used = NULL;
- mp->rd_inodes_reserved = NULL;
- }
+ string_freez(mp->mountroot);
+ mp->mountroot = NULL;
- return 0;
-}
+ rrdset_obsolete_and_pointer_null(mp->st_space);
+ rrdset_obsolete_and_pointer_null(mp->st_inodes);
-int mount_point_cleanup_cb(const DICTIONARY_ITEM *item, void *entry, void *data __maybe_unused) {
- const char *name = dictionary_acquired_item_name(item);
+ mp->rd_space_avail = NULL;
+ mp->rd_space_used = NULL;
+ mp->rd_space_reserved = NULL;
- return mount_point_cleanup(name, (struct mount_point_metadata *)entry, 0);
+ mp->rd_inodes_avail = NULL;
+ mp->rd_inodes_used = NULL;
+ mp->rd_inodes_reserved = NULL;
}
// a copy of basic mountinfo fields
struct basic_mountinfo {
char *persistent_id;
char *root;
+ char *mount_point_stat_path;
char *mount_point;
char *filesystem;
@@ -128,12 +124,13 @@ static netdata_mutex_t slow_mountinfo_mutex;
static struct basic_mountinfo *basic_mountinfo_create_and_copy(struct mountinfo* mi)
{
struct basic_mountinfo *bmi = callocz(1, sizeof(struct basic_mountinfo));
-
+
if (mi) {
bmi->persistent_id = strdupz(mi->persistent_id);
- bmi->root = strdupz(mi->root);
- bmi->mount_point = strdupz(mi->mount_point);
- bmi->filesystem = strdupz(mi->filesystem);
+ bmi->root = strdupz(mi->root);
+ bmi->mount_point_stat_path = strdupz(mi->mount_point_stat_path);
+ bmi->mount_point = strdupz(mi->mount_point);
+ bmi->filesystem = strdupz(mi->filesystem);
}
return bmi;
@@ -148,19 +145,20 @@ static void add_basic_mountinfo(struct basic_mountinfo **root, struct mountinfo
bmi->next = *root;
*root = bmi;
-};
+}
static void free_basic_mountinfo(struct basic_mountinfo *bmi)
{
if (bmi) {
freez(bmi->persistent_id);
freez(bmi->root);
+ freez(bmi->mount_point_stat_path);
freez(bmi->mount_point);
freez(bmi->filesystem);
freez(bmi);
}
-};
+}
static void free_basic_mountinfo_list(struct basic_mountinfo *root)
{
@@ -217,9 +215,7 @@ static void calculate_values_and_show_charts(
int rendered = 0;
- if(m->do_space == CONFIG_BOOLEAN_YES || (m->do_space == CONFIG_BOOLEAN_AUTO &&
- (bavail || breserved_root || bused ||
- netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) {
+ if (m->do_space == CONFIG_BOOLEAN_YES || m->do_space == CONFIG_BOOLEAN_AUTO) {
if(unlikely(!m->st_space) || m->st_space->update_every != update_every) {
m->do_space = CONFIG_BOOLEAN_YES;
m->st_space = rrdset_find_active_bytype_localhost("disk_space", disk);
@@ -257,9 +253,7 @@ static void calculate_values_and_show_charts(
rendered++;
}
- if(m->do_inodes == CONFIG_BOOLEAN_YES || (m->do_inodes == CONFIG_BOOLEAN_AUTO &&
- (favail || freserved_root || fused ||
- netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) {
+ if (m->do_inodes == CONFIG_BOOLEAN_YES || m->do_inodes == CONFIG_BOOLEAN_AUTO) {
if(unlikely(!m->st_inodes) || m->st_inodes->update_every != update_every) {
m->do_inodes = CONFIG_BOOLEAN_YES;
m->st_inodes = rrdset_find_active_bytype_localhost("disk_inodes", disk);
@@ -297,8 +291,6 @@ static void calculate_values_and_show_charts(
rendered++;
}
- m->function_ready = rendered > 0;
-
if(likely(rendered))
m->collected++;
}
@@ -341,11 +333,12 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) {
true);
dict_mountpoints = dictionary_create_advanced(DICT_OPTION_NONE, &dictionary_stats_category_collectors, 0);
+ dictionary_register_delete_callback(dict_mountpoints, mountpoint_delete_cb, NULL);
}
- struct mount_point_metadata *m = dictionary_get(dict_mountpoints, mi->mount_point);
- if(unlikely(!m)) {
- int slow = 0;
+ const DICTIONARY_ITEM *item = dictionary_get_and_acquire_item(dict_mountpoints, mi->mount_point);
+ if(unlikely(!item)) {
+ bool slow = false;
int def_space = config_get_boolean_ondemand(CONFIG_SECTION_DISKSPACE, "space usage for all disks", CONFIG_BOOLEAN_AUTO);
int def_inodes = config_get_boolean_ondemand(CONFIG_SECTION_DISKSPACE, "inodes usage for all disks", CONFIG_BOOLEAN_AUTO);
@@ -369,9 +362,9 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) {
usec_t start_time = now_monotonic_high_precision_usec();
struct stat bs;
- if(stat(mi->mount_point, &bs) == -1) {
+ if(stat(mi->mount_point_stat_path, &bs) == -1) {
collector_error("DISKSPACE: Cannot stat() mount point '%s' (disk '%s', filesystem '%s', root '%s')."
- , mi->mount_point
+ , mi->mount_point_stat_path
, disk
, mi->filesystem?mi->filesystem:""
, mi->root?mi->root:""
@@ -382,7 +375,7 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) {
else {
if((bs.st_mode & S_IFMT) != S_IFDIR) {
collector_error("DISKSPACE: Mount point '%s' (disk '%s', filesystem '%s', root '%s') is not a directory."
- , mi->mount_point
+ , mi->mount_point_stat_path
, disk
, mi->filesystem?mi->filesystem:""
, mi->root?mi->root:""
@@ -393,7 +386,7 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) {
}
if ((now_monotonic_high_precision_usec() - start_time) > slow_timeout)
- slow = 1;
+ slow = true;
}
char var_name[4096 + 1];
@@ -408,76 +401,76 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) {
do_inodes = config_get_boolean_ondemand(var_name, "inodes usage", def_inodes);
struct mount_point_metadata mp = {
- .do_space = do_space,
- .do_inodes = do_inodes,
- .shown_error = 0,
- .updated = 0,
- .slow = 0,
-
- .collected = 0,
-
- .st_space = NULL,
- .rd_space_avail = NULL,
- .rd_space_used = NULL,
- .rd_space_reserved = NULL,
-
- .st_inodes = NULL,
- .rd_inodes_avail = NULL,
- .rd_inodes_used = NULL,
- .rd_inodes_reserved = NULL
+ .do_space = do_space,
+ .do_inodes = do_inodes,
+ .shown_error = false,
+ .updated = false,
+ .slow = slow,
+
+ .collected = 0,
+ .filesystem = string_strdupz(mi->filesystem),
+ .mountroot = string_strdupz(mi->root),
+ .chart_labels = rrdlabels_create(),
+
+ .st_space = NULL,
+ .rd_space_avail = NULL,
+ .rd_space_used = NULL,
+ .rd_space_reserved = NULL,
+
+ .st_inodes = NULL,
+ .rd_inodes_avail = NULL,
+ .rd_inodes_used = NULL,
+ .rd_inodes_reserved = NULL
};
- mp.filesystem = string_strdupz(mi->filesystem);
- mp.mountroot = string_strdupz(mi->root);
-
- mp.chart_labels = rrdlabels_create();
rrdlabels_add(mp.chart_labels, "mount_point", mi->mount_point, RRDLABEL_SRC_AUTO);
rrdlabels_add(mp.chart_labels, "filesystem", mi->filesystem, RRDLABEL_SRC_AUTO);
rrdlabels_add(mp.chart_labels, "mount_root", mi->root, RRDLABEL_SRC_AUTO);
- m = dictionary_set(dict_mountpoints, mi->mount_point, &mp, sizeof(struct mount_point_metadata));
-
- m->slow = slow;
+ item = dictionary_set_and_acquire_item(dict_mountpoints, mi->mount_point, &mp, sizeof(struct mount_point_metadata));
}
+ struct mount_point_metadata *m = dictionary_acquired_item_value(item);
if (m->slow) {
add_basic_mountinfo(&slow_mountinfo_tmp_root, mi);
- return;
+ goto cleanup;
}
- m->updated = 1;
+ m->updated = true;
- if(unlikely(m->do_space == CONFIG_BOOLEAN_NO && m->do_inodes == CONFIG_BOOLEAN_NO))
- return;
+ if(unlikely(m->do_space == CONFIG_BOOLEAN_NO && m->do_inodes == CONFIG_BOOLEAN_NO)) {
+ goto cleanup;
+ }
if (unlikely(
mi->flags & MOUNTINFO_READONLY &&
!(mi->flags & MOUNTINFO_IS_IN_SYSD_PROTECTED_LIST) &&
!m->collected &&
m->do_space != CONFIG_BOOLEAN_YES &&
- m->do_inodes != CONFIG_BOOLEAN_YES))
- return;
+ m->do_inodes != CONFIG_BOOLEAN_YES)) {
+ goto cleanup;
+ }
usec_t start_time = now_monotonic_high_precision_usec();
struct statvfs buff_statvfs;
- if (statvfs(mi->mount_point, &buff_statvfs) < 0) {
+ if (statvfs(mi->mount_point_stat_path, &buff_statvfs) < 0) {
if(!m->shown_error) {
collector_error("DISKSPACE: failed to statvfs() mount point '%s' (disk '%s', filesystem '%s', root '%s')"
- , mi->mount_point
+ , mi->mount_point_stat_path
, disk
, mi->filesystem?mi->filesystem:""
, mi->root?mi->root:""
);
- m->shown_error = 1;
+ m->shown_error = true;
}
- return;
+ goto cleanup;
}
if ((now_monotonic_high_precision_usec() - start_time) > slow_timeout)
- m->slow = 1;
+ m->slow = true;
- m->shown_error = 0;
+ m->shown_error = false;
struct basic_mountinfo bmi;
bmi.mount_point = mi->mount_point;
@@ -486,34 +479,42 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) {
bmi.root = mi->root;
calculate_values_and_show_charts(&bmi, m, &buff_statvfs, update_every);
+
+cleanup:
+ dictionary_acquired_item_release(dict_mountpoints, item);
}
static inline void do_slow_disk_space_stats(struct basic_mountinfo *mi, int update_every) {
- struct mount_point_metadata *m = dictionary_get(dict_mountpoints, mi->mount_point);
+ const DICTIONARY_ITEM *item = dictionary_get_and_acquire_item(dict_mountpoints, mi->mount_point);
+ if(!item) return;
- m->updated = 1;
+ struct mount_point_metadata *m = dictionary_acquired_item_value(item);
+ m->updated = true;
struct statvfs buff_statvfs;
- if (statvfs(mi->mount_point, &buff_statvfs) < 0) {
+ if (statvfs(mi->mount_point_stat_path, &buff_statvfs) < 0) {
if(!m->shown_error) {
collector_error("DISKSPACE: failed to statvfs() mount point '%s' (disk '%s', filesystem '%s', root '%s')"
- , mi->mount_point
+ , mi->mount_point_stat_path
, mi->persistent_id
, mi->filesystem?mi->filesystem:""
, mi->root?mi->root:""
);
- m->shown_error = 1;
+ m->shown_error = true;
}
- return;
+ goto cleanup;
}
- m->shown_error = 0;
+ m->shown_error = false;
calculate_values_and_show_charts(mi, m, &buff_statvfs, update_every);
+
+cleanup:
+ dictionary_acquired_item_release(dict_mountpoints, item);
}
-static void diskspace_slow_worker_cleanup(void *ptr)
-{
- UNUSED(ptr);
+static void diskspace_slow_worker_cleanup(void *pptr) {
+ struct slow_worker_data *data = CLEANUP_FUNCTION_GET_PTR(pptr);
+ if(data) return;
collector_info("cleaning up...");
@@ -524,14 +525,14 @@ static void diskspace_slow_worker_cleanup(void *ptr)
#define WORKER_JOB_SLOW_CLEANUP 1
struct slow_worker_data {
- netdata_thread_t *slow_thread;
int update_every;
};
void *diskspace_slow_worker(void *ptr)
{
struct slow_worker_data *data = (struct slow_worker_data *)ptr;
-
+ CLEANUP_FUNCTION_REGISTER(diskspace_slow_worker_cleanup) cleanup_ptr = data;
+
worker_register("DISKSPACE_SLOW");
worker_register_job_name(WORKER_JOB_SLOW_MOUNTPOINT, "mountpoint");
worker_register_job_name(WORKER_JOB_SLOW_CLEANUP, "cleanup");
@@ -540,8 +541,6 @@ void *diskspace_slow_worker(void *ptr)
int slow_update_every = data->update_every > SLOW_UPDATE_EVERY ? data->update_every : SLOW_UPDATE_EVERY;
- netdata_thread_cleanup_push(diskspace_slow_worker_cleanup, data->slow_thread);
-
usec_t step = slow_update_every * USEC_PER_SEC;
usec_t real_step = USEC_PER_SEC;
heartbeat_t hb;
@@ -584,13 +583,9 @@ void *diskspace_slow_worker(void *ptr)
if(unlikely(!service_running(SERVICE_COLLECTORS))) break;
- worker_is_busy(WORKER_JOB_SLOW_CLEANUP);
-
- for(bmi = slow_mountinfo_root; bmi; bmi = bmi->next) {
- struct mount_point_metadata *m = dictionary_get(dict_mountpoints, bmi->mount_point);
-
- if (m)
- mount_point_cleanup(bmi->mount_point, m, 1);
+ if(dict_mountpoints) {
+ worker_is_busy(WORKER_JOB_SLOW_CLEANUP);
+ mount_points_cleanup(true);
}
usec_t dt = now_monotonic_high_precision_usec() - start_time;
@@ -602,26 +597,24 @@ void *diskspace_slow_worker(void *ptr)
}
}
- netdata_thread_cleanup_pop(1);
-
free_basic_mountinfo_list(slow_mountinfo_root);
return NULL;
}
-static void diskspace_main_cleanup(void *ptr) {
- rrd_collector_finished();
- worker_unregister();
+static void diskspace_main_cleanup(void *pptr) {
+ struct netdata_static_thread *static_thread = CLEANUP_FUNCTION_GET_PTR(pptr);
+ if(!static_thread) return;
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
collector_info("cleaning up...");
- if (diskspace_slow_thread) {
- netdata_thread_join(*diskspace_slow_thread, NULL);
- freez(diskspace_slow_thread);
- }
+ rrd_collector_finished();
+ worker_unregister();
+
+ if (diskspace_slow_thread)
+ nd_thread_join(diskspace_slow_thread);
free_basic_mountinfo_list(slow_mountinfo_tmp_root);
@@ -636,12 +629,8 @@ static void diskspace_main_cleanup(void *ptr) {
#error WORKER_UTILIZATION_MAX_JOB_TYPES has to be at least 3
#endif
-int diskspace_function_mount_points(BUFFER *wb, int timeout __maybe_unused, const char *function __maybe_unused,
- void *collector_data __maybe_unused,
- rrd_function_result_callback_t result_cb, void *result_cb_data,
- rrd_function_is_cancelled_cb_t is_cancelled_cb, void *is_cancelled_cb_data,
- rrd_function_register_canceller_cb_t register_canceller_cb __maybe_unused,
- void *register_canceller_cb_data __maybe_unused) {
+int diskspace_function_mount_points(BUFFER *wb, const char *function __maybe_unused) {
+ netdata_mutex_lock(&slow_mountinfo_mutex);
buffer_flush(wb);
wb->content_type = CT_APPLICATION_JSON;
@@ -651,6 +640,7 @@ int diskspace_function_mount_points(BUFFER *wb, int timeout __maybe_unused, cons
buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
buffer_json_member_add_string(wb, "type", "table");
buffer_json_member_add_time_t(wb, "update_every", 1);
+ buffer_json_member_add_boolean(wb, "has_history", false);
buffer_json_member_add_string(wb, "help", RRDFUNCTIONS_DISKSPACE_HELP);
buffer_json_member_add_array(wb, "data");
@@ -665,8 +655,8 @@ int diskspace_function_mount_points(BUFFER *wb, int timeout __maybe_unused, cons
double max_inodes_reserved = 0.0;
struct mount_point_metadata *mp;
- dfe_start_write(dict_mountpoints, mp) {
- if (!mp->function_ready)
+ dfe_start_read(dict_mountpoints, mp) {
+ if (!mp->collected)
continue;
buffer_json_add_array_item_array(wb);
@@ -846,28 +836,22 @@ int diskspace_function_mount_points(BUFFER *wb, int timeout __maybe_unused, cons
buffer_json_member_add_time_t(wb, "expires", now_realtime_sec() + 1);
buffer_json_finalize(wb);
- int response = HTTP_RESP_OK;
- if(is_cancelled_cb && is_cancelled_cb(is_cancelled_cb_data)) {
- buffer_flush(wb);
- response = HTTP_RESP_CLIENT_CLOSED_REQUEST;
- }
-
- if(result_cb)
- result_cb(wb, response, result_cb_data);
-
- return response;
+ netdata_mutex_unlock(&slow_mountinfo_mutex);
+ return HTTP_RESP_OK;
}
void *diskspace_main(void *ptr) {
+ CLEANUP_FUNCTION_REGISTER(diskspace_main_cleanup) cleanup_ptr = ptr;
+
worker_register("DISKSPACE");
worker_register_job_name(WORKER_JOB_MOUNTINFO, "mountinfo");
worker_register_job_name(WORKER_JOB_MOUNTPOINT, "mountpoint");
worker_register_job_name(WORKER_JOB_CLEANUP, "cleanup");
- rrd_collector_started();
- rrd_function_add(localhost, NULL, "mount-points", 10, RRDFUNCTIONS_DISKSPACE_HELP, true, diskspace_function_mount_points, NULL);
-
- netdata_thread_cleanup_push(diskspace_main_cleanup, ptr);
+ rrd_function_add_inline(localhost, NULL, "mount-points", 10,
+ RRDFUNCTIONS_PRIORITY_DEFAULT, RRDFUNCTIONS_DISKSPACE_HELP,
+ "top", HTTP_ACCESS_ANONYMOUS_DATA,
+ diskspace_function_mount_points);
cleanup_mount_points = config_get_boolean(CONFIG_SECTION_DISKSPACE, "remove charts of unmounted disks" , cleanup_mount_points);
@@ -881,12 +865,9 @@ void *diskspace_main(void *ptr) {
netdata_mutex_init(&slow_mountinfo_mutex);
- diskspace_slow_thread = mallocz(sizeof(netdata_thread_t));
-
- struct slow_worker_data slow_worker_data = {.slow_thread = diskspace_slow_thread, .update_every = update_every};
+ struct slow_worker_data slow_worker_data = { .update_every = update_every };
- netdata_thread_create(
- diskspace_slow_thread,
+ diskspace_slow_thread = nd_thread_create(
"P[diskspace slow]",
NETDATA_THREAD_OPTION_JOINABLE,
diskspace_slow_worker,
@@ -934,12 +915,8 @@ void *diskspace_main(void *ptr) {
if(dict_mountpoints) {
worker_is_busy(WORKER_JOB_CLEANUP);
- dictionary_walkthrough_read(dict_mountpoints, mount_point_cleanup_cb, NULL);
+ mount_points_cleanup(false);
}
-
}
- worker_unregister();
-
- netdata_thread_cleanup_pop(1);
return NULL;
}