diff options
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; } |