- gkrellm.h. Bump maximum line-/item-length for config to 512 (needed for long disk names on Darwin).

- src/disk.c, server/monitor.c: Add gkrellm_disk_add_by_name() that allows creating disks with a custom label from sysdep code.
- src/Makefile, server/Makefile: Cleanup of darwin/darwin9/macosx targets. All custom variables are now set in src/Makefile and server/Makefile to allow easy building inside these subdirs. Removed very old link-flags which were used before OS X 10.3.
- All Makefiles: Remove unused GTK_CONFIG definitions, they were neither passed as an argument nor executed anywhere.
- Makefile: Update comments documenting Darwin and OS X targets (darwin, darwin9 and macosx)
- src/sysdeps/darwin.c: Use utmpx instead of deprecated utmp.
- src/sysdeps/darwin.c: Fix possible leak in gkrellm_sys_cpu_init(), pinfo was never free'd.
- src/sysdeps/darwin.c: Rewrite disk device enumeration and performance gathering. The previous implementation failed as soon as a single device contained no medium, resulting in no/wrong performance data for all subsequent devices. Also provides labels for krells based on real device-names (uses new gkrellm_disk_add_by_name()).
This commit is contained in:
Stefan Gehn 2010-09-23 15:31:24 +00:00
parent d36c3ec662
commit c67cf611a6
9 changed files with 334 additions and 198 deletions

View File

@ -11,8 +11,12 @@
# make netbsd2 # make netbsd2
# For OpenBSD # For OpenBSD
# make openbsd # make openbsd
# For Darwin / Mac OS X # For Darwin < 9.0 / Mac OS X < 10.4
# make darwin # make darwin
# For newer Darwin systems
# make darwin9
# For Mac OS X with Quartz-based Gtk+ (experimental)
# make macosx
# For Solaris 2.x (8 tested so far): # For Solaris 2.x (8 tested so far):
# make solaris # make solaris
# For libgtop if you have version 1.1.x installed: # For libgtop if you have version 1.1.x installed:
@ -211,25 +215,13 @@ freebsd3 freebsd4 freebsd5 freebsd: gkrellm.pc
darwin: gkrellm.pc darwin: gkrellm.pc
(cd po && ${MAKE} all) (cd po && ${MAKE} all)
(cd src && ${MAKE} GTK_CONFIG=gtk-config STRIP= HAVE_GETADDRINFO=1 \ (cd src && ${MAKE} darwin)
EXTRAOBJS= SYS_LIBS="-lkvm -framework IOKit" \ (cd server && ${MAKE} darwin)
LINK_FLAGS="-prebind -Wl,-bind_at_load -framework CoreFoundation -lX11" \
gkrellm )
(cd server && ${MAKE} GTK_CONFIG=gtk-config STRIP= HAVE_GETADDRINFO=1 \
EXTRAOBJS= SYS_LIBS="-lkvm -framework IOKit" \
LINK_FLAGS="-prebind -Wl,-bind_at_load -framework CoreFoundation" \
gkrellmd )
darwin9: gkrellm.pc darwin9: gkrellm.pc
(cd po && ${MAKE} all) (cd po && ${MAKE} all)
(cd src && ${MAKE} GTK_CONFIG=gtk-config STRIP= HAVE_GETADDRINFO=1 \ (cd src && ${MAKE} darwin9)
EXTRAOBJS= SYS_LIBS="-framework IOKit" \ (cd server && ${MAKE} darwin9)
LINK_FLAGS="-prebind -Wl,-bind_at_load -framework CoreFoundation -lX11" \
gkrellm )
(cd server && ${MAKE} GTK_CONFIG=gtk-config STRIP= HAVE_GETADDRINFO=1 \
EXTRAOBJS= SYS_LIBS="-framework IOKit" \
LINK_FLAGS="-prebind -Wl,-bind_at_load -framework CoreFoundation" \
gkrellmd )
macosx: gkrellm.pc macosx: gkrellm.pc
(cd po && ${MAKE} all) (cd po && ${MAKE} all)

View File

@ -124,29 +124,30 @@ static: $(OBJS) $(EXTRAOBJS)
$(LDFLAGS) $(LIBS) $(LINK_FLAGS) $(LDFLAGS) $(LIBS) $(LINK_FLAGS)
freebsd2: freebsd2:
$(MAKE) GTK_CONFIG=gtk12-config \ $(MAKE) EXTRAOBJS= SYS_LIBS="-lkvm -lmd" gkrellmd
EXTRAOBJS= SYS_LIBS="-lkvm -lmd" gkrellmd
freebsd3 freebsd: freebsd3 freebsd:
$(MAKE) GTK_CONFIG=gtk12-config \ $(MAKE) EXTRAOBJS= SYS_LIBS="-lkvm -ldevstat -lmd" gkrellmd
EXTRAOBJS= SYS_LIBS="-lkvm -ldevstat -lmd" gkrellmd
# Darwin target for systems that still have libkvm
darwin: darwin:
$(MAKE) GTK_CONFIG=gtk-config STRIP= \
EXTRAOBJS= SYS_LIBS="-lkvm -lmd5" \
LINK_FLAGS="-flat_namespace -undefined warning" gkrellmd
darwin9:
$(MAKE) GTK_CONFIG=gtk-config STRIP= \
EXTRAOBJS= SYS_LIBS="-lmd5" \
LINK_FLAGS="-flat_namespace -undefined warning" gkrellmd
macosx:
$(MAKE) STRIP= HAVE_GETADDRINFO=1 \ $(MAKE) STRIP= HAVE_GETADDRINFO=1 \
EXTRAOBJS= SYS_LIBS="-lkvm" \ EXTRAOBJS= \
LINK_FLAGS="-flat_namespace -undefined warning" \ SYS_LIBS="-framework CoreFoundation -framework IOKit -lkvm" \
LINK_FLAGS="-Wl,-bind_at_load" \
gkrellmd gkrellmd
# Darwin 9.x and newer (OS X > 10.4) do not have libkvm, build without it
darwin9:
$(MAKE) STRIP= HAVE_GETADDRINFO=1 \
EXTRAOBJS= \
SYS_LIBS="-framework CoreFoundation -framework IOKit" \
LINK_FLAGS="-Wl,-bind_at_load" \
gkrellmd
# Same as darwin9
macosx: darwin9
netbsd1: netbsd1:
$(MAKE) EXTRAOBJS= SYS_LIBS="-lkvm" gkrellmd $(MAKE) EXTRAOBJS= SYS_LIBS="-lkvm" gkrellmd

View File

@ -435,6 +435,19 @@ gkrellm_disk_units_are_blocks(void)
units_are_blocks = TRUE; units_are_blocks = TRUE;
} }
void
gkrellm_disk_add_by_name(const gchar *name, const gchar *label)
{
gint order = -1;
if (NULL == name) // Cannot add disk without a name
return;
order = gkrellm_sys_disk_order_from_name(name);
/* FIXME: gkrellmd currently has no support for disk labels. Extend
network-protocol and server to support disks with both name and label. */
add_disk(name, order, 0, 0);
}
void void
gkrellm_disk_assign_data_by_device(gint device_number, gint unit_number, gkrellm_disk_assign_data_by_device(gint device_number, gint unit_number,
guint64 rb, guint64 wb, gboolean virtual) guint64 rb, guint64 wb, gboolean virtual)

View File

@ -138,33 +138,36 @@ else
$(MAKE) EXTRAOBJS= SYS_LIBS="-lkvm -ldevstat -lmd" gkrellm $(MAKE) EXTRAOBJS= SYS_LIBS="-lkvm -ldevstat -lmd" gkrellm
endif endif
# Darwin target for systems that still have libkvm
darwin: darwin:
ifeq ($(HAVE_SSL),1) ifeq ($(HAVE_SSL),1)
$(MAKE) GTK_CONFIG=gtk-config STRIP= \ $(MAKE) STRIP= HAVE_GETADDRINFO=1 \
EXTRAOBJS= SYS_LIBS="-lkvm" \ EXTRAOBJS= \
SYS_LIBS="-framework CoreFoundation -framework IOKit -lkvm" \
LINK_FLAGS="-Wl,-bind_at_load" \
gkrellm gkrellm
else else
$(MAKE) GTK_CONFIG=gtk-config STRIP= \ $(MAKE) STRIP= HAVE_GETADDRINFO=1 \
EXTRAOBJS= SYS_LIBS="-lkvm -lmd5" \ EXTRAOBJS= \
SYS_LIBS="-framework CoreFoundation -framework IOKit -lkvm -lmd5" \
LINK_FLAGS="-Wl,-bind_at_load" \
gkrellm gkrellm
endif endif
# Mac OS X target with X11-based Gtk+
darwin9: darwin9:
ifeq ($(HAVE_SSL),1) $(MAKE) STRIP= HAVE_GETADDRINFO=1 \
$(MAKE) GTK_CONFIG=gtk-config STRIP= \ EXTRAOBJS= \
EXTRAOBJS= SYS_LIBS="" \ SYS_LIBS="-framework CoreFoundation -framework IOKit" \
LINK_FLAGS="-Wl,-bind_at_load" \
gkrellm gkrellm
else
$(MAKE) GTK_CONFIG=gtk-config STRIP= \
EXTRAOBJS= SYS_LIBS="-lmd5" \
gkrellm
endif
# Mac OS X target with Quartz-based Gtk+ (experimental)
macosx: macosx:
$(MAKE) STRIP= HAVE_GETADDRINFO=1 \ $(MAKE) STRIP= HAVE_GETADDRINFO=1 \
EXTRAOBJS="winops-gtk-mac.o" \ EXTRAOBJS="winops-gtk-mac.o" \
LINK_FLAGS="-Wl,-bind_at_load -framework CoreFoundation" \ SYS_LIBS="-framework CoreFoundation -framework IOKit" \
SYS_LIBS="-lkvm -framework IOKit" \ LINK_FLAGS="-Wl,-bind_at_load" \
X11_LIBS="" \ X11_LIBS="" \
UNIXOBJS="" \ UNIXOBJS="" \
gkrellm gkrellm
@ -179,7 +182,7 @@ netbsd2:
gkrellm gkrellm
openbsd: openbsd:
$(MAKE) GTK_CONFIG=gtk-config GTOP_LIBS= SYS_LIBS="-lkvm -pthread" gkrellm $(MAKE) GTOP_LIBS= SYS_LIBS="-lkvm -pthread" gkrellm
solaris: solaris:
$(MAKE) CFLAGS="-Wno-implicit-int" \ $(MAKE) CFLAGS="-Wno-implicit-int" \

View File

@ -308,6 +308,7 @@ client_disk_line_from_server(gchar *line)
gint n; gint n;
gboolean virtual = FALSE; gboolean virtual = FALSE;
// FIXME: Extend client and server to support disks with both name and label
n = sscanf(line, "%15s %31s %31s %31s", name, s1, s2, s3); n = sscanf(line, "%15s %31s %31s %31s", name, s1, s2, s3);
if (n == 4) if (n == 4)
{ {

View File

@ -124,7 +124,7 @@ lookup_disk_by_device(gint major, gint minor)
} }
static DiskMon * static DiskMon *
lookup_disk_by_name(gchar *name) lookup_disk_by_name(const gchar *name)
{ {
DiskMon *disk; DiskMon *disk;
GList *list; GList *list;
@ -146,7 +146,7 @@ lookup_disk_by_name(gchar *name)
} }
static DiskMon * static DiskMon *
disk_new(gchar *name, gchar *label) disk_new(const gchar *name, const gchar *label)
{ {
DiskMon *disk; DiskMon *disk;
@ -161,7 +161,7 @@ disk_new(gchar *name, gchar *label)
} }
static DiskMon * static DiskMon *
add_disk(gchar *name, gchar *label, gint major, gint minor, gint order) add_disk(const gchar *name, const gchar *label, gint major, gint minor, gint order)
{ {
DiskMon *disk; DiskMon *disk;
GList *list; GList *list;
@ -190,7 +190,7 @@ add_disk(gchar *name, gchar *label, gint major, gint minor, gint order)
} }
static DiskMon * static DiskMon *
add_subdisk(gchar *subdisk_name, gchar *disk_name, gint subdisk) add_subdisk(const gchar *subdisk_name, const gchar *disk_name, gint subdisk)
{ {
DiskMon *disk, *sdisk; DiskMon *disk, *sdisk;
GList *list = NULL; GList *list = NULL;
@ -275,6 +275,22 @@ gkrellm_disk_units_are_blocks(void)
units_are_blocks = TRUE; units_are_blocks = TRUE;
} }
void
gkrellm_disk_add_by_name(const gchar *name, const gchar *label)
{
gint order = -1;
assign_method = DISK_ASSIGN_BY_NAME;
if (NULL == name) // Cannot add disk without a name
return;
if (order_from_name) // get optional order from sysdep-code
order = (*order_from_name)(name);
if (NULL != label) // label is optional and might be NULL
add_disk(name, label, 0, 0, order);
else
add_disk(name, name, 0, 0, order);
}
void void
gkrellm_disk_assign_data_by_device(gint device_number, gint unit_number, gkrellm_disk_assign_data_by_device(gint device_number, gint unit_number,
guint64 rb, guint64 wb, gboolean virtual) guint64 rb, guint64 wb, gboolean virtual)
@ -957,7 +973,7 @@ load_disk_config(gchar *arg)
{ {
DiskMon *disk = NULL; DiskMon *disk = NULL;
gchar config[32], item[CFG_BUFSIZE], gchar config[32], item[CFG_BUFSIZE],
name[32], item1[CFG_BUFSIZE]; name[CFG_BUFSIZE], item1[CFG_BUFSIZE];
gint major, minor, enabled, extra, order, subdisk = -1; gint major, minor, enabled, extra, order, subdisk = -1;
gint n; gint n;
gboolean enabled_subdisks = TRUE; gboolean enabled_subdisks = TRUE;
@ -971,7 +987,7 @@ load_disk_config(gchar *arg)
gkrellm_locale_dup_string(&text_format, item, &text_format_locale); gkrellm_locale_dup_string(&text_format, item, &text_format_locale);
else if (!strcmp(config, "assign_method")) else if (!strcmp(config, "assign_method"))
sscanf(item, "%d", &config_assign_method); sscanf(item, "%d", &config_assign_method);
else if (sscanf(item, "%31s %[^\n]", name, item1) == 2) else if (sscanf(item, "%s %[^\n]", name, item1) == 2)
disk = lookup_disk_by_name(name); disk = lookup_disk_by_name(name);
if (!strcmp(config, "device")) if (!strcmp(config, "device"))

View File

@ -162,6 +162,7 @@ gint gkrellm_sys_disk_order_from_name(gchar *name);
void gkrellm_disk_client_divert(void (*read_func)(), void gkrellm_disk_client_divert(void (*read_func)(),
gchar *(*name_from_device_func)(), gint (*order_from_name_func)()); gchar *(*name_from_device_func)(), gint (*order_from_name_func)());
void gkrellm_disk_add_by_name(const gchar *name, const gchar *label);
void gkrellm_disk_assign_data_by_device(gint device_number, void gkrellm_disk_assign_data_by_device(gint device_number,
gint unit_number, guint64 r, guint64 w, gboolean virtual); gint unit_number, guint64 r, guint64 w, gboolean virtual);
void gkrellm_disk_assign_data_nth(gint n, guint64 r, guint64 w, void gkrellm_disk_assign_data_nth(gint n, guint64 r, guint64 w,

View File

@ -155,7 +155,7 @@
#define ON 1 #define ON 1
#define OFF 0 #define OFF 0
#define CFG_BUFSIZE 384 #define CFG_BUFSIZE 512
/* Features /* Features

View File

@ -46,6 +46,9 @@ kvm_t *kvmd = NULL;
char errbuf[_POSIX2_LINE_MAX]; char errbuf[_POSIX2_LINE_MAX];
#endif #endif
static void gkrellm_sys_disk_cleanup(void);
void void
gkrellm_sys_main_init(void) gkrellm_sys_main_init(void)
{ {
@ -65,6 +68,7 @@ gkrellm_sys_main_init(void)
void void
gkrellm_sys_main_cleanup(void) gkrellm_sys_main_cleanup(void)
{ {
gkrellm_sys_disk_cleanup();
} }
/* ===================================================================== */ /* ===================================================================== */
@ -77,13 +81,13 @@ gkrellm_sys_cpu_read_data(void)
{ {
processor_cpu_load_info_data_t *pinfo; processor_cpu_load_info_data_t *pinfo;
mach_msg_type_number_t info_count; mach_msg_type_number_t info_count;
int i = 0; int i;
if (host_processor_info (mach_host_self (), if (host_processor_info (mach_host_self (),
PROCESSOR_CPU_LOAD_INFO, PROCESSOR_CPU_LOAD_INFO,
&n_cpus, &n_cpus,
(processor_info_array_t*)&pinfo, (processor_info_array_t*)&pinfo,
&info_count)) { &info_count) != KERN_SUCCESS) {
return; return;
} }
@ -109,9 +113,10 @@ gkrellm_sys_cpu_init(void)
PROCESSOR_CPU_LOAD_INFO, PROCESSOR_CPU_LOAD_INFO,
&n_cpus, &n_cpus,
(processor_info_array_t*)&pinfo, (processor_info_array_t*)&pinfo,
&info_count)) { &info_count) != KERN_SUCCESS) {
return FALSE; return FALSE;
} }
vm_deallocate (mach_task_self (), (vm_address_t) pinfo, info_count);
gkrellm_cpu_set_number_of_cpus(n_cpus); gkrellm_cpu_set_number_of_cpus(n_cpus);
return TRUE; return TRUE;
} }
@ -122,14 +127,14 @@ gkrellm_sys_cpu_init(void)
#include <sys/sysctl.h> #include <sys/sysctl.h>
#include <sys/user.h> #include <sys/user.h>
#define PID_MAX 30000
#ifdef HAVE_KVM_H #ifdef HAVE_KVM_H
#define PID_MAX 30000
#include <kvm.h> #include <kvm.h>
#endif #endif
#include <limits.h> #include <limits.h>
#include <paths.h> #include <paths.h>
#include <utmp.h> #include <utmpx.h>
static int oid_v_forks[CTL_MAXNAME + 2]; static int oid_v_forks[CTL_MAXNAME + 2];
static int oid_v_vforks[CTL_MAXNAME + 2]; static int oid_v_vforks[CTL_MAXNAME + 2];
@ -169,7 +174,10 @@ gkrellm_sys_proc_read_data(void)
{ {
static int oid_proc[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; static int oid_proc[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
double avenrun; double avenrun;
static u_int n_processes, n_forks = 0, curpid = -1; static u_int n_processes, n_forks = 0;
#ifdef HAVE_KVM_H
static u_int curpid = -1;
#endif
u_int n_vforks, n_rforks; u_int n_vforks, n_rforks;
gint r_forks, r_vforks, r_rforks; gint r_forks, r_vforks, r_rforks;
size_t len; size_t len;
@ -235,33 +243,29 @@ gkrellm_sys_proc_read_data(void)
void void
gkrellm_sys_proc_read_users(void) gkrellm_sys_proc_read_users(void)
{ {
gint n_users; struct utmpx *utmpx_entry;
struct stat sb, s; gchar ttybuf[MAXPATHLEN];
gchar ttybuf[MAXPATHLEN]; struct stat sb;
FILE *ut; gint n_users;
struct utmp utmp;
static time_t utmp_mtime;
if (stat(_PATH_UTMP, &s) != 0 || s.st_mtime == utmp_mtime) n_users = 0;
return; setutxent();
if ((ut = fopen(_PATH_UTMP, "r")) != NULL) while((utmpx_entry = getutxent()))
{ {
n_users = 0; if (utmpx_entry->ut_type != USER_PROCESS)
while (fread(&utmp, sizeof(utmp), 1, ut)) continue; // skip other entries (reboot, runlevel changes etc.)
{
if (utmp.ut_name[0] == '\0') (void)snprintf(ttybuf, sizeof(ttybuf), "%s/%s",
continue; _PATH_DEV, utmpx_entry->ut_line);
(void)snprintf(ttybuf, sizeof(ttybuf), "%s/%s",
_PATH_DEV, utmp.ut_line); if (stat(ttybuf, &sb))
/* corrupted record */ continue; // tty of entry missing, no real user
if (stat(ttybuf, &sb))
continue; ++n_users;
++n_users;
} }
(void)fclose(ut); endutxent();
gkrellm_proc_assign_users(n_users); gkrellm_proc_assign_users(n_users);
}
utmp_mtime = s.st_mtime;
} }
@ -270,11 +274,129 @@ gkrellm_sys_proc_read_users(void)
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h> #include <IOKit/IOKitLib.h>
#include <IOKit/storage/IOBlockStorageDevice.h>
#include <IOKit/storage/IOBlockStorageDriver.h> #include <IOKit/storage/IOBlockStorageDriver.h>
io_iterator_t drivelist = 0; /* needs release */ #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
mach_port_t masterPort = 0;
typedef struct _GK_DISK
{
io_service_t service;
io_string_t path;
} GK_DARWIN_DISK;
static GPtrArray *s_disk_ptr_array = NULL;
static GK_DARWIN_DISK *
gk_darwin_disk_new()
{
return g_new0(GK_DARWIN_DISK, 1);
}
static void
gk_darwin_disk_free(GK_DARWIN_DISK *disk)
{
if (disk->service != MACH_PORT_NULL)
IOObjectRelease(disk->service);
g_free(disk);
}
static gboolean
dict_get_int64(CFDictionaryRef dict, CFStringRef key, gint64 *value)
{
CFNumberRef number_ref;
number_ref = (CFNumberRef) CFDictionaryGetValue(dict, key);
if ((NULL == number_ref) ||
!CFNumberGetValue(number_ref, kCFNumberSInt64Type, value))
{
*value = 0;
return FALSE;
}
return TRUE;
}
static gboolean
dict_get_string(CFDictionaryRef dict, CFStringRef key, char *buf, size_t buf_len)
{
CFStringRef string_ref;
string_ref = (CFStringRef)CFDictionaryGetValue(dict, key);
if ((NULL == string_ref) ||
!CFStringGetCString(string_ref, buf, buf_len, kCFStringEncodingUTF8))
{
buf[0] = '\0';
return FALSE;
}
return TRUE;
}
static gboolean
add_storage_device(io_registry_entry_t service)
{
GK_DARWIN_DISK *disk;
CFMutableDictionaryRef chars_dict; /* needs release */
gchar vendor_str[128];
gchar product_str[128];
gchar *disk_label;
gkrellm_debug(DEBUG_SYSDEP, "add_storage_device(); START\n");
disk = gk_darwin_disk_new();
disk->service = service;
if (IORegistryEntryGetPath(service, kIOServicePlane, disk->path)
!= kIOReturnSuccess)
{
g_warning("Could not fetch io registry path for disk\n");
gk_darwin_disk_free(disk);
return FALSE;
}
chars_dict = (CFMutableDictionaryRef)IORegistryEntryCreateCFProperty(
service, CFSTR(kIOPropertyDeviceCharacteristicsKey),
kCFAllocatorDefault, 0);
if (NULL == chars_dict)
{
g_warning("Could not fetch properties for disk\n");
gk_darwin_disk_free(disk);
return FALSE;
}
gkrellm_debug(DEBUG_SYSDEP, "Getting vendor name\n");
dict_get_string(chars_dict, CFSTR(kIOPropertyVendorNameKey),
vendor_str, sizeof(vendor_str));
g_strstrip(vendor_str); // remove leading/trailing whitespace
gkrellm_debug(DEBUG_SYSDEP, "Getting product name\n");
dict_get_string(chars_dict, CFSTR(kIOPropertyProductNameKey),
product_str, sizeof(product_str));
g_strstrip(product_str); // remove leading/trailing whitespace
if (strlen(vendor_str) > 0)
disk_label = g_strdup_printf("%s %s", vendor_str, product_str);
else
disk_label = g_strdup(product_str);
gkrellm_debug(DEBUG_SYSDEP, "Adding disk '%s' with fancy label '%s'\n",
disk->path, disk_label);
// Add disk to internal list
g_ptr_array_add(s_disk_ptr_array, disk);
// Add disk to gkrellm list
gkrellm_disk_add_by_name(disk->path, disk_label);
/* we don't need to store the label, it is only for GUI display */
g_free(disk_label);
CFRelease(chars_dict);
gkrellm_debug(DEBUG_SYSDEP, "add_storage_device(); END\n");
return TRUE;
}
static GList *disk_list; /* list of names */
gchar * gchar *
gkrellm_sys_disk_name_from_device(gint device_number, gint unit_number, gkrellm_sys_disk_name_from_device(gint device_number, gint unit_number,
@ -295,127 +417,116 @@ gkrellm_sys_disk_order_from_name(gchar *name)
void void
gkrellm_sys_disk_read_data(void) gkrellm_sys_disk_read_data(void)
{ {
io_registry_entry_t drive = 0; /* needs release */ int i;
UInt64 totalReadBytes = 0; GK_DARWIN_DISK *disk;
UInt64 totalReadCount = 0;
UInt64 totalWriteBytes = 0;
UInt64 totalWriteCount = 0;
kern_return_t status = 0;
GList *list;
list = disk_list; for (i = 0; i < s_disk_ptr_array->len; i++)
while ( (drive = IOIteratorNext(drivelist)) ) {
{ io_registry_entry_t storage_driver; /* needs release */
CFNumberRef number = 0; /* don't release */ CFDictionaryRef storage_driver_stats; /* needs release */
CFDictionaryRef properties = 0; /* needs release */ gint64 bytes_read;
CFDictionaryRef statistics = 0; /* don't release */ gint64 bytes_written;
UInt64 value = 0;
disk = (GK_DARWIN_DISK *)g_ptr_array_index(s_disk_ptr_array, i);
/* Obtain the properties for this drive object */
//gkrellm_debug(DEBUG_SYSDEP, "Fetching disk stats for '%s'\n", disk->path);
status = IORegistryEntryCreateCFProperties (drive,
(CFMutableDictionaryRef *) &properties, /* get subitem of device, has to be some kind of IOStorageDriver */
kCFAllocatorDefault, if (IORegistryEntryGetChildEntry(disk->service, kIOServicePlane,
kNilOptions); &storage_driver) != kIOReturnSuccess)
if (properties) { {
gkrellm_debug(DEBUG_SYSDEP,
/* Obtain the statistics from the drive properties */ "No driver child found in storage device, skipping disk '%s'\n",
statistics = (CFDictionaryRef) CFDictionaryGetValue(properties, CFSTR(kIOBlockStorageDriverStatisticsKey)); disk->path);
// skip devices that have no driver child
if (statistics) { continue;
/* Obtain the number of bytes read from the drive statistics */
number = (CFNumberRef) CFDictionaryGetValue (statistics,
CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey));
if (number) {
status = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
totalReadBytes += value;
}
/* Obtain the number of reads from the drive statistics */
number = (CFNumberRef) CFDictionaryGetValue (statistics,
CFSTR(kIOBlockStorageDriverStatisticsReadsKey));
if (number) {
status = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
totalReadCount += value;
}
/* Obtain the number of writes from the drive statistics */
number = (CFNumberRef) CFDictionaryGetValue (statistics,
CFSTR(kIOBlockStorageDriverStatisticsWritesKey));
if (number) {
status = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
totalWriteCount += value;
}
/* Obtain the number of bytes written from the drive statistics */
number = (CFNumberRef) CFDictionaryGetValue (statistics,
CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey));
if (number) {
status = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
totalWriteBytes += value;
}
/* Release resources */
CFRelease(properties); properties = 0;
}
} }
IOObjectRelease(drive); drive = 0;
if (list) storage_driver_stats = IORegistryEntryCreateCFProperty(storage_driver,
{ CFSTR(kIOBlockStorageDriverStatisticsKey), kCFAllocatorDefault, 0);
gkrellm_disk_assign_data_by_name((gchar *) list->data,
totalReadCount, totalWriteCount, FALSE); if (NULL == storage_driver_stats)
list = list->next; {
} gkrellm_debug(DEBUG_SYSDEP,
"No statistics dict found in storage driver, skipping disk '%s'\n",
} disk->path);
IOIteratorReset(drivelist); CFRelease(storage_driver_stats);
IOObjectRelease(storage_driver);
continue;
}
/* Obtain the number of bytes read/written from the drive statistics */
if (dict_get_int64(storage_driver_stats,
CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey), &bytes_read)
&&
dict_get_int64(storage_driver_stats,
CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey), &bytes_written)
)
{
gkrellm_disk_assign_data_by_name(disk->path, bytes_read,
bytes_written, FALSE);
}
else
{
gkrellm_debug(DEBUG_SYSDEP,
"could not fetch read/write stats for disk '%s'\n",
disk->path);
}
CFRelease(storage_driver_stats);
IOObjectRelease(storage_driver);
} // for()
} }
gboolean gboolean
gkrellm_sys_disk_init(void) gkrellm_sys_disk_init(void)
{ {
io_registry_entry_t drive = 0; /* needs release */ /* needs release */
io_registry_entry_t child = 0; /* needs release */ io_iterator_t iter = MACH_PORT_NULL;
/* get ports and services for drive stats */
/* Obtain the I/O Kit communication handle */
if (IOMasterPort(MACH_PORT_NULL, &masterPort)) return FALSE;
/* Obtain the list of all drive objects */ /* needs release (if add_storage_device() failed) */
if (IOServiceGetMatchingServices(masterPort, io_service_t service = MACH_PORT_NULL;
IOServiceMatching("IOBlockStorageDriver"),
&drivelist))
return FALSE;
while ( (drive = IOIteratorNext(drivelist)) ) gkrellm_debug(DEBUG_SYSDEP, "gkrellm_sys_disk_init();\n");
{
gchar * name = malloc(128); /* io_name_t is char[128] */
kern_return_t status = 0;
int ptr = 0;
if(!name) return FALSE;
/* Obtain the properties for this drive object */
status = IORegistryEntryGetChildEntry(drive, kIOServicePlane, &child );
if(!status) s_disk_ptr_array = g_ptr_array_new();
status = IORegistryEntryGetName(child, name );
/* Convert spaces to underscores, for prefs safety */ if (IOServiceGetMatchingServices(kIOMasterPortDefault,
if(!status) IOServiceMatching(kIOBlockStorageDeviceClass),
&iter) == kIOReturnSuccess)
{ {
for(ptr = 0; ptr < strlen(name); ptr++) while ((service = IOIteratorNext(iter)) != MACH_PORT_NULL)
{ {
if(name[ptr] == ' ') if (!add_storage_device(service))
name[ptr] = '_'; IOObjectRelease(service);
} }
disk_list = g_list_append(disk_list, name); IOObjectRelease(iter);
} }
IOObjectRelease(drive); drive = 0;
gkrellm_debug(DEBUG_SYSDEP,
"gkrellm_sys_disk_init(); Found %u disk(s) for monitoring.\n",
s_disk_ptr_array->len);
return (s_disk_ptr_array->len == 0 ? FALSE : TRUE);
} }
IOIteratorReset(drivelist);
static void
return (disk_list != NULL) ? TRUE : FALSE; gkrellm_sys_disk_cleanup(void)
{
guint i;
if (NULL == s_disk_ptr_array)
return;
gkrellm_debug(DEBUG_SYSDEP,
"gkrellm_sys_disk_cleanup() Freeing counters for %u disk(s)\n",
s_disk_ptr_array->len);
for (i = 0; i < s_disk_ptr_array->len; i++)
gk_darwin_disk_free(g_ptr_array_index(s_disk_ptr_array, i));
g_ptr_array_free(s_disk_ptr_array, TRUE);
} }
/* ===================================================================== */
/* Inet monitor interface */
#include "../inet.h" #include "../inet.h"
@ -441,8 +552,6 @@ gkrellm_sys_disk_init(void)
#include <netinet/udp_var.h> #include <netinet/udp_var.h>
#include <sys/types.h> #include <sys/types.h>
#define warn(x...) fprintf(stderr,x)
void void
gkrellm_sys_inet_read_tcp_data(void) gkrellm_sys_inet_read_tcp_data(void)
{ {
@ -456,15 +565,15 @@ gkrellm_sys_disk_init(void)
size_t len=0; size_t len=0;
if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
if (errno != ENOENT) if (errno != ENOENT)
warn("sysctl: %s", mibvar); g_warning("sysctl: %s\n", mibvar);
return; return;
} }
if ((buf = malloc(len)) == 0) { if ((buf = malloc(len)) == 0) {
warn("malloc %lu bytes", (u_long)len); g_warning("malloc %lu bytes\n", (u_long)len);
return; return;
} }
if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
warn("sysctl: %s", mibvar); g_warning("sysctl: %s\n", mibvar);
free(buf); free(buf);
return; return;
} }