NetBSD Problem Report #51334

From ef@math.uni-bonn.de  Mon Jul 11 18:10:22 2016
Return-Path: <ef@math.uni-bonn.de>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(Client CN "mail.netbsd.org", Issuer "Postmaster NetBSD.org" (verified OK))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 55BDA7A3DB
	for <gnats-bugs@gnats.NetBSD.org>; Mon, 11 Jul 2016 18:10:22 +0000 (UTC)
Message-Id: <20160711165109.430865EDB@jade.math.uni-bonn.de>
Date: Mon, 11 Jul 2016 18:51:09 +0200 (CEST)
From: ef@math.uni-bonn.de
Reply-To: ef@math.uni-bonn.de
To: gnats-bugs@gnats.NetBSD.org
Subject: collectd disk plugin NetBSD implementation correction
X-Send-Pr-Version: 3.95

>Number:         51334
>Category:       pkg
>Synopsis:       collectd disk plugin NetBSD implementation correction
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    pkg-manager
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Jul 11 18:15:00 +0000 2016
>Closed-Date:    Thu Dec 17 15:57:00 +0000 2020
>Last-Modified:  Thu Dec 17 15:57:00 +0000 2020
>Originator:     Edgar Fuß
>Release:        pkgsrc-2016Q1
>Organization:
	Mathematisches Institut der Universität Bonn
>Environment:

>Description:
	The NetBSD implementation of the collectd disk plugin (sysutils/collectd/patches/patch-src_disk.c) is overly complicated, and mostly wrong. This is probably due to defiencies in the collect documentation.
	For a DERIVE Data source, the plugin simply provides the new value; it's the daemon's business to compute the change rate.
	It doesn't make sense on NetBSD to try to compute disk_time (the average time per read/write op) in a PenguinOS compatible way. There's no data source for separate read and write times spent by the disc.
	However, it's trivial to pass disk_io_time (the disc's busy ratio).
>How-To-Repeat:
	Use collectd's disk plugin on a NetBSD machine. Inspect disk_time.
>Fix:
	Replace patches/patch-src_disk.c with the following (and re-compute patch checksums and bump PKG_REVISION):
	$NetBSD: patch-src_disk.c $

	Provide a port to NetBSD.

	--- src/disk.c.orig	2015-03-10 14:14:45.000000000 +0000
	+++ src/disk.c
	@@ -124,6 +124,35 @@ static int numdisk;
	 static int pnumdisk;
	 /* #endif HAVE_PERFSTAT */

	+#elif HAVE_SYSCTL && KERNEL_NETBSD
	+
	+#include <sys/sysctl.h>
	+#include <sys/iostat.h>
	+
	+typedef struct diskstats {
	+	char *name;
	+
	+	u_int poll_count;
	+
	+	derive_t read_ops;
	+	derive_t write_ops;
	+
	+	derive_t read_bytes;
	+	derive_t write_bytes;
	+
	+	derive_t avg_io_time;
	+
	+	struct io_sysctl stats;
	+
	+	struct diskstats *next;
	+} diskstats_t;
	+
	+static diskstats_t *disklist;
	+static struct io_sysctl *drives = NULL;
	+static size_t ndrive = 0;
	+
	+/* #endif HAVE_SYSCTL && KERNEL_NETBSD */
	+
	 #else
	 # error "No applicable input method."
	 #endif
	@@ -241,7 +270,34 @@ static int disk_init (void)
				continue;
			ksp[numdisk++] = ksp_chain;
		}
	-#endif /* HAVE_LIBKSTAT */
	+/* #endif HAVE_LIBKSTAT */
	+
	+#elif HAVE_SYSCTL && KERNEL_NETBSD
	+	int mib[3];
	+	size_t size;
	+
	+	/* figure out number of drives */
	+	mib[0] = CTL_HW;
	+	mib[1] = HW_IOSTATS;
	+	mib[2] = sizeof(struct io_sysctl);
	+	if (sysctl(mib, 3, NULL, &size, NULL, 0) == -1) {
	+		ERROR ("disk plugin: sysctl for ndrives failed");
	+		return -1;
	+	}
	+	ndrive = size / sizeof(struct io_sysctl);
	+
	+	if (size == 0 ) {
	+		ERROR ("disk plugin: no drives found");
	+		return -1;
	+	}
	+	drives = (struct io_sysctl *)malloc(size);
	+	if (drives == NULL) {
	+		ERROR ("disk plugin: memory allocation failure");
	+		return -1;
	+	}
	+
	+#endif	/* HAVE_SYSCTL && KERNEL_NETBSD */
	+

		return (0);
	 } /* int disk_init */
	@@ -929,7 +985,129 @@ static int disk_read (void)
			write_time *= ((double)(_system_configuration.Xint)/(double)(_system_configuration.Xfrac)) / 1000000.0;
			disk_submit (stat_disk[i].name, "disk_time", read_time, write_time);
		}
	-#endif /* defined(HAVE_PERFSTAT) */
	+/* #endif defined(HAVE_PERFSTAT) */
	+
	+#elif HAVE_SYSCTL && KERNEL_NETBSD
	+	int mib[3];
	+	size_t size, i, nndrive;
	+	diskstats_t *ds, *pre_ds;
	+	char *output_name;
	+
	+	u_int64_t ops;
	+	u_int64_t delta_t;
	+
	+	/* figure out number of drives */
	+	mib[0] = CTL_HW;
	+	mib[1] = HW_IOSTATS;
	+	mib[2] = sizeof(struct io_sysctl);
	+	if (sysctl(mib, 3, NULL, &size, NULL, 0) == -1) {
	+		ERROR ("disk plugin: sysctl for ndrives failed");
	+		return -1;
	+	}
	+	nndrive = size / sizeof(struct io_sysctl);
	+
	+	if (size == 0 ) {
	+		ERROR ("disk plugin: no drives found");
	+		return -1;
	+	}
	+	/* number of drives changed, reallocate buffer */
	+	if (nndrive != ndrive) {
	+		drives = (struct io_sysctl *)realloc(drives, size);
	+		if (drives == NULL) {
	+			ERROR ("disk plugin: memory allocation failure");
	+			return -1;
	+		}
	+		ndrive = nndrive;
	+	}
	+
	+	/* get stats for all drives */
	+	mib[0] = CTL_HW;
	+	mib[1] = HW_IOSTATS;
	+	mib[2] = sizeof(struct io_sysctl);
	+	if (sysctl(mib, 3, drives, &size, NULL, 0) == -1) {
	+		ERROR ("disk plugin: sysctl for drive stats failed");
	+		return -1;
	+	}
	+
	+	for (i = 0; i < ndrive; i++) {
	+
	+		if (drives[i].type != IOSTAT_DISK)
	+			continue;
	+
	+		/* find drive stats, if present */
	+		for (ds = disklist, pre_ds = disklist;
	+		     ds != NULL;
	+		     pre_ds = ds, ds = ds->next) {
	+			if (strcmp (drives[i].name, ds->name) == 0)
	+				break;
	+		}
	+		if (ds == NULL) { /* not found; allocate & link in */
	+			if ((ds = calloc(1, sizeof(diskstats_t))) == NULL)
	+				continue;
	+			if ((ds->name = strdup(drives[i].name)) == NULL) {
	+				free(ds);
	+				continue;
	+			}
	+			if (pre_ds == NULL)
	+				disklist = ds;
	+			else
	+				pre_ds->next = ds;
	+		}
	+
	+		ds->poll_count++;
	+		if (ds->poll_count <= 2)
	+		{
	+			DEBUG ("disk plugin: (ds->poll_count = %i) <= "
	+					"(min_poll_count = 2); => Not writing.",
	+					ds->poll_count);
	+			ds->stats = drives[i]; /* but save base values */
	+			continue;
	+		}
	+		ds->read_ops    = drives[i].rxfer - ds->stats.rxfer;
	+		ds->write_ops   = drives[i].wxfer - ds->stats.wxfer;
	+		ds->read_bytes  = drives[i].rbytes - ds->stats.rbytes;
	+		ds->write_bytes = drives[i].wbytes - ds->stats.wbytes;
	+
	+		/* Need this dance because of unsigned values... */
	+		if (drives[i].time_usec < ds->stats.time_usec) {
	+			delta_t = ((drives[i].time_sec - 1 -
	+				    ds->stats.time_sec) * 1000) +
	+				((drives[i].time_usec + 1000000 -
	+				  ds->stats.time_usec) / 1000);
	+		} else {
	+			delta_t = ((drives[i].time_sec -
	+				    ds->stats.time_sec) * 1000) +
	+				((drives[i].time_usec -
	+				  ds->stats.time_usec) / 1000);
	+		}
	+
	+		ops = ds->read_ops + ds->write_ops;
	+		if (ops == 0) {
	+			DEBUG ("disk plugin: read + write ops == 0, "
	+			       "not writing");
	+			continue;
	+		}
	+		
	+		ds->avg_io_time = delta_t / ops;
	+
	+		output_name = drives[i].name;
	+
	+		if ((ds->read_bytes != 0) || (ds->write_bytes != 0))
	+			disk_submit (output_name, "disk_octets",
	+					ds->read_bytes, ds->write_bytes);
	+
	+		if ((ds->read_ops != 0) || (ds->write_ops != 0))
	+			disk_submit (output_name, "disk_ops",
	+					ds->read_ops, ds->write_ops);
	+
	+		if (ds->avg_io_time != 0)
	+			disk_submit (output_name, "disk_time",
	+					ds->avg_io_time, ds->avg_io_time);
	+		
	+		ds->stats = drives[i];
	+	}
	+
	+#endif /* HAVE_SYSCTL && KERNEL_NETBSD */

		return (0);
	 } /* int disk_read */

>Release-Note:

>Audit-Trail:

Responsible-Changed-From-To: pkg-manager->fhajny
Responsible-Changed-By: wiz@NetBSD.org
Responsible-Changed-When: Mon, 11 Jul 2016 21:46:59 +0000
Responsible-Changed-Why:
Over to maintainer.


From: Edgar =?iso-8859-1?B?RnXf?= <ef@math.uni-bonn.de>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: pkg/51334: collectd disk plugin NetBSD implementation correction
Date: Wed, 25 Oct 2017 19:16:23 +0200

 --bKyqfOwhbdpXa4YI
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline

 Unfortunately, the old, non-functional disk plugin patch has been ported to the new collectd version (mainly formatting changes) instead of the functional one in the PR.
 So here's a functional patch for the new collectd version. I hope I haven't mangled it.

 --bKyqfOwhbdpXa4YI
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename="patch-src_disk.c"

 $NetBSD: patch-src_disk.c,v $

 Provide a working port to NetBSD.

 --- src/disk.c.orig	2017-10-06 19:32:22.000000000 +0200
 +++ src/disk.c	2017-10-09 14:13:56.000000000 +0200
 @@ -135,6 +135,16 @@
  static int pnumdisk;
  /* #endif HAVE_PERFSTAT */

 +#elif HAVE_SYSCTL && KERNEL_NETBSD
 +
 +#include <sys/sysctl.h>
 +#include <sys/iostat.h>
 +
 +static struct io_sysctl *drives = NULL;
 +static size_t ndrive = 0;
 +
 +/* #endif HAVE_SYSCTL && KERNEL_NETBSD */
 +
  #else
  #error "No applicable input method."
  #endif
 @@ -253,7 +263,31 @@
        continue;
      ksp[numdisk++] = ksp_chain;
    }
 -#endif /* HAVE_LIBKSTAT */
 +/* #endif HAVE_LIBKSTAT */
 +#elif HAVE_SYSCTL && KERNEL_NETBSD
 +  int mib[3];
 +  size_t size;
 +
 +  /* figure out number of drives */
 +  mib[0] = CTL_HW;
 +  mib[1] = HW_IOSTATS;
 +  mib[2] = sizeof(struct io_sysctl);
 +  if (sysctl(mib, 3, NULL, &size, NULL, 0) == -1) {
 +    ERROR ("disk plugin: sysctl for ndrives failed");
 +    return -1;
 +  }
 +  ndrive = size / sizeof(struct io_sysctl);
 +
 +  if (size == 0 ) {
 +    ERROR ("disk plugin: no drives found");
 +    return -1;
 +  }
 +  drives = (struct io_sysctl *)malloc(size);
 +  if (drives == NULL) {
 +    ERROR ("disk plugin: memory allocation failure");
 +    return -1;
 +  }
 +#endif /* HAVE_SYSCTL && KERNEL_NETBSD */

    return (0);
  } /* int disk_init */
 @@ -284,7 +318,7 @@
    plugin_dispatch_values(&vl);
  } /* void disk_submit */

 -#if KERNEL_FREEBSD || KERNEL_LINUX
 +#if KERNEL_FREEBSD || (HAVE_SYSCTL && KERNEL_NETBSD) || KERNEL_LINUX
  static void submit_io_time(char const *plugin_instance, derive_t io_time,
                             derive_t weighted_time) {
    value_list_t vl = VALUE_LIST_INIT;
 @@ -300,7 +334,7 @@

    plugin_dispatch_values(&vl);
  } /* void submit_io_time */
 -#endif /* KERNEL_FREEBSD || KERNEL_LINUX */
 +#endif /* KERNEL_FREEBSD || (HAVE_SYSCTL && KERNEL_NETBSD) || KERNEL_LINUX */

  #if KERNEL_LINUX
  static void submit_in_progress(char const *disk_name, gauge_t in_progress) {
 @@ -1018,7 +1052,58 @@
                    1000000.0;
      disk_submit(stat_disk[i].name, "disk_time", read_time, write_time);
    }
 -#endif /* defined(HAVE_PERFSTAT) */
 +/* #endif defined(HAVE_PERFSTAT) */
 +#elif HAVE_SYSCTL && KERNEL_NETBSD
 +  int mib[3];
 +  size_t size, i, nndrive;
 +
 +  /* figure out number of drives */
 +  mib[0] = CTL_HW;
 +  mib[1] = HW_IOSTATS;
 +  mib[2] = sizeof(struct io_sysctl);
 +  if (sysctl(mib, 3, NULL, &size, NULL, 0) == -1) {
 +    ERROR ("disk plugin: sysctl for ndrives failed");
 +    return -1;
 +  }
 +  nndrive = size / sizeof(struct io_sysctl);
 +
 +  if (size == 0 ) {
 +    ERROR ("disk plugin: no drives found");
 +    return -1;
 +  }
 +  /* number of drives changed, reallocate buffer */
 +  if (nndrive != ndrive) {
 +    drives = (struct io_sysctl *)realloc(drives, size);
 +    if (drives == NULL) {
 +      ERROR ("disk plugin: memory allocation failure");
 +      return -1;
 +    }
 +    ndrive = nndrive;
 +  }
 +
 +  /* get stats for all drives */
 +  mib[0] = CTL_HW;
 +  mib[1] = HW_IOSTATS;
 +  mib[2] = sizeof(struct io_sysctl);
 +  if (sysctl(mib, 3, drives, &size, NULL, 0) == -1) {
 +    ERROR ("disk plugin: sysctl for drive stats failed");
 +    return -1;
 +  }
 +
 +  for (i = 0; i < ndrive; i++) {
 +    if (drives[i].type != IOSTAT_DISK)
 +      continue;
 +    if (ignorelist_match(ignorelist, drives[i].name))
 +      continue;
 +
 +    disk_submit(drives[i].name, "disk_octets",
 +                drives[i].rbytes, drives[i].wbytes);
 +    disk_submit(drives[i].name, "disk_ops",
 +                drives[i].rxfer, drives[i].wxfer);
 +    submit_io_time(drives[i].name,
 +                   drives[i].time_sec * 1000 + drives[i].time_usec / 1000, 0);
 +  }
 +#endif /* HAVE_SYSCTL && KERNEL_NETBSD */

    return (0);
  } /* int disk_read */

 --bKyqfOwhbdpXa4YI--

From: Edgar =?iso-8859-1?B?RnXf?= <ef@math.uni-bonn.de>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: pkg/51334 (collectd disk plugin NetBSD implementation correction)
Date: Fri, 7 Sep 2018 10:16:08 +0200

 And once again, the included, dysfunctional disk plugin patch for NetBSD has been ported to a newer version of collectd.
 And once again, I ported my working disk plugin for NetBSD to a newer version of collectd.
 Sigh.

 $NetBSD: patch-src_disk.c,v $

 Provide a working port to NetBSD.

 --- src/disk.c.orig	2018-08-30 15:04:48.000000000 +0200
 +++ src/disk.c	2018-08-30 15:04:49.000000000 +0200
 @@ -135,6 +135,16 @@ static int numdisk;
  static int pnumdisk;
  /* #endif HAVE_PERFSTAT */

 +#elif HAVE_SYSCTL && KERNEL_NETBSD
 +
 +#include <sys/sysctl.h>
 +#include <sys/iostat.h>
 +
 +static struct io_sysctl *drives = NULL;
 +static size_t ndrive = 0;
 +
 +/* #endif HAVE_SYSCTL && KERNEL_NETBSD */
 +
  #else
  #error "No applicable input method."
  #endif
 @@ -253,7 +263,31 @@ static int disk_init(void) {
        continue;
      ksp[numdisk++] = ksp_chain;
    }
 -#endif /* HAVE_LIBKSTAT */
 +/* #endif HAVE_LIBKSTAT */
 +#elif HAVE_SYSCTL && KERNEL_NETBSD
 +  int mib[3];
 +  size_t size;
 +
 +  /* figure out number of drives */
 +  mib[0] = CTL_HW;
 +  mib[1] = HW_IOSTATS;
 +  mib[2] = sizeof(struct io_sysctl);
 +  if (sysctl(mib, 3, NULL, &size, NULL, 0) == -1) {
 +    ERROR ("disk plugin: sysctl for ndrives failed");
 +    return -1;
 +  }
 +  ndrive = size / sizeof(struct io_sysctl);
 +
 +  if (size == 0 ) {
 +    ERROR ("disk plugin: no drives found");
 +    return -1;
 +  }
 +  drives = (struct io_sysctl *)malloc(size);
 +  if (drives == NULL) {
 +    ERROR ("disk plugin: memory allocation failure");
 +    return -1;
 +  }
 +#endif /* HAVE_SYSCTL && KERNEL_NETBSD */

    return 0;
  } /* int disk_init */
 @@ -284,7 +318,7 @@ static void disk_submit(const char *plug
    plugin_dispatch_values(&vl);
  } /* void disk_submit */

 -#if KERNEL_FREEBSD || KERNEL_LINUX
 +#if KERNEL_FREEBSD || (HAVE_SYSCTL && KERNEL_NETBSD) || KERNEL_LINUX
  static void submit_io_time(char const *plugin_instance, derive_t io_time,
                             derive_t weighted_time) {
    value_list_t vl = VALUE_LIST_INIT;
 @@ -300,7 +334,7 @@ static void submit_io_time(char const *p

    plugin_dispatch_values(&vl);
  } /* void submit_io_time */
 -#endif /* KERNEL_FREEBSD || KERNEL_LINUX */
 +#endif /* KERNEL_FREEBSD || (HAVE_SYSCTL && KERNEL_NETBSD) || KERNEL_LINUX */

  #if KERNEL_LINUX
  static void submit_in_progress(char const *disk_name, gauge_t in_progress) {
 @@ -1017,7 +1051,58 @@ static int disk_read(void) {
                    1000000.0;
      disk_submit(stat_disk[i].name, "disk_time", read_time, write_time);
    }
 -#endif /* defined(HAVE_PERFSTAT) */
 +/* #endif defined(HAVE_PERFSTAT) */
 +#elif HAVE_SYSCTL && KERNEL_NETBSD
 +  int mib[3];
 +  size_t size, i, nndrive;
 +
 +  /* figure out number of drives */
 +  mib[0] = CTL_HW;
 +  mib[1] = HW_IOSTATS;
 +  mib[2] = sizeof(struct io_sysctl);
 +  if (sysctl(mib, 3, NULL, &size, NULL, 0) == -1) {
 +    ERROR ("disk plugin: sysctl for ndrives failed");
 +    return -1;
 +  }
 +  nndrive = size / sizeof(struct io_sysctl);
 +
 +  if (size == 0 ) {
 +    ERROR ("disk plugin: no drives found");
 +    return -1;
 +  }
 +  /* number of drives changed, reallocate buffer */
 +  if (nndrive != ndrive) {
 +    drives = (struct io_sysctl *)realloc(drives, size);
 +    if (drives == NULL) {
 +      ERROR ("disk plugin: memory allocation failure");
 +      return -1;
 +    }
 +    ndrive = nndrive;
 +  }
 +
 +  /* get stats for all drives */
 +  mib[0] = CTL_HW;
 +  mib[1] = HW_IOSTATS;
 +  mib[2] = sizeof(struct io_sysctl);
 +  if (sysctl(mib, 3, drives, &size, NULL, 0) == -1) {
 +    ERROR ("disk plugin: sysctl for drive stats failed");
 +    return -1;
 +  }
 +
 +  for (i = 0; i < ndrive; i++) {
 +    if (drives[i].type != IOSTAT_DISK)
 +      continue;
 +    if (ignorelist_match(ignorelist, drives[i].name))
 +      continue;
 +
 +    disk_submit(drives[i].name, "disk_octets",
 +                drives[i].rbytes, drives[i].wbytes);
 +    disk_submit(drives[i].name, "disk_ops",
 +                drives[i].rxfer, drives[i].wxfer);
 +    submit_io_time(drives[i].name,
 +                   drives[i].time_sec * 1000 + drives[i].time_usec / 1000, 0);
 +  }
 +#endif /* HAVE_SYSCTL && KERNEL_NETBSD */

    return 0;
  } /* int disk_read */

Responsible-Changed-From-To: fhajny->pkg-manager
Responsible-Changed-By: wiz@NetBSD.org
Responsible-Changed-When: Wed, 27 May 2020 19:39:08 +0000
Responsible-Changed-Why:
Maintainer was reset


From: Edgar =?iso-8859-1?B?RnXf?= <ef@math.uni-bonn.de>
To: gnats-bugs@gnats.netbsd.org
Cc: 
Subject: Re: pkg/51334: collectd disk plugin NetBSD implementation correction
Date: Tue, 1 Dec 2020 19:24:19 +0100

 For the record, the (corrected) disk plugin (plus more of he@'s NetBSD implementations and an nfs plugin of my own) have been incorporated into collectd 5.11.0, which has been imported (via wip/me) to pkgsrc.

From: Benny Siegert <bsiegert@gmail.com>
To: gnats-bugs@netbsd.org
Cc: pkg-manager@netbsd.org, gnats-admin@netbsd.org, pkgsrc-bugs@netbsd.org, 
    ef@math.uni-bonn.de
Subject: Re: pkg/51334: collectd disk plugin NetBSD implementation
 correction
Date: Wed, 2 Dec 2020 08:25:19 +0000 (UTC)

 > For the record, the (corrected) disk plugin (plus more of he@'s NetBSD 
 > implementations and an nfs plugin of my own) have been incorporated into 
 > collectd 5.11.0, which has been imported (via wip/me) to pkgsrc.

 So this PR can be closed then?

 -- 
 Benny

State-Changed-From-To: open->closed
State-Changed-By: bsiegert@NetBSD.org
State-Changed-When: Thu, 17 Dec 2020 15:57:00 +0000
State-Changed-Why:
Submitter says this is fixed


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.46 2020/01/03 16:35:01 leot Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2020 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.