summaryrefslogtreecommitdiff
path: root/src/VBox/Main/src-server/solaris
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2014-03-26 19:21:20 +0000
committer <>2014-05-08 15:03:54 +0000
commitfb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch)
treec2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/Main/src-server/solaris
parent58ed4748338f9466599adfc8a9171280ed99e23f (diff)
downloadVirtualBox-master.tar.gz
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/Main/src-server/solaris')
-rw-r--r--src/VBox/Main/src-server/solaris/DynLoadLibSolaris.cpp2
-rw-r--r--src/VBox/Main/src-server/solaris/DynLoadLibSolaris.h2
-rw-r--r--src/VBox/Main/src-server/solaris/NetIf-solaris.cpp133
-rw-r--r--src/VBox/Main/src-server/solaris/PerformanceSolaris.cpp530
-rw-r--r--src/VBox/Main/src-server/solaris/USBProxyServiceSolaris.cpp6
5 files changed, 541 insertions, 132 deletions
diff --git a/src/VBox/Main/src-server/solaris/DynLoadLibSolaris.cpp b/src/VBox/Main/src-server/solaris/DynLoadLibSolaris.cpp
index 4bd864f1..a38b7654 100644
--- a/src/VBox/Main/src-server/solaris/DynLoadLibSolaris.cpp
+++ b/src/VBox/Main/src-server/solaris/DynLoadLibSolaris.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2008 Oracle Corporation
+ * Copyright (C) 2008-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Main/src-server/solaris/DynLoadLibSolaris.h b/src/VBox/Main/src-server/solaris/DynLoadLibSolaris.h
index 4fc35b8a..e306dac0 100644
--- a/src/VBox/Main/src-server/solaris/DynLoadLibSolaris.h
+++ b/src/VBox/Main/src-server/solaris/DynLoadLibSolaris.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2008 Oracle Corporation
+ * Copyright (C) 2008-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Main/src-server/solaris/NetIf-solaris.cpp b/src/VBox/Main/src-server/solaris/NetIf-solaris.cpp
index bc700820..82e8a338 100644
--- a/src/VBox/Main/src-server/solaris/NetIf-solaris.cpp
+++ b/src/VBox/Main/src-server/solaris/NetIf-solaris.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2008-2011 Oracle Corporation
+ * Copyright (C) 2008-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -24,6 +24,7 @@
#include <iprt/err.h>
#include <iprt/ctype.h>
+#include <iprt/mem.h>
#include <iprt/path.h>
#include <list>
@@ -73,10 +74,10 @@ static uint32_t getInstance(const char *pszIfaceName, char *pszDevName)
return uInstance;
}
-static uint64_t kstatGet(const char *name)
+static uint32_t kstatGet(const char *name)
{
kstat_ctl_t *kc;
- uint64_t uSpeed = 0;
+ uint32_t uSpeed = 0;
if ((kc = kstat_open()) == 0)
{
@@ -84,14 +85,14 @@ static uint64_t kstatGet(const char *name)
return 0;
}
- kstat_t *ksAdapter = kstat_lookup(kc, "link", -1, (char *)name);
+ kstat_t *ksAdapter = kstat_lookup(kc, (char *)"link", -1, (char *)name);
if (ksAdapter == 0)
{
char szModule[KSTAT_STRLEN];
uint32_t uInstance = getInstance(name, szModule);
- ksAdapter = kstat_lookup(kc, szModule, uInstance, "phys");
+ ksAdapter = kstat_lookup(kc, szModule, uInstance, (char *)"phys");
if (ksAdapter == 0)
- ksAdapter = kstat_lookup(kc, szModule, uInstance, name);
+ ksAdapter = kstat_lookup(kc, szModule, uInstance, (char*)name);
}
if (ksAdapter == 0)
LogRel(("Failed to get network statistics for %s\n", name));
@@ -103,15 +104,21 @@ static uint64_t kstatGet(const char *name)
if ((kn = (kstat_named_t *)kstat_data_lookup(ksAdapter, (char *)"ifspeed")) == 0)
LogRel(("kstat_data_lookup(ifspeed) -> %d, name=%s\n", errno, name));
else
- uSpeed = kn->value.ul;
+ uSpeed = kn->value.ul / 1000000; /* bits -> Mbits */
}
kstat_close(kc);
+ LogFlow(("kstatGet(%s) -> %u Mbit/s\n", name, uSpeed));
return uSpeed;
}
static void queryIfaceSpeed(PNETIFINFO pInfo)
{
- pInfo->uSpeedMbits = kstatGet(pInfo->szShortName) / 1000000; /* bits -> Mbits */
+ /* Don't query interface speed for inactive interfaces (see @bugref{6345}). */
+ if (pInfo->enmStatus == NETIF_S_UP)
+ pInfo->uSpeedMbits = kstatGet(pInfo->szShortName);
+ else
+ pInfo->uSpeedMbits = 0;
+ LogFlow(("queryIfaceSpeed(%s) -> %u\n", pInfo->szShortName, pInfo->uSpeedMbits));
}
static void vboxSolarisAddHostIface(char *pszIface, int Instance, void *pvHostNetworkInterfaceList)
@@ -192,12 +199,12 @@ static void vboxSolarisAddHostIface(char *pszIface, int Instance, void *pvHostNe
* Try to get IP V4 address and netmask as well as Ethernet address.
*/
NETIFINFO Info;
- memset(&Info, 0, sizeof(Info));
+ RT_ZERO(Info);
int Sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
if (Sock > 0)
{
struct lifreq IfReq;
- strcpy(IfReq.lifr_name, szNICInstance);
+ RTStrCopy(IfReq.lifr_name, sizeof(IfReq.lifr_name), szNICInstance);
if (ioctl(Sock, SIOCGLIFADDR, &IfReq) >= 0)
{
memcpy(Info.IPAddress.au8, &((struct sockaddr_in *)&IfReq.lifr_addr)->sin_addr.s_addr,
@@ -236,7 +243,7 @@ static void vboxSolarisAddHostIface(char *pszIface, int Instance, void *pvHostNe
if (Sock > 0)
{
struct lifreq IfReq;
- strcpy(IfReq.lifr_name, szNICInstance);
+ RTStrCopy(IfReq.lifr_name, sizeof(IfReq.lifr_name), szNICInstance);
if (ioctl(Sock, SIOCGLIFADDR, &IfReq) >= 0)
{
memcpy(Info.IPv6Address.au8, ((struct sockaddr_in6 *)&IfReq.lifr_addr)->sin6_addr.s6_addr,
@@ -269,7 +276,7 @@ static void vboxSolarisAddHostIface(char *pszIface, int Instance, void *pvHostNe
strncpy(Info.szShortName, szNICInstance, sizeof(Info.szShortName) - 1);
HostNetworkInterfaceType_T enmType;
- if (strncmp("vboxnet", szNICInstance, 7))
+ if (strncmp(szNICInstance, RT_STR_TUPLE("vboxnet")))
enmType = HostNetworkInterfaceType_Bridged;
else
enmType = HostNetworkInterfaceType_HostOnly;
@@ -285,15 +292,15 @@ static boolean_t vboxSolarisAddLinkHostIface(const char *pszIface, void *pvHostN
/*
* Skip IPSEC interfaces. It's at IP level.
*/
- if (!strncmp(pszIface, "ip.tun", 6))
+ if (!strncmp(pszIface, RT_STR_TUPLE("ip.tun")))
return _B_FALSE;
/*
* Skip our own dynamic VNICs but don't skip VNIC templates.
* These names originate from VBoxNetFltBow-solaris.c, hardcoded here for now.
*/
- if ( strncmp(pszIface, "vboxvnic_template", 17)
- && !strncmp(pszIface, "vboxvnic", 8))
+ if ( strncmp(pszIface, RT_STR_TUPLE("vboxvnic_template"))
+ && !strncmp(pszIface, RT_STR_TUPLE("vboxvnic")))
return _B_FALSE;
/*
@@ -406,59 +413,65 @@ int NetIfList(std::list <ComObjPtr<HostNetworkInterface> > &list)
if (Sock > 0)
{
struct lifnum IfNum;
- memset(&IfNum, 0, sizeof(IfNum));
+ RT_ZERO(IfNum);
IfNum.lifn_family = AF_INET;
int rc = ioctl(Sock, SIOCGLIFNUM, &IfNum);
if (!rc)
{
- struct lifreq Ifaces[24];
- struct lifconf IfConfig;
- memset(&IfConfig, 0, sizeof(IfConfig));
- IfConfig.lifc_family = AF_INET;
- IfConfig.lifc_len = sizeof(Ifaces);
- IfConfig.lifc_buf = (caddr_t)&(Ifaces[0]);
- rc = ioctl(Sock, SIOCGLIFCONF, &IfConfig);
- if (!rc)
+ int cIfaces = RT_MIN(1024, IfNum.lifn_count); /* sane limit */
+ int cbIfaces = cIfaces * sizeof(struct lifreq);
+ struct lifreq *Ifaces = (struct lifreq *)RTMemTmpAlloc(cbIfaces);
+ if (Ifaces)
{
- for (int i = 0; i < IfNum.lifn_count; i++)
+ struct lifconf IfConfig;
+ RT_ZERO(IfConfig);
+ IfConfig.lifc_family = AF_INET;
+ IfConfig.lifc_len = cbIfaces;
+ IfConfig.lifc_buf = (caddr_t)Ifaces;
+ rc = ioctl(Sock, SIOCGLIFCONF, &IfConfig);
+ if (!rc)
{
- /*
- * Skip loopback interfaces.
- */
- if (!strncmp(Ifaces[i].lifr_name, "lo", 2))
- continue;
-
-#if 0
- rc = ioctl(Sock, SIOCGLIFADDR, &(Ifaces[i]));
- if (rc >= 0)
+ for (int i = 0; i < cIfaces; i++)
{
- memcpy(Info.IPAddress.au8, ((struct sockaddr *)&Ifaces[i].lifr_addr)->sa_data,
- sizeof(Info.IPAddress.au8));
- // SIOCGLIFNETMASK
- struct arpreq ArpReq;
- memcpy(&ArpReq.arp_pa, &Ifaces[i].lifr_addr, sizeof(struct sockaddr_in));
-
/*
- * We might fail if the interface has not been assigned an IP address.
- * That doesn't matter; as long as it's plumbed we can pick it up.
- * But, if it has not acquired an IP address we cannot obtain it's MAC
- * address this way, so we just use all zeros there.
+ * Skip loopback interfaces.
*/
- rc = ioctl(Sock, SIOCGARP, &ArpReq);
+ if (!strncmp(Ifaces[i].lifr_name, RT_STR_TUPLE("lo")))
+ continue;
+
+#if 0
+ rc = ioctl(Sock, SIOCGLIFADDR, &(Ifaces[i]));
if (rc >= 0)
- memcpy(&Info.MACAddress, ArpReq.arp_ha.sa_data, sizeof(Info.MACAddress));
+ {
+ memcpy(Info.IPAddress.au8, ((struct sockaddr *)&Ifaces[i].lifr_addr)->sa_data,
+ sizeof(Info.IPAddress.au8));
+ // SIOCGLIFNETMASK
+ struct arpreq ArpReq;
+ memcpy(&ArpReq.arp_pa, &Ifaces[i].lifr_addr, sizeof(struct sockaddr_in));
+
+ /*
+ * We might fail if the interface has not been assigned an IP address.
+ * That doesn't matter; as long as it's plumbed we can pick it up.
+ * But, if it has not acquired an IP address we cannot obtain it's MAC
+ * address this way, so we just use all zeros there.
+ */
+ rc = ioctl(Sock, SIOCGARP, &ArpReq);
+ if (rc >= 0)
+ memcpy(&Info.MACAddress, ArpReq.arp_ha.sa_data, sizeof(Info.MACAddress));
+
+ char szNICDesc[LIFNAMSIZ + 256];
+ char *pszIface = Ifaces[i].lifr_name;
+ strcpy(szNICDesc, pszIface);
+
+ vboxSolarisAddLinkHostIface(pszIface, &list);
+ }
+#endif
- char szNICDesc[LIFNAMSIZ + 256];
char *pszIface = Ifaces[i].lifr_name;
- strcpy(szNICDesc, pszIface);
-
vboxSolarisAddLinkHostIface(pszIface, &list);
}
-#endif
-
- char *pszIface = Ifaces[i].lifr_name;
- vboxSolarisAddLinkHostIface(pszIface, &list);
}
+ RTMemTmpFree(Ifaces);
}
}
close(Sock);
@@ -486,3 +499,17 @@ int NetIfGetConfigByName(PNETIFINFO pInfo)
return VERR_NOT_IMPLEMENTED;
}
+/**
+ * Retrieve the physical link speed in megabits per second. If the interface is
+ * not up or otherwise unavailable the zero speed is returned.
+ *
+ * @returns VBox status code.
+ *
+ * @param pcszIfName Interface name.
+ * @param puMbits Where to store the link speed.
+ */
+int NetIfGetLinkSpeed(const char *pcszIfName, uint32_t *puMbits)
+{
+ *puMbits = kstatGet(pcszIfName);
+ return VINF_SUCCESS;
+}
diff --git a/src/VBox/Main/src-server/solaris/PerformanceSolaris.cpp b/src/VBox/Main/src-server/solaris/PerformanceSolaris.cpp
index 7abeae04..ed935116 100644
--- a/src/VBox/Main/src-server/solaris/PerformanceSolaris.cpp
+++ b/src/VBox/Main/src-server/solaris/PerformanceSolaris.cpp
@@ -6,7 +6,7 @@
*/
/*
- * Copyright (C) 2008 Oracle Corporation
+ * Copyright (C) 2008-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -26,33 +26,85 @@
#include <unistd.h>
#include <sys/sysinfo.h>
#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/statvfs.h>
#include <iprt/ctype.h>
#include <iprt/err.h>
#include <iprt/string.h>
#include <iprt/alloc.h>
#include <iprt/param.h>
-#include <VBox/log.h>
+#include <iprt/path.h>
+#include <iprt/system.h>
+
+#include "Logging.h"
#include "Performance.h"
+#include <dlfcn.h>
+
+#include <libzfs.h>
+#include <libnvpair.h>
+
+#include <map>
+
namespace pm {
+ typedef libzfs_handle_t *(*PFNZFSINIT)(void);
+ typedef void (*PFNZFSFINI)(libzfs_handle_t *);
+ typedef zfs_handle_t *(*PFNZFSOPEN)(libzfs_handle_t *, const char *, int);
+ typedef void (*PFNZFSCLOSE)(zfs_handle_t *);
+ typedef uint64_t (*PFNZFSPROPGETINT)(zfs_handle_t *, zfs_prop_t);
+ typedef zpool_handle_t *(*PFNZPOOLOPEN)(libzfs_handle_t *, const char *);
+ typedef void (*PFNZPOOLCLOSE)(zpool_handle_t *);
+ typedef nvlist_t *(*PFNZPOOLGETCONFIG)(zpool_handle_t *, nvlist_t **);
+ typedef char *(*PFNZPOOLVDEVNAME)(libzfs_handle_t *, zpool_handle_t *, nvlist_t *, boolean_t);
+
+ typedef std::map<RTCString,RTCString> FsMap;
+
class CollectorSolaris : public CollectorHAL
{
public:
CollectorSolaris();
virtual ~CollectorSolaris();
virtual int getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available);
+ virtual int getHostFilesystemUsage(const char *name, ULONG *total, ULONG *used, ULONG *available);
+ virtual int getHostDiskSize(const char *name, uint64_t *size);
virtual int getProcessMemoryUsage(RTPROCESS process, ULONG *used);
virtual int getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle);
virtual int getRawHostNetworkLoad(const char *name, uint64_t *rx, uint64_t *tx);
+ 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& listUsage, DiskList& listLoad);
private:
static uint32_t getInstance(const char *pszIfaceName, char *pszDevName);
- kstat_ctl_t *mKC;
- kstat_t *mSysPages;
- kstat_t *mZFSCache;
+ uint64_t getZfsTotal(uint64_t cbTotal, const char *szFsType, const char *szFsName);
+ void updateFilesystemMap(void);
+ RTCString physToInstName(const char *pcszPhysName);
+ RTCString pathToInstName(const char *pcszDevPathName);
+ uint64_t wrapCorrection(uint32_t cur, uint64_t prev, const char *name);
+ uint64_t wrapDetection(uint64_t cur, uint64_t prev, const char *name);
+
+ kstat_ctl_t *mKC;
+ kstat_t *mSysPages;
+ kstat_t *mZFSCache;
+
+ void *mZfsSo;
+ libzfs_handle_t *mZfsLib;
+ PFNZFSINIT mZfsInit;
+ PFNZFSFINI mZfsFini;
+ PFNZFSOPEN mZfsOpen;
+ PFNZFSCLOSE mZfsClose;
+ PFNZFSPROPGETINT mZfsPropGetInt;
+ PFNZPOOLOPEN mZpoolOpen;
+ PFNZPOOLCLOSE mZpoolClose;
+ PFNZPOOLGETCONFIG mZpoolGetConfig;
+ PFNZPOOLVDEVNAME mZpoolVdevName;
+
+ FsMap mFsMap;
+ uint32_t mCpus;
+ ULONG totalRAM;
};
CollectorHAL *createHAL()
@@ -66,7 +118,9 @@ CollectorHAL *createHAL()
CollectorSolaris::CollectorSolaris()
: mKC(0),
mSysPages(0),
- mZFSCache(0)
+ mZFSCache(0),
+ mZfsLib(0),
+ mCpus(0)
{
if ((mKC = kstat_open()) == 0)
{
@@ -84,12 +138,55 @@ CollectorSolaris::CollectorSolaris()
{
Log(("kstat_lookup(system_pages) -> %d\n", errno));
}
+
+ /* Try to load libzfs dynamically, it may be missing. */
+ mZfsSo = dlopen("libzfs.so", RTLD_LAZY);
+ if (mZfsSo)
+ {
+ mZfsInit = (PFNZFSINIT)(uintptr_t)dlsym(mZfsSo, "libzfs_init");
+ mZfsFini = (PFNZFSFINI)(uintptr_t)dlsym(mZfsSo, "libzfs_fini");
+ mZfsOpen = (PFNZFSOPEN)(uintptr_t)dlsym(mZfsSo, "zfs_open");
+ mZfsClose = (PFNZFSCLOSE)(uintptr_t)dlsym(mZfsSo, "zfs_close");
+ mZfsPropGetInt = (PFNZFSPROPGETINT)(uintptr_t)dlsym(mZfsSo, "zfs_prop_get_int");
+ mZpoolOpen = (PFNZPOOLOPEN)(uintptr_t)dlsym(mZfsSo, "zpool_open");
+ mZpoolClose = (PFNZPOOLCLOSE)(uintptr_t)dlsym(mZfsSo, "zpool_close");
+ mZpoolGetConfig = (PFNZPOOLGETCONFIG)(uintptr_t)dlsym(mZfsSo, "zpool_get_config");
+ mZpoolVdevName = (PFNZPOOLVDEVNAME)(uintptr_t)dlsym(mZfsSo, "zpool_vdev_name");
+
+ if ( mZfsInit
+ && mZfsOpen
+ && mZfsClose
+ && mZfsPropGetInt
+ && mZpoolOpen
+ && mZpoolClose
+ && mZpoolGetConfig
+ && mZpoolVdevName)
+ mZfsLib = mZfsInit();
+ else
+ LogRel(("Incompatible libzfs? libzfs_init=%p zfs_open=%p zfs_close=%p zfs_prop_get_int=%p\n",
+ mZfsInit, mZfsOpen, mZfsClose, mZfsPropGetInt));
+ }
+
+ updateFilesystemMap();
+ /* Notice that mCpus member will be initialized by HostCpuLoadRaw::init() */
+
+ uint64_t cb;
+ int rc = RTSystemQueryTotalRam(&cb);
+ if (RT_FAILURE(rc))
+ totalRAM = 0;
+ else
+ totalRAM = (ULONG)(cb / 1024);
}
CollectorSolaris::~CollectorSolaris()
{
if (mKC)
kstat_close(mKC);
+ /* Not calling libzfs_fini() causes file descriptor leaks (#6788). */
+ if (mZfsFini && mZfsLib)
+ mZfsFini(mZfsLib);
+ if (mZfsSo)
+ dlclose(mZfsSo);
}
int CollectorSolaris::getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64_t *idle)
@@ -123,6 +220,8 @@ int CollectorSolaris::getRawHostCpuLoad(uint64_t *user, uint64_t *kernel, uint64
Log(("no cpu stats found!\n"));
return VERR_INTERNAL_ERROR;
}
+ else
+ mCpus = cpus;
if (user) *user = tmpUser;
if (kernel) *kernel = tmpKernel;
@@ -148,8 +247,18 @@ int CollectorSolaris::getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, ui
{
//Assert((pid_t)process == pstatus.pr_pid);
//Log(("user=%u kernel=%u total=%u\n", prusage.pr_utime.tv_sec, prusage.pr_stime.tv_sec, prusage.pr_tstamp.tv_sec));
- *user = (uint64_t)prusage.pr_utime.tv_sec * 1000000000 + prusage.pr_utime.tv_nsec;
- *kernel = (uint64_t)prusage.pr_stime.tv_sec * 1000000000 + prusage.pr_stime.tv_nsec;
+ /*
+ * The CPU time spent must be adjusted by the number of cores for compatibility with
+ * other platforms (see @bugref{6345}).
+ */
+ Assert(mCpus);
+ if (mCpus)
+ {
+ *user = ((uint64_t)prusage.pr_utime.tv_sec * 1000000000 + prusage.pr_utime.tv_nsec) / mCpus;
+ *kernel = ((uint64_t)prusage.pr_stime.tv_sec * 1000000000 + prusage.pr_stime.tv_nsec) / mCpus;
+ }
+ else
+ *user = *kernel = 0;
*total = (uint64_t)prusage.pr_tstamp.tv_sec * 1000000000 + prusage.pr_tstamp.tv_nsec;
//Log(("user=%llu kernel=%llu total=%llu\n", *user, *kernel, *total));
}
@@ -171,61 +280,15 @@ int CollectorSolaris::getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, ui
int CollectorSolaris::getHostMemoryUsage(ULONG *total, ULONG *used, ULONG *available)
{
- int rc = VINF_SUCCESS;
-
- kstat_named_t *kn;
-
- if (mKC == 0 || mSysPages == 0)
- return VERR_INTERNAL_ERROR;
-
- if (kstat_read(mKC, mSysPages, 0) == -1)
+ AssertReturn(totalRAM, VERR_INTERNAL_ERROR);
+ uint64_t cb;
+ int rc = RTSystemQueryAvailableRam(&cb);
+ if (RT_SUCCESS(rc))
{
- Log(("kstat_read(sys_pages) -> %d\n", errno));
- return VERR_INTERNAL_ERROR;
+ *total = totalRAM;
+ *available = cb / 1024;
+ *used = *total - *available;
}
- if ((kn = (kstat_named_t *)kstat_data_lookup(mSysPages, (char *)"freemem")) == 0)
- {
- Log(("kstat_data_lookup(freemem) -> %d\n", errno));
- return VERR_INTERNAL_ERROR;
- }
- *available = kn->value.ul * (PAGE_SIZE/1024);
-
- if (kstat_read(mKC, mZFSCache, 0) != -1)
- {
- if (mZFSCache)
- {
- if ((kn = (kstat_named_t *)kstat_data_lookup(mZFSCache, (char *)"size")))
- {
- ulong_t ulSize = kn->value.ul;
-
- if ((kn = (kstat_named_t *)kstat_data_lookup(mZFSCache, (char *)"c_min")))
- {
- /*
- * Account for ZFS minimum arc cache size limit.
- * "c_min" is the target minimum size of the ZFS cache, and not the hard limit. It's possible
- * for "size" to shrink below "c_min" (e.g: during boot & high memory consumption).
- */
- ulong_t ulMin = kn->value.ul;
- *available += ulSize > ulMin ? (ulSize - ulMin) / 1024 : 0;
- }
- else
- Log(("kstat_data_lookup(c_min) ->%d\n", errno));
- }
- else
- Log(("kstat_data_lookup(size) -> %d\n", errno));
- }
- else
- Log(("mZFSCache missing.\n"));
- }
-
- if ((kn = (kstat_named_t *)kstat_data_lookup(mSysPages, (char *)"physmem")) == 0)
- {
- Log(("kstat_data_lookup(physmem) -> %d\n", errno));
- return VERR_INTERNAL_ERROR;
- }
- *total = kn->value.ul * (PAGE_SIZE/1024);
- *used = *total - *available;
-
return rc;
}
@@ -285,21 +348,53 @@ uint32_t CollectorSolaris::getInstance(const char *pszIfaceName, char *pszDevNam
return uInstance;
}
+uint64_t CollectorSolaris::wrapCorrection(uint32_t cur, uint64_t prev, const char *name)
+{
+ NOREF(name);
+ uint64_t corrected = (prev & 0xffffffff00000000) + cur;
+ if (cur < (prev & 0xffffffff))
+ {
+ /* wrap has occurred */
+ corrected += 0x100000000;
+ LogFlowThisFunc(("Corrected wrap on %s (%u < %u), returned %llu.\n",
+ name, cur, (uint32_t)prev, corrected));
+ }
+ return corrected;
+}
+
+uint64_t CollectorSolaris::wrapDetection(uint64_t cur, uint64_t prev, const char *name)
+{
+ static bool fNotSeen = true;
+
+ if (fNotSeen && cur < prev)
+ {
+ fNotSeen = false;
+ LogRel(("Detected wrap on %s (%llu < %llu).\n", name, cur, prev));
+ }
+ return cur;
+}
+
+/*
+ * WARNING! This function expects the previous values of rx and tx counter to
+ * be passed in as well as returnes new values in the same parameters. This is
+ * needed to provide a workaround for 32-bit counter wrapping.
+ */
int CollectorSolaris::getRawHostNetworkLoad(const char *name, uint64_t *rx, uint64_t *tx)
{
+ static bool g_fNotReported = true;
AssertReturn(strlen(name) < KSTAT_STRLEN, VERR_INVALID_PARAMETER);
LogFlowThisFunc(("m=%s i=%d n=%s\n", "link", -1, name));
- kstat_t *ksAdapter = kstat_lookup(mKC, "link", -1, (char *)name);
+ kstat_t *ksAdapter = kstat_lookup(mKC, (char *)"link", -1, (char *)name);
if (ksAdapter == 0)
{
char szModule[KSTAT_STRLEN];
uint32_t uInstance = getInstance(name, szModule);
LogFlowThisFunc(("m=%s i=%u n=%s\n", szModule, uInstance, "phys"));
- ksAdapter = kstat_lookup(mKC, szModule, uInstance, "phys");
+ ksAdapter = kstat_lookup(mKC, szModule, uInstance, (char *)"phys");
if (ksAdapter == 0)
{
LogFlowThisFunc(("m=%s i=%u n=%s\n", szModule, uInstance, name));
- ksAdapter = kstat_lookup(mKC, szModule, uInstance, name);
+ ksAdapter = kstat_lookup(mKC, szModule, uInstance, (char *)name);
if (ksAdapter == 0)
{
LogRel(("Failed to get network statistics for %s\n", name));
@@ -313,24 +408,311 @@ int CollectorSolaris::getRawHostNetworkLoad(const char *name, uint64_t *rx, uint
return VERR_INTERNAL_ERROR;
}
kstat_named_t *kn;
- if ((kn = (kstat_named_t *)kstat_data_lookup(ksAdapter, (char *)"rbytes")) == 0)
+ if ((kn = (kstat_named_t *)kstat_data_lookup(ksAdapter, (char *)"rbytes64")) == 0)
{
- LogRel(("kstat_data_lookup(rbytes) -> %d, name=%s\n", errno, name));
- return VERR_INTERNAL_ERROR;
+ if (g_fNotReported)
+ {
+ g_fNotReported = false;
+ LogRel(("Failed to locate rbytes64, falling back to 32-bit counters...\n"));
+ }
+ if ((kn = (kstat_named_t *)kstat_data_lookup(ksAdapter, (char *)"rbytes")) == 0)
+ {
+ LogRel(("kstat_data_lookup(rbytes) -> %d, name=%s\n", errno, name));
+ return VERR_INTERNAL_ERROR;
+ }
+ *rx = wrapCorrection(kn->value.ul, *rx, "rbytes");
}
- *rx = kn->value.ul;
- if ((kn = (kstat_named_t *)kstat_data_lookup(ksAdapter, (char *)"obytes")) == 0)
+ else
+ *rx = wrapDetection(kn->value.ull, *rx, "rbytes64");
+ if ((kn = (kstat_named_t *)kstat_data_lookup(ksAdapter, (char *)"obytes64")) == 0)
{
- LogRel(("kstat_data_lookup(obytes) -> %d\n", errno));
- return VERR_INTERNAL_ERROR;
+ if (g_fNotReported)
+ {
+ g_fNotReported = false;
+ LogRel(("Failed to locate obytes64, falling back to 32-bit counters...\n"));
+ }
+ if ((kn = (kstat_named_t *)kstat_data_lookup(ksAdapter, (char *)"obytes")) == 0)
+ {
+ LogRel(("kstat_data_lookup(obytes) -> %d\n", errno));
+ return VERR_INTERNAL_ERROR;
+ }
+ *tx = wrapCorrection(kn->value.ul, *tx, "obytes");
+ }
+ else
+ *tx = wrapDetection(kn->value.ull, *tx, "obytes64");
+ return VINF_SUCCESS;
+}
+
+int CollectorSolaris::getRawHostDiskLoad(const char *name, uint64_t *disk_ms, uint64_t *total_ms)
+{
+ int rc = VINF_SUCCESS;
+ AssertReturn(strlen(name) < KSTAT_STRLEN, VERR_INVALID_PARAMETER);
+ LogFlowThisFunc(("n=%s\n", name));
+ kstat_t *ksDisk = kstat_lookup(mKC, NULL, -1, (char *)name);
+ if (ksDisk != 0)
+ {
+ if (kstat_read(mKC, ksDisk, 0) == -1)
+ {
+ LogRel(("kstat_read(%s) -> %d\n", name, errno));
+ rc = VERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ kstat_io_t *ksIo = KSTAT_IO_PTR(ksDisk);
+ /*
+ * We do not care for wrap possibility here, although we may
+ * reconsider in about 300 years (9223372036854775807 ns).
+ */
+ *disk_ms = ksIo->rtime / 1000000;
+ *total_ms = ksDisk->ks_snaptime / 1000000;
+ }
}
- *tx = kn->value.ul;
+ else
+ {
+ LogRel(("kstat_lookup(%s) -> %d\n", name, errno));
+ rc = VERR_INTERNAL_ERROR;
+ }
+
+ return rc;
+}
+
+uint64_t CollectorSolaris::getZfsTotal(uint64_t cbTotal, const char *szFsType, const char *szFsName)
+{
+ if (strcmp(szFsType, "zfs"))
+ return cbTotal;
+ FsMap::iterator it = mFsMap.find(szFsName);
+ if (it == mFsMap.end())
+ return cbTotal;
+
+ char *pszDataset = strdup(it->second.c_str());
+ char *pszEnd = pszDataset + strlen(pszDataset);
+ uint64_t uAvail = 0;
+ while (pszEnd)
+ {
+ zfs_handle_t *hDataset;
+
+ *pszEnd = 0;
+ hDataset = mZfsOpen(mZfsLib, pszDataset, ZFS_TYPE_DATASET);
+ if (!hDataset)
+ break;
+
+ if (uAvail == 0)
+ {
+ uAvail = mZfsPropGetInt(hDataset, ZFS_PROP_REFQUOTA);
+ if (uAvail == 0)
+ uAvail = UINT64_MAX;
+ }
+
+ uint64_t uQuota = mZfsPropGetInt(hDataset, ZFS_PROP_QUOTA);
+ if (uQuota && uAvail > uQuota)
+ uAvail = uQuota;
+
+ pszEnd = strrchr(pszDataset, '/');
+ if (!pszEnd)
+ {
+ uint64_t uPoolSize = mZfsPropGetInt(hDataset, ZFS_PROP_USED) +
+ mZfsPropGetInt(hDataset, ZFS_PROP_AVAILABLE);
+ if (uAvail > uPoolSize)
+ uAvail = uPoolSize;
+ }
+ mZfsClose(hDataset);
+ }
+ free(pszDataset);
+
+ return uAvail ? uAvail : cbTotal;
+}
+
+int CollectorSolaris::getHostFilesystemUsage(const char *path, ULONG *total, ULONG *used, ULONG *available)
+{
+ struct statvfs64 stats;
+
+ if (statvfs64(path, &stats) == -1)
+ {
+ LogRel(("Failed to collect %s filesystem usage: errno=%d.\n", path, errno));
+ return VERR_ACCESS_DENIED;
+ }
+ uint64_t cbBlock = stats.f_frsize ? stats.f_frsize : stats.f_bsize;
+ *total = (ULONG)(getZfsTotal(cbBlock * stats.f_blocks, stats.f_basetype, path) / _1M);
+ LogFlowThisFunc(("f_blocks=%llu.\n", stats.f_blocks));
+ *used = (ULONG)(cbBlock * (stats.f_blocks - stats.f_bfree) / _1M);
+ *available = (ULONG)(cbBlock * stats.f_bavail / _1M);
+
return VINF_SUCCESS;
}
-int getDiskListByFs(const char *name, DiskList& list)
+int CollectorSolaris::getHostDiskSize(const char *name, uint64_t *size)
{
- return VERR_NOT_IMPLEMENTED;
+ int rc = VINF_SUCCESS;
+ AssertReturn(strlen(name) + 5 < KSTAT_STRLEN, VERR_INVALID_PARAMETER);
+ LogFlowThisFunc(("n=%s\n", name));
+ char szName[KSTAT_STRLEN];
+ strcpy(szName, name);
+ strcat(szName, ",err");
+ kstat_t *ksDisk = kstat_lookup(mKC, NULL, -1, szName);
+ if (ksDisk != 0)
+ {
+ if (kstat_read(mKC, ksDisk, 0) == -1)
+ {
+ LogRel(("kstat_read(%s) -> %d\n", name, errno));
+ rc = VERR_INTERNAL_ERROR;
+ }
+ else
+ {
+ kstat_named_t *kn;
+ if ((kn = (kstat_named_t *)kstat_data_lookup(ksDisk, (char *)"Size")) == 0)
+ {
+ LogRel(("kstat_data_lookup(rbytes) -> %d, name=%s\n", errno, name));
+ return VERR_INTERNAL_ERROR;
+ }
+ *size = kn->value.ull;
+ }
+ }
+ else
+ {
+ LogRel(("kstat_lookup(%s) -> %d\n", szName, errno));
+ rc = VERR_INTERNAL_ERROR;
+ }
+
+
+ return rc;
+}
+
+RTCString CollectorSolaris::physToInstName(const char *pcszPhysName)
+{
+ FILE *fp = fopen("/etc/path_to_inst", "r");
+ if (!fp)
+ return RTCString();
+
+ RTCString strInstName;
+ size_t cbName = strlen(pcszPhysName);
+ char szBuf[RTPATH_MAX];
+ while (fgets(szBuf, sizeof(szBuf), fp))
+ {
+ if (szBuf[0] == '"' && strncmp(szBuf + 1, pcszPhysName, cbName) == 0)
+ {
+ char *pszDriver, *pszInstance;
+ pszDriver = strrchr(szBuf, '"');
+ if (pszDriver)
+ {
+ *pszDriver = '\0';
+ pszDriver = strrchr(szBuf, '"');
+ if (pszDriver)
+ {
+ *pszDriver++ = '\0';
+ pszInstance = strrchr(szBuf, ' ');
+ if (pszInstance)
+ {
+ *pszInstance = '\0';
+ pszInstance = strrchr(szBuf, ' ');
+ if (pszInstance)
+ {
+ *pszInstance++ = '\0';
+ strInstName = pszDriver;
+ strInstName += pszInstance;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ fclose(fp);
+
+ return strInstName;
+}
+
+RTCString CollectorSolaris::pathToInstName(const char *pcszDevPathName)
+{
+ char szLink[RTPATH_MAX];
+ if (readlink(pcszDevPathName, szLink, sizeof(szLink)) != -1)
+ {
+ char *pszStart, *pszEnd;
+ pszStart = strstr(szLink, "/devices/");
+ pszEnd = strrchr(szLink, ':');
+ if (pszStart && pszEnd)
+ {
+ pszStart += 8; // Skip "/devices"
+ *pszEnd = '\0'; // Trim partition
+ return physToInstName(pszStart);
+ }
+ }
+
+ return RTCString(pcszDevPathName);
+}
+
+int CollectorSolaris::getDiskListByFs(const char *name, DiskList& listUsage, DiskList& listLoad)
+{
+ FsMap::iterator it = mFsMap.find(name);
+ if (it == mFsMap.end())
+ return VERR_INVALID_PARAMETER;
+
+ RTCString strName = it->second.substr(0, it->second.find("/"));
+ if (mZpoolOpen && mZpoolClose && mZpoolGetConfig && !strName.isEmpty())
+ {
+ zpool_handle_t *zh = mZpoolOpen(mZfsLib, strName.c_str());
+ if (zh)
+ {
+ unsigned int cChildren = 0;
+ nvlist_t **nvChildren = NULL;
+ nvlist_t *nvRoot = NULL;
+ nvlist_t *nvConfig = mZpoolGetConfig(zh, NULL);
+ if ( !nvlist_lookup_nvlist(nvConfig, ZPOOL_CONFIG_VDEV_TREE, &nvRoot)
+ && !nvlist_lookup_nvlist_array(nvRoot, ZPOOL_CONFIG_CHILDREN, &nvChildren, &cChildren))
+ {
+ for (unsigned int i = 0; i < cChildren; ++i)
+ {
+ uint64_t fHole = 0;
+ uint64_t fLog = 0;
+
+ nvlist_lookup_uint64(nvChildren[i], ZPOOL_CONFIG_IS_HOLE, &fHole);
+ nvlist_lookup_uint64(nvChildren[i], ZPOOL_CONFIG_IS_LOG, &fLog);
+
+ if (!fHole && !fLog)
+ {
+ char *pszChildName = mZpoolVdevName(mZfsLib, zh, nvChildren[i], _B_FALSE);
+ Assert(pszChildName);
+ RTCString strDevPath("/dev/dsk/");
+ strDevPath += pszChildName;
+ char szLink[RTPATH_MAX];
+ if (readlink(strDevPath.c_str(), szLink, sizeof(szLink)) != -1)
+ {
+ char *pszStart, *pszEnd;
+ pszStart = strstr(szLink, "/devices/");
+ pszEnd = strrchr(szLink, ':');
+ if (pszStart && pszEnd)
+ {
+ pszStart += 8; // Skip "/devices"
+ *pszEnd = '\0'; // Trim partition
+ listUsage.push_back(physToInstName(pszStart));
+ }
+ }
+ free(pszChildName);
+ }
+ }
+ }
+ mZpoolClose(zh);
+ }
+ }
+ else
+ listUsage.push_back(pathToInstName(it->second.c_str()));
+ listLoad = listUsage;
+ return VINF_SUCCESS;
+}
+
+void CollectorSolaris::updateFilesystemMap(void)
+{
+ FILE *fp = fopen("/etc/mnttab", "r");
+ if (fp)
+ {
+ struct mnttab Entry;
+ int rc = 0;
+ resetmnttab(fp);
+ while ((rc = getmntent(fp, &Entry)) == 0)
+ mFsMap[Entry.mnt_mountp] = Entry.mnt_special;
+ fclose(fp);
+ if (rc != -1)
+ LogRel(("Error while reading mnttab: %d\n", rc));
+ }
}
}
diff --git a/src/VBox/Main/src-server/solaris/USBProxyServiceSolaris.cpp b/src/VBox/Main/src-server/solaris/USBProxyServiceSolaris.cpp
index 8261d990..0d6d85e8 100644
--- a/src/VBox/Main/src-server/solaris/USBProxyServiceSolaris.cpp
+++ b/src/VBox/Main/src-server/solaris/USBProxyServiceSolaris.cpp
@@ -173,7 +173,7 @@ static int solarisWalkDeviceNode(di_node_t Node, void *pvArg)
char *pszCompatNames = NULL;
int cCompatNames = di_compatible_names(Node, &pszCompatNames);
for (int i = 0; i < cCompatNames; i++, pszCompatNames += strlen(pszCompatNames) + 1)
- if (!strncmp(pszCompatNames, "usb", 3))
+ if (!strncmp(pszCompatNames, RT_STR_TUPLE("usb")))
{
fUSBDevice = true;
break;
@@ -304,7 +304,7 @@ static int solarisWalkDeviceNode(di_node_t Node, void *pvArg)
pList->pTail = pList->pHead = pCur;
rc = DI_WALK_CONTINUE;
- } while(0);
+ } while (0);
di_devfs_path_free(pszDevicePath);
if (!fValidDevice)
@@ -322,7 +322,7 @@ static USBDEVICESTATE solarisDetermineUSBDeviceState(PUSBDEVICE pDevice, di_node
if (!pszDriverName)
return USBDEVICESTATE_UNUSED;
- if (!strncmp(pszDriverName, VBOXUSB_DRIVER_NAME, sizeof(VBOXUSB_DRIVER_NAME) - 1))
+ if (!strncmp(pszDriverName, RT_STR_TUPLE(VBOXUSB_DRIVER_NAME)))
return USBDEVICESTATE_HELD_BY_PROXY;
NOREF(pDevice);