Commit 25446637 authored by Konstantin Khlebnikov's avatar Konstantin Khlebnikov

ioping: add option for keeping/reusing working file

This option helps to get stable results from run to run.
Signed-off-by: default avatarKonstantin Khlebnikov <koct9i@gmail.com>
parent b96f42e8
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
ioping \- simple disk I/O latency monitoring tool ioping \- simple disk I/O latency monitoring tool
.SH SYNOPSYS .SH SYNOPSYS
.SY ioping .SY ioping
.OP \-LABCDWRq .OP \-LABCDWRkq
.OP \-c count .OP \-c count
.OP \-w deadline .OP \-w deadline
.OP \-p period .OP \-p period
...@@ -47,6 +47,10 @@ Working set size (\fB1m\fR for directory, full size for file or device). ...@@ -47,6 +47,10 @@ Working set size (\fB1m\fR for directory, full size for file or device).
.BI \-o \ offset .BI \-o \ offset
Offset of working set in the file/device (0). Offset of working set in the file/device (0).
.TP .TP
.BI \-k
Do no delete temporary working file "ioping.tmp" and reuse it at next run.
This speeds up preparation and helps to get more stable results from run to run.
.TP
.B \-L .B \-L
Use sequential operations rather than random. This also sets request size Use sequential operations rather than random. This also sets request size
to \fB256k\fR (as in \fB-s 256k\fR). to \fB256k\fR (as in \fB-s 256k\fR).
......
...@@ -234,6 +234,7 @@ void usage(void) ...@@ -234,6 +234,7 @@ void usage(void)
" -s <size> request size (4k)\n" " -s <size> request size (4k)\n"
" -S <wsize> working set size (1m)\n" " -S <wsize> working set size (1m)\n"
" -o <offset> working set offset (0)\n" " -o <offset> working set offset (0)\n"
" -k keep and reuse temporary working file\n"
" -L use sequential operations (includes -s 256k)\n" " -L use sequential operations (includes -s 256k)\n"
" -A use asynchronous I/O\n" " -A use asynchronous I/O\n"
" -C use cached I/O\n" " -C use cached I/O\n"
...@@ -416,6 +417,8 @@ ssize_t size = 1<<12; ...@@ -416,6 +417,8 @@ ssize_t size = 1<<12;
off_t wsize = 0; off_t wsize = 0;
off_t temp_wsize = 1<<20; off_t temp_wsize = 1<<20;
int keep_file = 0;
off_t offset = 0; off_t offset = 0;
off_t woffset = 0; off_t woffset = 0;
...@@ -433,7 +436,7 @@ void parse_options(int argc, char **argv) ...@@ -433,7 +436,7 @@ void parse_options(int argc, char **argv)
exit(1); exit(1);
} }
while ((opt = getopt(argc, argv, "hvALRDCWBqi:w:s:S:c:o:p:P:")) != -1) { while ((opt = getopt(argc, argv, "hvkALRDCWBqi:w:s:S:c:o:p:P:")) != -1) {
switch (opt) { switch (opt) {
case 'h': case 'h':
usage(); usage();
...@@ -494,6 +497,9 @@ void parse_options(int argc, char **argv) ...@@ -494,6 +497,9 @@ void parse_options(int argc, char **argv)
case 'c': case 'c':
count = parse_int(optarg); count = parse_int(optarg);
break; break;
case 'k':
keep_file = 1;
break;
case '?': case '?':
usage(); usage();
exit(1); exit(1);
...@@ -757,15 +763,19 @@ int create_temp(char *path, char *name) ...@@ -757,15 +763,19 @@ int create_temp(char *path, char *name)
{ {
int length = strlen(path) + strlen(name) + 9; int length = strlen(path) + strlen(name) + 9;
char *temp = malloc(length); char *temp = malloc(length);
DWORD attr = 0;
HANDLE h; HANDLE h;
DWORD attr;
if (!temp) if (!temp)
err(2, NULL); err(2, NULL);
snprintf(temp, length, "%s\\%s.XXXXXX", path, name);
mktemp(temp);
attr = FILE_ATTRIBUTE_HIDDEN | FILE_FLAG_DELETE_ON_CLOSE; snprintf(temp, length, "%s\\%s", path, name);
if (!keep_file) {
strcat(tmp, ".XXXXXX");
mktemp(temp);
attr |= FILE_ATTRIBUTE_HIDDEN | FILE_FLAG_DELETE_ON_CLOSE;
}
if (!cached) if (!cached)
attr |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH; attr |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH;
if (randomize) if (randomize)
...@@ -814,6 +824,13 @@ int create_temp(char *path, char *name) ...@@ -814,6 +824,13 @@ int create_temp(char *path, char *name)
snprintf(temp, length, "%s/%s", path, name); snprintf(temp, length, "%s/%s", path, name);
if (keep_file) {
fd = open(temp, O_RDWR|O_CREAT, 0600);
if (fd < 0)
goto out;
goto done;
}
#ifdef O_TMPFILE #ifdef O_TMPFILE
fd = open(temp, O_RDWR|O_TMPFILE, 0600); fd = open(temp, O_RDWR|O_TMPFILE, 0600);
if (fd >= 0) if (fd >= 0)
...@@ -827,9 +844,7 @@ int create_temp(char *path, char *name) ...@@ -827,9 +844,7 @@ int create_temp(char *path, char *name)
if (unlink(temp)) if (unlink(temp))
err(2, "unlink \"%s\" failed", temp); err(2, "unlink \"%s\" failed", temp);
#ifdef O_TMPFILE
done: done:
#endif
#ifdef HAVE_DIRECT_IO #ifdef HAVE_DIRECT_IO
if (direct && fcntl(fd, F_SETFL, O_DIRECT)) if (direct && fcntl(fd, F_SETFL, O_DIRECT))
errx(2, "fcntl failed, please retry without -D"); errx(2, "fcntl failed, please retry without -D");
...@@ -959,10 +974,18 @@ int main (int argc, char **argv) ...@@ -959,10 +974,18 @@ int main (int argc, char **argv)
fd = create_temp(path, "ioping.tmp"); fd = create_temp(path, "ioping.tmp");
if (fd < 0) if (fd < 0)
err(2, "failed to create temporary file at \"%s\"", path); err(2, "failed to create temporary file at \"%s\"", path);
if (keep_file) {
if (fstat(fd, &st))
err(2, "fstat at \"%s\" failed", path);
if (st.st_size >= offset + wsize &&
st.st_blocks >= (st.st_size + 511) / 512)
goto skip_preparation;
}
for (woffset = 0 ; woffset + size <= wsize ; woffset += size) { for (woffset = 0 ; woffset + size <= wsize ; woffset += size) {
if (pwrite(fd, buf, size, offset + woffset) != size) if (pwrite(fd, buf, size, offset + woffset) != size)
err(2, "write failed"); err(2, "write failed");
} }
skip_preparation:
if (fsync(fd)) if (fsync(fd))
err(2, "fsync failed"); err(2, "fsync failed");
} else if (S_ISREG(st.st_mode)) { } else if (S_ISREG(st.st_mode)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment