summaryrefslogtreecommitdiff
path: root/src/VBox/Main/src-server/linux/PerformanceLinux.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Main/src-server/linux/PerformanceLinux.cpp')
-rw-r--r--src/VBox/Main/src-server/linux/PerformanceLinux.cpp144
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;
}