X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fprocesses.c;h=82a485900537e891336ac5185c67cd951ed33d28;hb=b165cd13cd30a30ac830df1f6f6fbd52474a6f64;hp=63c3c0e526fb6c2bc36dcbc44e5b264494aa5188;hpb=79963d13c1884d1d92667cc502ad20758b084a12;p=collectd.git diff --git a/src/processes.c b/src/processes.c index 63c3c0e5..82a48590 100644 --- a/src/processes.c +++ b/src/processes.c @@ -32,6 +32,7 @@ * Manuel Sanmartin * Clément Stenac * Cosmin Ioiart + * Pavel Rochnyack **/ #include "collectd.h" @@ -159,25 +160,47 @@ #endif #endif -typedef struct procstat_entry_s { +#define PROCSTAT_NAME_LEN 256 +typedef struct process_entry_s { unsigned long id; - unsigned long age; + char name[PROCSTAT_NAME_LEN]; unsigned long num_proc; unsigned long num_lwp; + unsigned long num_fd; unsigned long vmem_size; unsigned long vmem_rss; unsigned long vmem_data; unsigned long vmem_code; unsigned long stack_size; - unsigned long vmem_minflt; - unsigned long vmem_majflt; derive_t vmem_minflt_counter; derive_t vmem_majflt_counter; - unsigned long cpu_user; - unsigned long cpu_system; + derive_t cpu_user_counter; + derive_t cpu_system_counter; + + /* io data */ + derive_t io_rchar; + derive_t io_wchar; + derive_t io_syscr; + derive_t io_syscw; + _Bool has_io; + + derive_t cswitch_vol; + derive_t cswitch_invol; + _Bool has_cswitch; + + _Bool has_fd; +} process_entry_t; + +typedef struct procstat_entry_s { + unsigned long id; + unsigned long age; + + derive_t vmem_minflt_counter; + derive_t vmem_majflt_counter; + derive_t cpu_user_counter; derive_t cpu_system_counter; @@ -193,7 +216,6 @@ typedef struct procstat_entry_s { struct procstat_entry_s *next; } procstat_entry_t; -#define PROCSTAT_NAME_LEN 256 typedef struct procstat { char name[PROCSTAT_NAME_LEN]; #if HAVE_REGEX_H @@ -202,6 +224,7 @@ typedef struct procstat { unsigned long num_proc; unsigned long num_lwp; + unsigned long num_fd; unsigned long vmem_size; unsigned long vmem_rss; unsigned long vmem_data; @@ -223,13 +246,18 @@ typedef struct procstat { derive_t cswitch_vol; derive_t cswitch_invol; + _Bool report_fd_num; + _Bool report_ctx_switch; + struct procstat *next; struct procstat_entry_s *instances; } procstat_t; static procstat_t *list_head_g = NULL; +static _Bool want_init = 1; static _Bool report_ctx_switch = 0; +static _Bool report_fd_num = 0; #if HAVE_THREAD_INFO static mach_port_t port_host_self; @@ -241,6 +269,7 @@ static mach_msg_type_number_t pset_list_len; #elif KERNEL_LINUX static long pagesize_g; +static void ps_fill_details(const procstat_t *ps, process_entry_t *entry); /* #endif KERNEL_LINUX */ #elif HAVE_LIBKVM_GETPROCS && \ @@ -265,7 +294,7 @@ int getargs(void *processBuffer, int bufferLen, char *argsBuffer, int argsLen); /* put name of process from config to list_head_g tree * list_head_g is a list of 'procstat_t' structs with * processes names we want to watch */ -static void ps_list_register(const char *name, const char *regexp) { +static procstat_t *ps_list_register(const char *name, const char *regexp) { procstat_t *new; procstat_t *ptr; int status; @@ -273,10 +302,20 @@ static void ps_list_register(const char *name, const char *regexp) { new = calloc(1, sizeof(*new)); if (new == NULL) { ERROR("processes plugin: ps_list_register: calloc failed."); - return; + return NULL; } sstrncpy(new->name, name, sizeof(new->name)); + new->io_rchar = -1; + new->io_wchar = -1; + new->io_syscr = -1; + new->io_syscw = -1; + new->cswitch_vol = -1; + new->cswitch_invol = -1; + + new->report_fd_num = report_fd_num; + new->report_ctx_switch = report_ctx_switch; + #if HAVE_REGEX_H if (regexp != NULL) { DEBUG("ProcessMatch: adding \"%s\" as criteria to process %s.", regexp, @@ -285,7 +324,7 @@ static void ps_list_register(const char *name, const char *regexp) { if (new->re == NULL) { ERROR("processes plugin: ps_list_register: malloc failed."); sfree(new); - return; + return NULL; } status = regcomp(new->re, regexp, REG_EXTENDED | REG_NOSUB); @@ -294,7 +333,7 @@ static void ps_list_register(const char *name, const char *regexp) { regexp); sfree(new->re); sfree(new); - return; + return NULL; } } #else @@ -305,7 +344,7 @@ static void ps_list_register(const char *name, const char *regexp) { "has been disabled at compile time.", regexp); sfree(new); - return; + return NULL; } #endif @@ -320,7 +359,7 @@ static void ps_list_register(const char *name, const char *regexp) { sfree(new->re); #endif sfree(new); - return; + return NULL; } if (ptr->next == NULL) @@ -331,6 +370,8 @@ static void ps_list_register(const char *name, const char *regexp) { list_head_g = new; else ptr->next = new; + + return new; } /* void ps_list_register */ /* try to match name against entry, returns 1 if success */ @@ -352,48 +393,52 @@ static int ps_list_match(const char *name, const char *cmdline, /* pmatch = */ NULL, /* eflags = */ 0); if (status == 0) - return (1); + return 1; } else #endif if (strcmp(ps->name, name) == 0) - return (1); + return 1; - return (0); + return 0; } /* int ps_list_match */ -static void ps_update_counter(_Bool init, derive_t *group_counter, - derive_t *curr_counter, unsigned long *curr_value, - derive_t new_counter, unsigned long new_value) { - if (init) { - *curr_value = new_value; - *curr_counter += new_value; - *group_counter += new_value; +static void ps_update_counter(derive_t *group_counter, derive_t *curr_counter, + derive_t new_counter) { + unsigned long curr_value; + + if (want_init) { + *curr_counter = new_counter; return; } if (new_counter < *curr_counter) - *curr_value = new_counter + (ULONG_MAX - *curr_counter); + curr_value = new_counter + (ULONG_MAX - *curr_counter); else - *curr_value = new_counter - *curr_counter; + curr_value = new_counter - *curr_counter; + + if (*group_counter == -1) + *group_counter = 0; *curr_counter = new_counter; - *group_counter += *curr_value; + *group_counter += curr_value; } /* add process entry to 'instances' of process 'name' (or refresh it) */ static void ps_list_add(const char *name, const char *cmdline, - procstat_entry_t *entry) { + process_entry_t *entry) { procstat_entry_t *pse; if (entry->id == 0) return; for (procstat_t *ps = list_head_g; ps != NULL; ps = ps->next) { - _Bool want_init; - if ((ps_list_match(name, cmdline, ps)) == 0) continue; +#if KERNEL_LINUX + ps_fill_details(ps, entry); +#endif + for (pse = ps->instances; pse != NULL; pse = pse->next) if ((pse->id == entry->id) || (pse->next == NULL)) break; @@ -415,52 +460,42 @@ static void ps_list_add(const char *name, const char *cmdline, } pse->age = 0; - pse->num_proc = entry->num_proc; - pse->num_lwp = entry->num_lwp; - pse->vmem_size = entry->vmem_size; - pse->vmem_rss = entry->vmem_rss; - pse->vmem_data = entry->vmem_data; - pse->vmem_code = entry->vmem_code; - pse->stack_size = entry->stack_size; - pse->io_rchar = entry->io_rchar; - pse->io_wchar = entry->io_wchar; - pse->io_syscr = entry->io_syscr; - pse->io_syscw = entry->io_syscw; - pse->cswitch_vol = entry->cswitch_vol; - pse->cswitch_invol = entry->cswitch_invol; - - ps->num_proc += pse->num_proc; - ps->num_lwp += pse->num_lwp; - ps->vmem_size += pse->vmem_size; - ps->vmem_rss += pse->vmem_rss; - ps->vmem_data += pse->vmem_data; - ps->vmem_code += pse->vmem_code; - ps->stack_size += pse->stack_size; - - ps->io_rchar += ((pse->io_rchar == -1) ? 0 : pse->io_rchar); - ps->io_wchar += ((pse->io_wchar == -1) ? 0 : pse->io_wchar); - ps->io_syscr += ((pse->io_syscr == -1) ? 0 : pse->io_syscr); - ps->io_syscw += ((pse->io_syscw == -1) ? 0 : pse->io_syscw); - - ps->cswitch_vol += ((pse->cswitch_vol == -1) ? 0 : pse->cswitch_vol); - ps->cswitch_invol += ((pse->cswitch_invol == -1) ? 0 : pse->cswitch_invol); - - want_init = - (entry->vmem_minflt_counter == 0) && (entry->vmem_majflt_counter == 0); - ps_update_counter(want_init, &ps->vmem_minflt_counter, - &pse->vmem_minflt_counter, &pse->vmem_minflt, - entry->vmem_minflt_counter, entry->vmem_minflt); - ps_update_counter(want_init, &ps->vmem_majflt_counter, - &pse->vmem_majflt_counter, &pse->vmem_majflt, - entry->vmem_majflt_counter, entry->vmem_majflt); - - want_init = - (entry->cpu_user_counter == 0) && (entry->cpu_system_counter == 0); - ps_update_counter(want_init, &ps->cpu_user_counter, &pse->cpu_user_counter, - &pse->cpu_user, entry->cpu_user_counter, entry->cpu_user); - ps_update_counter(want_init, &ps->cpu_system_counter, - &pse->cpu_system_counter, &pse->cpu_system, - entry->cpu_system_counter, entry->cpu_system); + + ps->num_proc += entry->num_proc; + ps->num_lwp += entry->num_lwp; + ps->num_fd += entry->num_fd; + ps->vmem_size += entry->vmem_size; + ps->vmem_rss += entry->vmem_rss; + ps->vmem_data += entry->vmem_data; + ps->vmem_code += entry->vmem_code; + ps->stack_size += entry->stack_size; + + if ((entry->io_rchar != -1) && (entry->io_wchar != -1)) { + ps_update_counter(&ps->io_rchar, &pse->io_rchar, entry->io_rchar); + ps_update_counter(&ps->io_wchar, &pse->io_wchar, entry->io_wchar); + } + + if ((entry->io_syscr != -1) && (entry->io_syscw != -1)) { + ps_update_counter(&ps->io_syscr, &pse->io_syscr, entry->io_syscr); + ps_update_counter(&ps->io_syscw, &pse->io_syscw, entry->io_syscw); + } + + if ((entry->cswitch_vol != -1) && (entry->cswitch_vol != -1)) { + ps_update_counter(&ps->cswitch_vol, &pse->cswitch_vol, + entry->cswitch_vol); + ps_update_counter(&ps->cswitch_invol, &pse->cswitch_invol, + entry->cswitch_invol); + } + + ps_update_counter(&ps->vmem_minflt_counter, &pse->vmem_minflt_counter, + entry->vmem_minflt_counter); + ps_update_counter(&ps->vmem_majflt_counter, &pse->vmem_majflt_counter, + entry->vmem_majflt_counter); + + ps_update_counter(&ps->cpu_user_counter, &pse->cpu_user_counter, + entry->cpu_user_counter); + ps_update_counter(&ps->cpu_system_counter, &pse->cpu_system_counter, + entry->cpu_system_counter); } } @@ -472,17 +507,12 @@ static void ps_list_reset(void) { for (procstat_t *ps = list_head_g; ps != NULL; ps = ps->next) { ps->num_proc = 0; ps->num_lwp = 0; + ps->num_fd = 0; ps->vmem_size = 0; ps->vmem_rss = 0; ps->vmem_data = 0; ps->vmem_code = 0; ps->stack_size = 0; - ps->io_rchar = -1; - ps->io_wchar = -1; - ps->io_syscr = -1; - ps->io_syscw = -1; - ps->cswitch_vol = -1; - ps->cswitch_invol = -1; pse_prev = NULL; pse = ps->instances; @@ -510,6 +540,20 @@ static void ps_list_reset(void) { } /* for (ps = list_head_g; ps != NULL; ps = ps->next) */ } +static void ps_tune_instance(oconfig_item_t *ci, procstat_t *ps) { + for (int i = 0; i < ci->children_num; i++) { + oconfig_item_t *c = ci->children + i; + + if (strcasecmp(c->key, "CollectContextSwitch") == 0) + cf_util_get_boolean(c, &ps->report_ctx_switch); + else if (strcasecmp(c->key, "CollectFileDescriptor") == 0) + cf_util_get_boolean(c, &ps->report_fd_num); + else { + ERROR("processes plugin: Option `%s' not allowed here.", c->key); + } + } /* for (ci->children) */ +} /* void ps_tune_instance */ + /* put all pre-defined 'Process' names from config to list_head_g tree */ static int ps_config(oconfig_item_t *ci) { #if KERNEL_LINUX @@ -518,6 +562,8 @@ static int ps_config(oconfig_item_t *ci) { const size_t max_procname_len = MAXCOMLEN - 1; #endif + procstat_t *ps; + for (int i = 0; i < ci->children_num; ++i) { oconfig_item_t *c = ci->children + i; @@ -529,13 +575,6 @@ static int ps_config(oconfig_item_t *ci) { continue; } - if (c->children_num != 0) { - WARNING("processes plugin: the `Process' config option " - "does not expect any child elements -- ignoring " - "content (%i elements) of the block.", - c->children_num, c->values[0].value.string); - } - #if KERNEL_LINUX || KERNEL_SOLARIS || KERNEL_FREEBSD if (strlen(c->values[0].value.string) > max_procname_len) { WARNING("processes plugin: this platform has a %zu character limit " @@ -545,7 +584,10 @@ static int ps_config(oconfig_item_t *ci) { } #endif - ps_list_register(c->values[0].value.string, NULL); + ps = ps_list_register(c->values[0].value.string, NULL); + + if (c->children_num != 0 && ps != NULL) + ps_tune_instance(c, ps); } else if (strcasecmp(c->key, "ProcessMatch") == 0) { if ((c->values_num != 2) || (OCONFIG_TYPE_STRING != c->values[0].type) || (OCONFIG_TYPE_STRING != c->values[1].type)) { @@ -555,18 +597,15 @@ static int ps_config(oconfig_item_t *ci) { continue; } - if (c->children_num != 0) { - WARNING("processes plugin: the `ProcessMatch' config option " - "does not expect any child elements -- ignoring " - "content (%i elements) of the " - "block.", - c->children_num, c->values[0].value.string, - c->values[1].value.string); - } + ps = ps_list_register(c->values[0].value.string, + c->values[1].value.string); - ps_list_register(c->values[0].value.string, c->values[1].value.string); + if (c->children_num != 0 && ps != NULL) + ps_tune_instance(c, ps); } else if (strcasecmp(c->key, "CollectContextSwitch") == 0) { cf_util_get_boolean(c, &report_ctx_switch); + } else if (strcasecmp(c->key, "CollectFileDescriptor") == 0) { + cf_util_get_boolean(c, &report_fd_num); } else { ERROR("processes plugin: The `%s' configuration option is not " "understood and will be ignored.", @@ -575,7 +614,7 @@ static int ps_config(oconfig_item_t *ci) { } } - return (0); + return 0; } static int ps_init(void) { @@ -597,7 +636,7 @@ static int ps_init(void) { ERROR("host_processor_sets failed: %s\n", mach_error_string(status)); pset_list = NULL; pset_list_len = 0; - return (-1); + return -1; } /* #endif HAVE_THREAD_INFO */ @@ -616,19 +655,15 @@ static int ps_init(void) { pagesize = getpagesize(); #endif /* HAVE_PROCINFO_H */ - return (0); + return 0; } /* int ps_init */ /* submit global state (e.g.: qty of zombies, running, etc..) */ static void ps_submit_state(const char *state, double value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t){.gauge = value}; vl.values_len = 1; - sstrncpy(vl.host, hostname_g, sizeof(vl.host)); sstrncpy(vl.plugin, "processes", sizeof(vl.plugin)); sstrncpy(vl.plugin_instance, "", sizeof(vl.plugin_instance)); sstrncpy(vl.type, "ps_state", sizeof(vl.type)); @@ -639,12 +674,10 @@ static void ps_submit_state(const char *state, double value) { /* submit info about specific process (e.g.: memory taken, cpu usage, etc..) */ static void ps_submit_proc_list(procstat_t *ps) { - value_t values[2]; value_list_t vl = VALUE_LIST_INIT; + value_t values[2]; vl.values = values; - vl.values_len = 2; - sstrncpy(vl.host, hostname_g, sizeof(vl.host)); sstrncpy(vl.plugin, "processes", sizeof(vl.plugin)); sstrncpy(vl.plugin_instance, ps->name, sizeof(vl.plugin_instance)); @@ -707,7 +740,14 @@ static void ps_submit_proc_list(procstat_t *ps) { plugin_dispatch_values(&vl); } - if (report_ctx_switch) { + if (ps->num_fd > 0) { + sstrncpy(vl.type, "file_handles", sizeof(vl.type)); + vl.values[0].gauge = ps->num_fd; + vl.values_len = 1; + plugin_dispatch_values(&vl); + } + + if ((ps->cswitch_vol != -1) && (ps->cswitch_invol != -1)) { sstrncpy(vl.type, "contextswitch", sizeof(vl.type)); sstrncpy(vl.type_instance, "voluntary", sizeof(vl.type_instance)); vl.values[0].derive = ps->cswitch_vol; @@ -721,7 +761,7 @@ static void ps_submit_proc_list(procstat_t *ps) { plugin_dispatch_values(&vl); } - DEBUG("name = %s; num_proc = %lu; num_lwp = %lu; " + DEBUG("name = %s; num_proc = %lu; num_lwp = %lu; num_fd = %lu; " "vmem_size = %lu; vmem_rss = %lu; vmem_data = %lu; " "vmem_code = %lu; " "vmem_minflt_counter = %" PRIi64 "; vmem_majflt_counter = %" PRIi64 "; " @@ -729,8 +769,8 @@ static void ps_submit_proc_list(procstat_t *ps) { "io_rchar = %" PRIi64 "; io_wchar = %" PRIi64 "; " "io_syscr = %" PRIi64 "; io_syscw = %" PRIi64 "; " "cswitch_vol = %" PRIi64 "; cswitch_invol = %" PRIi64 ";", - ps->name, ps->num_proc, ps->num_lwp, ps->vmem_size, ps->vmem_rss, - ps->vmem_data, ps->vmem_code, ps->vmem_minflt_counter, + ps->name, ps->num_proc, ps->num_lwp, ps->num_fd, ps->vmem_size, + ps->vmem_rss, ps->vmem_data, ps->vmem_code, ps->vmem_minflt_counter, ps->vmem_majflt_counter, ps->cpu_user_counter, ps->cpu_system_counter, ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw, ps->cswitch_vol, ps->cswitch_invol); @@ -738,14 +778,10 @@ static void ps_submit_proc_list(procstat_t *ps) { #if KERNEL_LINUX || KERNEL_SOLARIS static void ps_submit_fork_rate(derive_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].derive = value; - - vl.values = values; + vl.values = &(value_t){.derive = value}; vl.values_len = 1; - sstrncpy(vl.host, hostname_g, sizeof(vl.host)); sstrncpy(vl.plugin, "processes", sizeof(vl.plugin)); sstrncpy(vl.plugin_instance, "", sizeof(vl.plugin_instance)); sstrncpy(vl.type, "fork_rate", sizeof(vl.type)); @@ -757,7 +793,7 @@ static void ps_submit_fork_rate(derive_t value) { /* ------- additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */ #if KERNEL_LINUX -static procstat_t *ps_read_tasks_status(long pid, procstat_t *ps) { +static int ps_read_tasks_status(process_entry_t *ps) { char dirname[64]; DIR *dh; char filename[64]; @@ -769,11 +805,11 @@ static procstat_t *ps_read_tasks_status(long pid, procstat_t *ps) { char *fields[8]; int numfields; - ssnprintf(dirname, sizeof(dirname), "/proc/%li/task", pid); + ssnprintf(dirname, sizeof(dirname), "/proc/%li/task", ps->id); if ((dh = opendir(dirname)) == NULL) { DEBUG("Failed to open directory `%s'", dirname); - return (NULL); + return -1; } while ((ent = readdir(dh)) != NULL) { @@ -784,7 +820,7 @@ static procstat_t *ps_read_tasks_status(long pid, procstat_t *ps) { tpid = ent->d_name; - ssnprintf(filename, sizeof(filename), "/proc/%li/task/%s/status", pid, + ssnprintf(filename, sizeof(filename), "/proc/%li/task/%s/status", ps->id, tpid); if ((fh = fopen(filename, "r")) == NULL) { DEBUG("Failed to open file `%s'", filename); @@ -827,11 +863,11 @@ static procstat_t *ps_read_tasks_status(long pid, procstat_t *ps) { ps->cswitch_vol = cswitch_vol; ps->cswitch_invol = cswitch_invol; - return (ps); + return 0; } /* int *ps_read_tasks_status */ /* Read data from /proc/pid/status */ -static procstat_t *ps_read_status(long pid, procstat_t *ps) { +static int ps_read_status(long pid, process_entry_t *ps) { FILE *fh; char buffer[1024]; char filename[64]; @@ -844,7 +880,7 @@ static procstat_t *ps_read_status(long pid, procstat_t *ps) { ssnprintf(filename, sizeof(filename), "/proc/%li/status", pid); if ((fh = fopen(filename, "r")) == NULL) - return (NULL); + return -1; while (fgets(buffer, sizeof(buffer), fh) != NULL) { unsigned long tmp; @@ -884,10 +920,10 @@ static procstat_t *ps_read_status(long pid, procstat_t *ps) { if (threads != 0) ps->num_lwp = threads; - return (ps); -} /* procstat_t *ps_read_vmem */ + return 0; +} /* int *ps_read_status */ -static procstat_t *ps_read_io(long pid, procstat_t *ps) { +static int ps_read_io(process_entry_t *ps) { FILE *fh; char buffer[1024]; char filename[64]; @@ -895,9 +931,11 @@ static procstat_t *ps_read_io(long pid, procstat_t *ps) { char *fields[8]; int numfields; - ssnprintf(filename, sizeof(filename), "/proc/%li/io", pid); - if ((fh = fopen(filename, "r")) == NULL) - return (NULL); + ssnprintf(filename, sizeof(filename), "/proc/%li/io", ps->id); + if ((fh = fopen(filename, "r")) == NULL) { + DEBUG("ps_read_io: Failed to open file `%s'", filename); + return -1; + } while (fgets(buffer, sizeof(buffer), fh) != NULL) { derive_t *val = NULL; @@ -933,11 +971,55 @@ static procstat_t *ps_read_io(long pid, procstat_t *ps) { char errbuf[1024]; WARNING("processes: fclose: %s", sstrerror(errno, errbuf, sizeof(errbuf))); } + return 0; +} /* int ps_read_io (...) */ + +static int ps_count_fd(int pid) { + char dirname[64]; + DIR *dh; + struct dirent *ent; + int count = 0; + + ssnprintf(dirname, sizeof(dirname), "/proc/%i/fd", pid); + + if ((dh = opendir(dirname)) == NULL) { + DEBUG("Failed to open directory `%s'", dirname); + return -1; + } + while ((ent = readdir(dh)) != NULL) { + if (!isdigit((int)ent->d_name[0])) + continue; + else + count++; + } + closedir(dh); + + return (count >= 1) ? count : 1; +} /* int ps_count_fd (pid) */ + +static void ps_fill_details(const procstat_t *ps, process_entry_t *entry) { + if (entry->has_io == 0) { + ps_read_io(entry); + entry->has_io = 1; + } + + if (ps->report_ctx_switch) { + if (entry->has_cswitch == 0) { + ps_read_tasks_status(entry); + entry->has_cswitch = 1; + } + } - return (ps); -} /* procstat_t *ps_read_io */ + if (ps->report_fd_num) { + int num_fd; + if (entry->has_fd == 0 && (num_fd = ps_count_fd(entry->id)) > 0) { + entry->num_fd = num_fd; + } + entry->has_fd = 1; + } +} /* void ps_fill_details (...) */ -static int ps_read_process(long pid, procstat_t *ps, char *state) { +static int ps_read_process(long pid, process_entry_t *ps, char *state) { char filename[64]; char buffer[1024]; @@ -959,13 +1041,11 @@ static int ps_read_process(long pid, procstat_t *ps, char *state) { ssize_t status; - memset(ps, 0, sizeof(procstat_t)); - ssnprintf(filename, sizeof(filename), "/proc/%li/stat", pid); status = read_file_contents(filename, buffer, sizeof(buffer) - 1); if (status <= 0) - return (-1); + return -1; buffer_len = (size_t)status; buffer[buffer_len] = 0; @@ -987,7 +1067,7 @@ static int ps_read_process(long pid, procstat_t *ps, char *state) { if (name_start_pos >= name_end_pos) { ERROR("processes plugin: name_start_pos = %zu >= name_end_pos = %zu", name_start_pos, name_end_pos); - return (-1); + return -1; } name_len = (name_end_pos - name_start_pos) - 1; @@ -997,7 +1077,7 @@ static int ps_read_process(long pid, procstat_t *ps, char *state) { sstrncpy(ps->name, &buffer[name_start_pos + 1], name_len + 1); if ((buffer_len - name_end_pos) < 2) - return (-1); + return -1; buffer_ptr = &buffer[name_end_pos + 2]; fields_len = strsplit(buffer_ptr, fields, STATIC_ARRAY_SIZE(fields)); @@ -1005,7 +1085,7 @@ static int ps_read_process(long pid, procstat_t *ps, char *state) { DEBUG("processes plugin: ps_read_process (pid = %li):" " `%s' has only %i fields..", pid, filename, fields_len); - return (-1); + return -1; } *state = fields[0][0]; @@ -1015,7 +1095,7 @@ static int ps_read_process(long pid, procstat_t *ps, char *state) { ps->num_proc = 0; } else { ps->num_lwp = strtoul(fields[17], /* endptr = */ NULL, /* base = */ 10); - if ((ps_read_status(pid, ps)) == NULL) { + if ((ps_read_status(pid, ps)) != 0) { /* No VMem data */ ps->vmem_data = -1; ps->vmem_code = -1; @@ -1031,7 +1111,7 @@ static int ps_read_process(long pid, procstat_t *ps, char *state) { DEBUG("processes plugin: This is only a zombie: pid = %li; " "name = %s;", pid, ps->name); - return (0); + return 0; } cpu_user_counter = atoll(fields[11]); @@ -1060,29 +1140,17 @@ static int ps_read_process(long pid, procstat_t *ps, char *state) { ps->vmem_rss = (unsigned long)vmem_rss; ps->stack_size = (unsigned long)stack_size; - if ((ps_read_io(pid, ps)) == NULL) { - /* no io data */ - ps->io_rchar = -1; - ps->io_wchar = -1; - ps->io_syscr = -1; - ps->io_syscw = -1; + /* no data by default. May be filled by ps_fill_details () */ + ps->io_rchar = -1; + ps->io_wchar = -1; + ps->io_syscr = -1; + ps->io_syscw = -1; - DEBUG("ps_read_process: not get io data for pid %li", pid); - } - - if (report_ctx_switch) { - if ((ps_read_tasks_status(pid, ps)) == NULL) { - ps->cswitch_vol = -1; - ps->cswitch_invol = -1; - - DEBUG("ps_read_tasks_status: not get context " - "switch data for pid %li", - pid); - } - } + ps->cswitch_vol = -1; + ps->cswitch_invol = -1; /* success */ - return (0); + return 0; } /* int ps_read_process (...) */ static char *ps_get_cmdline(long pid, char *name, char *buf, size_t buf_len) { @@ -1189,7 +1257,7 @@ static int read_fork_rate(void) { char errbuf[1024]; ERROR("processes plugin: fopen (/proc/stat) failed: %s", sstrerror(errno, errbuf, sizeof(errbuf))); - return (-1); + return -1; } while (fgets(buffer, sizeof(buffer), proc_stat) != NULL) { @@ -1213,10 +1281,10 @@ static int read_fork_rate(void) { fclose(proc_stat); if (!value_valid) - return (-1); + return -1; ps_submit_fork_rate(value.derive); - return (0); + return 0; } #endif /*KERNEL_LINUX */ @@ -1236,13 +1304,13 @@ static char *ps_get_cmdline(long pid, "while reading \"%s\": " "Returned %zd but expected %zu.", path, status, buffer_size); - return (NULL); + return NULL; } info.pr_psargs[sizeof(info.pr_psargs) - 1] = 0; sstrncpy(buffer, info.pr_psargs, buffer_size); - return (buffer); + return buffer; } /* }}} int ps_get_cmdline */ /* @@ -1252,7 +1320,7 @@ static char *ps_get_cmdline(long pid, * The values for input and ouput chars are calculated "by hand" * Added a few "solaris" specific process states as well */ -static int ps_read_process(long pid, procstat_t *ps, char *state) { +static int ps_read_process(long pid, process_entry_t *ps, char *state) { char filename[64]; char f_psinfo[64], f_usage[64]; char *buffer; @@ -1287,7 +1355,7 @@ static int ps_read_process(long pid, procstat_t *ps, char *state) { sfree(myStatus); sfree(myInfo); sfree(myUsage); - return (0); + return 0; } else { ps->num_proc = 1; ps->num_lwp = myInfo->pr_nlwp; @@ -1317,6 +1385,11 @@ static int ps_read_process(long pid, procstat_t *ps, char *state) { ps->stack_size = myStatus->pr_stksize; /* + * TODO: File descriptor count for Solaris + */ + ps->num_fd = 0; + + /* * Calculating input/ouput chars * Formula used is total chars / total blocks => chars/block * then convert input/output blocks to chars @@ -1359,7 +1432,7 @@ static int ps_read_process(long pid, procstat_t *ps, char *state) { sfree(myInfo); sfree(myUsage); - return (0); + return 0; } /* @@ -1372,7 +1445,7 @@ static int read_fork_rate(void) { derive_t result = 0; if (kc == NULL) - return (-1); + return -1; for (kstat_t *ksp_chain = kc->kc_chain; ksp_chain != NULL; ksp_chain = ksp_chain->ks_next) { @@ -1390,7 +1463,7 @@ static int read_fork_rate(void) { } ps_submit_fork_rate(result); - return (0); + return 0; } #endif /* KERNEL_SOLARIS */ @@ -1407,12 +1480,12 @@ static int mach_get_task_name(task_t t, int *pid, char *name, mib[2] = KERN_PROC_PID; if (pid_for_task(t, pid) != KERN_SUCCESS) - return (-1); + return -1; mib[3] = *pid; kp_size = sizeof(kp); if (sysctl(mib, 4, &kp, &kp_size, NULL, 0) != 0) - return (-1); + return -1; if (name_max_len > (MAXCOMLEN + 1)) name_max_len = MAXCOMLEN + 1; @@ -1426,7 +1499,7 @@ static int mach_get_task_name(task_t t, int *pid, char *name, * `top' does it, because it is a lot of work and only used when * debugging. -octo */ - return (0); + return 0; } #endif /* HAVE_THREAD_INFO */ /* ------- end of additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- @@ -1457,7 +1530,7 @@ static int ps_read(void) { int blocked = 0; procstat_t *ps; - procstat_entry_t pse; + process_entry_t pse; ps_list_reset(); @@ -1539,6 +1612,14 @@ static int ps_read(void) { pse.vmem_data = 0; pse.vmem_code = 0; + pse.io_rchar = -1; + pse.io_wchar = -1; + pse.io_syscr = -1; + pse.io_syscw = -1; + + /* File descriptor count not implemented */ + pse.num_fd = 0; + pse.vmem_minflt_counter = task_events_info.cow_faults; pse.vmem_majflt_counter = task_events_info.faults; @@ -1670,8 +1751,7 @@ static int ps_read(void) { char cmdline[CMDLINE_BUFFER_SIZE]; int status; - procstat_t ps; - procstat_entry_t pse; + process_entry_t pse; char state; running = sleeping = zombies = stopped = paging = blocked = 0; @@ -1680,7 +1760,7 @@ static int ps_read(void) { if ((proc = opendir("/proc")) == NULL) { char errbuf[1024]; ERROR("Cannot open `/proc': %s", sstrerror(errno, errbuf, sizeof(errbuf))); - return (-1); + return -1; } while ((ent = readdir(proc)) != NULL) { @@ -1690,42 +1770,15 @@ static int ps_read(void) { if ((pid = atol(ent->d_name)) < 1) continue; - status = ps_read_process(pid, &ps, &state); + memset(&pse, 0, sizeof(pse)); + pse.id = pid; + + status = ps_read_process(pid, &pse, &state); if (status != 0) { DEBUG("ps_read_process failed: %i", status); continue; } - memset(&pse, 0, sizeof(pse)); - pse.id = pid; - pse.age = 0; - - pse.num_proc = ps.num_proc; - pse.num_lwp = ps.num_lwp; - pse.vmem_size = ps.vmem_size; - pse.vmem_rss = ps.vmem_rss; - pse.vmem_data = ps.vmem_data; - pse.vmem_code = ps.vmem_code; - pse.stack_size = ps.stack_size; - - pse.vmem_minflt = 0; - pse.vmem_minflt_counter = ps.vmem_minflt_counter; - pse.vmem_majflt = 0; - pse.vmem_majflt_counter = ps.vmem_majflt_counter; - - pse.cpu_user = 0; - pse.cpu_user_counter = ps.cpu_user_counter; - pse.cpu_system = 0; - pse.cpu_system_counter = ps.cpu_system_counter; - - pse.io_rchar = ps.io_rchar; - pse.io_wchar = ps.io_wchar; - pse.io_syscr = ps.io_syscr; - pse.io_syscw = ps.io_syscw; - - pse.cswitch_vol = ps.cswitch_vol; - pse.cswitch_invol = ps.cswitch_invol; - switch (state) { case 'R': running++; @@ -1747,8 +1800,8 @@ static int ps_read(void) { break; } - ps_list_add(ps.name, ps_get_cmdline(pid, ps.name, cmdline, sizeof(cmdline)), - &pse); + ps_list_add(pse.name, + ps_get_cmdline(pid, pse.name, cmdline, sizeof(cmdline)), &pse); } closedir(proc); @@ -1781,7 +1834,7 @@ static int ps_read(void) { struct kinfo_proc *proc_ptr = NULL; int count; /* returns number of processes */ - procstat_entry_t pse; + process_entry_t pse; ps_list_reset(); @@ -1789,7 +1842,7 @@ static int ps_read(void) { kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, errbuf); if (kd == NULL) { ERROR("processes plugin: Cannot open kvm interface: %s", errbuf); - return (0); + return 0; } /* Get the list of processes. */ @@ -1798,7 +1851,7 @@ static int ps_read(void) { ERROR("processes plugin: Cannot get kvm processes list: %s", kvm_geterr(kd)); kvm_close(kd); - return (0); + return 0; } /* Iterate through the processes in kinfo_proc */ @@ -1831,8 +1884,8 @@ static int ps_read(void) { } } /* if (process has argument list) */ + memset(&pse, 0, sizeof(pse)); pse.id = procs[i].ki_pid; - pse.age = 0; pse.num_proc = 1; pse.num_lwp = procs[i].ki_numthreads; @@ -1842,13 +1895,9 @@ static int ps_read(void) { pse.vmem_data = procs[i].ki_dsize * pagesize; pse.vmem_code = procs[i].ki_tsize * pagesize; pse.stack_size = procs[i].ki_ssize * pagesize; - pse.vmem_minflt = 0; pse.vmem_minflt_counter = procs[i].ki_rusage.ru_minflt; - pse.vmem_majflt = 0; pse.vmem_majflt_counter = procs[i].ki_rusage.ru_majflt; - pse.cpu_user = 0; - pse.cpu_system = 0; pse.cpu_user_counter = 0; pse.cpu_system_counter = 0; /* @@ -1871,6 +1920,9 @@ static int ps_read(void) { pse.io_syscr = -1; pse.io_syscw = -1; + /* file descriptor count not implemented */ + pse.num_fd = 0; + /* context switch counters not implemented */ pse.cswitch_vol = -1; pse.cswitch_invol = -1; @@ -1932,15 +1984,15 @@ static int ps_read(void) { struct kinfo_proc *proc_ptr = NULL; int count; /* returns number of processes */ - procstat_entry_t pse; + process_entry_t pse; ps_list_reset(); /* Open the kvm interface, get a descriptor */ - kd = kvm_open(NULL, NULL, NULL, 0, errbuf); + kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); if (kd == NULL) { ERROR("processes plugin: Cannot open kvm interface: %s", errbuf); - return (0); + return 0; } /* Get the list of processes. */ @@ -1949,7 +2001,7 @@ static int ps_read(void) { ERROR("processes plugin: Cannot get kvm processes list: %s", kvm_geterr(kd)); kvm_close(kd); - return (0); + return 0; } /* Iterate through the processes in kinfo_proc */ @@ -1984,7 +2036,6 @@ static int ps_read(void) { memset(&pse, 0, sizeof(pse)); pse.id = procs[i].p_pid; - pse.age = 0; pse.num_proc = 1; pse.num_lwp = 1; /* XXX: accumulate p_tid values for a single p_pid ? */ @@ -1994,13 +2045,9 @@ static int ps_read(void) { pse.vmem_code = procs[i].p_vm_tsize * pagesize; pse.stack_size = procs[i].p_vm_ssize * pagesize; pse.vmem_size = pse.stack_size + pse.vmem_code + pse.vmem_data; - pse.vmem_minflt = 0; pse.vmem_minflt_counter = procs[i].p_uru_minflt; - pse.vmem_majflt = 0; pse.vmem_majflt_counter = procs[i].p_uru_majflt; - pse.cpu_user = 0; - pse.cpu_system = 0; pse.cpu_user_counter = procs[i].p_uutime_usec + (1000000lu * procs[i].p_uutime_sec); pse.cpu_system_counter = @@ -2012,6 +2059,9 @@ static int ps_read(void) { pse.io_syscr = -1; pse.io_syscw = -1; + /* file descriptor count not implemented */ + pse.num_fd = 0; + /* context switch counters not implemented */ pse.cswitch_vol = -1; pse.cswitch_invol = -1; @@ -2070,7 +2120,7 @@ static int ps_read(void) { pid_t pindex = 0; int nprocs; - procstat_entry_t pse; + process_entry_t pse; ps_list_reset(); while ((nprocs = getprocs64(procentry, sizeof(struct procentry64), @@ -2110,8 +2160,9 @@ static int ps_read(void) { } } + memset(&pse, 0, sizeof(pse)); + pse.id = procentry[i].pi_pid; - pse.age = 0; pse.num_lwp = procentry[i].pi_thcount; pse.num_proc = 1; @@ -2148,24 +2199,20 @@ static int ps_read(void) { break; } - pse.cpu_user = 0; /* tv_usec is nanosec ??? */ pse.cpu_user_counter = procentry[i].pi_ru.ru_utime.tv_sec * 1000000 + procentry[i].pi_ru.ru_utime.tv_usec / 1000; - pse.cpu_system = 0; /* tv_usec is nanosec ??? */ pse.cpu_system_counter = procentry[i].pi_ru.ru_stime.tv_sec * 1000000 + procentry[i].pi_ru.ru_stime.tv_usec / 1000; - pse.vmem_minflt = 0; pse.vmem_minflt_counter = procentry[i].pi_minflt; - pse.vmem_majflt = 0; pse.vmem_majflt_counter = procentry[i].pi_majflt; pse.vmem_size = procentry[i].pi_tsize + procentry[i].pi_dvm * pagesize; pse.vmem_rss = (procentry[i].pi_drss + procentry[i].pi_trss) * pagesize; - /* Not supported */ + /* Not supported/implemented */ pse.vmem_data = 0; pse.vmem_code = 0; pse.stack_size = 0; @@ -2175,6 +2222,8 @@ static int ps_read(void) { pse.io_syscr = -1; pse.io_syscw = -1; + pse.num_fd = 0; + pse.cswitch_vol = -1; pse.cswitch_invol = -1; @@ -2223,12 +2272,11 @@ static int ps_read(void) { proc = opendir("/proc"); if (proc == NULL) - return (-1); + return -1; while ((ent = readdir(proc)) != NULL) { long pid; - struct procstat ps; - procstat_entry_t pse; + process_entry_t pse; char *endptr; if (!isdigit((int)ent->d_name[0])) @@ -2238,42 +2286,15 @@ static int ps_read(void) { if (*endptr != 0) /* value didn't completely parse as a number */ continue; - status = ps_read_process(pid, &ps, &state); + memset(&pse, 0, sizeof(pse)); + pse.id = pid; + + status = ps_read_process(pid, &pse, &state); if (status != 0) { DEBUG("ps_read_process failed: %i", status); continue; } - memset(&pse, 0, sizeof(pse)); - pse.id = pid; - pse.age = 0; - - pse.num_proc = ps.num_proc; - pse.num_lwp = ps.num_lwp; - pse.vmem_size = ps.vmem_size; - pse.vmem_rss = ps.vmem_rss; - pse.vmem_data = ps.vmem_data; - pse.vmem_code = ps.vmem_code; - pse.stack_size = ps.stack_size; - - pse.vmem_minflt = 0; - pse.vmem_minflt_counter = ps.vmem_minflt_counter; - pse.vmem_majflt = 0; - pse.vmem_majflt_counter = ps.vmem_majflt_counter; - - pse.cpu_user = 0; - pse.cpu_user_counter = ps.cpu_user_counter; - pse.cpu_system = 0; - pse.cpu_system_counter = ps.cpu_system_counter; - - pse.io_rchar = ps.io_rchar; - pse.io_wchar = ps.io_wchar; - pse.io_syscr = ps.io_syscr; - pse.io_syscw = ps.io_syscw; - - pse.cswitch_vol = -1; - pse.cswitch_invol = -1; - switch (state) { case 'R': running++; @@ -2301,8 +2322,8 @@ static int ps_read(void) { break; } - ps_list_add(ps.name, ps_get_cmdline(pid, ps.name, cmdline, sizeof(cmdline)), - &pse); + ps_list_add(pse.name, + ps_get_cmdline(pid, pse.name, cmdline, sizeof(cmdline)), &pse); } /* while(readdir) */ closedir(proc); @@ -2321,7 +2342,9 @@ static int ps_read(void) { read_fork_rate(); #endif /* KERNEL_SOLARIS */ - return (0); + want_init = 0; + + return 0; } /* int ps_read */ void module_register(void) {