@cryptotaxi247 / netdata-1 / commits / ce381953c

Add FreeBSD support to apps.plugin

Vladimir Kobal committed Feb 21, 2017 at 14:32 UTC ce381953ca239d092b3085ee29798a4908f32747
1 file changed +271 -4
src/apps_plugin.c
+271 -4
@@ -7,6 +7,10 @@
7
8 #include "common.h"
9
10 +#ifdef __FreeBSD__
11 +#include <sys/user.h>
12 +#endif
13 +
14 // ----------------------------------------------------------------------------
15 // per O/S configuration
16
@@ -19,8 +23,11 @@
23 // set this to 1
24 // when set to 0, apps.plugin builds a sort list of processes, in order
25 // to process children processes, before parent processes
26 +#ifdef __FreeBSD__
27 +#define ALL_PIDS_ARE_READ_INSTANTLY 1
28 +#else
29 #define ALL_PIDS_ARE_READ_INSTANTLY 0
23 -
30 +#endif
31
32 // ----------------------------------------------------------------------------
33 // string lengths
@@ -774,6 +781,17 @@ static inline void assign_target_to_pid(struct pid_stat *p) {
781
782 static inline int read_proc_pid_cmdline(struct pid_stat *p) {
783
784 +#ifdef __FreeBSD__
785 + size_t i, bytes = MAX_CMDLINE;
786 + int mib[4];
787 +
788 + mib[0] = CTL_KERN;
789 + mib[1] = KERN_PROC;
790 + mib[2] = KERN_PROC_ARGS;
791 + mib[3] = p->pid;
792 + if (unlikely(sysctl(mib, 4, p->cmdline, &bytes, NULL, 0)))
793 + goto cleanup;
794 +#else
795 if(unlikely(!p->cmdline_filename)) {
796 char filename[FILENAME_MAX + 1];
797 snprintfz(filename, FILENAME_MAX, "%s/proc/%d/cmdline", netdata_configured_host_prefix, p->pid);
@@ -787,6 +805,7 @@ static inline int read_proc_pid_cmdline(struct pid_stat *p) {
805 close(fd);
806
807 if(unlikely(bytes < 0)) goto cleanup;
808 +#endif
809
810 p->cmdline[bytes] = '\0';
811 for(i = 0; i < bytes ; i++)
@@ -805,7 +824,14 @@ cleanup:
824
825 static inline int read_proc_pid_ownership(struct pid_stat *p, void *ptr) {
826 (void)ptr;
827 +#ifdef __FreeBSD__
828 + struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr;
829
830 + p->uid = proc_info->ki_uid;
831 + p->gid = proc_info->ki_groups[0];
832 +
833 + return 1;
834 +#else
835 if(unlikely(!p->stat_filename)) {
836 error("pid %d does not have a stat_filename", p->pid);
837 return 0;
@@ -824,6 +850,7 @@ static inline int read_proc_pid_ownership(struct pid_stat *p, void *ptr) {
850 p->gid = st.st_gid;
851
852 return 1;
853 +#endif
854 }
855
856 // ----------------------------------------------------------------------------
@@ -847,6 +874,12 @@ static inline int read_proc_pid_ownership(struct pid_stat *p, void *ptr) {
874 static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) {
875 (void)ptr;
876
877 +#ifdef __FreeBSD__
878 + struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr;
879 +
880 + if (unlikely(proc_info->ki_tdflags & TDF_IDLETD))
881 + goto cleanup;
882 +#else
883 static procfile *ff = NULL;
884
885 if(unlikely(!p->stat_filename)) {
@@ -866,11 +899,16 @@ static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) {
899
900 ff = procfile_readall(ff);
901 if(unlikely(!ff)) goto cleanup;
902 +#endif
903
904 p->last_stat_collected_usec = p->stat_collected_usec;
905 p->stat_collected_usec = now_monotonic_usec();
906 calls_counter++;
907
908 +#ifdef __FreeBSD__
909 + char *comm = proc_info->ki_comm;
910 + p->ppid = proc_info->ki_ppid;
911 +#else
912 // p->pid = str2pid_t(procfile_lineword(ff, 0, 0));
913 char *comm = procfile_lineword(ff, 0, 1);
914 // p->state = *(procfile_lineword(ff, 0, 2));
@@ -880,6 +918,7 @@ static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) {
918 // p->tty_nr = (int32_t)str2pid_t(procfile_lineword(ff, 0, 6));
919 // p->tpgid = (int32_t)str2pid_t(procfile_lineword(ff, 0, 7));
920 // p->flags = str2uint64_t(procfile_lineword(ff, 0, 8));
921 +#endif
922
923 if(strcmp(p->comm, comm)) {
924 if(unlikely(debug)) {
@@ -898,6 +937,23 @@ static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) {
937 assign_target_to_pid(p);
938 }
939
940 +#ifdef __FreeBSD__
941 + pid_incremental_rate(stat, p->minflt, (kernel_uint_t)proc_info->ki_rusage.ru_minflt);
942 + pid_incremental_rate(stat, p->cminflt, (kernel_uint_t)proc_info->ki_rusage_ch.ru_minflt);
943 + pid_incremental_rate(stat, p->majflt, (kernel_uint_t)proc_info->ki_rusage.ru_majflt);
944 + pid_incremental_rate(stat, p->cmajflt, (kernel_uint_t)proc_info->ki_rusage_ch.ru_majflt);
945 + pid_incremental_rate(stat, p->utime, (kernel_uint_t)proc_info->ki_rusage.ru_utime.tv_sec * 100 + proc_info->ki_rusage.ru_utime.tv_usec / 10000);
946 + pid_incremental_rate(stat, p->stime, (kernel_uint_t)proc_info->ki_rusage.ru_stime.tv_sec * 100 + proc_info->ki_rusage.ru_stime.tv_usec / 10000);
947 + pid_incremental_rate(stat, p->cutime, (kernel_uint_t)proc_info->ki_rusage_ch.ru_utime.tv_sec * 100 + proc_info->ki_rusage_ch.ru_utime.tv_usec / 10000);
948 + pid_incremental_rate(stat, p->cstime, (kernel_uint_t)proc_info->ki_rusage_ch.ru_stime.tv_sec * 100 + proc_info->ki_rusage_ch.ru_utime.tv_usec / 10000);
949 +
950 + p->num_threads = proc_info->ki_numthreads;
951 +
952 + if(enable_guest_charts) {
953 + enable_guest_charts = 0;
954 + info("Guest charts aren't supported by FreeBSD");
955 + }
956 +#else
957 pid_incremental_rate(stat, p->minflt, str2kernel_uint_t(procfile_lineword(ff, 0, 9)));
958 pid_incremental_rate(stat, p->cminflt, str2kernel_uint_t(procfile_lineword(ff, 0, 10)));
959 pid_incremental_rate(stat, p->majflt, str2kernel_uint_t(procfile_lineword(ff, 0, 11)));
@@ -906,7 +962,6 @@ static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) {
962 pid_incremental_rate(stat, p->stime, str2kernel_uint_t(procfile_lineword(ff, 0, 14)));
963 pid_incremental_rate(stat, p->cutime, str2kernel_uint_t(procfile_lineword(ff, 0, 15)));
964 pid_incremental_rate(stat, p->cstime, str2kernel_uint_t(procfile_lineword(ff, 0, 16)));
909 -
965 // p->priority = str2kernel_uint_t(procfile_lineword(ff, 0, 17));
966 // p->nice = str2kernel_uint_t(procfile_lineword(ff, 0, 18));
967 p->num_threads = (int32_t)str2uint32_t(procfile_lineword(ff, 0, 19));
@@ -944,6 +999,7 @@ static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) {
999 show_guest_time = 1;
1000 }
1001 }
1002 +#endif
1003
1004 if(unlikely(debug || (p->target && p->target->debug)))
1005 fprintf(stderr, "apps.plugin: READ PROC/PID/STAT: %s/proc/%d/stat, process: '%s' on target '%s' (dt=%llu) VALUES: utime=" KERNEL_UINT_FORMAT ", stime=" KERNEL_UINT_FORMAT ", cutime=" KERNEL_UINT_FORMAT ", cstime=" KERNEL_UINT_FORMAT ", minflt=" KERNEL_UINT_FORMAT ", majflt=" KERNEL_UINT_FORMAT ", cminflt=" KERNEL_UINT_FORMAT ", cmajflt=" KERNEL_UINT_FORMAT ", threads=%d\n", netdata_configured_host_prefix, p->pid, p->comm, (p->target)?p->target->name:"UNSET", p->stat_collected_usec - p->last_stat_collected_usec, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt, p->num_threads);
@@ -981,7 +1037,9 @@ cleanup:
1037
1038 static inline int read_proc_pid_statm(struct pid_stat *p, void *ptr) {
1039 (void)ptr;
984 -
1040 +#ifdef __FreeBSD__
1041 + struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr;
1042 +#else
1043 static procfile *ff = NULL;
1044
1045 if(unlikely(!p->statm_filename)) {
@@ -995,9 +1053,15 @@ static inline int read_proc_pid_statm(struct pid_stat *p, void *ptr) {
1053
1054 ff = procfile_readall(ff);
1055 if(unlikely(!ff)) goto cleanup;
1056 +#endif
1057
1058 calls_counter++;
1059
1060 +#ifdef __FreeBSD__
1061 + p->statm_size = proc_info->ki_size / sysconf(_SC_PAGESIZE);
1062 + p->statm_resident = proc_info->ki_rssize;
1063 + p->statm_share = 0; // do we have to use ru_ixrss here?
1064 +#else
1065 p->statm_size = str2kernel_uint_t(procfile_lineword(ff, 0, 0));
1066 p->statm_resident = str2kernel_uint_t(procfile_lineword(ff, 0, 1));
1067 p->statm_share = str2kernel_uint_t(procfile_lineword(ff, 0, 2));
@@ -1005,6 +1069,7 @@ static inline int read_proc_pid_statm(struct pid_stat *p, void *ptr) {
1069 // p->statm_lib = str2kernel_uint_t(procfile_lineword(ff, 0, 4));
1070 // p->statm_data = str2kernel_uint_t(procfile_lineword(ff, 0, 5));
1071 // p->statm_dirty = str2kernel_uint_t(procfile_lineword(ff, 0, 6));
1072 +#endif
1073
1074 return 1;
1075
@@ -1021,7 +1086,9 @@ cleanup:
1086
1087 static inline int read_proc_pid_io(struct pid_stat *p, void *ptr) {
1088 (void)ptr;
1024 -
1089 +#ifdef __FreeBSD__
1090 + struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr;
1091 +#else
1092 static procfile *ff = NULL;
1093
1094 if(unlikely(!p->io_filename)) {
@@ -1036,12 +1103,17 @@ static inline int read_proc_pid_io(struct pid_stat *p, void *ptr) {
1103
1104 ff = procfile_readall(ff);
1105 if(unlikely(!ff)) goto cleanup;
1106 +#endif
1107
1108 calls_counter++;
1109
1110 p->last_io_collected_usec = p->io_collected_usec;
1111 p->io_collected_usec = now_monotonic_usec();
1112
1113 +#ifdef __FreeBSD__
1114 + pid_incremental_rate(io, p->io_storage_bytes_read, proc_info->ki_rusage.ru_inblock);
1115 + pid_incremental_rate(io, p->io_storage_bytes_written, proc_info->ki_rusage.ru_oublock);
1116 +#else
1117 pid_incremental_rate(io, p->io_logical_bytes_read, str2kernel_uint_t(procfile_lineword(ff, 0, 1)));
1118 pid_incremental_rate(io, p->io_logical_bytes_written, str2kernel_uint_t(procfile_lineword(ff, 1, 1)));
1119 // pid_incremental_rate(io, p->io_read_calls, str2kernel_uint_t(procfile_lineword(ff, 2, 1)));
@@ -1049,6 +1121,7 @@ static inline int read_proc_pid_io(struct pid_stat *p, void *ptr) {
1121 pid_incremental_rate(io, p->io_storage_bytes_read, str2kernel_uint_t(procfile_lineword(ff, 4, 1)));
1122 pid_incremental_rate(io, p->io_storage_bytes_written, str2kernel_uint_t(procfile_lineword(ff, 5, 1)));
1123 // pid_incremental_rate(io, p->io_cancelled_write_bytes, str2kernel_uint_t(procfile_lineword(ff, 6, 1)));
1124 +#endif
1125
1126 if(unlikely(global_iterations_counter == 1)) {
1127 p->io_logical_bytes_read = 0;
@@ -1074,11 +1147,23 @@ cleanup:
1147 }
1148
1149 static inline int read_proc_stat() {
1150 +#ifdef __FreeBSD__
1151 + long cp_time[CPUSTATES];
1152 + int i;
1153 +
1154 + if (unlikely(CPUSTATES != 5)) {
1155 + error("FREEBSD: There are %d CPU states (5 was expected)", CPUSTATES);
1156 + goto cleanup;
1157 + }
1158 + if (unlikely(GETSYSCTL("kern.cp_time", cp_time))) goto cleanup;
1159 +#else
1160 static char filename[FILENAME_MAX + 1] = "";
1161 static procfile *ff = NULL;
1162 +#endif
1163 static kernel_uint_t utime_raw = 0, stime_raw = 0, gtime_raw = 0, gntime_raw = 0, ntime_raw = 0;
1164 static usec_t collected_usec = 0, last_collected_usec = 0;
1165
1166 +#ifndef __FreeBSD__
1167 if(unlikely(!ff)) {
1168 snprintfz(filename, FILENAME_MAX, "%s/proc/stat", netdata_configured_host_prefix);
1169 ff = procfile_open(filename, " \t:", PROCFILE_FLAG_DEFAULT);
@@ -1087,6 +1172,7 @@ static inline int read_proc_stat() {
1172
1173 ff = procfile_readall(ff);
1174 if(unlikely(!ff)) goto cleanup;
1175 +#endif
1176
1177 last_collected_usec = collected_usec;
1178 collected_usec = now_monotonic_usec();
@@ -1096,13 +1182,25 @@ static inline int read_proc_stat() {
1182 // temporary - it is added global_ntime;
1183 kernel_uint_t global_ntime = 0;
1184
1185 +#ifdef __FreeBSD__
1186 + incremental_rate(global_utime, utime_raw, cp_time[0], collected_usec, last_collected_usec);
1187 + incremental_rate(global_ntime, ntime_raw, cp_time[1], collected_usec, last_collected_usec);
1188 + incremental_rate(global_stime, stime_raw, cp_time[2], collected_usec, last_collected_usec);
1189 +#else
1190 incremental_rate(global_utime, utime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 1)), collected_usec, last_collected_usec);
1191 incremental_rate(global_ntime, ntime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 2)), collected_usec, last_collected_usec);
1192 incremental_rate(global_stime, stime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 3)), collected_usec, last_collected_usec);
1193 incremental_rate(global_gtime, gtime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 10)), collected_usec, last_collected_usec);
1194 +#endif
1195
1196 global_utime += global_ntime;
1197
1198 +#ifdef __FreeBSD__
1199 + if(enable_guest_charts) {
1200 + enable_guest_charts = 0;
1201 + info("Guest charts aren't supported by FreeBSD");
1202 + }
1203 +#else
1204 if(enable_guest_charts) {
1205 // temporary - it is added global_ntime;
1206 kernel_uint_t global_gntime = 0;
@@ -1115,6 +1213,7 @@ static inline int read_proc_stat() {
1213 // remove guest time from user time
1214 global_utime -= (global_utime > global_gtime) ? global_gtime : global_utime;
1215 }
1216 +#endif
1217
1218 if(unlikely(global_iterations_counter == 1)) {
1219 global_utime = 0;
@@ -1393,7 +1492,127 @@ static inline void zero_pid_fds(struct pid_stat *p, int first, int size) {
1492
1493 static inline int read_pid_file_descriptors(struct pid_stat *p, void *ptr) {
1494 (void)ptr;
1495 +#ifdef __FreeBSD__
1496 + int mib[4];
1497 + size_t size;
1498 + struct kinfo_file *fds;
1499 + static char *fdsbuf;
1500 + char *bfdsbuf, *efdsbuf;
1501 + char fdsname[FILENAME_MAX + 1];
1502 +
1503 + // we make all pid fds negative, so that
1504 + // we can detect unused file descriptors
1505 + // at the end, to free them
1506 + make_all_pid_fds_negative(p);
1507 +
1508 + mib[0] = CTL_KERN;
1509 + mib[1] = KERN_PROC;
1510 + mib[2] = KERN_PROC_FILEDESC;
1511 + mib[3] = p->pid;
1512 +
1513 + if (unlikely(sysctl(mib, 4, NULL, &size, NULL, 0))) {
1514 + error("sysctl error: Can't get file descriptors data size for pid %d", p->pid);
1515 + return 0;
1516 + }
1517 + if (likely(size > 0))
1518 + fdsbuf = reallocz(fdsbuf, size);
1519 + if (unlikely(sysctl(mib, 4, fdsbuf, &size, NULL, 0))) {
1520 + error("sysctl error: Can't get file descriptors data for pid %d", p->pid);
1521 + return 0;
1522 + }
1523 +
1524 + bfdsbuf = fdsbuf;
1525 + efdsbuf = fdsbuf + size;
1526 + while (bfdsbuf < efdsbuf) {
1527 + fds = (struct kinfo_file *)(uintptr_t)bfdsbuf;
1528 + if (unlikely(fds->kf_structsize == 0))
1529 + break;
1530
1531 + // do not process file descriptors for current working directory, root directory,
1532 + // jail directory, ktrace vnode, text vnode and controlling terminal
1533 + if (unlikely(fds->kf_fd < 0)) {
1534 + bfdsbuf += fds->kf_structsize;
1535 + continue;
1536 + }
1537 +
1538 + // get file descriptors array index
1539 + int fdid = fds->kf_fd;
1540 +
1541 + // check if the fds array is small
1542 + if (unlikely(fdid >= p->fds_size)) {
1543 + // it is small, extend it
1544 +
1545 + if (unlikely(debug))
1546 + fprintf(stderr, "apps.plugin: extending fd memory slots for %s from %d to %d\n", p->comm, p->fds_size, fdid + MAX_SPARE_FDS);
1547 +
1548 + p->fds = reallocz(p->fds, (fdid + MAX_SPARE_FDS) * sizeof(int));
1549 +
1550 + // and initialize it
1551 + zero_pid_fds(p, p->fds_size, (fdid + MAX_SPARE_FDS) - p->fds_size);
1552 + p->fds_size = fdid + MAX_SPARE_FDS;
1553 + }
1554 +
1555 + if (unlikely(p->fds[fdid] == 0)) {
1556 + // we don't know this fd, get it
1557 +
1558 + switch (fds->kf_type) {
1559 + case KF_TYPE_FIFO:
1560 + case KF_TYPE_VNODE:
1561 + if (unlikely(!fds->kf_path[0])) {
1562 + sprintf(fdsname, "other: inode: %lu", fds->kf_un.kf_file.kf_file_fileid);
1563 + break;
1564 + }
1565 + sprintf(fdsname, "%s", fds->kf_path);
1566 + break;
1567 + case KF_TYPE_SOCKET:
1568 + switch (fds->kf_sock_domain) {
1569 + case AF_INET:
1570 + case AF_INET6:
1571 + if (fds->kf_sock_protocol == IPPROTO_TCP)
1572 + sprintf(fdsname, "socket: %d %lx", fds->kf_sock_protocol, fds->kf_un.kf_sock.kf_sock_inpcb);
1573 + else
1574 + sprintf(fdsname, "socket: %d %lx", fds->kf_sock_protocol, fds->kf_un.kf_sock.kf_sock_pcb);
1575 + break;
1576 + case AF_UNIX:
1577 + /* print address of pcb and connected pcb */
1578 + sprintf(fdsname, "socket: %lx %lx", fds->kf_un.kf_sock.kf_sock_pcb, fds->kf_un.kf_sock.kf_sock_unpconn);
1579 + break;
1580 + default:
1581 + /* print protocol number and socket address */
1582 + sprintf(fdsname, "socket: other: %d %s %s", fds->kf_sock_protocol, fds->kf_sa_local.__ss_pad1, fds->kf_sa_local.__ss_pad2);
1583 + }
1584 + break;
1585 + case KF_TYPE_PIPE:
1586 + sprintf(fdsname, "pipe: %lu %lu", fds->kf_un.kf_pipe.kf_pipe_addr, fds->kf_un.kf_pipe.kf_pipe_peer);
1587 + break;
1588 + case KF_TYPE_PTS:
1589 + sprintf(fdsname, "other: pts: %u", fds->kf_un.kf_pts.kf_pts_dev);
1590 + break;
1591 + case KF_TYPE_SHM:
1592 + sprintf(fdsname, "other: shm: %s size: %lu", fds->kf_path, fds->kf_un.kf_file.kf_file_size);
1593 + break;
1594 + case KF_TYPE_SEM:
1595 + sprintf(fdsname, "other: sem: %u", fds->kf_un.kf_sem.kf_sem_value);
1596 + break;
1597 + default:
1598 + sprintf(fdsname, "other: pid: %d fd: %d", fds->kf_un.kf_proc.kf_pid, fds->kf_fd);
1599 + }
1600 +
1601 + // if another process already has this, we will get
1602 + // the same id
1603 + p->fds[fdid] = file_descriptor_find_or_add(fdsname);
1604 + }
1605 +
1606 + // else make it positive again, we need it
1607 + // of course, the actual file may have changed, but we don't care so much
1608 + // FIXME: we could compare the inode as returned by readdir dirent structure
1609 +
1610 + else
1611 + p->fds[fdid] = -p->fds[fdid];
1612 +
1613 + bfdsbuf += fds->kf_structsize;
1614 + }
1615 +#else
1616 if(unlikely(!p->fds_dirname)) {
1617 char dirname[FILENAME_MAX+1];
1618 snprintfz(dirname, FILENAME_MAX, "%s/proc/%d/fd", netdata_configured_host_prefix, p->pid);
@@ -1473,6 +1692,7 @@ static inline int read_pid_file_descriptors(struct pid_stat *p, void *ptr) {
1692 }
1693
1694 closedir(fds);
1695 +#endif
1696 cleanup_negative_pid_fds(p);
1697
1698 return 1;
@@ -1846,6 +2066,28 @@ static inline int collect_data_for_pid(pid_t pid, void *ptr) {
2066 static int collect_data_for_all_processes(void) {
2067 struct pid_stat *p = NULL;
2068
2069 +#ifdef __FreeBSD__
2070 + int i, procnum;
2071 + size_t procbase_size;
2072 + static struct kinfo_proc *procbase;
2073 +
2074 + int mib[3];
2075 +
2076 + mib[0] = CTL_KERN;
2077 + mib[1] = KERN_PROC;
2078 + mib[2] = KERN_PROC_PROC;
2079 + if (unlikely(sysctl(mib, 3, NULL, &procbase_size, NULL, 0))) {
2080 + error("sysctl error: Can't get processes data size");
2081 + return 0;
2082 + }
2083 + procbase = reallocz(procbase, procbase_size);
2084 + if (unlikely(sysctl(mib, 3, procbase, &procbase_size, NULL, 0))) {
2085 + error("sysctl error: Can't get processes data");
2086 + return 0;
2087 + }
2088 + procnum = procbase_size / sizeof(struct kinfo_proc);
2089 +#endif
2090 +
2091 if(all_pids_count) {
2092 size_t slc = 0;
2093 for(p = root_of_pids; p ; p = p->next) {
@@ -1884,6 +2126,12 @@ static int collect_data_for_all_processes(void) {
2126 #endif
2127 }
2128
2129 +#ifdef __FreeBSD__
2130 + for (i = INIT_PID; i < procnum - INIT_PID; ++i) {
2131 + pid_t pid = procbase[i].ki_pid;
2132 + collect_data_for_pid(pid, &procbase[i]);
2133 + }
2134 +#else
2135 char dirname[FILENAME_MAX + 1];
2136
2137 snprintfz(dirname, FILENAME_MAX, "%s/proc", netdata_configured_host_prefix);
@@ -1907,6 +2155,7 @@ static int collect_data_for_all_processes(void) {
2155 collect_data_for_pid(pid, NULL);
2156 }
2157 closedir(dir);
2158 +#endif
2159
2160 if(!all_pids_count)
2161 return 0;
@@ -2704,6 +2953,7 @@ static void send_collected_data_to_netdata(struct target *root, const char *type
2953 }
2954 send_END();
2955
2956 +#ifndef __FreeBSD__
2957 send_BEGIN(type, "lreads", usec);
2958 for (w = root; w ; w = w->next) {
2959 if(unlikely(w->exposed))
@@ -2717,6 +2967,7 @@ static void send_collected_data_to_netdata(struct target *root, const char *type
2967 send_SET(w->name, w->io_logical_bytes_written);
2968 }
2969 send_END();
2970 +#endif
2971
2972 send_BEGIN(type, "preads", usec);
2973 for (w = root; w ; w = w->next) {
@@ -2842,6 +3093,7 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type
3093 fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
3094 }
3095
3096 +#ifndef __FreeBSD__
3097 fprintf(stdout, "CHART %s.lreads '' '%s Disk Logical Reads' 'kilobytes/s' disk %s.lreads stacked 20042 %d\n", type, title, type, update_every);
3098 for (w = root; w ; w = w->next) {
3099 if(unlikely(w->exposed))
@@ -2853,7 +3105,21 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type
3105 if(unlikely(w->exposed))
3106 fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
3107 }
3108 +#endif
3109 +
3110 +#ifdef __FreeBSD__
3111 + fprintf(stdout, "CHART %s.preads '' '%s Disk Reads' 'blocks/s' disk %s.preads stacked 20002 %d\n", type, title, type, update_every);
3112 + for (w = root; w ; w = w->next) {
3113 + if(unlikely(w->exposed))
3114 + fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
3115 + }
3116
3117 + fprintf(stdout, "CHART %s.pwrites '' '%s Disk Writes' 'blocks/s' disk %s.pwrites stacked 20002 %d\n", type, title, type, update_every);
3118 + for (w = root; w ; w = w->next) {
3119 + if(unlikely(w->exposed))
3120 + fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
3121 + }
3122 +#else
3123 fprintf(stdout, "CHART %s.preads '' '%s Disk Reads' 'kilobytes/s' disk %s.preads stacked 20002 %d\n", type, title, type, update_every);
3124 for (w = root; w ; w = w->next) {
3125 if(unlikely(w->exposed))
@@ -2865,6 +3131,7 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type
3131 if(unlikely(w->exposed))
3132 fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
3133 }
3134 +#endif
3135
3136 if(enable_file_charts) {
3137 fprintf(stdout, "CHART %s.files '' '%s Open Files' 'open files' disk %s.files stacked 20050 %d\n", type,