long get_system_cpus(void) { processors = 1; #ifdef __APPLE__ int32_t tmp_processors; if (unlikely(GETSYSCTL_BY_NAME("hw.logicalcpu", tmp_processors))) { error("Assuming system has %d processors.", processors); } else { processors = tmp_processors; } return processors; #elif __FreeBSD__ int32_t tmp_processors; if (unlikely(GETSYSCTL_BY_NAME("hw.ncpu", tmp_processors))) { error("Assuming system has %d processors.", processors); } else { processors = tmp_processors; } return processors; #else char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s/proc/stat", netdata_configured_host_prefix); procfile *ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT); if(!ff) { error("Cannot open file '%s'. Assuming system has %d processors.", filename, processors); return processors; } ff = procfile_readall(ff); if(!ff) { error("Cannot open file '%s'. Assuming system has %d processors.", filename, processors); return processors; } processors = 0; unsigned int i; for(i = 0; i < procfile_lines(ff); i++) { if(!procfile_linewords(ff, i)) continue; if(strncmp(procfile_lineword(ff, i, 0), "cpu", 3) == 0) processors++; } processors--; if(processors < 1) processors = 1; procfile_close(ff); debug(D_SYSTEM, "System has %d processors.", processors); return processors; #endif /* __APPLE__, __FreeBSD__ */ }
// read the whole mountinfo into a linked list struct mountinfo *mountinfo_read(int do_statvfs) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s/proc/self/mountinfo", netdata_configured_host_prefix); procfile *ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT); if(unlikely(!ff)) { snprintfz(filename, FILENAME_MAX, "%s/proc/1/mountinfo", netdata_configured_host_prefix); ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT); if(unlikely(!ff)) return NULL; } ff = procfile_readall(ff); if(unlikely(!ff)) return NULL; struct mountinfo *root = NULL, *last = NULL, *mi = NULL; unsigned long l, lines = procfile_lines(ff); for(l = 0; l < lines ;l++) { if(unlikely(procfile_linewords(ff, l) < 5)) continue; mi = mallocz(sizeof(struct mountinfo)); unsigned long w = 0; mi->id = str2ul(procfile_lineword(ff, l, w)); w++; mi->parentid = str2ul(procfile_lineword(ff, l, w)); w++; char *major = procfile_lineword(ff, l, w), *minor; w++; for(minor = major; *minor && *minor != ':' ;minor++) ; if(unlikely(!*minor)) { error("Cannot parse major:minor on '%s' at line %lu of '%s'", major, l + 1, filename); freez(mi); continue; } *minor = '\0'; minor++; mi->flags = 0; mi->major = str2ul(major); mi->minor = str2ul(minor); mi->root = strdupz(procfile_lineword(ff, l, w)); w++; mi->root_hash = simple_hash(mi->root); mi->mount_point = strdupz_decoding_octal(procfile_lineword(ff, l, w)); w++; mi->mount_point_hash = simple_hash(mi->mount_point); mi->persistent_id = strdupz(mi->mount_point); netdata_fix_chart_id(mi->persistent_id); mi->persistent_id_hash = simple_hash(mi->persistent_id); mi->mount_options = strdupz(procfile_lineword(ff, l, w)); w++; if(unlikely(is_read_only(mi->mount_options))) mi->flags |= MOUNTINFO_READONLY; // count the optional fields /* unsigned long wo = w; */ mi->optional_fields_count = 0; char *s = procfile_lineword(ff, l, w); while(*s && *s != '-') { w++; s = procfile_lineword(ff, l, w); mi->optional_fields_count++; } /* if(unlikely(mi->optional_fields_count)) { // we have some optional fields // read them into a new array of pointers; mi->optional_fields = mallocz(mi->optional_fields_count * sizeof(char *)); int i; for(i = 0; i < mi->optional_fields_count ; i++) { *mi->optional_fields[wo] = strdupz(procfile_lineword(ff, l, w)); wo++; } } else mi->optional_fields = NULL; */ if(likely(*s == '-')) { w++; mi->filesystem = strdupz(procfile_lineword(ff, l, w)); w++; mi->filesystem_hash = simple_hash(mi->filesystem); mi->mount_source = strdupz_decoding_octal(procfile_lineword(ff, l, w)); w++; mi->mount_source_hash = simple_hash(mi->mount_source); mi->super_options = strdupz(procfile_lineword(ff, l, w)); w++; if(unlikely(is_read_only(mi->super_options))) mi->flags |= MOUNTINFO_READONLY; if(unlikely(ME_DUMMY(mi->mount_source, mi->filesystem))) mi->flags |= MOUNTINFO_IS_DUMMY; if(unlikely(ME_REMOTE(mi->mount_source, mi->filesystem))) mi->flags |= MOUNTINFO_IS_REMOTE; // mark as BIND the duplicates (i.e. same filesystem + same source) if(do_statvfs) { struct stat buf; if(unlikely(stat(mi->mount_point, &buf) == -1)) { mi->st_dev = 0; mi->flags |= MOUNTINFO_NO_STAT; } else { mi->st_dev = buf.st_dev; struct mountinfo *mt; for(mt = root; mt; mt = mt->next) { if(unlikely(mt->st_dev == mi->st_dev && !(mt->flags & MOUNTINFO_IS_SAME_DEV))) { if(strlen(mi->mount_point) < strlen(mt->mount_point)) mt->flags |= MOUNTINFO_IS_SAME_DEV; else mi->flags |= MOUNTINFO_IS_SAME_DEV; } } } } else { mi->st_dev = 0; } } else { mi->filesystem = NULL; mi->filesystem_hash = 0; mi->mount_source = NULL; mi->mount_source_hash = 0; mi->super_options = NULL; mi->st_dev = 0; } // check if it has size if(do_statvfs && !(mi->flags & MOUNTINFO_IS_DUMMY)) { struct statvfs buff_statvfs; if(unlikely(statvfs(mi->mount_point, &buff_statvfs) < 0)) { mi->flags |= MOUNTINFO_NO_STAT; } else if(unlikely(!buff_statvfs.f_blocks /* || !buff_statvfs.f_files */)) { mi->flags |= MOUNTINFO_NO_SIZE; } } // link it if(unlikely(!root)) root = mi; else last->next = mi; last = mi; mi->next = NULL; /* #ifdef NETDATA_INTERNAL_CHECKS fprintf(stderr, "MOUNTINFO: %ld %ld %lu:%lu root '%s', persistent id '%s', mount point '%s', mount options '%s', filesystem '%s', mount source '%s', super options '%s'%s%s%s%s%s%s\n", mi->id, mi->parentid, mi->major, mi->minor, mi->root, mi->persistent_id, (mi->mount_point)?mi->mount_point:"", (mi->mount_options)?mi->mount_options:"", (mi->filesystem)?mi->filesystem:"", (mi->mount_source)?mi->mount_source:"", (mi->super_options)?mi->super_options:"", (mi->flags & MOUNTINFO_IS_DUMMY)?" DUMMY":"", (mi->flags & MOUNTINFO_IS_BIND)?" BIND":"", (mi->flags & MOUNTINFO_IS_REMOTE)?" REMOTE":"", (mi->flags & MOUNTINFO_NO_STAT)?" NOSTAT":"", (mi->flags & MOUNTINFO_NO_SIZE)?" NOSIZE":"", (mi->flags & MOUNTINFO_IS_SAME_DEV)?" SAMEDEV":"" ); #endif */ } /* find if the mount options have "bind" in them { FILE *fp = setmntent(MOUNTED, "r"); if (fp != NULL) { struct mntent mntbuf; struct mntent *mnt; char buf[4096 + 1]; while ((mnt = getmntent_r(fp, &mntbuf, buf, 4096))) { char *bind = hasmntopt(mnt, "bind"); if(unlikely(bind)) { struct mountinfo *mi; for(mi = root; mi ; mi = mi->next) { if(unlikely(strcmp(mnt->mnt_dir, mi->mount_point) == 0)) { fprintf(stderr, "Mount point '%s' is BIND\n", mi->mount_point); mi->flags |= MOUNTINFO_IS_BIND; break; } } #ifdef NETDATA_INTERNAL_CHECKS if(unlikely(!mi)) { error("Mount point '%s' not found in /proc/self/mountinfo", mnt->mnt_dir); } #endif } } endmntent(fp); } } */ procfile_close(ff); return root; }
static int read_per_core_time_in_state_files(struct cpu_chart *all_cpu_charts, size_t len, size_t index) { size_t x, files_read = 0, files_nonzero = 0; for(x = 0; x < len ; x++) { struct per_core_single_number_file *f = &all_cpu_charts[x].files[index]; struct per_core_time_in_state_file *tsf = &all_cpu_charts[x].time_in_state_files; f->found = 0; if(unlikely(!tsf->filename)) continue; if(unlikely(!tsf->ff)) { tsf->ff = procfile_open(tsf->filename, " \t:", PROCFILE_FLAG_DEFAULT); if(unlikely(!tsf->ff)) { error("Cannot open file '%s'", tsf->filename); continue; } } tsf->ff = procfile_readall(tsf->ff); if(unlikely(!tsf->ff)) { error("Cannot read file '%s'", tsf->filename); procfile_close(tsf->ff); tsf->ff = NULL; continue; } else { // successful read size_t lines = procfile_lines(tsf->ff), l; size_t words; unsigned long long total_ticks_since_last = 0, avg_freq = 0; // Check if there is at least one frequency in time_in_state if (procfile_word(tsf->ff, 0)[0] == '\0') { if(unlikely(keep_per_core_fds_open != CONFIG_BOOLEAN_YES)) { procfile_close(tsf->ff); tsf->ff = NULL; } // TODO: Is there a better way to avoid spikes than calculating the average over // the whole period under schedutil governor? // freez(tsf->last_ticks); // tsf->last_ticks = NULL; // tsf->last_ticks_len = 0; continue; } if (unlikely(tsf->last_ticks_len < lines || tsf->last_ticks == NULL)) { tsf->last_ticks = reallocz(tsf->last_ticks, sizeof(struct last_ticks) * lines); memset(tsf->last_ticks, 0, sizeof(struct last_ticks) * lines); tsf->last_ticks_len = lines; } f->value = 0; for(l = 0; l < lines - 1 ;l++) { unsigned long long frequency = 0, ticks = 0, ticks_since_last = 0; words = procfile_linewords(tsf->ff, l); if(unlikely(words < 2)) { error("Cannot read time_in_state line. Expected 2 params, read %zu.", words); continue; } frequency = str2ull(procfile_lineword(tsf->ff, l, 0)); ticks = str2ull(procfile_lineword(tsf->ff, l, 1)); // It is assumed that frequencies are static and sorted ticks_since_last = ticks - tsf->last_ticks[l].ticks; tsf->last_ticks[l].frequency = frequency; tsf->last_ticks[l].ticks = ticks; total_ticks_since_last += ticks_since_last; avg_freq += frequency * ticks_since_last; } if (likely(total_ticks_since_last)) { avg_freq /= total_ticks_since_last; f->value = avg_freq; } if(unlikely(keep_per_core_fds_open != CONFIG_BOOLEAN_YES)) { procfile_close(tsf->ff); tsf->ff = NULL; } } files_read++; f->found = 1; if(likely(f->value != 0)) files_nonzero++; } if(unlikely(files_read == 0)) return -1; if(unlikely(files_nonzero == 0)) return 0; return (int)files_nonzero; }
// read the whole mountinfo into a linked list struct mountinfo *mountinfo_read() { procfile *ff = NULL; char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s/proc/self/mountinfo", global_host_prefix); ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT); if(!ff) { snprintfz(filename, FILENAME_MAX, "%s/proc/1/mountinfo", global_host_prefix); ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT); if(!ff) return NULL; } ff = procfile_readall(ff); if(!ff) return NULL; struct mountinfo *root = NULL, *last = NULL, *mi = NULL; unsigned long l, lines = procfile_lines(ff); for(l = 0; l < lines ;l++) { if(procfile_linewords(ff, l) < 5) continue; mi = malloc(sizeof(struct mountinfo)); if(unlikely(!mi)) fatal("Cannot allocate memory for mountinfo"); if(unlikely(!root)) root = last = mi; else last->next = mi; last = mi; mi->next = NULL; unsigned long w = 0; mi->id = strtoul(procfile_lineword(ff, l, w), NULL, 10); w++; mi->parentid = strtoul(procfile_lineword(ff, l, w), NULL, 10); w++; char *major = procfile_lineword(ff, l, w), *minor; w++; for(minor = major; *minor && *minor != ':' ;minor++) ; *minor = '\0'; minor++; mi->major = strtoul(major, NULL, 10); mi->minor = strtoul(minor, NULL, 10); mi->root = strdup(procfile_lineword(ff, l, w)); w++; if(unlikely(!mi->root)) fatal("Cannot allocate memory"); mi->root_hash = simple_hash(mi->root); mi->mount_point = strdup(procfile_lineword(ff, l, w)); w++; if(unlikely(!mi->mount_point)) fatal("Cannot allocate memory"); mi->mount_point_hash = simple_hash(mi->mount_point); mi->mount_options = strdup(procfile_lineword(ff, l, w)); w++; if(unlikely(!mi->mount_options)) fatal("Cannot allocate memory"); // count the optional fields /* unsigned long wo = w; */ mi->optional_fields_count = 0; char *s = procfile_lineword(ff, l, w); while(*s && *s != '-') { w++; s = procfile_lineword(ff, l, w); mi->optional_fields_count++; } /* if(unlikely(mi->optional_fields_count)) { // we have some optional fields // read them into a new array of pointers; mi->optional_fields = malloc(mi->optional_fields_count * sizeof(char *)); if(unlikely(!mi->optional_fields)) fatal("Cannot allocate memory for %d mountinfo optional fields", mi->optional_fields_count); int i; for(i = 0; i < mi->optional_fields_count ; i++) { *mi->optional_fields[wo] = strdup(procfile_lineword(ff, l, w)); if(!mi->optional_fields[wo]) fatal("Cannot allocate memory"); wo++; } } else mi->optional_fields = NULL; */ if(likely(*s == '-')) { w++; mi->filesystem = strdup(procfile_lineword(ff, l, w)); w++; if(!mi->filesystem) fatal("Cannot allocate memory"); mi->filesystem_hash = simple_hash(mi->filesystem); mi->mount_source = strdup(procfile_lineword(ff, l, w)); w++; if(!mi->mount_source) fatal("Cannot allocate memory"); mi->mount_source_hash = simple_hash(mi->mount_source); mi->super_options = strdup(procfile_lineword(ff, l, w)); w++; if(!mi->super_options) fatal("Cannot allocate memory"); } else { mi->filesystem = NULL; mi->mount_source = NULL; mi->super_options = NULL; } /* info("MOUNTINFO: %u %u %u:%u root '%s', mount point '%s', mount options '%s', filesystem '%s', mount source '%s', super options '%s'", mi->id, mi->parentid, mi->major, mi->minor, mi->root, mi->mount_point, mi->mount_options, mi->filesystem, mi->mount_source, mi->super_options ); */ } procfile_close(ff); return root; }