diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c index a02da072..c1ccd420 100644 --- a/linux/LinuxProcessList.c +++ b/linux/LinuxProcessList.c @@ -89,6 +89,7 @@ typedef struct LinuxProcessList_ { CPUData* cpus; TtyDriver* ttyDrivers; + bool haveSmapsRollup; #ifdef HAVE_DELAYACCT struct nl_sock *netlink_socket; @@ -240,8 +241,17 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidWhiteList, ui LinuxProcessList_initNetlinkSocket(this); #endif + // Check for /proc/*/smaps_rollup availability (improves smaps parsing speed, Linux 4.14+) + FILE* file = fopen(PROCDIR "/self/smaps_rollup", "r"); + if(file != NULL) { + this->haveSmapsRollup = true; + fclose(file); + } else { + this->haveSmapsRollup = false; + } + // Update CPU count: - FILE* file = fopen(PROCSTATFILE, "r"); + file = fopen(PROCSTATFILE, "r"); if (file == NULL) { CRT_fatalError("Cannot open " PROCSTATFILE); } @@ -486,7 +496,7 @@ static bool LinuxProcessList_readStatmFile(LinuxProcess* process, const char* di return (errno == 0); } -static bool LinuxProcessList_readSmapsFile(LinuxProcess* process, const char* dirname, const char* name) { +static bool LinuxProcessList_readSmapsFile(LinuxProcess* process, const char* dirname, const char* name, bool haveSmapsRollup) { //http://elixir.free-electrons.com/linux/v4.10/source/fs/proc/task_mmu.c#L719 //kernel will return data in chunks of size PAGE_SIZE or less. @@ -494,7 +504,11 @@ static bool LinuxProcessList_readSmapsFile(LinuxProcess* process, const char* di char *start,*end; ssize_t nread=0; int tmp=0; + if(haveSmapsRollup) {// only available in Linux 4.14+ + snprintf(buffer, MAX_NAME, "%s/%s/smaps_rollup", dirname, name); + } else { snprintf(buffer, MAX_NAME, "%s/%s/smaps", dirname, name); + } int fd = open(buffer, O_RDONLY); if (fd == -1) return false; @@ -872,7 +886,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, const char* // Read smaps file of each process only every second pass to improve performance static int smaps_flag = 0; if ((pid & 1) == smaps_flag){ - LinuxProcessList_readSmapsFile(lp, dirname, name); + LinuxProcessList_readSmapsFile(lp, dirname, name, this->haveSmapsRollup); } if (pid == 1) { smaps_flag = !smaps_flag; diff --git a/linux/LinuxProcessList.h b/linux/LinuxProcessList.h index f30b487d..59e83bcb 100644 --- a/linux/LinuxProcessList.h +++ b/linux/LinuxProcessList.h @@ -62,6 +62,7 @@ typedef struct LinuxProcessList_ { CPUData* cpus; TtyDriver* ttyDrivers; + bool haveSmapsRollup; #ifdef HAVE_DELAYACCT struct nl_sock *netlink_socket;