Merge remote-tracking branch 'github/pr/1681'
[collectd.git] / src / processes.c
index 6e472e6..727ec7f 100644 (file)
@@ -185,6 +185,8 @@ typedef struct process_entry_s {
   derive_t io_wchar;
   derive_t io_syscr;
   derive_t io_syscw;
+  derive_t io_diskr;
+  derive_t io_diskw;
   _Bool has_io;
 
   derive_t cswitch_vol;
@@ -209,6 +211,8 @@ typedef struct procstat_entry_s {
   derive_t io_wchar;
   derive_t io_syscr;
   derive_t io_syscw;
+  derive_t io_diskr;
+  derive_t io_diskw;
 
   derive_t cswitch_vol;
   derive_t cswitch_invol;
@@ -242,6 +246,8 @@ typedef struct procstat {
   derive_t io_wchar;
   derive_t io_syscr;
   derive_t io_syscw;
+  derive_t io_diskr;
+  derive_t io_diskw;
 
   derive_t cswitch_vol;
   derive_t cswitch_invol;
@@ -302,7 +308,7 @@ static procstat_t *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 (NULL);
+    return NULL;
   }
   sstrncpy(new->name, name, sizeof(new->name));
 
@@ -310,6 +316,8 @@ static procstat_t *ps_list_register(const char *name, const char *regexp) {
   new->io_wchar = -1;
   new->io_syscr = -1;
   new->io_syscw = -1;
+  new->io_diskr = -1;
+  new->io_diskw = -1;
   new->cswitch_vol = -1;
   new->cswitch_invol = -1;
 
@@ -324,7 +332,7 @@ static procstat_t *ps_list_register(const char *name, const char *regexp) {
     if (new->re == NULL) {
       ERROR("processes plugin: ps_list_register: malloc failed.");
       sfree(new);
-      return (NULL);
+      return NULL;
     }
 
     status = regcomp(new->re, regexp, REG_EXTENDED | REG_NOSUB);
@@ -333,7 +341,7 @@ static procstat_t *ps_list_register(const char *name, const char *regexp) {
             regexp);
       sfree(new->re);
       sfree(new);
-      return (NULL);
+      return NULL;
     }
   }
 #else
@@ -344,7 +352,7 @@ static procstat_t *ps_list_register(const char *name, const char *regexp) {
           "has been disabled at compile time.",
           regexp);
     sfree(new);
-    return (NULL);
+    return NULL;
   }
 #endif
 
@@ -359,7 +367,7 @@ static procstat_t *ps_list_register(const char *name, const char *regexp) {
       sfree(new->re);
 #endif
       sfree(new);
-      return (NULL);
+      return NULL;
     }
 
     if (ptr->next == NULL)
@@ -371,7 +379,7 @@ static procstat_t *ps_list_register(const char *name, const char *regexp) {
   else
     ptr->next = new;
 
-  return (new);
+  return new;
 } /* void ps_list_register */
 
 /* try to match name against entry, returns 1 if success */
@@ -393,13 +401,13 @@ 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(derive_t *group_counter, derive_t *curr_counter,
@@ -480,6 +488,11 @@ static void ps_list_add(const char *name, const char *cmdline,
       ps_update_counter(&ps->io_syscw, &pse->io_syscw, entry->io_syscw);
     }
 
+    if ((entry->io_diskr != -1) && (entry->io_diskw != -1)) {
+      ps_update_counter(&ps->io_diskr, &pse->io_diskr, entry->io_diskr);
+      ps_update_counter(&ps->io_diskw, &pse->io_diskw, entry->io_diskw);
+    }
+
     if ((entry->cswitch_vol != -1) && (entry->cswitch_vol != -1)) {
       ps_update_counter(&ps->cswitch_vol, &pse->cswitch_vol,
                         entry->cswitch_vol);
@@ -614,7 +627,7 @@ static int ps_config(oconfig_item_t *ci) {
     }
   }
 
-  return (0);
+  return 0;
 }
 
 static int ps_init(void) {
@@ -636,7 +649,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 */
 
@@ -655,7 +668,7 @@ 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..) */
@@ -725,7 +738,7 @@ static void ps_submit_proc_list(procstat_t *ps) {
   plugin_dispatch_values(&vl);
 
   if ((ps->io_rchar != -1) && (ps->io_wchar != -1)) {
-    sstrncpy(vl.type, "ps_disk_octets", sizeof(vl.type));
+    sstrncpy(vl.type, "io_octets", sizeof(vl.type));
     vl.values[0].derive = ps->io_rchar;
     vl.values[1].derive = ps->io_wchar;
     vl.values_len = 2;
@@ -733,13 +746,21 @@ static void ps_submit_proc_list(procstat_t *ps) {
   }
 
   if ((ps->io_syscr != -1) && (ps->io_syscw != -1)) {
-    sstrncpy(vl.type, "ps_disk_ops", sizeof(vl.type));
+    sstrncpy(vl.type, "io_ops", sizeof(vl.type));
     vl.values[0].derive = ps->io_syscr;
     vl.values[1].derive = ps->io_syscw;
     vl.values_len = 2;
     plugin_dispatch_values(&vl);
   }
 
+  if ((ps->io_diskr != -1) && (ps->io_diskw != -1)) {
+    sstrncpy(vl.type, "disk_octets", sizeof(vl.type));
+    vl.values[0].derive = ps->io_diskr;
+    vl.values[1].derive = ps->io_diskw;
+    vl.values_len = 2;
+    plugin_dispatch_values(&vl);
+  }
+
   if (ps->num_fd > 0) {
     sstrncpy(vl.type, "file_handles", sizeof(vl.type));
     vl.values[0].gauge = ps->num_fd;
@@ -768,12 +789,13 @@ static void ps_submit_proc_list(procstat_t *ps) {
         "cpu_user_counter = %" PRIi64 "; cpu_system_counter = %" PRIi64 "; "
         "io_rchar = %" PRIi64 "; io_wchar = %" PRIi64 "; "
         "io_syscr = %" PRIi64 "; io_syscw = %" PRIi64 "; "
+        "io_diskr = %" PRIi64 "; io_diskw = %" PRIi64 "; "
         "cswitch_vol = %" PRIi64 "; cswitch_invol = %" PRIi64 ";",
         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);
+        ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw, ps->io_diskr,
+        ps->io_diskw, ps->cswitch_vol, ps->cswitch_invol);
 } /* void ps_submit_proc_list */
 
 #if KERNEL_LINUX || KERNEL_SOLARIS
@@ -805,11 +827,11 @@ static int ps_read_tasks_status(process_entry_t *ps) {
   char *fields[8];
   int numfields;
 
-  ssnprintf(dirname, sizeof(dirname), "/proc/%li/task", ps->id);
+  snprintf(dirname, sizeof(dirname), "/proc/%li/task", ps->id);
 
   if ((dh = opendir(dirname)) == NULL) {
     DEBUG("Failed to open directory `%s'", dirname);
-    return (-1);
+    return -1;
   }
 
   while ((ent = readdir(dh)) != NULL) {
@@ -820,8 +842,12 @@ static int ps_read_tasks_status(process_entry_t *ps) {
 
     tpid = ent->d_name;
 
-    ssnprintf(filename, sizeof(filename), "/proc/%li/task/%s/status", ps->id,
-              tpid);
+    if (snprintf(filename, sizeof(filename), "/proc/%li/task/%s/status", ps->id,
+                 tpid) >= sizeof(filename)) {
+      DEBUG("Filename too long: `%s'", filename);
+      continue;
+    }
+
     if ((fh = fopen(filename, "r")) == NULL) {
       DEBUG("Failed to open file `%s'", filename);
       continue;
@@ -863,7 +889,7 @@ static int ps_read_tasks_status(process_entry_t *ps) {
   ps->cswitch_vol = cswitch_vol;
   ps->cswitch_invol = cswitch_invol;
 
-  return (0);
+  return 0;
 } /* int *ps_read_tasks_status */
 
 /* Read data from /proc/pid/status */
@@ -878,9 +904,9 @@ static int ps_read_status(long pid, process_entry_t *ps) {
   char *fields[8];
   int numfields;
 
-  ssnprintf(filename, sizeof(filename), "/proc/%li/status", pid);
+  snprintf(filename, sizeof(filename), "/proc/%li/status", pid);
   if ((fh = fopen(filename, "r")) == NULL)
-    return (-1);
+    return -1;
 
   while (fgets(buffer, sizeof(buffer), fh) != NULL) {
     unsigned long tmp;
@@ -920,7 +946,7 @@ static int ps_read_status(long pid, process_entry_t *ps) {
   if (threads != 0)
     ps->num_lwp = threads;
 
-  return (0);
+  return 0;
 } /* int *ps_read_status */
 
 static int ps_read_io(process_entry_t *ps) {
@@ -931,10 +957,10 @@ static int ps_read_io(process_entry_t *ps) {
   char *fields[8];
   int numfields;
 
-  ssnprintf(filename, sizeof(filename), "/proc/%li/io", ps->id);
+  snprintf(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);
+    return -1;
   }
 
   while (fgets(buffer, sizeof(buffer), fh) != NULL) {
@@ -950,6 +976,10 @@ static int ps_read_io(process_entry_t *ps) {
       val = &(ps->io_syscr);
     else if (strncasecmp(buffer, "syscw:", 6) == 0)
       val = &(ps->io_syscw);
+    else if (strncasecmp(buffer, "read_bytes:", 11) == 0)
+      val = &(ps->io_diskr);
+    else if (strncasecmp(buffer, "write_bytes:", 12) == 0)
+      val = &(ps->io_diskw);
     else
       continue;
 
@@ -971,7 +1001,7 @@ static int ps_read_io(process_entry_t *ps) {
     char errbuf[1024];
     WARNING("processes: fclose: %s", sstrerror(errno, errbuf, sizeof(errbuf)));
   }
-  return (0);
+  return 0;
 } /* int ps_read_io (...) */
 
 static int ps_count_fd(int pid) {
@@ -980,11 +1010,11 @@ static int ps_count_fd(int pid) {
   struct dirent *ent;
   int count = 0;
 
-  ssnprintf(dirname, sizeof(dirname), "/proc/%i/fd", pid);
+  snprintf(dirname, sizeof(dirname), "/proc/%i/fd", pid);
 
   if ((dh = opendir(dirname)) == NULL) {
     DEBUG("Failed to open directory `%s'", dirname);
-    return (-1);
+    return -1;
   }
   while ((ent = readdir(dh)) != NULL) {
     if (!isdigit((int)ent->d_name[0]))
@@ -994,7 +1024,7 @@ static int ps_count_fd(int pid) {
   }
   closedir(dh);
 
-  return ((count >= 1) ? count : 1);
+  return (count >= 1) ? count : 1;
 } /* int ps_count_fd (pid) */
 
 static void ps_fill_details(const procstat_t *ps, process_entry_t *entry) {
@@ -1041,11 +1071,11 @@ static int ps_read_process(long pid, process_entry_t *ps, char *state) {
 
   ssize_t status;
 
-  ssnprintf(filename, sizeof(filename), "/proc/%li/stat", pid);
+  snprintf(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;
 
@@ -1067,7 +1097,7 @@ static int ps_read_process(long pid, process_entry_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;
@@ -1077,7 +1107,7 @@ static int ps_read_process(long pid, process_entry_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));
@@ -1085,7 +1115,7 @@ static int ps_read_process(long pid, process_entry_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];
@@ -1111,7 +1141,7 @@ static int ps_read_process(long pid, process_entry_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]);
@@ -1145,12 +1175,14 @@ static int ps_read_process(long pid, process_entry_t *ps, char *state) {
   ps->io_wchar = -1;
   ps->io_syscr = -1;
   ps->io_syscw = -1;
+  ps->io_diskr = -1;
+  ps->io_diskw = -1;
 
   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) {
@@ -1165,7 +1197,7 @@ static char *ps_get_cmdline(long pid, char *name, char *buf, size_t buf_len) {
   if ((pid < 1) || (NULL == buf) || (buf_len < 2))
     return NULL;
 
-  ssnprintf(file, sizeof(file), "/proc/%li/cmdline", pid);
+  snprintf(file, sizeof(file), "/proc/%li/cmdline", pid);
 
   errno = 0;
   fd = open(file, O_RDONLY);
@@ -1220,7 +1252,7 @@ static char *ps_get_cmdline(long pid, char *name, char *buf, size_t buf_len) {
     if (NULL == name)
       return NULL;
 
-    ssnprintf(buf, buf_len, "[%s]", name);
+    snprintf(buf, buf_len, "[%s]", name);
     return buf;
   }
 
@@ -1257,7 +1289,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) {
@@ -1281,10 +1313,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 */
 
@@ -1304,13 +1336,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 */
 
 /*
@@ -1355,7 +1387,7 @@ static int ps_read_process(long pid, process_entry_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;
@@ -1403,6 +1435,8 @@ static int ps_read_process(long pid, process_entry_t *ps, char *state) {
   ps->io_wchar = myUsage->pr_oublk * chars_per_block;
   ps->io_syscr = myUsage->pr_sysc;
   ps->io_syscw = myUsage->pr_sysc;
+  ps->io_diskr = -1;
+  ps->io_diskw = -1;
 
   /*
    * TODO: context switch counters for Solaris
@@ -1432,7 +1466,7 @@ static int ps_read_process(long pid, process_entry_t *ps, char *state) {
   sfree(myInfo);
   sfree(myUsage);
 
-  return (0);
+  return 0;
 }
 
 /*
@@ -1445,7 +1479,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) {
@@ -1463,7 +1497,7 @@ static int read_fork_rate(void) {
   }
 
   ps_submit_fork_rate(result);
-  return (0);
+  return 0;
 }
 #endif /* KERNEL_SOLARIS */
 
@@ -1480,12 +1514,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;
@@ -1499,7 +1533,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 -------
@@ -1616,6 +1650,8 @@ static int ps_read(void) {
         pse.io_wchar = -1;
         pse.io_syscr = -1;
         pse.io_syscw = -1;
+        pse.io_diskr = -1;
+        pse.io_diskw = -1;
 
         /* File descriptor count not implemented */
         pse.num_fd = 0;
@@ -1760,7 +1796,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) {
@@ -1842,7 +1878,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. */
@@ -1851,7 +1887,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 */
@@ -1919,6 +1955,8 @@ static int ps_read(void) {
       pse.io_wchar = -1;
       pse.io_syscr = -1;
       pse.io_syscw = -1;
+      pse.io_diskr = -1;
+      pse.io_diskw = -1;
 
       /* file descriptor count not implemented */
       pse.num_fd = 0;
@@ -1992,7 +2030,7 @@ static int ps_read(void) {
   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. */
@@ -2001,7 +2039,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 */
@@ -2058,6 +2096,8 @@ static int ps_read(void) {
       pse.io_wchar = -1;
       pse.io_syscr = -1;
       pse.io_syscw = -1;
+      pse.io_diskr = -1;
+      pse.io_diskw = -1;
 
       /* file descriptor count not implemented */
       pse.num_fd = 0;
@@ -2221,6 +2261,8 @@ static int ps_read(void) {
       pse.io_wchar = -1;
       pse.io_syscr = -1;
       pse.io_syscw = -1;
+      pse.io_diskr = -1;
+      pse.io_diskw = -1;
 
       pse.num_fd = 0;
 
@@ -2272,7 +2314,7 @@ static int ps_read(void) {
 
   proc = opendir("/proc");
   if (proc == NULL)
-    return (-1);
+    return -1;
 
   while ((ent = readdir(proc)) != NULL) {
     long pid;
@@ -2344,7 +2386,7 @@ static int ps_read(void) {
 
   want_init = 0;
 
-  return (0);
+  return 0;
 } /* int ps_read */
 
 void module_register(void) {