VirtualBox

Ignore:
Timestamp:
Oct 12, 2012 9:26:07 AM (12 years ago)
Author:
vboxsync
Message:

Main/Metrics: Linux fs/disk metrics, VBoxManage filtering + minor fixes (#6345)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-server/linux/PerformanceLinux.cpp

    r43512 r43629  
    1919
    2020#include <stdio.h>
     21#include <unistd.h>
     22#include <sys/statvfs.h>
     23#include <errno.h>
     24#include <mntent.h>
    2125#include <iprt/alloc.h>
     26#include <iprt/cdefs.h>
     27#include <iprt/ctype.h>
    2228#include <iprt/err.h>
    2329#include <iprt/param.h>
    2430#include <iprt/string.h>
     31#include <iprt/mp.h>
    2532
    2633#include <map>
     
    3542{
    3643public:
     44    CollectorLinux();
    3745    virtual int preCollect(const CollectorHints& hints, uint64_t /* iTick */);
    3846    virtual int getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available);
     47    virtual int getHostFilesystemUsage(const char *name, ULONG *total, ULONG *used, ULONG *available);
    3948    virtual int getProcessMemoryUsage(RTPROCESS process, ULONG *used);
    4049
    4150    virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
    4251    virtual int getRawHostNetworkLoad(const char *name, uint64_t *rx, uint64_t *tx);
     52    virtual int getRawHostDiskLoad(const char *name, uint64_t *disk_ms, uint64_t *total_ms);
    4353    virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total);
    4454private:
    45     virtual int _getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
     55    virtual int _getRawHostCpuLoad();
    4656    int getRawProcessStats(RTPROCESS process, uint64_t *cpuUser, uint64_t *cpuKernel, ULONG *memPagesUsed);
    4757
     
    5767    VMProcessMap mProcessStats;
    5868    uint64_t     mUser, mKernel, mIdle;
     69    uint64_t     mSingleUser, mSingleKernel, mSingleIdle;
     70    uint32_t     mHZ;
    5971};
    6072
     
    6577
    6678// Collector HAL for Linux
     79
     80CollectorLinux::CollectorLinux()
     81{
     82    long hz = sysconf(_SC_CLK_TCK);
     83    if (hz == -1)
     84    {
     85        LogRel(("CollectorLinux failed to obtain HZ from kernel, assuming 100.\n"));
     86        mHZ = 100;
     87    }
     88    else
     89        mHZ = hz;
     90    LogFlowThisFunc(("mHZ=%u\n", mHZ));
     91}
    6792
    6893int CollectorLinux::preCollect(const CollectorHints& hints, uint64_t /* iTick */)
     
    84109    if (hints.isHostCpuLoadCollected() || mProcessStats.size())
    85110    {
    86         _getRawHostCpuLoad(&mUser, &mKernel, &mIdle);
    87     }
    88     return VINF_SUCCESS;
    89 }
    90 
    91 int CollectorLinux::_getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle)
    92 {
    93     int rc = VINF_SUCCESS;
    94     ULONG u32user, u32nice, u32kernel, u32idle;
     111        _getRawHostCpuLoad();
     112    }
     113    return VINF_SUCCESS;
     114}
     115
     116int CollectorLinux::_getRawHostCpuLoad()
     117{
     118    int rc = VINF_SUCCESS;
     119    long long unsigned uUser, uNice, uKernel, uIdle, uIowait, uIrq, uSoftirq;
    95120    FILE *f = fopen("/proc/stat", "r");
    96121
    97122    if (f)
    98123    {
    99         if (fscanf(f, "cpu %u %u %u %u", &u32user, &u32nice, &u32kernel, &u32idle) == 4)
    100         {
    101             *user   = (uint64_t)u32user + u32nice;
    102             *kernel = u32kernel;
    103             *idle   = u32idle;
     124        char szBuf[128];
     125        if (fgets(szBuf, sizeof(szBuf), f))
     126        {
     127            if (sscanf(szBuf, "cpu %llu %llu %llu %llu %llu %llu %llu",
     128                       &uUser, &uNice, &uKernel, &uIdle, &uIowait,
     129                       &uIrq, &uSoftirq) == 7)
     130            {
     131                mUser   = uUser + uNice;
     132                mKernel = uKernel + uIrq + uSoftirq;
     133                mIdle   = uIdle + uIowait;
     134            }
     135            /* Try to get single CPU stats. */
     136            if (fgets(szBuf, sizeof(szBuf), f))
     137            {
     138                if (sscanf(szBuf, "cpu0 %llu %llu %llu %llu %llu %llu %llu",
     139                           &uUser, &uNice, &uKernel, &uIdle, &uIowait,
     140                           &uIrq, &uSoftirq) == 7)
     141                {
     142                    mSingleUser   = uUser + uNice;
     143                    mSingleKernel = uKernel + uIrq + uSoftirq;
     144                    mSingleIdle   = uIdle + uIowait;
     145                }
     146                else
     147                {
     148                    /* Assume that this is not an SMP system. */
     149                    Assert(RTMpGetCount() == 1);
     150                    mSingleUser   = mUser;
     151                    mSingleKernel = mKernel;
     152                    mSingleIdle   = mIdle;
     153                }
     154            }
     155            else
     156                rc = VERR_FILE_IO_ERROR;
    104157        }
    105158        else
     
    161214
    162215    return rc;
     216}
     217
     218int CollectorLinux::getHostFilesystemUsage(const char *path, ULONG *total, ULONG *used, ULONG *available)
     219{
     220    struct statvfs stats;
     221    const unsigned _MB = 1024 * 1024;
     222
     223    if (statvfs(path, &stats) == -1)
     224    {
     225        LogRel(("Failed to collect %s filesystem usage: errno=%d.\n", path, errno));
     226        return VERR_ACCESS_DENIED;
     227    }
     228    uint64_t cbBlock = stats.f_frsize ? stats.f_frsize : stats.f_bsize;
     229    *total = (ULONG)(cbBlock * stats.f_blocks / _MB);
     230    *used  = (ULONG)(cbBlock * (stats.f_blocks - stats.f_bfree) / _MB);
     231    *available = (ULONG)(cbBlock * stats.f_bavail / _MB);
     232
     233    return VINF_SUCCESS;
    163234}
    164235
     
    252323}
    253324
    254 }
    255 
     325int CollectorLinux::getRawHostDiskLoad(const char *name, uint64_t *disk_ms, uint64_t *total_ms)
     326{
     327    int rc = VINF_SUCCESS;
     328    char szIfName[/*IFNAMSIZ*/ 16 + 36];
     329    long long unsigned int u64Busy, tmp;
     330
     331    RTStrPrintf(szIfName, sizeof(szIfName), "/sys/class/block/%s/stat", name);
     332    FILE *f = fopen(szIfName, "r");
     333    if (f)
     334    {
     335        if (fscanf(f, "%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
     336                   &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &u64Busy, &tmp) == 11)
     337        {
     338            *disk_ms   = u64Busy;
     339            *total_ms  = (uint64_t)(mSingleUser + mSingleKernel + mSingleIdle) * 1000 / mHZ;
     340        }
     341        else
     342            rc = VERR_FILE_IO_ERROR;
     343        fclose(f);
     344    }
     345    else
     346        rc = VERR_ACCESS_DENIED;
     347
     348    return rc;
     349}
     350
     351static char *getDiskName(char *pszDiskName, size_t cbDiskName, const char *pszDevName)
     352{
     353    unsigned cbName = 0;
     354    unsigned cbDevName = strlen(pszDevName);
     355    const char *pszEnd = pszDevName + cbDevName - 1;
     356    while (pszEnd > pszDevName && RT_C_IS_DIGIT(*pszEnd))
     357        pszEnd--;
     358    while (pszEnd > pszDevName && *pszEnd != '/')
     359    {
     360        cbName++;
     361        pszEnd--;
     362    }
     363    RTStrCopy(pszDiskName, RT_MIN(cbName + 1, cbDiskName), pszEnd + 1);
     364    return pszDiskName;
     365}
     366
     367
     368int getDiskListByFs(const char *pszPath, DiskList& listDisks)
     369{
     370    FILE *mtab = setmntent("/etc/mtab", "r");
     371    if (mtab)
     372    {
     373        struct mntent *mntent;
     374        while ((mntent = getmntent(mtab)))
     375        {
     376            if (strcmp(pszPath, mntent->mnt_dir) == 0)
     377            {
     378                char szDevName[32];
     379                listDisks.push_back(RTCString(getDiskName(szDevName, sizeof(szDevName), mntent->mnt_fsname)));
     380                break;
     381            }
     382        }
     383        endmntent(mtab);
     384    }
     385    return VINF_SUCCESS;
     386}
     387
     388}
     389
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette