VirtualBox

Changeset 43831 in vbox for trunk/src/VBox/Main/src-server


Ignore:
Timestamp:
Nov 7, 2012 1:11:51 PM (12 years ago)
Author:
vboxsync
Message:

Main/Metrics: Disk and filesystem metrics for Solaris (#6345)

Location:
trunk/src/VBox/Main/src-server
Files:
4 edited

Legend:

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

    r43629 r43831  
    29302930    /* For now we are concerned with the root file system only. */
    29312931    pm::DiskList disks;
    2932     int rc = pm::getDiskListByFs("/", disks);
     2932    int rc = hal->getDiskListByFs("/", disks);
    29332933    if (RT_FAILURE(rc) || disks.empty())
    29342934        return;
  • trunk/src/VBox/Main/src-server/Performance.cpp

    r43629 r43831  
    8585
    8686int CollectorHAL::getProcessMemoryUsage(RTPROCESS /* process */, ULONG * /* used */)
     87{
     88    return E_NOTIMPL;
     89}
     90
     91int CollectorHAL::getDiskListByFs(const char * /* name */, DiskList& /* list */)
    8792{
    8893    return E_NOTIMPL;
  • trunk/src/VBox/Main/src-server/linux/PerformanceLinux.cpp

    r43715 r43831  
    5555    virtual int getRawHostDiskLoad(const char *name, uint64_t *disk_ms, uint64_t *total_ms);
    5656    virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total);
     57
     58    virtual int getDiskListByFs(const char *name, DiskList& list);
    5759private:
    5860    virtual int _getRawHostCpuLoad();
     
    394396}
    395397
    396 int getDiskListByFs(const char *pszPath, DiskList& listDisks)
     398int CollectorLinux::getDiskListByFs(const char *pszPath, DiskList& listDisks)
    397399{
    398400    FILE *mtab = setmntent("/etc/mtab", "r");
  • trunk/src/VBox/Main/src-server/solaris/PerformanceSolaris.cpp

    r43629 r43831  
    2727#include <sys/sysinfo.h>
    2828#include <sys/time.h>
     29#include <sys/types.h>
     30#include <sys/statvfs.h>
    2931
    3032#include <iprt/ctype.h>
     
    3335#include <iprt/alloc.h>
    3436#include <iprt/param.h>
     37#include <iprt/path.h>
    3538#include <VBox/log.h>
    3639#include "Performance.h"
    3740
     41#include <dlfcn.h>
     42
     43#include <libzfs.h>
     44#include <libnvpair.h>
     45
     46#include <map>
     47
    3848namespace pm {
     49
     50    typedef libzfs_handle_t *(*PFNZFSINIT)(void);
     51    typedef zfs_handle_t *(*PFNZFSOPEN)(libzfs_handle_t *, const char *, int);
     52    typedef void (*PFNZFSCLOSE)(zfs_handle_t *);
     53    typedef uint64_t (*PFNZFSPROPGETINT)(zfs_handle_t *, zfs_prop_t);
     54    typedef zpool_handle_t *(*PFNZPOOLOPEN)(libzfs_handle_t *, const char *);
     55    typedef void (*PFNZPOOLCLOSE)(zpool_handle_t *);
     56    typedef nvlist_t *(*PFNZPOOLGETCONFIG)(zpool_handle_t *, nvlist_t **);
     57    typedef char *(*PFNZPOOLVDEVNAME)(libzfs_handle_t *, zpool_handle_t *, nvlist_t *, boolean_t);
     58
     59    typedef std::map<RTCString,RTCString> FsMap;
    3960
    4061class CollectorSolaris : public CollectorHAL
     
    4465    virtual ~CollectorSolaris();
    4566    virtual int getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available);
     67    virtual int getHostFilesystemUsage(const char *name, ULONG *total, ULONG *used, ULONG *available);
    4668    virtual int getProcessMemoryUsage(RTPROCESS process, ULONG *used);
    4769
    4870    virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
    4971    virtual int getRawHostNetworkLoad(const char *name, uint64_t *rx, uint64_t *tx);
     72    virtual int getRawHostDiskLoad(const char *name, uint64_t *disk_ms, uint64_t *total_ms);
    5073    virtual int getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total);
     74
     75    virtual int getDiskListByFs(const char *name, DiskList& list);
    5176private:
    5277    static uint32_t getInstance(const char *pszIfaceName, char *pszDevName);
     78    uint64_t getZfsTotal(uint64_t cbTotal, const char *szFsType, const char *szFsName);
     79    void updateFilesystemMap(void);
     80    RTCString physToInstName(const char *pcszPhysName);
     81
    5382    kstat_ctl_t *mKC;
    5483    kstat_t     *mSysPages;
    5584    kstat_t     *mZFSCache;
     85
     86    void             *mZfsSo;
     87    libzfs_handle_t  *mZfsLib;
     88    PFNZFSINIT        mZfsInit;
     89    PFNZFSOPEN        mZfsOpen;
     90    PFNZFSCLOSE       mZfsClose;
     91    PFNZFSPROPGETINT  mZfsPropGetInt;
     92    PFNZPOOLOPEN      mZpoolOpen;
     93    PFNZPOOLCLOSE     mZpoolClose;
     94    PFNZPOOLGETCONFIG mZpoolGetConfig;
     95    PFNZPOOLVDEVNAME  mZpoolVdevName;
     96
     97    FsMap             mFsMap;
    5698};
    5799
     
    67109    : mKC(0),
    68110      mSysPages(0),
    69       mZFSCache(0)
     111      mZFSCache(0),
     112      mZfsLib(0)
    70113{
    71114    if ((mKC = kstat_open()) == 0)
     
    85128        Log(("kstat_lookup(system_pages) -> %d\n", errno));
    86129    }
     130
     131    /* Try to load libzfs dynamically, it may be missing. */
     132    mZfsSo = dlopen("libzfs.so", RTLD_LAZY);
     133    if (mZfsSo)
     134    {
     135        mZfsInit        =        (PFNZFSINIT)dlsym(mZfsSo, "libzfs_init");
     136        mZfsOpen        =        (PFNZFSOPEN)dlsym(mZfsSo, "zfs_open");
     137        mZfsClose       =       (PFNZFSCLOSE)dlsym(mZfsSo, "zfs_close");
     138        mZfsPropGetInt  =  (PFNZFSPROPGETINT)dlsym(mZfsSo, "zfs_prop_get_int");
     139        mZpoolOpen      =      (PFNZPOOLOPEN)dlsym(mZfsSo, "zpool_open");
     140        mZpoolClose     =     (PFNZPOOLCLOSE)dlsym(mZfsSo, "zpool_close");
     141        mZpoolGetConfig = (PFNZPOOLGETCONFIG)dlsym(mZfsSo, "zpool_get_config");
     142        mZpoolVdevName  =  (PFNZPOOLVDEVNAME)dlsym(mZfsSo, "zpool_vdev_name");
     143
     144        if (mZfsInit && mZfsOpen && mZfsClose && mZfsPropGetInt
     145            && mZpoolOpen && mZpoolClose && mZpoolGetConfig && mZpoolVdevName)
     146            mZfsLib = mZfsInit();
     147        else
     148            LogRel(("Incompatible libzfs? libzfs_init=%p zfs_open=%p zfs_close=%p zfs_prop_get_int=%p\n",
     149                    mZfsInit, mZfsOpen, mZfsClose, mZfsPropGetInt));
     150    }
     151
     152    updateFilesystemMap();
    87153}
    88154
     
    91157    if (mKC)
    92158        kstat_close(mKC);
     159    if (mZfsSo)
     160        dlclose(mZfsSo);
    93161}
    94162
     
    300368        {
    301369            LogFlowThisFunc(("m=%s i=%u n=%s\n", szModule, uInstance, name));
    302             ksAdapter = kstat_lookup(mKC, szModule, uInstance, name);
     370            ksAdapter = kstat_lookup(mKC, szModule, uInstance, (char *)name);
    303371            if (ksAdapter == 0)
    304372            {
     
    329397}
    330398
    331 int getDiskListByFs(const char *name, DiskList& list)
    332 {
    333     return VERR_NOT_IMPLEMENTED;
    334 }
    335 
    336 }
     399int CollectorSolaris::getRawHostDiskLoad(const char *name, uint64_t *disk_ms, uint64_t *total_ms)
     400{
     401    int rc = VINF_SUCCESS;
     402    AssertReturn(strlen(name) < KSTAT_STRLEN, VERR_INVALID_PARAMETER);
     403    LogFlowThisFunc(("n=%s\n", name));
     404    kstat_t *ksDisk = kstat_lookup(mKC, NULL, -1, (char *)name);
     405    if (ksDisk != 0)
     406    {
     407        if (kstat_read(mKC, ksDisk, 0) == -1)
     408        {
     409            LogRel(("kstat_read(%s) -> %d\n", name, errno));
     410            rc = VERR_INTERNAL_ERROR;
     411        }
     412        else
     413        {
     414            kstat_io_t *ksIo = KSTAT_IO_PTR(ksDisk);
     415            /*
     416             * We do not care for wrap possibility here, although we may
     417             * reconsider in about 300 years (9223372036854775807 ns).
     418             */
     419            *disk_ms = ksIo->rtime / 1000000;
     420            *total_ms = ksDisk->ks_snaptime / 1000000;
     421        }
     422    }
     423    else
     424    {
     425        LogRel(("kstat_lookup(%s) -> %d\n", name, errno));
     426        rc = VERR_INTERNAL_ERROR;
     427    }
     428
     429    return rc;
     430}
     431
     432uint64_t CollectorSolaris::getZfsTotal(uint64_t cbTotal, const char *szFsType, const char *szFsName)
     433{
     434    if (strcmp(szFsType, "zfs"))
     435        return cbTotal;
     436    FsMap::iterator it = mFsMap.find(szFsName);
     437    if (it == mFsMap.end())
     438        return cbTotal;
     439
     440    char *pszDataset = strdup(it->second.c_str());
     441    char *pszEnd = pszDataset + strlen(pszDataset);
     442    uint64_t uAvail = 0;
     443    while (pszEnd)
     444    {
     445        zfs_handle_t *hDataset;
     446
     447        *pszEnd = 0;
     448        hDataset = mZfsOpen(mZfsLib, pszDataset, ZFS_TYPE_DATASET);
     449        if (!hDataset)
     450            break;
     451
     452        if (uAvail == 0)
     453        {
     454            uAvail = mZfsPropGetInt(hDataset, ZFS_PROP_REFQUOTA);
     455            if (uAvail == 0)
     456                uAvail = UINT64_MAX;
     457        }
     458
     459        uint64_t uQuota = mZfsPropGetInt(hDataset, ZFS_PROP_QUOTA);
     460        if (uQuota && uAvail > uQuota)
     461            uAvail = uQuota;
     462
     463        pszEnd = strrchr(pszDataset, '/');
     464        if (!pszEnd)
     465        {
     466            uint64_t uPoolSize = mZfsPropGetInt(hDataset, ZFS_PROP_USED) +
     467                                 mZfsPropGetInt(hDataset, ZFS_PROP_AVAILABLE);
     468            if (uAvail > uPoolSize)
     469                uAvail = uPoolSize;
     470        }
     471        mZfsClose(hDataset);
     472    }
     473    free(pszDataset);
     474
     475    return uAvail ? uAvail : cbTotal;
     476}
     477
     478int CollectorSolaris::getHostFilesystemUsage(const char *path, ULONG *total, ULONG *used, ULONG *available)
     479{
     480    struct statvfs64 stats;
     481    const unsigned _MB = 1024 * 1024;
     482
     483    if (statvfs64(path, &stats) == -1)
     484    {
     485        LogRel(("Failed to collect %s filesystem usage: errno=%d.\n", path, errno));
     486        return VERR_ACCESS_DENIED;
     487    }
     488    uint64_t cbBlock = stats.f_frsize ? stats.f_frsize : stats.f_bsize;
     489    *total = (ULONG)(getZfsTotal(cbBlock * stats.f_blocks, stats.f_basetype, path) / _MB);
     490    LogRel(("f_blocks=%llu.\n", stats.f_blocks));
     491    *used  = (ULONG)(cbBlock * (stats.f_blocks - stats.f_bfree) / _MB);
     492    *available = (ULONG)(cbBlock * stats.f_bavail / _MB);
     493
     494    return VINF_SUCCESS;
     495}
     496
     497RTCString CollectorSolaris::physToInstName(const char *pcszPhysName)
     498{
     499    FILE *fp = fopen("/etc/path_to_inst", "r");
     500    if (!fp)
     501        return RTCString();
     502
     503    RTCString strInstName;
     504    size_t cbName = strlen(pcszPhysName);
     505    char szBuf[RTPATH_MAX];
     506    while (fgets(szBuf, sizeof(szBuf), fp))
     507    {
     508        if (szBuf[0] == '"' && strncmp(szBuf + 1, pcszPhysName, cbName) == 0)
     509        {
     510            char *pszDriver, *pszInstance;
     511            pszDriver = strrchr(szBuf, '"');
     512            if (pszDriver)
     513            {
     514                *pszDriver = '\0';
     515                pszDriver = strrchr(szBuf, '"');
     516                if (pszDriver)
     517                {
     518                    *pszDriver++ = '\0';
     519                    pszInstance = strrchr(szBuf, ' ');
     520                    if (pszInstance)
     521                    {
     522                        *pszInstance = '\0';
     523                        pszInstance = strrchr(szBuf, ' ');
     524                        if (pszInstance)
     525                        {
     526                            *pszInstance++ = '\0';
     527                            strInstName = pszDriver;
     528                            strInstName += pszInstance;
     529                            break;
     530                        }
     531                    }
     532                }
     533            }
     534        }
     535    }
     536    fclose(fp);
     537
     538    return strInstName;
     539}
     540
     541int CollectorSolaris::getDiskListByFs(const char *name, DiskList& list)
     542{
     543    FsMap::iterator it = mFsMap.find(name);
     544    if (it == mFsMap.end())
     545        return VERR_INVALID_PARAMETER;
     546
     547    RTCString strName = it->second.substr(0, it->second.find("/"));
     548    if (mZpoolOpen && mZpoolClose && mZpoolGetConfig)
     549    {
     550        zpool_handle_t *zh = mZpoolOpen(mZfsLib, strName.c_str());
     551        if (zh)
     552        {
     553            unsigned int cChildren;
     554            nvlist_t **nvChildren, *nvRoot, *nvConfig = mZpoolGetConfig(zh, NULL);
     555            Assert(!nvlist_lookup_nvlist(nvConfig, ZPOOL_CONFIG_VDEV_TREE, &nvRoot));
     556            if (!nvlist_lookup_nvlist_array(nvRoot, ZPOOL_CONFIG_CHILDREN, &nvChildren, &cChildren))
     557            {
     558                for (unsigned int i = 0; i < cChildren; ++i)
     559                {
     560                    uint64_t fHole = 0;
     561                    uint64_t fLog  = 0;
     562
     563                    nvlist_lookup_uint64(nvChildren[i], ZPOOL_CONFIG_IS_HOLE, &fHole);
     564                    nvlist_lookup_uint64(nvChildren[i], ZPOOL_CONFIG_IS_LOG,  &fLog);
     565
     566                    if (!fHole && !fLog)
     567                    {
     568                        char *pszChildName = mZpoolVdevName(mZfsLib, zh, nvChildren[i], _B_FALSE);
     569                        Assert(pszChildName);
     570                        RTCString strDevPath("/dev/dsk/");
     571                        strDevPath += pszChildName;
     572                        char szLink[RTPATH_MAX];
     573                        if (readlink(strDevPath.c_str(), szLink, sizeof(szLink)) != -1)
     574                        {
     575                            char *pszStart, *pszEnd;
     576                            pszStart = strstr(szLink, "/devices/");
     577                            pszEnd = strrchr(szLink, ':');
     578                            if (pszStart && pszEnd)
     579                            {
     580                                pszStart += 8; // Skip "/devices"
     581                                *pszEnd = '\0'; // Trim partition
     582                                list.push_back(physToInstName(pszStart));
     583                            }
     584                        }
     585                        free(pszChildName);
     586                    }
     587                }
     588            }
     589            mZpoolClose(zh);
     590        }
     591    }
     592    else
     593        list.push_back(RTCString(name));
     594    return VINF_SUCCESS;
     595}
     596
     597void CollectorSolaris::updateFilesystemMap(void)
     598{
     599    FILE *fp = fopen("/etc/mnttab", "r");
     600    if (fp)
     601    {
     602        struct mnttab Entry;
     603        int rc = 0;
     604        resetmnttab(fp);
     605        while ((rc = getmntent(fp, &Entry)) == 0)
     606            mFsMap[Entry.mnt_mountp] = Entry.mnt_special;
     607        fclose(fp);
     608        if (rc != -1)
     609            LogRel(("Error while reading mnttab: %d\n", rc));
     610    }
     611}
     612
     613}
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