#include #include #include #include #include #include #include #include #include #include #include #include /* * Retained from UCD implementation */ /* * Get the number of pages that are swapped out. * We think this is correct and are valid values * but not sure. Time will tell if it's correct. * Note: this routine is _expensive_!!! we run this * as little as possible by caching it's return so * it's not run on every poll. * Apple, please give us a better way! :) */ int pages_swapped(void) { boolean_t retval; kern_return_t error; processor_set_t *psets, pset; task_t *tasks; unsigned i, j, pcnt, tcnt; int pid; mach_msg_type_number_t count; vm_address_t address; mach_port_t object_name; vm_region_extended_info_data_t info; vm_size_t size; mach_port_t mach_port; int swapped_pages; int swapped_pages_total = 0; char errmsg[1024]; mach_port = mach_host_self(); error = host_processor_sets(mach_port, &psets, &pcnt); if (error != KERN_SUCCESS) { snmp_log(LOG_ERR, "Error in host_processor_sets(): %s\n", mach_error_string(error)); return(0); } for (i = 0; i < pcnt; i++) { error = host_processor_set_priv(mach_port, psets[i], &pset); if (error != KERN_SUCCESS) { snprintf(errmsg, sizeof(errmsg),"Error in host_processor_set_priv(): %s\n", mach_error_string(error)); snmp_log_perror(errmsg); return(0); } error = processor_set_tasks(pset, &tasks, &tcnt); if (error != KERN_SUCCESS) { snprintf(errmsg, sizeof(errmsg),"Error in processor_set_tasks(): %s\n", mach_error_string(error)); snmp_log_perror(errmsg); return(0); } for (j = 0; j < tcnt; j++) { error = pid_for_task(tasks[j], &pid); if (error != KERN_SUCCESS) { /* Not a process, or the process is gone. */ continue; } swapped_pages = 0; for (address = 0;; address += size) { /* Get memory region. */ count = VM_REGION_EXTENDED_INFO_COUNT; #if defined(__ppc64__) || defined(__x86_64__) if (vm_region_64(tasks[j], &address, &size, VM_REGION_EXTENDED_INFO, &info, &count, &object_name) != KERN_SUCCESS) { #else if (vm_region(tasks[j], &address, &size, VM_REGION_EXTENDED_INFO, &info, &count, &object_name) != KERN_SUCCESS) { #endif /* No more memory regions. */ break; } if(info.pages_swapped_out > 0) { swapped_pages += info.pages_swapped_out; } } if(swapped_pages > 0) { swapped_pages_total += swapped_pages; } if (tasks[j] != mach_task_self()) { mach_port_deallocate(mach_task_self(), tasks[j]); } } } return(swapped_pages_total); } off_t swapsize(void) { int pagesize; int i, n; DIR *dirp; struct dirent *dp; struct stat buf; char errmsg[1024]; char full_name[1024]; off_t swapSize; /* we set the size to -1 if we're not supported */ swapSize = -1; #if defined(SWAPFILE_DIR) && defined(SWAPFILE_PREFIX) dirp = opendir((const char *) SWAPFILE_DIR); while((dp = readdir(dirp)) != NULL) { /* if the file starts with the same as SWAPFILE_PREFIX * we want to stat the file to get it's size */ if(strspn(dp->d_name,(char *) SWAPFILE_PREFIX) == strlen((char *) SWAPFILE_PREFIX)) { snprintf(full_name, sizeof(full_name),"%s/%s",SWAPFILE_DIR,dp->d_name); /* we need to stat each swapfile to get it's size */ if(stat(full_name,&buf) != 0) { snprintf(errmsg, sizeof(errmsg), "swapsize: can't stat file %s",full_name); snmp_log_perror(errmsg); } else { /* total swap allocated is the size of * all the swapfile's that exist in * the SWAPFILE_DIR dir */ swapSize += buf.st_size; } } } closedir(dirp); #else /* we set the size to -1 if we're not supported */ swapSize = -1; #endif return swapSize; } /* * Load the latest memory usage statistics * * HW_PHYSMEM is capped at 2 Gigs so we use HW_MEMSIZE */ int netsnmp_mem_arch_load( netsnmp_cache *cache, void *magic ) { netsnmp_memory_info *mem; uint64_t phys_mem; /* bytes */ size_t phys_mem_size = sizeof(phys_mem); int phys_mem_mib[] = { CTL_HW, HW_MEMSIZE }; int pagesize; /* bytes */ size_t pagesize_size = sizeof(pagesize); int pagesize_mib[] = { CTL_HW, HW_PAGESIZE }; uint64_t pages_used; off_t swapSize; off_t swapUsed; vm_statistics_data_t vm_stat; unsigned int count = HOST_VM_INFO_COUNT; sysctl(phys_mem_mib, 2, &phys_mem, &phys_mem_size, NULL, 0); sysctl(pagesize_mib, 2, &pagesize, &pagesize_size, NULL, 0); host_statistics(mach_host_self(),HOST_VM_INFO,(host_info_t)&vm_stat,&count); pages_used = vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count; swapSize = swapsize(); /* in bytes */ swapUsed = pages_swapped(); mem = netsnmp_memory_get_byIdx( NETSNMP_MEM_TYPE_PHYSMEM, 1 ); if (!mem) { snmp_log_perror("No Memory info entry"); } else { if (!mem->descr) mem->descr = strdup( "Physical memory" ); mem->units = pagesize; /* 4096 */ mem->size = phys_mem/pagesize; mem->free = (phys_mem/pagesize) - pages_used; mem->other = -1; } mem = netsnmp_memory_get_byIdx( NETSNMP_MEM_TYPE_SWAP, 1 ); if (!mem) { snmp_log_perror("No Swap info entry"); } else { if (!mem->descr) mem->descr = strdup( "Swap space" ); mem->units = pagesize; /* 4096 */ mem->size = swapSize/pagesize; mem->free = (swapSize/pagesize) - swapUsed; mem->other = -1; } /* mem = netsnmp_memory_get_byIdx( NETSNMP_MEM_TYPE_MISC, 1 ); if (!mem) { snmp_log_perror("No Buffer, etc info entry"); } else { mem->units = pagesize; mem->size = -1; mem->free = (phys_mem - pages_used) + (swapSize - swapUsed); mem->other = -1; } */ return 0; }