void cgroup_get_chart_id(struct cgroup *cg) { debug(D_CGROUP, "getting the name of cgroup '%s'", cg->id); pid_t cgroup_pid; char buffer[CGROUP_CHARTID_LINE_MAX + 1]; snprintfz(buffer, CGROUP_CHARTID_LINE_MAX, "exec %s '%s'", config_get("plugin:cgroups", "script to get cgroup names", PLUGINS_DIR "/cgroup-name.sh"), cg->chart_id); debug(D_CGROUP, "executing command '%s' for cgroup '%s'", buffer, cg->id); FILE *fp = mypopen(buffer, &cgroup_pid); if(!fp) { error("CGROUP: Cannot popen(\"%s\", \"r\").", buffer); return; } debug(D_CGROUP, "reading from command '%s' for cgroup '%s'", buffer, cg->id); char *s = fgets(buffer, CGROUP_CHARTID_LINE_MAX, fp); debug(D_CGROUP, "closing command for cgroup '%s'", cg->id); mypclose(fp, cgroup_pid); debug(D_CGROUP, "closed command for cgroup '%s'", cg->id); if(s && *s && *s != '\n') { debug(D_CGROUP, "cgroup '%s' should be renamed to '%s'", cg->id, s); trim(s); free(cg->chart_title); cg->chart_title = strdup(s); if(!cg->chart_title) fatal("CGROUP: Cannot allocate memory for chart name of cgroup '%s' chart name: '%s'", cg->id, s); netdata_fix_chart_name(cg->chart_title); free(cg->chart_id); cg->chart_id = strdup(s); if(!cg->chart_id) fatal("CGROUP: Cannot allocate memory for chart id of cgroup '%s' chart id: '%s'", cg->id, s); netdata_fix_chart_id(cg->chart_id); debug(D_CGROUP, "cgroup '%s' renamed to '%s' (title: '%s')", cg->id, cg->chart_id, cg->chart_title); } else debug(D_CGROUP, "cgroup '%s' is not to be renamed (will be shown as '%s')", cg->id, cg->chart_id); }
// 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; }