diff options
Diffstat (limited to 'src/VBox/Main/src-server/linux/PerformanceLinux.cpp')
| -rw-r--r-- | src/VBox/Main/src-server/linux/PerformanceLinux.cpp | 144 |
1 files changed, 116 insertions, 28 deletions
diff --git a/src/VBox/Main/src-server/linux/PerformanceLinux.cpp b/src/VBox/Main/src-server/linux/PerformanceLinux.cpp index 4eff670c3..128748479 100644 --- a/src/VBox/Main/src-server/linux/PerformanceLinux.cpp +++ b/src/VBox/Main/src-server/linux/PerformanceLinux.cpp @@ -29,6 +29,7 @@ #include <iprt/param.h> #include <iprt/path.h> #include <iprt/string.h> +#include <iprt/system.h> #include <iprt/mp.h> #include <map> @@ -56,13 +57,15 @@ public: virtual int getRawHostDiskLoad(const char *name, uint64_t *disk_ms, uint64_t *total_ms); virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total); - virtual int getDiskListByFs(const char *name, DiskList& list); + virtual int getDiskListByFs(const char *name, DiskList& listUsage, DiskList& listLoad); private: virtual int _getRawHostCpuLoad(); int getRawProcessStats(RTPROCESS process, uint64_t *cpuUser, uint64_t *cpuKernel, ULONG *memPagesUsed); char *getDiskName(char *pszDiskName, size_t cbDiskName, const char *pszDevName, bool fTrimDigits); void addVolumeDependencies(const char *pcszVolume, DiskList& listDisks); + void addRaidDisks(const char *pcszDevice, DiskList& listDisks); char *trimTrailingDigits(char *pszName); + char *trimNewline(char *pszName); struct VMProcessStats { @@ -77,6 +80,7 @@ private: uint64_t mUser, mKernel, mIdle; uint64_t mSingleUser, mSingleKernel, mSingleIdle; uint32_t mHZ; + ULONG totalRAM; }; CollectorHAL *createHAL() @@ -97,6 +101,13 @@ CollectorLinux::CollectorLinux() else mHZ = hz; LogFlowThisFunc(("mHZ=%u\n", mHZ)); + + uint64_t cb; + int rc = RTSystemQueryTotalRam(&cb); + if (RT_FAILURE(rc)) + totalRAM = 0; + else + totalRAM = (ULONG)(cb / 1024); } int CollectorLinux::preCollect(const CollectorHints& hints, uint64_t /* iTick */) @@ -199,28 +210,15 @@ int CollectorLinux::getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint int CollectorLinux::getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available) { - int rc = VINF_SUCCESS; - ULONG buffers, cached; - FILE *f = fopen("/proc/meminfo", "r"); - - if (f) + AssertReturn(totalRAM, VERR_INTERNAL_ERROR); + uint64_t cb; + int rc = RTSystemQueryAvailableRam(&cb); + if (RT_SUCCESS(rc)) { - int processed = fscanf(f, "MemTotal: %u kB\n", total); - processed += fscanf(f, "MemFree: %u kB\n", available); - processed += fscanf(f, "Buffers: %u kB\n", &buffers); - processed += fscanf(f, "Cached: %u kB\n", &cached); - if (processed == 4) - { - *available += buffers + cached; - *used = *total - *available; - } - else - rc = VERR_FILE_IO_ERROR; - fclose(f); + *total = totalRAM; + *available = cb / 1024; + *used = *total - *available; } - else - rc = VERR_ACCESS_DENIED; - return rc; } @@ -424,6 +422,20 @@ int CollectorLinux::getRawHostDiskLoad(const char *name, uint64_t *disk_ms, uint return rc; } +char *CollectorLinux::trimNewline(char *pszName) +{ + unsigned cbName = strlen(pszName); + if (cbName == 0) + return pszName; + + char *pszEnd = pszName + cbName - 1; + while (pszEnd > pszName && *pszEnd == '\n') + pszEnd--; + pszEnd[1] = '\0'; + + return pszName; +} + char *CollectorLinux::trimTrailingDigits(char *pszName) { unsigned cbName = strlen(pszName); @@ -455,6 +467,54 @@ char *CollectorLinux::getDiskName(char *pszDiskName, size_t cbDiskName, const ch return pszDiskName; } +void CollectorLinux::addRaidDisks(const char *pcszDevice, DiskList& listDisks) +{ + FILE *f = fopen("/proc/mdstat", "r"); + if (f) + { + char szBuf[128]; + while (fgets(szBuf, sizeof(szBuf), f)) + { + char *pszBufName = szBuf; + + char *pszBufData = strchr(pszBufName, ' '); + if (!pszBufData) + { + LogRel(("CollectorLinux::addRaidDisks() failed to parse disk stats: %s\n", szBuf)); + continue; + } + *pszBufData++ = '\0'; + if (!strcmp(pcszDevice, pszBufName)) + { + while (*pszBufData == ':') ++pszBufData; /* Skip delimiter */ + while (*pszBufData == ' ') ++pszBufData; /* Skip spaces */ + while (RT_C_IS_ALNUM(*pszBufData)) ++pszBufData; /* Skip status */ + while (*pszBufData == ' ') ++pszBufData; /* Skip spaces */ + while (RT_C_IS_ALNUM(*pszBufData)) ++pszBufData; /* Skip type */ + + while (*pszBufData != '\0') + { + while (*pszBufData == ' ') ++pszBufData; /* Skip spaces */ + char *pszDisk = pszBufData; + while (RT_C_IS_ALPHA(*pszBufData)) + ++pszBufData; + if (*pszBufData) + { + *pszBufData++ = '\0'; + listDisks.push_back(RTCString(pszDisk)); + while (*pszBufData != '\0' && *pszBufData != ' ') + ++pszBufData; + } + else + listDisks.push_back(RTCString(pszDisk)); + } + break; + } + } + fclose(f); + } +} + void CollectorLinux::addVolumeDependencies(const char *pcszVolume, DiskList& listDisks) { char szVolInfo[RTPATH_MAX]; @@ -473,7 +533,10 @@ void CollectorLinux::addVolumeDependencies(const char *pcszVolume, DiskList& lis char szBuf[128]; while (fgets(szBuf, sizeof(szBuf), fp)) - listDisks.push_back(RTCString(trimTrailingDigits(szBuf))); + if (strncmp(szBuf, "dm-", 3)) + listDisks.push_back(RTCString(trimTrailingDigits(szBuf))); + else + listDisks.push_back(RTCString(trimNewline(szBuf))); pclose(fp); } @@ -481,7 +544,7 @@ void CollectorLinux::addVolumeDependencies(const char *pcszVolume, DiskList& lis listDisks.push_back(RTCString(pcszVolume)); } -int CollectorLinux::getDiskListByFs(const char *pszPath, DiskList& listDisks) +int CollectorLinux::getDiskListByFs(const char *pszPath, DiskList& listUsage, DiskList& listLoad) { FILE *mtab = setmntent("/etc/mtab", "r"); if (mtab) @@ -489,18 +552,43 @@ int CollectorLinux::getDiskListByFs(const char *pszPath, DiskList& listDisks) struct mntent *mntent; while ((mntent = getmntent(mtab))) { + /* Skip rootfs entry, there must be another root mount. */ + if (strcmp(mntent->mnt_fsname, "rootfs") == 0) + continue; if (strcmp(pszPath, mntent->mnt_dir) == 0) { char szDevName[128]; - if (strncmp(mntent->mnt_fsname, "/dev/mapper", 11)) + char szFsName[1024]; + /* Try to resolve symbolic link if necessary */ + ssize_t cbFsName = readlink(mntent->mnt_fsname, szFsName, sizeof(szFsName) - 1); + if (cbFsName != -1) + szFsName[cbFsName] = '\0'; + else + strcpy(szFsName, mntent->mnt_fsname); + if (!strncmp(szFsName, "/dev/mapper", 11)) { - getDiskName(szDevName, sizeof(szDevName), mntent->mnt_fsname, true); - listDisks.push_back(RTCString(szDevName)); + /* LVM */ + getDiskName(szDevName, sizeof(szDevName), szFsName, false); + addVolumeDependencies(szDevName, listUsage); + listLoad = listUsage; + } + else if (!strncmp(szFsName, "/dev/md", 7)) + { + /* Software RAID */ + getDiskName(szDevName, sizeof(szDevName), szFsName, false); + listUsage.push_back(RTCString(szDevName)); + addRaidDisks(szDevName, listLoad); } else { - getDiskName(szDevName, sizeof(szDevName), mntent->mnt_fsname, false); - addVolumeDependencies(szDevName, listDisks); + /* Plain disk partition */ + getDiskName(szDevName, sizeof(szDevName), mntent->mnt_fsname, true); + listUsage.push_back(RTCString(szDevName)); + listLoad.push_back(RTCString(szDevName)); + } + if (listUsage.empty() || listLoad.empty()) + { + LogRel(("Failed to retrive disk info: getDiskName(%s) --> %s\n", mntent->mnt_fsname, szDevName)); } break; } |
