From 64d3a8bc2198c8655bd946674dfd47ce8fb31a8a Mon Sep 17 00:00:00 2001 From: phk Date: Wed, 9 Apr 2003 10:52:10 +0000 Subject: Diskinfo is a small program to access the basic properties of a disk device: sectorsize, mediasize etc. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It also contains a small and naïve benchmark which reports on seek and transfer performance. --- usr.sbin/diskinfo/Makefile | 11 ++ usr.sbin/diskinfo/diskinfo.8 | 69 ++++++++++ usr.sbin/diskinfo/diskinfo.c | 303 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 383 insertions(+) create mode 100644 usr.sbin/diskinfo/Makefile create mode 100644 usr.sbin/diskinfo/diskinfo.8 create mode 100644 usr.sbin/diskinfo/diskinfo.c (limited to 'usr.sbin/diskinfo') diff --git a/usr.sbin/diskinfo/Makefile b/usr.sbin/diskinfo/Makefile new file mode 100644 index 0000000..e0c9cc7 --- /dev/null +++ b/usr.sbin/diskinfo/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +PROG= diskinfo +MAN= diskinfo.8 + +.include + +test: ${PROG} + ./${PROG} /dev/ad4 md50 + ./${PROG} -v /dev/ad4 md50 + ./${PROG} -t /dev/ad4 diff --git a/usr.sbin/diskinfo/diskinfo.8 b/usr.sbin/diskinfo/diskinfo.8 new file mode 100644 index 0000000..876567f --- /dev/null +++ b/usr.sbin/diskinfo/diskinfo.8 @@ -0,0 +1,69 @@ +.\" +.\" Copyright (c) 2003 Poul-Henning Kamp +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. The names of the authors may not be used to endorse or promote +.\" products derived from this software without specific prior written +.\" permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd April 9, 2003 +.Dt DISKINFO 8 +.Os +.Sh NAME +.Nm diskinfo +.Nd get information about disk device +.Sh SYNOPSIS +.Nm +.Op Fl v +.Op Fl t +.Ar disk ... +.Sh DESCRIPTION +The +.Nm +utility prints out information about a diskdevice and optionally runs a naïve performance test on the device. +.Pp +If given no arguments the output will be a single line per specified device +with the following fields: device name, sectorsize, media size in bytes, +media size in sectors, firmware cylinders, firmware heads and firmware sectors. +The last three fields are only present if the information is available. +.Pp +If given the +.Fl v +option, the fields will be printed one per line with a descriptive comment. +.Pp +The +.Fl t +option triggers a simple and rather naïve benchmark of the disks seek +and transfer performance. +.Sh AUTHORS +.An Poul-Henning Kamp +.Sh BUGS +There are in order of increasing severity lies, +damn lines, statistics and computer benchmarks. +.Sh HISTORY +.The +.Nm +command appeared in +.Fx 5.1 diff --git a/usr.sbin/diskinfo/diskinfo.c b/usr.sbin/diskinfo/diskinfo.c new file mode 100644 index 0000000..0db8756 --- /dev/null +++ b/usr.sbin/diskinfo/diskinfo.c @@ -0,0 +1,303 @@ +/*- + * Copyright (c) 2003 Poul-Henning Kamp + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the authors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static void +usage(void) +{ + fprintf(stderr, "Usage: diskinfo [-tv]\n"); + exit (1); +} + +static int opt_t, opt_v; + +static void speeddisk(const char *name, int fd, off_t mediasize, u_int sectorsize); + +int +main(int argc, char **argv) +{ + int i, ch, fd, error; + char buf[BUFSIZ]; + off_t mediasize; + u_int sectorsize, fwsectors, fwheads; + + while ((ch = getopt(argc, argv, "tv")) != -1) { + switch (ch) { + case 't': + opt_t = 1; + opt_v = 1; + break; + case 'v': + opt_v = 1; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + + for (i = 0; i < argc; i++) { + fd = open(argv[i], O_RDONLY); + if (fd < 0 && errno == ENOENT && *argv[i] != '/') { + sprintf(buf, "%s%s", _PATH_DEV, argv[i]); + fd = open(buf, O_RDONLY); + } + if (fd < 0) + err(1, argv[i]); + error = ioctl(fd, DIOCGMEDIASIZE, &mediasize); + if (error) + err(1, "%s: ioctl(DIOCGMEDIASIZE) failed, probably not a disk.", argv[i]); + error = ioctl(fd, DIOCGSECTORSIZE, §orsize); + if (error) + err(1, "%s: DIOCGSECTORSIZE failed, probably not a disk.", argv[i]); + error = ioctl(fd, DIOCGFWSECTORS, &fwsectors); + if (error) + fwsectors = 0; + error = ioctl(fd, DIOCGFWHEADS, &fwheads); + if (error) + fwheads = 0; + if (!opt_v) { + printf("%s", argv[i]); + printf("\t%u", sectorsize); + printf("\t%jd", (intmax_t)mediasize); + printf("\t%jd", (intmax_t)mediasize/sectorsize); + if (fwsectors != 0 && fwheads != 0) { + printf("\t%jd", (intmax_t)mediasize / + (fwsectors * fwheads * sectorsize)); + printf("\t%u", fwheads); + printf("\t%u", fwsectors); + } + } else { + printf("%s\n", argv[i]); + printf("\t%-12u\t# sectorsize\n", sectorsize); + printf("\t%-12jd\t# mediasize in bytes\n", + (intmax_t)mediasize); + printf("\t%-12jd\t# mediasize in sectors\n", + (intmax_t)mediasize/sectorsize); + if (fwsectors != 0 && fwheads != 0) { + printf("\t%-12jd\t# Cylinders according to firmware.\n", (intmax_t)mediasize / + (fwsectors * fwheads * sectorsize)); + printf("\t%-12u\t# Heads according to firmware.\n", fwheads); + printf("\t%-12u\t# Sectors according to firmware.\n", fwsectors); + } + } + printf("\n"); + if (opt_t) + speeddisk(argv[i], fd, mediasize, sectorsize); + close(fd); + } + exit (0); +} + + +static char sector[65536]; +static char mega[1024 * 1024]; + +static void +rdsect(int fd, u_int blockno, u_int sectorsize) +{ + int error; + + lseek(fd, blockno * sectorsize, SEEK_SET); + error = read(fd, sector, sectorsize); + if (error != sectorsize) + err(1, "read error or disk too small for test."); +} + +static void +rdmega(int fd) +{ + int error; + + error = read(fd, mega, sizeof(mega)); + if (error != sizeof(mega)) + err(1, "read error or disk too small for test."); +} + +static struct timeval tv1, tv2; + +static void +T0(void) +{ + + fflush(stdout); + sync(); + sleep(1); + sync(); + sync(); + gettimeofday(&tv1, NULL); +} + +static void +TN(int count) +{ + double dt; + + gettimeofday(&tv2, NULL); + dt = (tv2.tv_usec - tv1.tv_usec) / 1e6; + dt += (tv2.tv_sec - tv1.tv_sec); + printf("%5d iter in %10.6f sec = %8.3f msec\n", + count, dt, dt * 1000.0 / count); +} + +static void +TR(double count) +{ + double dt; + + gettimeofday(&tv2, NULL); + dt = (tv2.tv_usec - tv1.tv_usec) / 1e6; + dt += (tv2.tv_sec - tv1.tv_sec); + printf("%8.0f kbytes in %10.6f sec = %8.0f kbytes/sec\n", + count, dt, count / dt); +} + +static void +speeddisk(const char *name, int fd, off_t mediasize, u_int sectorsize) +{ + int error, i; + uint b0, b1, sectorcount; + + off_t size; + sectorcount = mediasize / sectorsize; + + printf("Seek times:\n"); + printf("\tFull stroke:\t"); + b0 = 0; + b1 = sectorcount - 1 - 125 * 16384; + T0(); + for (i = 0; i < 125; i++) { + rdsect(fd, b0, sectorsize); + b0 += 16384; + rdsect(fd, b1, sectorsize); + b1 += 16384; + } + TN(250); + + printf("\tHalf stroke:\t"); + b0 = sectorcount / 4; + b1 = b0 + sectorcount / 2; + T0(); + for (i = 0; i < 125; i++) { + rdsect(fd, b0, sectorsize); + b0 += 16384; + rdsect(fd, b1, sectorsize); + b1 += 16384; + } + TN(250); + printf("\tQuarter stroke:\t"); + b0 = sectorcount / 4; + b1 = b0 + sectorcount / 4; + T0(); + for (i = 0; i < 250; i++) { + rdsect(fd, b0, sectorsize); + b0 += 16384; + rdsect(fd, b1, sectorsize); + b1 += 16384; + } + TN(500); + + printf("\tShort forward:\t"); + b0 = sectorcount / 2; + T0(); + for (i = 0; i < 1000; i++) { + rdsect(fd, b0, sectorsize); + b0 += 16384; + } + TN(1000); + + printf("\tShort backward:\t"); + b0 = sectorcount / 2; + T0(); + for (i = 0; i < 1000; i++) { + rdsect(fd, b0, sectorsize); + b0 -= 16384; + } + TN(1000); + + printf("\tSeq outer:\t"); + b0 = 0; + T0(); + for (i = 0; i < 20480; i++) { + rdsect(fd, b0, sectorsize); + b0++; + } + TN(20480); + + printf("\tSeq inner:\t"); + b0 = sectorcount - 20480 - 1; + T0(); + for (i = 0; i < 20480; i++) { + rdsect(fd, b0, sectorsize); + b0++; + } + TN(20480); + + printf("Transfer rates:\n"); + printf("\toutside: "); + rdsect(fd, 0, sectorsize); + T0(); + for (i = 0; i < 100; i++) { + rdmega(fd); + } + TR(100 * 1024); + + printf("\tmiddle: "); + b0 = sectorcount / 2; + rdsect(fd, b0, sectorsize); + T0(); + for (i = 0; i < 100; i++) { + rdmega(fd); + } + TR(100 * 1024); + + printf("\tinside: "); + b0 = sectorcount - 100 * (1024*1024 / sectorsize) - 1;; + rdsect(fd, b0, sectorsize); + T0(); + for (i = 0; i < 100; i++) { + rdmega(fd); + } + TR(100 * 1024); + + printf("\n"); + + return; +} -- cgit v1.1