Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37770028
en ru br
Репозитории ALT

Группа :: Работа с файлами
Пакет: ioping

 Главная   Изменения   Спек   Патчи   Исходники   Загрузить   Gear   Bugs and FR  Repocop 

ioping-0.8/000075500000000000000000000000001226302306400126425ustar00rootroot00000000000000ioping-0.8/Makefile000064400000000000000000000027251226302306400143100ustar00rootroot00000000000000CFLAGS+=-std=gnu99 -g -Wall -Wextra -pedantic
LIBS=-lm
PREFIX=/usr/local
BINDIR=$(PREFIX)/bin
MAN1DIR=$(PREFIX)/share/man/man1

SRCS=ioping.c
OBJS=$(SRCS:.c=.o)
BINS=ioping
MANS=ioping.1
MANS_F=$(MANS:.1=.txt) $(MANS:.1=.pdf)
DOCS=README changelog
SPEC=ioping.spec

PACKAGE=ioping
VERSION=$(shell cat version)
DISTDIR=$(PACKAGE)-$(VERSION)
DISTFILES=$(SRCS) $(MANS) $(DOCS) $(SPEC) Makefile
PACKFILES=$(BINS) $(MANS) $(MANS_F) $(DOCS)

STRIP=strip
TARGET=$(shell ${CC} -dumpmachine | cut -d- -f 2)

ifdef MINGW
CC=i686-w64-mingw32-gcc
STRIP=i686-w64-mingw32-strip
TARGET=win32
BINS:=$(BINS:=.exe)
endif

all: version $(BINS)

version: $(DISTFILES)
test ! -d .git || git describe --tags --dirty=+ | sed 's/^v//;s/-/./g' > $@

clean:
$(RM) -f $(OBJS) $(BINS) $(MANS_F)

install: $(BINS) $(MANS)
mkdir -p $(DESTDIR)$(BINDIR)
install -s -m 0755 $(BINS) $(DESTDIR)$(BINDIR)
mkdir -p $(DESTDIR)$(MAN1DIR)
install -m 644 $(MANS) $(DESTDIR)$(MAN1DIR)

%.o: %.c version
$(CC) $(CFLAGS) -DVERSION=\"${VERSION}\" -c -o $@ $<

%.ps: %.1
man -t ./$< > $@

%.pdf: %.ps
ps2pdf $< $@

%.txt: %.1
MANWIDTH=80 man ./$< | col -b > $@

$(BINS): $(OBJS)
$(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) $(LIBS)

dist: version $(DISTFILES)
tar -cz --transform='s,^,$(DISTDIR)/,S' $^ -f $(DISTDIR).tar.gz

binary-tgz: $(PACKFILES)
${STRIP} ${BINS}
tar czf ${PACKAGE}-${VERSION}-${TARGET}.tgz $^

binary-zip: $(PACKFILES)
${STRIP} ${BINS}
zip ${PACKAGE}-${VERSION}-${TARGET}.zip $^

.PHONY: all clean install dist
ioping-0.8/README000064400000000000000000000006451226302306400135270ustar00rootroot00000000000000ioping
======

An tool to monitor I/O latency in real time.
It shows disk latency in the same way as ping shows network latency.

Homepage: http://code.google.com/p/ioping/

Please send your patches, issues and questions to
http://code.google.com/p/ioping/issues/

Authors:
Konstantin Khlebnikov <koct9i@gmail.com>
Kir Kolyshkin <kir@openvz.org>

Licensed under GPLv3 (or later) <http://www.gnu.org/licenses/gpl-3.0.txt>
ioping-0.8/changelog000064400000000000000000000007351226302306400145210ustar00rootroot00000000000000since v0.4
- rate-test, new key -R
- FreeBSD port
- OSX port

since v0.5
- fixes in man page and internal help
- fixes in OSX and FreeBSD ports
- Debian/kFreeBSD port
- Debian/HURD port

since v0.6
- Linux AIO support, new key -A
- extended raw statistics, keys -p -P
- batched mode, new key -B
- write requests, key -W
- automatic git-based versioning
- Windows/MinGW port
- DragonFlyBSD port

since v0.7
- OpenBSD port
- switch to IEEE 1541-2002 units: MiB/s
ioping-0.8/ioping.1000064400000000000000000000103531226302306400142130ustar00rootroot00000000000000.TH IOPING "1" "Dec 2013" "" "User Commands"
.SH NAME
ioping \- simple disk I/O latency monitoring tool
.SH SYNOPSYS
.SY ioping
.OP \-LABCDWRq
.OP \-c count
.OP \-w deadline
.OP \-p period
.OP \-P period
.OP \-i interval
.OP \-s size
.OP \-S wsize
.OP \-o offset
.IR directory | file | device
.br
.SY ioping
.B -h
|
.B -v
.br
.SH DESCRIPTION
This tool lets you monitor I/O latency in real time.
.SH OPTIONS
.TP
.BI \-c \ count
Stop after \fIcount\fR requests.
.TP
.BI \-w \ deadline
Stop after \fIdeadline\fR time passed.
.TP
.BI \-p \ period
Print raw statistics for every \fIperiod\fR requests.
.TP
.BI \-P \ period
Print raw statistics for every \fIperiod\fR in time.
.TP
.BI \-i \ interval
Set time between requests to \fIinterval\fR (\fB1s\fR).
.TP
.BI \-s \ size
Request size (\fB4k\fR).
.TP
.BI \-S \ size
Working set size (\fB1m\fR for directory, full size for file or device).
.TP
.BI \-o \ offset
Offset of working set in the file/device (0).
.TP
.B \-L
Use sequential operations rather than random. This also sets request size
to \fB256k\fR (as in \fB-s 256k\fR).
.TP
.B \-A
Use asynchronous I/O (syscalls \fBio_submit\fR(2), \fBio_submit\fR(2), etc).
.TP
.B \-C
Use cached I/O (suppress cache invalidation via \fBposix_fadvise\fR(2)).
.TP
.B \-D
Use direct I/O (see \fBO_DIRECT\fR in \fBopen\fR(2)).
.TP
.B \-W
Use writes rather than reads.
\fB*DANGEROUS*\fR It will shred your data if target is file or device,
repeat key tree times (\fB-WWW\fR) to do this.
.TP
.B \-R
Disk seek rate test (same as \fB\-q \-i 0 \-w 3 \-S 64m\fR).
.TP
.B \-B
Batch mode. Be quiet and print final statistics in raw format.
.TP
.B \-q
Suppress periodical human-readable output.
.TP
.B \-h
Display help message and exit.
.TP
.B \-v
Display version and exit.
.SS Argument suffixes
For options that expect time argument (\fB\-i\fR, \fB\-P\fR and \fB\-w\fR),
default is seconds, unless you specify one of the following suffixes
(case-insensitive):
.TP
.BR us ,\ usec
microseconds (a millionth of a second, 1 / 1 000 000)
.TP
.BR ms ,\ msec
milliseconds (a thousandth of a second, 1 / 1 000)
.TP
.BR s ,\ sec
seconds
.TP
.BR m ,\ min
minutes
.TP
.BR h ,\ hour
hours
.PP
For options that expect "size" argument (\fB\-s\fR, \fB\-S\fR and \fB\-o\fR),
default is bytes, unless you specify one of the following suffixes
(case-insensitive):
.TP
.B sector
disk sectors (a sector is always 512).
.TP
.BR KiB ,\ k ,\ kb
kilobytes (1 024 bytes)
.TP
.B page
memory pages (a page is always 4KiB).
.TP
.BR MiB ,\ m ,\ mb
megabytes (1 048 576 bytes)
.TP
.BR GiB ,\ g ,\ gb
gigabytes (1 073 741 824 bytes)
.TP
.BR TiB ,\ t ,\ tb
terabytes (1 099 511 627 776 bytes)
.PP
For options that expect "number" argument (\fB-p\fR and \fB-c\fR) you
can optionally specify one of the following suffixes (case-insensitive):
.TP
.B k
kilo (thousands, 1 000)
.TP
.B m
mega (millions, 1 000 000)
.TP
.B g
giga (billions, 1 000 000 000)
.TP
.B t
tera (trillions, 1 000 000 000 000)
.SH EXIT STATUS
Returns \fB0\fR upon success. The following error codes are defined:
.TP
.B 1
Invalid usage (error in arguments).
.TP
.B 2
Error during preparation stage.
.TP
.B 3
Error during runtime.
.SH RAW STATISTICS
.B ioping -p 100 -c 200 -i 0 -q .
.ad l
.br
\f(CW100 26694 3746 15344272 188 267 1923 228
.br
100 24165 4138 16950134 190 242 2348 214
.br
(1) (2) (3) (4) (5) (6) (7) (8)
.br

.br
(1) number of requests
.br
(2) serving time (usec)
.br
(3) requests per second (iops)
.br
(4) transfer speed (bytes/sec)
.br
(5) minimal request time (usec)
.br
(6) average request time (usec)
.br
(7) maximum request time (usec)
.br
(8) request time standard deviation (usec)
.SH EXAMPLES
.TP
.B ioping .
Show disk I/O latency using the default values and the current directory,
until interrupted.
.TP
.B ioping -c 10 -s 1M /tmp
Measure latency on \fB/tmp\fR using 10 requests of 1 megabyte each.
.TP
.B ioping -R /dev/sda
Measure disk seek rate.
.TP
.B ioping -RL /dev/sda
Measure disk sequential speed.
.SH SEE ALSO
.BR iostat (1),
.BR dd (1),
.BR fio (1),
.BR dbench (1),
.BR fsstress,
.BR xfstests,
.BR hdparm (8),
.BR badblocks (8),
.BR
.SH HOMEPAGE
.UR http://code.google.com/p/ioping/
.UE .
.SH AUTHORS
This program was written by Konstantin Khlebnikov
.MT koct9i@gmail.com
.ME .
.br
Man-page was written by Kir Kolyshkin
.MT kir@openvz.org
.ME .
ioping-0.8/ioping.c000064400000000000000000000547711226302306400143110ustar00rootroot00000000000000/*
* ioping -- simple I/0 latency measuring tool
*
* Copyright (C) 2011-2013 Konstantin Khlebnikov <koct9i@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

#define _GNU_SOURCE
#define _FILE_OFFSET_BITS 64

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <inttypes.h>
#include <getopt.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <math.h>
#include <limits.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>

#ifdef __linux__
# include <sys/ioctl.h>
# include <sys/mount.h>
# define HAVE_POSIX_FADVICE
# define HAVE_POSIX_MEMALIGN
# define HAVE_DIRECT_IO
# define HAVE_LINUX_ASYNC_IO
# define HAVE_ERR_INCLUDE
#endif

#ifdef __gnu_hurd__
# include <sys/ioctl.h>
# define HAVE_POSIX_MEMALIGN
# define HAVE_ERR_INCLUDE
#endif

#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
# include <sys/ioctl.h>
# include <sys/mount.h>
# include <sys/disk.h>
# define HAVE_DIRECT_IO
# define HAVE_ERR_INCLUDE
#endif

#ifdef __DragonFly__
# include <sys/diskslice.h>
# define HAVE_ERR_INCLUDE
#endif

#ifdef __OpenBSD__
# include <sys/ioctl.h>
# include <sys/disklabel.h>
# include <sys/dkio.h>
# include <sys/param.h>
# include <sys/mount.h>
# define HAVE_POSIX_MEMALIGN
# define HAVE_ERR_INCLUDE
#endif

#ifdef __APPLE__
# include <sys/ioctl.h>
# include <sys/mount.h>
# include <sys/disk.h>
# include <sys/uio.h>
# define HAVE_NOCACHE_IO
# define HAVE_ERR_INCLUDE
#endif

#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
# define HAVE_POSIX_FDATASYNC
#endif

#ifdef HAVE_ERR_INCLUDE
# include <err.h>
#else

#define ERR_PREFIX "ioping: "

void err(int eval, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, ERR_PREFIX);
vfprintf(stderr, fmt, ap);
fprintf(stderr, ": %s\n", strerror(errno));
va_end(ap);
exit(eval);
}

void errx(int eval, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, ERR_PREFIX);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
exit(eval);
}

void warnx(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, ERR_PREFIX);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
}

#endif /* HAVE_ERR_INCLUDE */

#ifdef __MINGW32__
#include <io.h>
#include <stdarg.h>
#include <windows.h>

ssize_t pread(int fd, void *buf, size_t count, off_t offset)
{
HANDLE h = (HANDLE)_get_osfhandle(fd);
DWORD r;
OVERLAPPED o;

memset(&o, 0, sizeof(o));
o.Offset = offset;
o.OffsetHigh = offset >> 32;

if (ReadFile(h, buf, count, &r, &o))
return r;
return -1;
}

ssize_t pwrite(int fd, void *buf, size_t count, off_t offset)
{
HANDLE h = (HANDLE)_get_osfhandle(fd);
DWORD r;
OVERLAPPED o;

memset(&o, 0, sizeof(o));
o.Offset = offset;
o.OffsetHigh = offset >> 32;

if (WriteFile(h, buf, count, &r, &o))
return r;
return -1;
}

int fsync(int fd)
{
HANDLE h = (HANDLE)_get_osfhandle(fd);

return FlushFileBuffers(h) ? 0 : -1;
}

void srandom(unsigned int seed)
{
srand(seed);
}

long int random(void)
{
return rand();
}

int nanosleep(const struct timespec *req, struct timespec *rem)
{
(void)rem;
Sleep(req->tv_sec * 1000 + req->tv_nsec / 1000000);
return 0;
}

#endif /* __MINGW32__ */

#ifndef HAVE_POSIX_MEMALIGN
/* don't free it */
int posix_memalign(void **memptr, size_t alignment, size_t size)
{
char *ptr;
ptr = malloc(size + alignment);
if (!ptr)
return -ENOMEM;
*memptr = ptr + alignment - (size_t)ptr % alignment;
return 0;
}
#endif

#ifndef HAVE_POSIX_FDATASYNC
int fdatasync(int fd)
{
return fsync(fd);
}
#endif

void usage(void)
{
fprintf(stderr,
" Usage: ioping [-LABCDWRq] [-c count] [-w deadline] [-pP period] [-i interval]\n"
" [-s size] [-S wsize] [-o offset] directory|file|device\n"
" ioping -h | -v\n"
"\n"
" -c <count> stop after <count> requests\n"
" -w <deadline> stop after <deadline>\n"
" -p <period> print raw statistics for every <period> requests\n"
" -P <period> print raw statistics for every <period> in time\n"
" -i <interval> interval between requests (1s)\n"
" -s <size> request size (4k)\n"
" -S <wsize> working set size (1m)\n"
" -o <offset> working set offset (0)\n"
" -L use sequential operations (includes -s 256k)\n"
" -A use asynchronous I/O\n"
" -C use cached I/O\n"
" -D use direct I/O\n"
" -W use write I/O *DANGEROUS*\n"
" -R seek rate test (same as -q -i 0 -w 3 -S 64m)\n"
" -B print final statistics in raw format\n"
" -q suppress human-readable output\n"
" -h display this message and exit\n"
" -v display version and exit\n"
"\n"
);
}

#ifndef VERSION
# warning ioping version undefined
# define VERSION ""
#endif

void version(void)
{
fprintf(stderr, "ioping %s\n", VERSION);
}

struct suffix {
const char *txt;
long long mul;
};

static struct suffix int_suffix[] = {
{ "T", 1000000000000ll },
{ "G", 1000000000ll },
{ "M", 1000000ll },
{ "k", 1000ll },
{ "", 1ll },
{ "da", 10ll },
{ "P", 1000000000000000ll },
{ "E", 1000000000000000000ll },
{ NULL, 0ll },
};

static struct suffix size_suffix[] = {
/* These are first match for printing */
{ "PiB", 1ll<<50 },
{ "TiB", 1ll<<40 },
{ "GiB", 1ll<<30 },
{ "MiB", 1ll<<20 },
{ "KiB", 1ll<<10 },
{ "B", 1 },
{ "", 1 },
/* Should be decimal, keep binary for compatibility */
{ "k", 1ll<<10 },
{ "kb", 1ll<<10 },
{ "m", 1ll<<20 },
{ "mb", 1ll<<20 },
{ "g", 1ll<<30 },
{ "gb", 1ll<<30 },
{ "t", 1ll<<40 },
{ "tb", 1ll<<40 },
{ "pb", 1ll<<50 },
{ "eb", 1ll<<60 },
{ "sector", 512 },
{ "page", 4096 },
{ NULL, 0ll },
};

static struct suffix time_suffix[] = {
{ "day", 1000000ll * 60 * 60 * 24 },
{ "hour", 1000000ll * 60 * 60 },
{ "min", 1000000ll * 60 },
{ "s", 1000000ll },
{ "ms", 1000ll },
{ "us", 1ll },
{ "usec", 1ll },
{ "msec", 1000ll },
{ "", 1000000ll },
{ "sec", 1000000ll },
{ "m", 1000000ll * 60 },
{ "h", 1000000ll * 60 * 60 },
{ "week", 1000000ll * 60 * 60 * 24 * 7 },
{ "month", 1000000ll * 60 * 60 * 24 * 7 * 30 },
{ "year", 1000000ll * 60 * 60 * 24 * 7 * 365 },
{ "century", 1000000ll * 60 * 60 * 24 * 7 * 365 * 100 },
{ "millenium", 1000000ll * 60 * 60 * 24 * 7 * 365 * 1000 },
{ NULL, 0ll },
};

long long parse_suffix(const char *str, struct suffix *sfx)
{
char *end;
double val;

val = strtod(str, &end);
for ( ; sfx->txt ; sfx++ ) {
if (!strcasecmp(end, sfx->txt))
return val * sfx->mul;
}
errx(1, "invalid suffix: \"%s\"", end);
return 0;
}

long long parse_int(const char *str)
{
return parse_suffix(str, int_suffix);
}

long long parse_size(const char *str)
{
return parse_suffix(str, size_suffix);
}

long long parse_time(const char *str)
{
return parse_suffix(str, time_suffix);
}

void print_suffix(int64_t val, struct suffix *sfx)
{
while (val < sfx->mul && sfx->mul > 1)
sfx++;
if (sfx->mul == 1)
printf("%" PRId64, val);
else
printf("%.1f", val * 1.0 / sfx->mul);
if (*sfx->txt)
printf(" %s", sfx->txt);
}

void print_int(long long val)
{
print_suffix(val, int_suffix);
}

void print_size(long long val)
{
print_suffix(val, size_suffix);
}

void print_time(long long val)
{
print_suffix(val, time_suffix);
}

long long now(void)
{
struct timeval tv;

if (gettimeofday(&tv, NULL))
err(3, "gettimeofday failed");

return tv.tv_sec * 1000000ll + tv.tv_usec;
}

char *path = NULL;
char *fstype = "";
char *device = "";
off_t device_size = 0;

int fd;
void *buf;

int quiet = 0;
int batch_mode = 0;
int direct = 0;
int async = 0;
int cached = 0;
int randomize = 1;
int write_test = 0;

ssize_t (*make_request) (int fd, void *buf, size_t nbytes, off_t offset) = pread;

int period_request = 0;
long long period_time = 0;

long long interval = 1000000;
struct timespec interval_ts;
long long deadline = 0;

ssize_t size = 1<<12;
off_t wsize = 0;
off_t temp_wsize = 1<<20;

off_t offset = 0;
off_t woffset = 0;

int request;
int count = 0;

int exiting = 0;

void parse_options(int argc, char **argv)
{
int opt;

if (argc < 2) {
usage();
exit(1);
}

while ((opt = getopt(argc, argv, "hvALRDCWBqi:w:s:S:c:o:p:P:")) != -1) {
switch (opt) {
case 'h':
usage();
exit(0);
case 'v':
version();
exit(0);
case 'L':
randomize = 0;
size = 1<<18;
break;
case 'R':
interval = 0;
deadline = 3000000;
temp_wsize = 1<<26;
quiet = 1;
break;
case 'D':
direct = 1;
break;
case 'C':
cached = 1;
break;
case 'A':
async = 1;
break;
case 'W':
write_test++;
break;
case 'i':
interval = parse_time(optarg);
break;
case 'w':
deadline = parse_time(optarg);
break;
case 's':
size = parse_size(optarg);
break;
case 'S':
wsize = parse_size(optarg);
break;
case 'o':
offset = parse_size(optarg);
break;
case 'p':
period_request = parse_int(optarg);
break;
case 'P':
period_time = parse_time(optarg);
break;
case 'q':
quiet = 1;
break;
case 'B':
quiet = 1;
batch_mode = 1;
break;
case 'c':
count = parse_int(optarg);
break;
case '?':
usage();
exit(1);
}
}

if (optind > argc-1)
errx(1, "no destination specified");
if (optind < argc-1)
errx(1, "more than one destination specified");
path = argv[optind];
}

#ifdef __linux__

void parse_device(dev_t dev)
{
char *buf = NULL, *ptr;
unsigned major, minor;
struct stat st;
size_t len;
FILE *file;

/* since v2.6.26 */
file = fopen("/proc/self/mountinfo", "r");
if (!file)
goto old;
while (getline(&buf, &len, file) > 0) {
sscanf(buf, "%*d %*d %u:%u", &major, &minor);
if (makedev(major, minor) != dev)
continue;
ptr = strstr(buf, " - ") + 3;
fstype = strdup(strsep(&ptr, " "));
device = strdup(strsep(&ptr, " "));
goto out;
}
old:
/* for older versions */
file = fopen("/proc/mounts", "r");
if (!file)
return;
while (getline(&buf, &len, file) > 0) {
ptr = buf;
strsep(&ptr, " ");
if (*buf != '/' || stat(buf, &st) || st.st_rdev != dev)
continue;
strsep(&ptr, " ");
fstype = strdup(strsep(&ptr, " "));
device = strdup(buf);
goto out;
}
out:
free(buf);
fclose(file);
}

#elif defined(__APPLE__) || defined(__OpenBSD__) \
|| defined(__FreeBSD__) || defined(__FreeBSD_kernel__)

void parse_device(dev_t dev)
{
struct statfs fs;
(void)dev;

if (statfs(path, &fs))
return;

fstype = strdup(fs.f_fstypename);
device = strdup(fs.f_mntfromname);
}

#else

void parse_device(dev_t dev)
{
(void)dev;
}

#endif

off_t get_device_size(int fd, struct stat *st)
{
unsigned long long blksize = 0;
int ret = 0;

#if defined(BLKGETSIZE64)
/* linux */
ret = ioctl(fd, BLKGETSIZE64, &blksize);
#elif defined(DIOCGMEDIASIZE)
/* freebsd */
ret = ioctl(fd, DIOCGMEDIASIZE, &blksize);
#elif defined(DKIOCGETBLOCKCOUNT)
/* macos */
ret = ioctl(fd, DKIOCGETBLOCKCOUNT, &blksize);
blksize <<= 9;
#elif defined(__gnu_hurd__)
/* hurd */
blksize = st->st_size;
#elif defined(__MINGW32__)
blksize = 0;
#elif defined(__DragonFly__)
struct partinfo pinfo;
ret = ioctl(fd, DIOCGPART, &pinfo);
blksize = pinfo.media_size;
#elif defined(__OpenBSD__)
struct disklabel label;
struct partition part;

ret = ioctl(fd, DIOCGDINFO, &label);
part = label.d_partitions[DISKPART(st->st_rdev)];

blksize = DL_GETPSIZE(&part) * label.d_secsize;
#else
# error no get disk size method
#endif
(void)fd;
(void)st;

if (ret)
err(2, "block get size ioctl failed");

return blksize;
}

ssize_t do_pwrite(int fd, void *buf, size_t nbytes, off_t offset)
{
ssize_t ret;

ret = pwrite(fd, buf, nbytes, offset);
if (ret < 0)
return ret;
if (!cached && fdatasync(fd) < 0)
return -1;
return ret;
}

#ifdef HAVE_LINUX_ASYNC_IO

#include <sys/syscall.h>
#include <linux/aio_abi.h>

static long io_setup(unsigned nr_reqs, aio_context_t *ctx) {
return syscall(__NR_io_setup, nr_reqs, ctx);
}

static long io_submit(aio_context_t ctx, long n, struct iocb **paiocb) {
return syscall(__NR_io_submit, ctx, n, paiocb);
}

static long io_getevents(aio_context_t ctx, long min_nr, long nr,
struct io_event *events, struct timespec *tmo) {
return syscall(__NR_io_getevents, ctx, min_nr, nr, events, tmo);
}

#if 0
static long io_cancel(aio_context_t ctx, struct iocb *aiocb,
struct io_event *res) {
return syscall(__NR_io_cancel, ctx, aiocb, res);
}

static long io_destroy(aio_context_t ctx) {
return syscall(__NR_io_destroy, ctx);
}
#endif

aio_context_t aio_ctx;
struct iocb aio_cb;
struct iocb *aio_cbp = &aio_cb;
struct io_event aio_ev;

static ssize_t aio_pread(int fd, void *buf, size_t nbytes, off_t offset)
{
aio_cb.aio_lio_opcode = IOCB_CMD_PREAD;
aio_cb.aio_fildes = fd;
aio_cb.aio_buf = (unsigned long) buf;
aio_cb.aio_nbytes = nbytes;
aio_cb.aio_offset = offset;

if (io_submit(aio_ctx, 1, &aio_cbp) != 1)
err(1, "aio submit failed");

if (io_getevents(aio_ctx, 1, 1, &aio_ev, NULL) != 1)
err(1, "aio getevents failed");

if (aio_ev.res < 0) {
errno = -aio_ev.res;
return -1;
}

return aio_ev.res;
}

static ssize_t aio_pwrite(int fd, void *buf, size_t nbytes, off_t offset)
{
aio_cb.aio_lio_opcode = IOCB_CMD_PWRITE;
aio_cb.aio_fildes = fd;
aio_cb.aio_buf = (unsigned long) buf;
aio_cb.aio_nbytes = nbytes;
aio_cb.aio_offset = offset;

if (io_submit(aio_ctx, 1, &aio_cbp) != 1)
err(1, "aio submit failed");

if (io_getevents(aio_ctx, 1, 1, &aio_ev, NULL) != 1)
err(1, "aio getevents failed");

if (aio_ev.res < 0) {
errno = -aio_ev.res;
return -1;
}

if (!cached && fdatasync(fd) < 0)
return -1;

return aio_ev.res;

#if 0
aio_cb.aio_lio_opcode = IOCB_CMD_FDSYNC;
if (io_submit(aio_ctx, 1, &aio_cbp) != 1)
err(1, "aio fdsync submit failed");

if (io_getevents(aio_ctx, 1, 1, &aio_ev, NULL) != 1)
err(1, "aio getevents failed");

if (aio_ev.res < 0)
return aio_ev.res;
#endif
}

static void aio_setup(void)
{
memset(&aio_ctx, 0, sizeof aio_ctx);
memset(&aio_cb, 0, sizeof aio_cb);

if (io_setup(1, &aio_ctx))
err(2, "aio setup failed");

make_request = write_test ? aio_pwrite : aio_pread;
}

#else

static void aio_setup(void)
{
errx(1, "asynchronous I/O not supportted by this platform");
}

#endif

#ifdef __MINGW32__

int create_temp(char *path, char *template)
{
int length = strlen(path) + strlen(template) + 2;
char *temp = malloc(length);
HANDLE h;
DWORD attr;

if (!temp)
err(2, NULL);
snprintf(temp, length, "%s\\%s", path, template);
mktemp(temp);

attr = FILE_ATTRIBUTE_HIDDEN | FILE_FLAG_DELETE_ON_CLOSE;
if (!cached)
attr |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH;
if (randomize)
attr |= FILE_FLAG_RANDOM_ACCESS;
else
attr |= FILE_FLAG_SEQUENTIAL_SCAN;

h = CreateFile(temp, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, CREATE_ALWAYS, attr, NULL);

free(temp);
if (h == INVALID_HANDLE_VALUE)
return -1;
return _open_osfhandle((long)h, 0);
}

BOOL WINAPI sig_exit(DWORD type)
{
switch (type) {
case CTRL_C_EVENT:
if (exiting)
exit(4);
exiting = 1;
return TRUE;
default:
return FALSE;
}
}

void set_signal(void)
{
SetConsoleCtrlHandler(sig_exit, TRUE);
}

#else /* __MINGW32__ */

int create_temp(char *path, char *template)
{
int length = strlen(path) + strlen(template) + 2;
char *temp = malloc(length);
int fd;

if (!temp)
err(2, NULL);
snprintf(temp, length, "%s/%s", path, template);

fd = mkstemp(temp);
if (fd < 0)
err(2, "failed to create temporary file at \"%s\"", path);
if (unlink(temp))
err(2, "unlink \"%s\" failed", temp);
free(temp);
# ifdef HAVE_DIRECT_IO
if (direct && fcntl(fd, F_SETFL, O_DIRECT))
errx(2, "fcntl failed, please retry without -D");
# endif
return fd;
}

void sig_exit(int signo)
{
(void)signo;
if (exiting)
exit(4);
exiting = 1;
}

void set_signal(void)
{
struct sigaction sa;

memset(&sa, 0, sizeof(sa));
sa.sa_handler = sig_exit;
sigaction(SIGINT, &sa, NULL);
}

#endif /* __MINGW32__ */

int main (int argc, char **argv)
{
long ret_size;
struct stat st;
int ret, flags;

int part_request;
long long this_time, time_total;
double part_min, part_max, time_min, time_max;
double time_sum, time_sum2, time_mdev, time_avg;
double part_sum, part_sum2, part_mdev, part_avg;
long long time_now, time_next, period_deadline;

parse_options(argc, argv);

interval_ts.tv_sec = interval / 1000000;
interval_ts.tv_nsec = (interval % 1000000) * 1000;

if (wsize)
temp_wsize = wsize;
else if (size > temp_wsize)
temp_wsize = size;

if (size <= 0)
errx(1, "request size must be greather than zero");

flags = O_RDONLY;

#if !defined(HAVE_POSIX_FADVICE) && !defined(HAVE_NOCACHE_IO)
# if defined(HAVE_DIRECT_IO)
direct |= !cached;
# else
if (!cached)
warnx("non-cached I/O not supportted by this platform,"
" results will be unreliable.");
cached = 1;
# endif
#endif

if (write_test) {
flags = O_RDWR;
make_request = do_pwrite;
}

if (async)
aio_setup();

if (direct)
#ifdef HAVE_DIRECT_IO
flags |= O_DIRECT;
#else
errx(1, "direct I/O not supportted by this platform");
#endif

#ifdef __MINGW32__
flags |= O_BINARY;
#endif

if (stat(path, &st))
err(2, "stat \"%s\" failed", path);

if (!S_ISDIR(st.st_mode) && write_test && write_test < 3)
errx(2, "think twice, then use -WWW to shred this target");

if (S_ISDIR(st.st_mode) || S_ISREG(st.st_mode)) {
if (S_ISDIR(st.st_mode))
st.st_size = offset + temp_wsize;
parse_device(st.st_dev);
} else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
fd = open(path, flags);
if (fd < 0)
err(2, "failed to open \"%s\"", path);

device_size = get_device_size(fd, &st);
st.st_size = device_size;
fstype = "device";
} else {
errx(2, "unsupported destination: \"%s\"", path);
}

if (offset + wsize > st.st_size)
errx(2, "target is too small for this");

if (!wsize)
wsize = st.st_size - offset;

if (size > wsize)
errx(2, "request size is too big for this target");

ret = posix_memalign(&buf, 0x1000, size);
if (ret)
errx(2, "buffer allocation failed");
memset(buf, '*', size);

if (S_ISDIR(st.st_mode)) {
fd = create_temp(path, "ioping.XXXXXX");
for (woffset = 0 ; woffset + size <= wsize ; woffset += size) {
if (pwrite(fd, buf, size, offset + woffset) != size)
err(2, "write failed");
}
if (fsync(fd))
err(2, "fsync failed");
} else if (S_ISREG(st.st_mode)) {
fd = open(path, flags);
if (fd < 0)
err(2, "failed to open \"%s\"", path);
}

if (!cached) {
#ifdef HAVE_POSIX_FADVICE
ret = posix_fadvise(fd, offset, wsize, POSIX_FADV_RANDOM);
if (ret)
err(2, "fadvise failed");
#endif
#ifdef HAVE_NOCACHE_IO
ret = fcntl(fd, F_NOCACHE, 1);
if (ret)
err(2, "fcntl nocache failed");
#endif
}

srandom(now());

if (deadline)
deadline += now();

set_signal();

request = 0;
woffset = 0;

part_request = 0;
part_min = time_min = LLONG_MAX;
part_max = time_max = LLONG_MIN;
part_sum = time_sum = 0;
part_sum2 = time_sum2 = 0;

time_now = now();
time_total = time_now;
period_deadline = time_now + period_time;

while (!exiting) {
request++;
part_request++;

if (randomize)
woffset = random() % (wsize / size) * size;

#ifdef HAVE_POSIX_FADVICE
if (!cached) {
ret = posix_fadvise(fd, offset + woffset, size,
POSIX_FADV_DONTNEED);
if (ret)
err(3, "fadvise failed");
}
#endif

this_time = now();

ret_size = make_request(fd, buf, size, offset + woffset);
if (ret_size < 0 && errno != EINTR)
err(3, "request failed");

time_now = now();
this_time = time_now - this_time;
time_next = time_now + interval;

part_sum += this_time;
part_sum2 += this_time * this_time;
if (this_time < part_min)
part_min = this_time;
if (this_time > part_max)
part_max = this_time;

if (!quiet) {
print_size(ret_size);
printf(" from %s (%s %s", path, fstype, device);
if (device_size)
print_size(device_size);
printf("): request=%d time=", request);
print_time(this_time);
printf("\n");
}

if ((period_request && (part_request >= period_request)) ||
(period_time && (time_next >= period_deadline))) {
part_avg = part_sum / part_request;
part_mdev = sqrt(part_sum2 / part_request - part_avg * part_avg);

printf("%d %.0f %.0f %.0f %.0f %.0f %.0f %.0f\n",
part_request, part_sum,
1000000. * part_request / part_sum,
1000000. * part_request * size / part_sum,
part_min, part_avg,
part_max, part_mdev);

time_sum += part_sum;
time_sum2 += part_sum2;
if (part_min < time_min)
time_min = part_min;
if (part_max > time_max)
time_max = part_max;
part_min = LLONG_MAX;
part_max = LLONG_MIN;
part_sum = part_sum2 = 0;
part_request = 0;

period_deadline = time_now + period_time;
}

if (!randomize) {
woffset += size;
if (woffset + size > wsize)
woffset = 0;
}

if (exiting)
break;

if (count && request >= count)
break;

if (deadline && time_next >= deadline)
break;

if (interval)
nanosleep(&interval_ts, NULL);
}

time_total = now() - time_total;

time_sum += part_sum;
time_sum2 += part_sum2;
if (part_min < time_min)
time_min = part_min;
if (part_max > time_max)
time_max = part_max;

time_avg = time_sum / request;
time_mdev = sqrt(time_sum2 / request - time_avg * time_avg);

if (batch_mode) {
printf("%d %.0f %.0f %.0f %.0f %.0f %.0f %.0f\n",
request, time_sum,
1000000. * request / time_sum,
1000000. * request * size / time_sum,
time_min, time_avg,
time_max, time_mdev);
} else if (!quiet || (!period_time && !period_request)) {
printf("\n--- %s (%s %s", path, fstype, device);
if (device_size)
print_size(device_size);
printf(") ioping statistics ---\n");
print_int(request);
printf(" requests completed in ");
print_time(time_total);
printf(", ");
print_int(request * 1000000. / time_sum);
printf(" iops, ");
print_size(request * size * 1000000. / time_sum);
printf("/s\n");
printf("min/avg/max/mdev = ");
print_time(time_min);
printf(" / ");
print_time(time_avg);
printf(" / ");
print_time(time_max);
printf(" / ");
print_time(time_mdev);
printf("\n");
}

return 0;
}
ioping-0.8/ioping.spec000064400000000000000000000023201226302306400150000ustar00rootroot00000000000000Name: ioping
Version: %(cat version)
Release: 1%{?dist}
Summary: simple disk I/O latency monitoring tool

Group: Applications/System
License: GPLv3+
URL: http://code.google.com/p/ioping
Source0: ioping-%{version}.tar.gz
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)

BuildRequires: gcc, make

%description
This tool lets you monitor I/O latency in real time, in a way
similar to how ping(1) does for network latency.

%prep
%setup -q


%build
CFLAGS="$RPM_OPT_FLAGS" make %{?_smp_mflags}


%install
rm -rf $RPM_BUILD_ROOT
make install PREFIX=%{_prefix} DESTDIR=$RPM_BUILD_ROOT


%clean
rm -rf $RPM_BUILD_ROOT


%files
%defattr(-,root,root,-)
%attr(755,root,root) %{_bindir}/ioping
%attr(644, root, root) %{_mandir}/man1/ioping.1.*
%doc

%changelog
* Mon Aug 1 2011 Konstantin Khlebnikov <koct9i@gmail.com> - 0.6-1
- many fixes
- port to GNU/Hurd

* Thu Jun 16 2011 Konstantin Khlebnikov <koct9i@gmail.com> - 0.5-1
- rate tests
- freebsd and macosx ports

* Thu Jun 2 2011 Konstantin Khlebnikov <koct9i@gmail.com> - 0.4-1
- fix linking

* Thu Jun 2 2011 Kir Kolyshkin <kir@openvz.org> - 0.3-1
- fix i386 build on x86_64

* Mon May 30 2011 Kir Kolyshkin <kir@openvz.org> - 0.1-1
- initial packaging
ioping-0.8/version000064400000000000000000000000041226302306400142440ustar00rootroot000000000000000.8
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin