int refresh_proc_sys_fs(proc_sys_fs_t *proc_sys_fs) { static int err_reported; char buf[MAXPATHLEN]; FILE *filesp = NULL; FILE *inodep = NULL; FILE *dentryp = NULL; memset(proc_sys_fs, 0, sizeof(proc_sys_fs_t)); if ((filesp = linux_statsfile("/proc/sys/fs/file-nr", buf, sizeof(buf))) == NULL || (inodep = linux_statsfile("/proc/sys/fs/inode-state", buf, sizeof(buf))) == NULL || (dentryp = linux_statsfile("/proc/sys/fs/dentry-state", buf, sizeof(buf))) == NULL) { proc_sys_fs->errcode = -oserror(); if (err_reported == 0) fprintf(stderr, "Warning: vfs metrics are not available : %s\n", osstrerror()); } else { proc_sys_fs->errcode = 0; if (fscanf(filesp, "%d %d %d", &proc_sys_fs->fs_files_count, &proc_sys_fs->fs_files_free, &proc_sys_fs->fs_files_max) != 3) proc_sys_fs->errcode = PM_ERR_VALUE; if (fscanf(inodep, "%d %d", &proc_sys_fs->fs_inodes_count, &proc_sys_fs->fs_inodes_free) != 2) proc_sys_fs->errcode = PM_ERR_VALUE; if (fscanf(dentryp, "%d %d", &proc_sys_fs->fs_dentry_count, &proc_sys_fs->fs_dentry_free) != 2) proc_sys_fs->errcode = PM_ERR_VALUE; #if PCP_DEBUG if (pmDebug & DBG_TRACE_LIBPMDA) { if (proc_sys_fs->errcode == 0) fprintf(stderr, "refresh_proc_sys_fs: found vfs metrics\n"); else fprintf(stderr, "refresh_proc_sys_fs: botch! missing vfs metrics\n"); } #endif } if (filesp) fclose(filesp); if (inodep) fclose(inodep); if (dentryp) fclose(dentryp); if (!err_reported) err_reported = 1; if (proc_sys_fs->errcode == 0) return 0; return -1; }
static int refresh_net_dev_ipv6_addr(pmInDom indom) { FILE *fp; char addr6p[8][5]; char addr6[40], devname[20+1]; char addr[INET6_ADDRSTRLEN]; char buf[MAXPATHLEN]; struct sockaddr_in6 sin6; int sts, plen, scope, dad_status, if_idx; net_addr_t *netip; static uint32_t cache_err; if ((fp = linux_statsfile("/proc/net/if_inet6", buf, sizeof(buf))) == NULL) return 0; while (fscanf(fp, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n", addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope, &dad_status, devname) != EOF) { sts = pmdaCacheLookupName(indom, devname, NULL, (void **)&netip); if (sts == PM_ERR_INST || (sts >= 0 && netip == NULL)) { /* first time since re-loaded, else new one */ netip = (net_addr_t *)calloc(1, sizeof(net_addr_t)); } else if (sts < 0) { if (cache_err++ < 10) { fprintf(stderr, "refresh_net_dev_ipv6_addr: " "pmdaCacheLookupName(%s, %s, ...) failed: %s\n", pmInDomStr(indom), devname, pmErrStr(sts)); } continue; } if ((sts = pmdaCacheStore(indom, PMDA_CACHE_ADD, devname, (void *)netip)) < 0) { if (cache_err++ < 10) { fprintf(stderr, "refresh_net_dev_ipv6_addr: " "pmdaCacheStore(%s, PMDA_CACHE_ADD, %s, " PRINTF_P_PFX "%p) failed: %s\n", pmInDomStr(indom), devname, netip, pmErrStr(sts)); } continue; } sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]); if (inet_pton(AF_INET6, addr6, sin6.sin6_addr.s6_addr) != 1) continue; sin6.sin6_family = AF_INET6; sin6.sin6_port = 0; if (!inet_ntop(AF_INET6, &sin6.sin6_addr, addr, INET6_ADDRSTRLEN)) continue; snprintf(netip->ipv6, sizeof(netip->ipv6), "%s/%d", addr, plen); netip->ipv6scope = (uint16_t)scope; netip->has_ipv6 = 1; } fclose(fp); return 0; }
int refresh_proc_net_snmp(proc_net_snmp_t *snmp) { char buf[MAXPATHLEN]; char header[1024]; FILE *fp; init_refresh_proc_net_snmp(snmp); if ((fp = linux_statsfile("/proc/net/snmp", buf, sizeof(buf))) == NULL) return -oserror(); while (fgets(header, sizeof(header), fp) != NULL) { if (fgets(buf, sizeof(buf), fp) != NULL) { if (strncmp(buf, "Ip:", 3) == 0) get_fields(ip_fields, header, buf); else if (strncmp(buf, "Icmp:", 5) == 0) get_fields(icmp_fields, header, buf); else if (strncmp(buf, "IcmpMsg:", 8) == 0) get_ordinal_fields(icmpmsg_fields, header, buf, NR_ICMPMSG_COUNTERS); else if (strncmp(buf, "Tcp:", 4) == 0) get_fields(tcp_fields, header, buf); else if (strncmp(buf, "Udp:", 4) == 0) get_fields(udp_fields, header, buf); else if (strncmp(buf, "UdpLite:", 8) == 0) get_fields(udplite_fields, header, buf); else fprintf(stderr, "Error: unrecognised snmp row: %s", buf); } } fclose(fp); return 0; }
int refresh_interrupt_values(void) { FILE *fp; char buf[4096]; int i, ncolumns; if (cpu_count == 0) { long ncpus = sysconf(_SC_NPROCESSORS_CONF); online_cpumap = malloc(ncpus * sizeof(int)); if (!online_cpumap) return -oserror(); cpu_count = ncpus; } memset(online_cpumap, 0, cpu_count * sizeof(int)); if ((fp = linux_statsfile("/proc/interrupts", buf, sizeof(buf))) == NULL) return -oserror(); /* first parse header, which maps online CPU number to column number */ if (fgets(buf, sizeof(buf), fp)) { ncolumns = map_online_cpus(buf); } else { fclose(fp); return -EINVAL; /* unrecognised file format */ } /* next we parse each interrupt line row (starting with a digit) */ i = 0; while (fgets(buf, sizeof(buf), fp)) if (!extract_interrupt_lines(buf, ncolumns, i++)) break; /* parse other per-CPU interrupt counter rows (starts non-digit) */ i = 0; while (fgets(buf, sizeof(buf), fp) != NULL) { if (extract_interrupt_errors(buf)) continue; if (extract_interrupt_misses(buf)) continue; if (!extract_interrupt_other(buf, ncolumns, i++)) break; } fclose(fp); return 0; }
int refresh_proc_net_softnet(proc_net_softnet_t *proc_net_softnet) { char buf[1024]; int count, flags; FILE *fp; uint64_t filler; proc_net_softnet_t sn; if ((fp = linux_statsfile("/proc/net/softnet_stat", buf, sizeof(buf))) == NULL) return -oserror(); memset(proc_net_softnet, 0, sizeof(proc_net_softnet_t)); while (fgets(buf, sizeof(buf), fp) != NULL) { memset(&sn, 0, sizeof(sn)); count = sscanf(buf, "%08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx", &sn.processed, &sn.dropped, &sn.time_squeeze, &filler, &filler, &filler, &filler, &filler, &sn.cpu_collision, &sn.received_rps, &sn.flow_limit_count); flags = 0; if (count >= 9) flags |= SN_PROCESSED | SN_DROPPED | SN_TIME_SQUEEZE | SN_CPU_COLLISION; if (count >= 10) flags |= SN_RECEIVED_RPS; if (count >= 11) flags |= SN_FLOW_LIMIT_COUNT; proc_net_softnet->flags = flags; /* summed, one line per-cpu */ proc_net_softnet->processed += sn.processed; proc_net_softnet->dropped += sn.dropped; proc_net_softnet->time_squeeze += sn.time_squeeze; proc_net_softnet->cpu_collision += sn.cpu_collision; proc_net_softnet->received_rps += sn.received_rps; proc_net_softnet->flow_limit_count += sn.flow_limit_count; } fclose(fp); return 0; }
int refresh_proc_net_netstat(proc_net_netstat_t *netstat) { /* Need a sufficiently large value to hold a full line */ char buf[MAXPATHLEN]; char header[2048]; FILE *fp; init_refresh_proc_net_netstat(netstat); if ((fp = linux_statsfile("/proc/net/netstat", buf, sizeof(buf))) == NULL) return -oserror(); while (fgets(header, sizeof(header), fp) != NULL) { if (fgets(buf, sizeof(buf), fp) != NULL) { if (strncmp(buf, "IpExt:", 6) == 0) get_fields(netstat_ip_fields, header, buf); else if (strncmp(buf, "TcpExt:", 7) == 0) get_fields(netstat_tcp_fields, header, buf); else __pmNotifyErr(LOG_ERR, "Unrecognised netstat row: %s\n", buf); } } fclose(fp); return 0; }
int refresh_proc_partitions(pmInDom disk_indom, pmInDom partitions_indom, pmInDom dm_indom) { FILE *fp; int devmin; int devmaj; int n; int indom; int have_proc_diskstats; int inst; unsigned long long blocks; partitions_entry_t *p; int indom_changes = 0; char *dmname; char buf[MAXPATHLEN]; char namebuf[MAXPATHLEN]; static int first = 1; if (first) { /* initialize the instance domain caches */ pmdaCacheOp(disk_indom, PMDA_CACHE_LOAD); pmdaCacheOp(partitions_indom, PMDA_CACHE_LOAD); pmdaCacheOp(dm_indom, PMDA_CACHE_LOAD); first = 0; indom_changes = 1; } pmdaCacheOp(disk_indom, PMDA_CACHE_INACTIVE); pmdaCacheOp(partitions_indom, PMDA_CACHE_INACTIVE); pmdaCacheOp(dm_indom, PMDA_CACHE_INACTIVE); if ((fp = linux_statsfile("/proc/diskstats", buf, sizeof(buf))) != NULL) /* 2.6 style disk stats */ have_proc_diskstats = 1; else { if ((fp = linux_statsfile("/proc/partitions", buf, sizeof(buf))) != NULL) have_proc_diskstats = 0; else return -oserror(); } while (fgets(buf, sizeof(buf), fp) != NULL) { dmname = NULL; if (buf[0] != ' ' || buf[0] == '\n') { /* skip heading */ continue; } if (have_proc_diskstats) { if ((n = sscanf(buf, "%d %d %s", &devmaj, &devmin, namebuf)) != 3) continue; } else { /* /proc/partitions */ if ((n = sscanf(buf, "%d %d %llu %s", &devmaj, &devmin, &blocks, namebuf)) != 4) continue; } if (_pm_isdm(namebuf)) { indom = dm_indom; dmname = strdup(namebuf); } else if (_pm_ispartition(namebuf)) indom = partitions_indom; else if (_pm_isdisk(namebuf)) indom = disk_indom; else continue; if (indom == dm_indom) { /* replace dm-[0-9]* with the persistent name from /dev/mapper */ if (!map_persistent_dm_name(namebuf, sizeof(namebuf), devmaj, devmin)) { /* skip dm devices that have no persistent name mapping */ free(dmname); continue; } } p = NULL; if (pmdaCacheLookupName(indom, namebuf, &inst, (void **)&p) < 0 || !p) { /* not found: allocate and add a new entry */ p = (partitions_entry_t *)malloc(sizeof(partitions_entry_t)); memset(p, 0, sizeof(partitions_entry_t)); indom_changes++; } if (p->dmname) free(p->dmname); p->dmname = dmname; /* NULL if not a dm device */ if (!p->namebuf) p->namebuf = strdup(namebuf); else if (strcmp(namebuf, p->namebuf) != 0) { free(p->namebuf); p->namebuf = strdup(namebuf); } /* activate this entry */ if (p->udevnamebuf) /* long xscsi name */ inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, p->udevnamebuf, p); else /* short /proc/diskstats or /proc/partitions name */ inst = pmdaCacheStore(indom, PMDA_CACHE_ADD, namebuf, p); if (have_proc_diskstats) { /* 2.6 style /proc/diskstats */ p->nr_blocks = 0; namebuf[0] = '\0'; /* Linux source: block/genhd.c::diskstats_show(1) */ n = sscanf(buf, "%u %u %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u", &p->major, &p->minor, namebuf, &p->rd_ios, &p->rd_merges, &p->rd_sectors, &p->rd_ticks, &p->wr_ios, &p->wr_merges, &p->wr_sectors, &p->wr_ticks, &p->ios_in_flight, &p->io_ticks, &p->aveq); if (n != 14) { p->rd_merges = p->wr_merges = p->wr_ticks = p->ios_in_flight = p->io_ticks = p->aveq = 0; /* Linux source: block/genhd.c::diskstats_show(2) */ n = sscanf(buf, "%u %u %s %u %u %u %u\n", &p->major, &p->minor, namebuf, (unsigned int *)&p->rd_ios, (unsigned int *)&p->rd_sectors, (unsigned int *)&p->wr_ios, (unsigned int *)&p->wr_sectors); } } else { /* 2.4 style /proc/partitions */ namebuf[0] = '\0'; n = sscanf(buf, "%u %u %lu %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u", &p->major, &p->minor, &p->nr_blocks, namebuf, &p->rd_ios, &p->rd_merges, &p->rd_sectors, &p->rd_ticks, &p->wr_ios, &p->wr_merges, &p->wr_sectors, &p->wr_ticks, &p->ios_in_flight, &p->io_ticks, &p->aveq); } } /* * If any new disks or partitions have appeared then we * we need to remap the long device names (if /dev/xscsi * exists) and then flush the pmda cache. * * We just let inactive instances rot in the inactive state * (this doesn't happen very often, so is only a minor leak). */ if (indom_changes) { refresh_udev(disk_indom, partitions_indom); pmdaCacheOp(disk_indom, PMDA_CACHE_SAVE); pmdaCacheOp(partitions_indom, PMDA_CACHE_SAVE); pmdaCacheOp(dm_indom, PMDA_CACHE_SAVE); } /* * success */ if (fp) fclose(fp); return 0; }
int refresh_proc_net_dev(pmInDom indom, linux_container_t *container) { static uint32_t gen; /* refresh generation number */ static uint32_t cache_err; /* throttle messages */ char buf[1024]; FILE *fp; char *p, *v; int j, sts; net_interface_t *netip; if ((fp = linux_statsfile("/proc/net/dev", buf, sizeof(buf))) == NULL) return -oserror(); if (gen == 0) { /* * first time, reload cache from external file, and force any * subsequent changes to be saved */ pmdaCacheOp(indom, PMDA_CACHE_LOAD); gen++; } /* Inter-| Receive | Transmit face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed lo: 4060748 39057 0 0 0 0 0 0 4060748 39057 0 0 0 0 0 0 eth0: 0 337614 0 0 0 0 0 0 0 267537 0 0 0 27346 62 0 */ pmdaCacheOp(indom, PMDA_CACHE_INACTIVE); while (fgets(buf, sizeof(buf), fp) != NULL) { if ((p = v = strchr(buf, ':')) == NULL) continue; *p = '\0'; for (p=buf; *p && isspace((int)*p); p++) {;} sts = pmdaCacheLookupName(indom, p, NULL, (void **)&netip); if (sts == PM_ERR_INST || (sts >= 0 && netip == NULL)) { /* first time since re-loaded, else new one */ netip = (net_interface_t *)calloc(1, sizeof(net_interface_t)); #if PCP_DEBUG if (pmDebug & DBG_TRACE_LIBPMDA) { fprintf(stderr, "refresh_proc_net_dev: initialize \"%s\"\n", p); } #endif } else if (sts < 0) { if (cache_err++ < 10) { fprintf(stderr, "refresh_proc_net_dev: pmdaCacheLookupName(%s, %s, ...) failed: %s\n", pmInDomStr(indom), p, pmErrStr(sts)); } continue; } if ((sts = pmdaCacheStore(indom, PMDA_CACHE_ADD, p, (void *)netip)) < 0) { if (cache_err++ < 10) { fprintf(stderr, "refresh_proc_net_dev: pmdaCacheStore(%s, PMDA_CACHE_ADD, %s, " PRINTF_P_PFX "%p) failed: %s\n", pmInDomStr(indom), p, netip, pmErrStr(sts)); } continue; } memset(&netip->ioc, 0, sizeof(netip->ioc)); for (p=v, j=0; j < PROC_DEV_COUNTERS_PER_LINE; j++) { for (; !isdigit((int)*p); p++) {;} sscanf(p, "%llu", (long long unsigned int *)&netip->counters[j]); for (; !isspace((int)*p); p++) {;} } } /* success */ fclose(fp); if (!container) pmdaCacheOp(indom, PMDA_CACHE_SAVE); return 0; }
int refresh_proc_slabinfo(pmInDom slab_indom, proc_slabinfo_t *slabinfo) { slab_cache_t sbuf, *s; char buf[BUFSIZ]; char name[128]; char *w, *p; FILE *fp; int i, sts = 0, indom_change = 0; static int major_version = -1; static int minor_version = 0; for (pmdaCacheOp(slab_indom, PMDA_CACHE_WALK_REWIND);;) { if ((i = pmdaCacheOp(slab_indom, PMDA_CACHE_WALK_NEXT)) < 0) break; if (!pmdaCacheLookup(slab_indom, i, NULL, (void **)&s) || !s) continue; s->seen = 0; } pmdaCacheOp(slab_indom, PMDA_CACHE_INACTIVE); if ((fp = linux_statsfile("/proc/slabinfo", buf, sizeof(buf))) == NULL) return -oserror(); /* skip header */ if (fgets(buf, sizeof(buf), fp) == NULL) { /* oops, no header! */ fclose(fp); return -oserror(); } if (major_version < 0) { major_version = minor_version = 0; if (strstr(buf, "slabinfo - version:")) { for (p = buf; *p; p++) { if (isdigit((int)*p)) { sscanf(p, "%d.%d", &major_version, &minor_version); break; } } } } while (fgets(buf, sizeof(buf), fp) != NULL) { /* try to convert whitespace in cache names to underscores, */ /* by looking for alphabetic chars which follow whitespace. */ if (buf[0] == '#') continue; for (w = NULL, p = buf; *p != '\0'; p++) { if (isspace((int)*p)) w = p; else if (isdigit((int)*p)) break; else if (isalpha((int)*p) && w) { for (; w && w != p; w++) *w = '_'; w = NULL; } } memset(&sbuf, 0, sizeof(slab_cache_t)); if (major_version == 1 && minor_version == 0) { /* * <name> <active_objs> <num_objs> * (generally 2.2 kernels) */ i = sscanf(buf, "%s %lu %lu", name, (unsigned long *)&sbuf.num_active_objs, (unsigned long *)&sbuf.total_objs); if (i != 3) { sts = PM_ERR_APPVERSION; break; } } else if (major_version == 1 && minor_version == 1) { /* * <name> <active_objs> <num_objs> <objsize> <active_slabs> <num_slabs> <pagesperslab> * (generally 2.4 kernels) */ i = sscanf(buf, "%s %lu %lu %u %u %u %u", name, (unsigned long *)&sbuf.num_active_objs, (unsigned long *)&sbuf.total_objs, &sbuf.object_size, &sbuf.num_active_slabs, &sbuf.total_slabs, &sbuf.pages_per_slab); if (i != 7) { sts = PM_ERR_APPVERSION; break; } sbuf.total_size = sbuf.pages_per_slab * sbuf.num_active_slabs; sbuf.total_size <<= _pm_pageshift; } else if (major_version == 2 && minor_version >= 0 && minor_version <= 1) { /* * <name> <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> .. and more * (generally for kernels up to at least 2.6.11) */ i = sscanf(buf, "%s %lu %lu %u %u %u", name, (unsigned long *)&sbuf.num_active_objs, (unsigned long *)&sbuf.total_objs, &sbuf.object_size, &sbuf.objects_per_slab, &sbuf.pages_per_slab); if (i != 6) { sts = PM_ERR_APPVERSION; break; } sbuf.total_size = sbuf.pages_per_slab * sbuf.num_active_objs; sbuf.total_size <<= _pm_pageshift; sbuf.total_size /= sbuf.objects_per_slab; } else { /* no support */ sts = PM_ERR_APPVERSION; break; } sts = pmdaCacheLookupName(slab_indom, name, &i, (void **)&s); if (sts < 0 || !s) { /* new cache has appeared */ if ((s = calloc(1, sizeof(*s))) == NULL) continue; #if PCP_DEBUG if (pmDebug & DBG_TRACE_LIBPMDA) fprintf(stderr, "refresh_slabinfo: added \"%s\"\n", name); #endif indom_change++; } s->num_active_objs = sbuf.num_active_objs; s->total_objs = sbuf.total_objs; s->object_size = sbuf.object_size; s->num_active_slabs = sbuf.num_active_slabs; s->total_slabs = sbuf.total_slabs; s->pages_per_slab = sbuf.pages_per_slab; s->objects_per_slab = sbuf.objects_per_slab; s->total_size = sbuf.total_size; s->seen = major_version * 10 + minor_version; pmdaCacheStore(slab_indom, PMDA_CACHE_ADD, name, s); } fclose(fp); if (indom_change) pmdaCacheOp(slab_indom, PMDA_CACHE_SAVE); return sts; }
int refresh_proc_meminfo(proc_meminfo_t *proc_meminfo) { char buf[1024]; char *bufp; int64_t *p; int i; FILE *fp; for (i = 0; meminfo_fields[i].field != NULL; i++) { p = MOFFSET(i, proc_meminfo); *p = -1; /* marked as "no value available" */ } if ((fp = linux_statsfile("/proc/meminfo", buf, sizeof(buf))) == NULL) return -oserror(); while (fgets(buf, sizeof(buf), fp) != NULL) { if ((bufp = strchr(buf, ':')) == NULL) continue; *bufp = '\0'; for (i=0; meminfo_fields[i].field != NULL; i++) { if (strcmp(buf, meminfo_fields[i].field) != 0) continue; p = MOFFSET(i, proc_meminfo); for (bufp++; *bufp; bufp++) { if (isdigit((int)*bufp)) { sscanf(bufp, "%llu", (unsigned long long *)p); *p *= 1024; /* kbytes -> bytes */ break; } } } } fclose(fp); /* * MemAvailable is only in 3.x or later kernels but we can calculate it * using other values, similar to upstream kernel commit 34e431b0ae. */ if (!MEMINFO_VALID_VALUE(proc_meminfo->MemAvailable) || (linux_test_mode & LINUX_TEST_MEMINFO)) { if (MEMINFO_VALID_VALUE(proc_meminfo->MemTotal) && MEMINFO_VALID_VALUE(proc_meminfo->MemFree) && MEMINFO_VALID_VALUE(proc_meminfo->Active_file) && MEMINFO_VALID_VALUE(proc_meminfo->Inactive_file) && MEMINFO_VALID_VALUE(proc_meminfo->SlabReclaimable)) { int64_t pagecache; int64_t wmark_low = 0; /* * sum for each zone->watermark[WMARK_LOW]; */ if ((fp = linux_statsfile("/proc/zoneinfo", buf, sizeof(buf))) != NULL) { while (fgets(buf, sizeof(buf), fp) != NULL) { if ((bufp = strstr(buf, "low ")) != NULL) { int64_t low; if (sscanf(bufp+4, "%lld", (long long int *)&low) == 1) wmark_low += low; } } fclose(fp); wmark_low <<= _pm_pageshift; } /* * Free memory cannot be taken below the low watermark, before the * system starts swapping. */ proc_meminfo->MemAvailable = proc_meminfo->MemFree - wmark_low; /* * Not all the page cache can be freed, otherwise the system will * start swapping. Assume at least half of the page cache, or the * low watermark worth of cache, needs to stay. */ pagecache = proc_meminfo->Active_file + proc_meminfo->Inactive_file; pagecache -= MIN(pagecache / 2, wmark_low); proc_meminfo->MemAvailable += pagecache; /* * Part of the reclaimable slab consists of items that are in use, * and cannot be freed. Cap this estimate at the low watermark. */ proc_meminfo->MemAvailable += proc_meminfo->SlabReclaimable; proc_meminfo->MemAvailable -= MIN(proc_meminfo->SlabReclaimable / 2, wmark_low); if (proc_meminfo->MemAvailable < 0) proc_meminfo->MemAvailable = 0; } } /* success */ return 0; }
int refresh_proc_net_softnet(proc_net_softnet_t *proc_net_softnet) { char buf[1024]; int count; unsigned flags = 0; int cpu; FILE *fp; uint64_t filler; proc_net_softnet_t *sn = proc_net_softnet; /* size > (11*7)+1 bytes, where 7 == strlen("%08llx "), and +1 for '\0' */ static char fmt[128] = { '\0' }; if (fmt[0] == '\0') { int i; /* * one trip initialization to decide the correct sscanf format * for a uint64_t data type .. needs to be * "%08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx" * or * "%08llx %08llx %08llx %08llx %08llx %08llx %08llx %08llx %08llx %08llx %08llx" */ fmt[0] = '\0'; if (strcmp(FMT_INT64, "lld") == 0) { for (i = 0; i < 11; i++) strcat(fmt, "%08llx "); } else { for (i = 0; i < 11; i++) strcat(fmt, "%08lx "); } /* chop off last ' ' */ fmt[strlen(fmt)] = '\0'; /* one-trip - allocate per-cpu counter arrays */ memset(sn, 0, sizeof(proc_net_softnet_t)); sn->processed = (uint64_t *)malloc(_pm_ncpus * sizeof(uint64_t)); sn->dropped = (uint64_t *)malloc(_pm_ncpus * sizeof(uint64_t)); sn->time_squeeze = (uint64_t *)malloc(_pm_ncpus * sizeof(uint64_t)); sn->cpu_collision = (uint64_t *)malloc(_pm_ncpus * sizeof(uint64_t)); sn->received_rps = (uint64_t *)malloc(_pm_ncpus * sizeof(uint64_t)); sn->flow_limit_count = (uint64_t *)malloc(_pm_ncpus * sizeof(uint64_t)); if (!sn->processed || !sn->dropped || !sn->time_squeeze || !sn->cpu_collision || !sn->received_rps || !sn->flow_limit_count) { return -ENOMEM; } } if ((fp = linux_statsfile("/proc/net/softnet_stat", buf, sizeof(buf))) == NULL) return -oserror(); for (cpu=0; cpu < _pm_ncpus; cpu++) { if (fgets(buf, sizeof(buf), fp) == NULL) break; count = sscanf(buf, fmt, &sn->processed[cpu], &sn->dropped[cpu], &sn->time_squeeze[cpu], &filler, &filler, &filler, &filler, &filler, &sn->cpu_collision[cpu], &sn->received_rps[cpu], &sn->flow_limit_count[cpu]); sn->flags = 0; if (count >= 9) sn->flags |= SN_PROCESSED | SN_DROPPED | SN_TIME_SQUEEZE | SN_CPU_COLLISION; if (count >= 10) sn->flags |= SN_RECEIVED_RPS; if (count >= 11) sn->flags |= SN_FLOW_LIMIT_COUNT; if (cpu > 0 && sn->flags != flags) fprintf(stderr, "refresh_proc_net_softnet: warning: inconsistent flags, cpu %d\n", cpu); flags = sn->flags; } fclose(fp); return 0; }
int refresh_proc_net_softnet(proc_net_softnet_t *proc_net_softnet) { char buf[1024]; int count, flags; FILE *fp; uint64_t filler; proc_net_softnet_t sn; /* size > (11*7)+1 bytes, where 7 == strlen("%08llx "), and +1 for '\0' */ static char fmt[128] = { '\0' }; if (fmt[0] == '\0') { int i; /* * one trip initialization to decide the correct sscanf format * for a uint64_t data type .. needs to be * "%08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx" * or * "%08llx %08llx %08llx %08llx %08llx %08llx %08llx %08llx %08llx %08llx %08llx" */ fmt[0] = '\0'; if (strcmp(FMT_INT64, "lld") == 0) { for (i = 0; i < 11; i++) strcat(fmt, "%08llx "); } else { for (i = 0; i < 11; i++) strcat(fmt, "%08lx "); } /* chop off last ' ' */ fmt[strlen(fmt)] = '\0'; } if ((fp = linux_statsfile("/proc/net/softnet_stat", buf, sizeof(buf))) == NULL) return -oserror(); memset(proc_net_softnet, 0, sizeof(proc_net_softnet_t)); while (fgets(buf, sizeof(buf), fp) != NULL) { memset(&sn, 0, sizeof(sn)); count = sscanf(buf, fmt, &sn.processed, &sn.dropped, &sn.time_squeeze, &filler, &filler, &filler, &filler, &filler, &sn.cpu_collision, &sn.received_rps, &sn.flow_limit_count); flags = 0; if (count >= 9) flags |= SN_PROCESSED | SN_DROPPED | SN_TIME_SQUEEZE | SN_CPU_COLLISION; if (count >= 10) flags |= SN_RECEIVED_RPS; if (count >= 11) flags |= SN_FLOW_LIMIT_COUNT; proc_net_softnet->flags = flags; /* summed, one line per-cpu */ proc_net_softnet->processed += sn.processed; proc_net_softnet->dropped += sn.dropped; proc_net_softnet->time_squeeze += sn.time_squeeze; proc_net_softnet->cpu_collision += sn.cpu_collision; proc_net_softnet->received_rps += sn.received_rps; proc_net_softnet->flow_limit_count += sn.flow_limit_count; } fclose(fp); return 0; }
int refresh_proc_buddyinfo(proc_buddyinfo_t *proc_buddyinfo) { int i, j; char buf[2048]; char read_buf[SPLIT_MAX][128]; FILE *fp; static int next_id = -1; if (next_id < 0) { next_id = 0; proc_buddyinfo->nbuddys = 0; if ((fp = linux_statsfile("/proc/buddyinfo", buf, sizeof(buf))) == NULL) return -oserror(); if (fgets(buf,sizeof(buf),fp) == NULL) { /* read first line */ fclose(fp); return -oserror(); } fclose(fp); MAX_ORDER = read_buddyinfo(buf,read_buf,0) - 5; /* get maximum page order */ } if ((fp = linux_statsfile("/proc/buddyinfo", buf, sizeof(buf))) == NULL) return -oserror(); while (fgets(buf,sizeof(buf),fp) != NULL) { char node_name[64]; char *zone_name; int values[SPLIT_MAX]; i = read_node_name(buf, node_name); i+=6; /* erase ", zone" */ read_buddyinfo(buf+i, read_buf, MAX_ORDER+1); /* read zone name and page order */ zone_name=read_buf[0]; for (i=0; i < MAX_ORDER; i++) values[i] = atoi(read_buf[i+1]); for (i=0; i < proc_buddyinfo->nbuddys; i++) { if (strcmp(proc_buddyinfo->buddys[i].node_name, node_name)==0 && strcmp(proc_buddyinfo->buddys[i].zone_name, zone_name)==0 ) break; } if (i==proc_buddyinfo->nbuddys) { proc_buddyinfo->nbuddys += MAX_ORDER; proc_buddyinfo->buddys = (buddyinfo_t *)realloc(proc_buddyinfo->buddys, proc_buddyinfo->nbuddys * sizeof(buddyinfo_t)); for (j=0; j < MAX_ORDER; j++) { proc_buddyinfo->buddys[i+j].id = next_id++; strncpy(proc_buddyinfo->buddys[i+j].node_name, node_name, sizeof(proc_buddyinfo->buddys[i+j].node_name) - 1); strncpy(proc_buddyinfo->buddys[i+j].zone_name, zone_name, sizeof(proc_buddyinfo->buddys[i+j].zone_name) - 1); snprintf(proc_buddyinfo->buddys[i+j].id_name, sizeof(proc_buddyinfo->buddys[i+j].id_name), "%s::order%u::%s", zone_name, j, node_name); } } /* update data */ for (j=0; j < MAX_ORDER; j++) { proc_buddyinfo->buddys[i+j].value = values[j]; } } fclose(fp); /* refresh buddyinfo indom */ if (proc_buddyinfo->indom->it_numinst != proc_buddyinfo->nbuddys) { proc_buddyinfo->indom->it_numinst = proc_buddyinfo->nbuddys; proc_buddyinfo->indom->it_set = (pmdaInstid *)realloc(proc_buddyinfo->indom->it_set, proc_buddyinfo->nbuddys * sizeof(pmdaInstid)); memset(proc_buddyinfo->indom->it_set, 0, proc_buddyinfo->nbuddys * sizeof(pmdaInstid)); } for (i=0; i < proc_buddyinfo->nbuddys; i++) { proc_buddyinfo->indom->it_set[i].i_inst = proc_buddyinfo->buddys[i].id; proc_buddyinfo->indom->it_set[i].i_name = proc_buddyinfo->buddys[i].id_name; } return 0; }