On linux systems, this fixes parsing of /proc/pid/meminfo to avoid overflow for values larger than a 32-bit integer. It also reads the total memory on the system from /proc/meminfo, rather than /proc/kcore, as the latter source is no longer accurate. Further it reads not the random three header lines used in 2.4 kernels, as those disappeared in 2.6. --- pbs-2.3.12/src/resmom/linux/mom_mach.c | 82 +++++++++++++++++++++------------ 1 files changed, 53 insertions(+), 29 deletions(-) diff -puN src/resmom/linux/mom_mach.c~meminfo-2 src/resmom/linux/mom_mach.c --- pbs-2.3.12-orig/src/resmom/linux/mom_mach.c~meminfo-2 2004-08-06 17:28:43.000000000 -0400 +++ pbs-2.3.12/src/resmom/linux/mom_mach.c 2004-08-06 17:59:08.000000000 -0400 @@ -182,9 +182,9 @@ extern char *nullproc A_((struct rm_attr time_t wait_time = 10; typedef struct proc_mem { - unsigned total; - unsigned used; - unsigned free; + unsigned long long total; + unsigned long long used; + unsigned long long free; } proc_mem_t; /* @@ -288,26 +288,41 @@ proc_stat_t *get_proc_stat(pid) return(&ps); } +static const char path_meminfo[] = "/proc/meminfo"; -proc_mem_t *get_proc_mem() +/* + * Return memory stats, in units of kB. + */ +static proc_mem_t * +get_proc_mem(void) { static proc_mem_t mm; FILE *fp; - unsigned m_tot, m_use, m_free; - unsigned s_tot, s_use, s_free; + char buf[2048]; + unsigned long long m_tot, m_use, m_free; + unsigned long long s_tot, s_use, s_free; - if ((fp = fopen("/proc/meminfo", "r")) == NULL) + if ((fp = fopen(path_meminfo, "r")) == NULL) return(NULL); - fscanf(fp, "%*[^\n]%*c"); /* lose the text header */; - fscanf(fp, "%*s %u %u %u %*[^\n]%*c", &m_tot, &m_use, &m_free); - fscanf(fp, "%*s %u %u %u %*[^\n]%*c", &s_tot, &s_use, &s_free); - - mm.total = m_tot + s_tot; - mm.used = m_use + s_use; - mm.free = m_free + s_free; + /* Changed to ignore swap, seems meaningless these days. --pw */ + mm.total = mm.used = mm.free = 0; + while (fgets(buf, sizeof(buf), fp) != NULL) { + if (!strncmp(buf, "MemTotal:", 9)) { + if (sscanf(buf, "%*s %Lu", &mm.total) != 1) + goto out; + } + if (!strncmp(buf, "MemFree:", 8)) { + if (sscanf(buf, "%*s %Lu", &mm.free) != 1) + goto out; + break; + } + } + + mm.used = mm.total - mm.free; + out: fclose(fp); return(&mm); } @@ -1669,8 +1684,8 @@ struct rm_attribute *attrib; rm_errno = RM_ERR_SYSTEM; return NULL; } - DBPRT(("%s: total mem=%u\n", id, mm->total)) - sprintf(ret_string, "%lukb", (ulong)mm->total >> 10); /* KB */ + DBPRT(("%s: total mem=%Lu\n", id, mm->total)) + sprintf(ret_string, "%Lukb", mm->total); /* KB */ return ret_string; } @@ -1692,8 +1707,8 @@ struct rm_attribute *attrib; rm_errno = RM_ERR_SYSTEM; return NULL; } - DBPRT(("%s: free mem=%u\n", id, mm->free)) - sprintf(ret_string, "%lukb", (ulong)mm->free >> 10); /* KB */ + DBPRT(("%s: free mem=%Lu\n", id, mm->free)) + sprintf(ret_string, "%Lukb", mm->free); /* KB */ return ret_string; } @@ -1732,25 +1747,34 @@ static char * physmem(attrib) struct rm_attribute *attrib; { - char *id = "physmem"; - struct stat buf; + char *id = "physmem"; + char buf[2048]; + unsigned long long mem = 0; + FILE *fp; if (attrib) { log_err(-1, id, extra_parm); rm_errno = RM_ERR_BADPARAM; - return NULL; + return 0; } - if (stat("/proc/kcore", &buf)) { - log_err(-1, id, extra_parm); + if (!(fp = fopen(path_meminfo, "r"))) { rm_errno = RM_ERR_SYSTEM; - return NULL; - } else { - /* length of /proc/kcore == physical memory + 4K */ - sprintf(ret_string, "%lukb", - ((ulong)buf.st_size - (ulong)4096) >> 10); /* KB */ - return ret_string; + return 0; + } + while (fgets(buf, sizeof(buf), fp) != NULL) { + if (!strncmp(buf, "MemTotal:", 9)) { + if (sscanf(buf, "%*s %Lu", &mem) != 1) { + fclose(fp); + rm_errno = RM_ERR_SYSTEM; + return 0; + } + break; + } } + fclose(fp); + sprintf(ret_string, "%Lukb", mem); + return ret_string; } char * _