From: Eric Sandeen <sandeen@redhat.com>
To: xfs mailing list <xfs@oss.sgi.com>
Subject: [PATCH] xfstests: update aio-stress.c, with copyright information intact
Date: Fri, 05 Jun 2009 11:20:44 -0500 [thread overview]
Message-ID: <4A2945DC.8040809@redhat.com> (raw)
Pulled from:
http://ltp.cvs.sourceforge.net/viewvc/ltp/ltp/testcases/kernel/io/ltp-aiodio/aio-stress.c
revision 1.8
There are a couple new options, but the main motivator is to
get the license text intact again.
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
---
iff --git a/ltp/aio-stress.c b/ltp/aio-stress.c
index 6ebe082..ab9e006 100644
--- a/ltp/aio-stress.c
+++ b/ltp/aio-stress.c
@@ -1,7 +1,45 @@
/*
+ * Copyright (c) 2004 SuSE, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ *
+ * aio-stress
+ *
+ * will open or create each file on the command line, and start a series
+ * of aio to it.
+ *
+ * aio is done in a rotating loop. first file1 gets 8 requests, then
+ * file2, then file3 etc. As each file finishes writing, it is switched
+ * to reads
+ *
+ * io buffers are aligned in case you want to do raw io
+ *
+ * compile with gcc -Wall -laio -lpthread -o aio-stress aio-stress.c
+ *
+ * run aio-stress -h to see the options
+ *
+ * Please mail Chris Mason (mason@suse.com) with bug reports or patches
*/
#define _FILE_OFFSET_BITS 64
-#define PROG_VERSION "0.18"
+#define PROG_VERSION "0.21"
#define NEW_GETEVENTS
#include <stdio.h>
@@ -50,6 +88,7 @@ unsigned long page_size_mask;
int o_direct = 0;
int o_sync = 0;
int latency_stats = 0;
+int completion_latency_stats = 0;
int io_iter = 8;
int iterations = RUN_FOREVER;
int max_io_submit = 0;
@@ -67,6 +106,7 @@ int padded_reclen = 0;
int stonewall = 1;
int verify = 0;
char *verify_buf = NULL;
+int unlink_files = 0;
struct io_unit;
struct thread_info;
@@ -164,6 +204,8 @@ struct io_unit {
long res;
struct io_unit *next;
+
+ struct timeval io_start_time; /* time of io_submit */
};
struct thread_info {
@@ -203,15 +245,20 @@ struct thread_info {
/* how much io this thread did in the last stage */
double stage_mb_trans;
+
+ /* latency completion stats i/o time from io_submit until io_getevents */
+ struct io_latency io_completion_latency;
};
-static double time_since(struct timeval *tv) {
+/*
+ * return seconds between start_tv and stop_tv in double precision
+ */
+static double time_since(struct timeval *start_tv, struct timeval *stop_tv)
+{
double sec, usec;
double ret;
- struct timeval stop;
- gettimeofday(&stop, NULL);
- sec = stop.tv_sec - tv->tv_sec;
- usec = stop.tv_usec - tv->tv_usec;
+ sec = stop_tv->tv_sec - start_tv->tv_sec;
+ usec = stop_tv->tv_usec - start_tv->tv_usec;
if (sec > 0 && usec < 0) {
sec--;
usec += 1000000;
@@ -222,11 +269,25 @@ static double time_since(struct timeval *tv) {
return ret;
}
-static void calc_latency(struct timeval *tv, struct io_latency *lat)
+/*
+ * return seconds between start_tv and now in double precision
+ */
+static double time_since_now(struct timeval *start_tv)
+{
+ struct timeval stop_time;
+ gettimeofday(&stop_time, NULL);
+ return time_since(start_tv, &stop_time);
+}
+
+/*
+ * Add latency info to latency struct
+ */
+static void calc_latency(struct timeval *start_tv, struct timeval *stop_tv,
+ struct io_latency *lat)
{
double delta;
int i;
- delta = time_since(tv);
+ delta = time_since(start_tv, stop_tv);
delta = delta * 1000;
if (delta > lat->max)
@@ -344,20 +405,19 @@ static void print_time(struct io_oper *oper) {
double tput;
double mb;
- runtime = time_since(&oper->start_time);
+ runtime = time_since_now(&oper->start_time);
mb = oper_mb_trans(oper);
tput = mb / runtime;
fprintf(stderr, "%s on %s (%.2f MB/s) %.2f MB in %.2fs\n",
stage_name(oper->rw), oper->file_name, tput, mb, runtime);
}
-static void print_latency(struct thread_info *t) {
- struct io_latency *lat = &t->io_submit_latency;
+static void print_lat(char *str, struct io_latency *lat) {
double avg = lat->total_lat / lat->total_io;
int i;
double total_counted = 0;
- fprintf(stderr, "latency min %.2f avg %.2f max %.2f\n\t",
- lat->min, avg, lat->max);
+ fprintf(stderr, "%s min %.2f avg %.2f max %.2f\n\t",
+ str, lat->min, avg, lat->max);
for (i = 0 ; i < DEVIATIONS ; i++) {
fprintf(stderr, " %.0f < %d", lat->deviations[i], deviations[i]);
@@ -366,16 +426,30 @@ static void print_latency(struct thread_info *t) {
if (total_counted && lat->total_io - total_counted)
fprintf(stderr, " < %.0f", lat->total_io - total_counted);
fprintf(stderr, "\n");
- memset(&t->io_submit_latency, 0, sizeof(t->io_submit_latency));
+ memset(lat, 0, sizeof(*lat));
+}
+
+static void print_latency(struct thread_info *t)
+{
+ struct io_latency *lat = &t->io_submit_latency;
+ print_lat("latency", lat);
+}
+
+static void print_completion_latency(struct thread_info *t)
+{
+ struct io_latency *lat = &t->io_completion_latency;
+ print_lat("completion latency", lat);
}
/*
* updates the fields in the io operation struct that belongs to this
* io unit, and make the io unit reusable again
*/
-void finish_io(struct thread_info *t, struct io_unit *io, long result) {
+void finish_io(struct thread_info *t, struct io_unit *io, long result,
+ struct timeval *tv_now) {
struct io_oper *oper = io->io_oper;
+ calc_latency(&io->io_start_time, tv_now, &t->io_completion_latency);
io->res = result;
io->busy = IO_FREE;
io->next = t->free_ious;
@@ -396,6 +470,7 @@ int read_some_events(struct thread_info *t) {
int nr;
int i;
int min_nr = io_iter;
+ struct timeval stop_time;
if (t->num_global_pending < io_iter)
min_nr = t->num_global_pending;
@@ -408,10 +483,11 @@ int read_some_events(struct thread_info *t) {
if (nr <= 0)
return nr;
+ gettimeofday(&stop_time, NULL);
for (i = 0 ; i < nr ; i++) {
event = t->events + i;
event_io = (struct io_unit *)((unsigned long)event->obj);
- finish_io(t, event_io, event->res);
+ finish_io(t, event_io, event->res, &stop_time);
}
return nr;
}
@@ -465,9 +541,11 @@ static int io_oper_wait(struct thread_info *t, struct io_oper *oper) {
#else
while(io_getevents(t->io_ctx, 1, &event, NULL) > 0) {
#endif
+ struct timeval tv_now;
event_io = (struct io_unit *)((unsigned long)event.obj);
- finish_io(t, event_io, event.res);
+ gettimeofday(&tv_now, NULL);
+ finish_io(t, event_io, event.res, &tv_now);
if (oper->num_pending == 0)
break;
@@ -641,7 +719,8 @@ int build_oper(struct thread_info *t, struct io_oper *oper, int num_ios,
* runs through the iocbs in the array provided and updates
* counters in the associated oper struct
*/
-static void update_iou_counters(struct iocb **my_iocbs, int nr)
+static void update_iou_counters(struct iocb **my_iocbs, int nr,
+ struct timeval *tv_now)
{
struct io_unit *io;
int i;
@@ -649,6 +728,7 @@ static void update_iou_counters(struct iocb **my_iocbs, int nr)
io = (struct io_unit *)(my_iocbs[i]);
io->io_oper->num_pending++;
io->io_oper->started_ios++;
+ io->io_start_time = *tv_now; /* set time of io_submit */
}
}
@@ -657,15 +737,18 @@ int run_built(struct thread_info *t, int num_ios, struct iocb **my_iocbs)
{
int ret;
struct timeval start_time;
+ struct timeval stop_time;
resubmit:
gettimeofday(&start_time, NULL);
ret = io_submit(t->io_ctx, num_ios, my_iocbs);
- calc_latency(&start_time, &t->io_submit_latency);
+ gettimeofday(&stop_time, NULL);
+ calc_latency(&start_time, &stop_time, &t->io_submit_latency);
+
if (ret != num_ios) {
/* some ios got through */
if (ret > 0) {
- update_iou_counters(my_iocbs, ret);
+ update_iou_counters(my_iocbs, ret, &stop_time);
my_iocbs += ret;
t->num_global_pending += ret;
num_ios -= ret;
@@ -675,15 +758,19 @@ resubmit:
* retry
*/
if (ret > 0 || ret == -EAGAIN) {
+ int old_ret = ret;
if ((ret = read_some_events(t) > 0)) {
goto resubmit;
+ } else {
+ fprintf(stderr, "ret was %d and now is %d\n", ret, old_ret);
+ abort();
}
}
fprintf(stderr, "ret %d (%s) on io_submit\n", ret, strerror(-ret));
return -1;
}
- update_iou_counters(my_iocbs, ret);
+ update_iou_counters(my_iocbs, ret, &stop_time);
t->num_global_pending += ret;
return 0;
}
@@ -972,7 +1059,7 @@ free_buffers:
*/
void global_thread_throughput(struct thread_info *t, char *this_stage) {
int i;
- double runtime = time_since(&global_stage_start_time);
+ double runtime = time_since_now(&global_stage_start_time);
double total_mb = 0;
double min_trans = 0;
@@ -1013,121 +1100,109 @@ int worker(struct thread_info *t)
aio_setup(&t->io_ctx, 512);
restart:
- printf("Starting %s iter:%d \n", __FUNCTION__,iteration);
if (num_threads > 1) {
- printf("num_threads %d \n", num_threads);
pthread_mutex_lock(&stage_mutex);
- threads_starting++;
- if (threads_starting == num_threads) {
- threads_ending = 0;
- gettimeofday(&global_stage_start_time, NULL);
- pthread_cond_broadcast(&stage_cond);
- }
- while (threads_starting != num_threads)
- pthread_cond_wait(&stage_cond, &stage_mutex);
+ threads_starting++;
+ if (threads_starting == num_threads) {
+ threads_ending = 0;
+ gettimeofday(&global_stage_start_time, NULL);
+ pthread_cond_broadcast(&stage_cond);
+ }
+ while (threads_starting != num_threads)
+ pthread_cond_wait(&stage_cond, &stage_mutex);
pthread_mutex_unlock(&stage_mutex);
}
if (t->active_opers) {
-// printf("active_opers %p line:%d\n", t->active_opers, __LINE__);
this_stage = stage_name(t->active_opers->rw);
- gettimeofday(&stage_time, NULL);
- t->stage_mb_trans = 0;
+ gettimeofday(&stage_time, NULL);
+ t->stage_mb_trans = 0;
}
+
cnt = 0;
/* first we send everything through aio */
-// printf("cnt:%d max_iterations:%d oper:%p\n",cnt, iterations,oper);
-
- while (t->active_opers && (cnt < iterations || iterations == RUN_FOREVER)) {
-// printf("active_opers %p line:%d cnt:%d ", t->active_opers,__LINE__,cnt);
- if (stonewall && threads_ending) {
- oper = t->active_opers;
- oper->stonewalled = 1;
- oper_list_del(oper, &t->active_opers);
- oper_list_add(oper, &t->finished_opers);
-// printf(" if branch\n");
- } else {
- run_active_list(t, io_iter, max_io_submit);
-// printf(" else branch\n");
+ while(t->active_opers && (cnt < iterations || iterations == RUN_FOREVER)) {
+ if (stonewall && threads_ending) {
+ oper = t->active_opers;
+ oper->stonewalled = 1;
+ oper_list_del(oper, &t->active_opers);
+ oper_list_add(oper, &t->finished_opers);
+ } else {
+ run_active_list(t, io_iter, max_io_submit);
}
- cnt++;
+ cnt++;
}
-
if (latency_stats)
print_latency(t);
+ if (completion_latency_stats)
+ print_completion_latency(t);
+
/* then we wait for all the operations to finish */
oper = t->finished_opers;
-// printf("line:%d oper:%p\n", __LINE__, oper);
do {
- io_oper_wait(t, oper);
- if (oper != NULL) {
- oper = oper->next;
- }
- } while (oper != t->finished_opers);
-// printf("finished_opers %p line:%d\n", t->finished_opers,__LINE__);
+ if (!oper)
+ break;
+ io_oper_wait(t, oper);
+ oper = oper->next;
+ } while(oper != t->finished_opers);
/* then we do an fsync to get the timing for any future operations
* right, and check to see if any of these need to get restarted
*/
oper = t->finished_opers;
-// printf("oper %p line:%d\n", oper,__LINE__);
- while (oper) {
- if (fsync_stages)
+ while(oper) {
+ if (fsync_stages)
fsync(oper->fd);
- t->stage_mb_trans += oper_mb_trans(oper);
- if (restart_oper(oper)) {
- oper_list_del(oper, &t->finished_opers);
- oper_list_add(oper, &t->active_opers);
- oper = t->finished_opers;
- continue;
- }
- oper = oper->next;
- if (oper == t->finished_opers)
- break;
+ t->stage_mb_trans += oper_mb_trans(oper);
+ if (restart_oper(oper)) {
+ oper_list_del(oper, &t->finished_opers);
+ oper_list_add(oper, &t->active_opers);
+ oper = t->finished_opers;
+ continue;
+ }
+ oper = oper->next;
+ if (oper == t->finished_opers)
+ break;
}
if (t->stage_mb_trans && t->num_files > 0) {
-// printf("num_files %d line:%d\n", t->num_files,__LINE__);
- double seconds = time_since(&stage_time);
- fprintf(stderr, "thread %d %s totals (%.2f MB/s) %.2f MB in %.2fs\n",
- t - global_thread_info, this_stage, t->stage_mb_trans/seconds,
- t->stage_mb_trans, seconds);
+ double seconds = time_since_now(&stage_time);
+ fprintf(stderr, "thread %d %s totals (%.2f MB/s) %.2f MB in %.2fs\n",
+ t - global_thread_info, this_stage, t->stage_mb_trans/seconds,
+ t->stage_mb_trans, seconds);
}
if (num_threads > 1) {
-// printf("num_threads %d line:%d\n", num_threads,__LINE__);
- pthread_mutex_lock(&stage_mutex);
- threads_ending++;
- if (threads_ending == num_threads) {
- threads_starting = 0;
- pthread_cond_broadcast(&stage_cond);
- global_thread_throughput(t, this_stage);
- }
-// printf("threads_ending %d line:%d\n", threads_ending,__LINE__);
- while (threads_ending != num_threads)
- pthread_cond_wait(&stage_cond, &stage_mutex);
- pthread_mutex_unlock(&stage_mutex);
+ pthread_mutex_lock(&stage_mutex);
+ threads_ending++;
+ if (threads_ending == num_threads) {
+ threads_starting = 0;
+ pthread_cond_broadcast(&stage_cond);
+ global_thread_throughput(t, this_stage);
+ }
+ while(threads_ending != num_threads)
+ pthread_cond_wait(&stage_cond, &stage_mutex);
+ pthread_mutex_unlock(&stage_mutex);
}
-
+
/* someone got restarted, go back to the beginning */
if (t->active_opers && (cnt < iterations || iterations == RUN_FOREVER)) {
- iteration++;
+ iteration++;
goto restart;
}
/* finally, free all the ram */
-// printf("finished_opers %p line:%d\n", t->finished_opers,__LINE__);
- while (t->finished_opers) {
- oper = t->finished_opers;
- oper_list_del(oper, &t->finished_opers);
- status = finish_oper(t, oper);
+ while(t->finished_opers) {
+ oper = t->finished_opers;
+ oper_list_del(oper, &t->finished_opers);
+ status = finish_oper(t, oper);
}
if (t->num_global_pending) {
fprintf(stderr, "global num pending is %d\n", t->num_global_pending);
}
io_queue_release(t->io_ctx);
-
+
return status;
}
@@ -1138,7 +1213,6 @@ int run_workers(struct thread_info *t, int num_threads)
int thread_ret;
int i;
-// printf("%s num_threads %d line:%d\n", __FUNCTION__,num_threads,__LINE__);
for(i = 0 ; i < num_threads ; i++) {
ret = pthread_create(&t[i].tid, NULL, (start_routine)worker, t + i);
if (ret) {
@@ -1178,6 +1252,10 @@ off_t parse_size(char *size_arg, off_t mult) {
case 'K':
mult = 1024;
break;
+ case 'b':
+ case 'B':
+ mult = 1;
+ break;
}
ret = mult * num;
return ret;
@@ -1205,7 +1283,9 @@ void print_usage(void) {
printf("\t-m shmfs mmap a file in /dev/shm for io buffers\n");
printf("\t-n no fsyncs between write stage and read stage\n");
printf("\t-l print io_submit latencies after each stage\n");
+ printf("\t-L print io completion latencies after each stage\n");
printf("\t-t number of threads to run\n");
+ printf("\t-u unlink files after completion\n");
printf("\t-v verification of bytes written\n");
printf("\t-x turn off thread stonewalling\n");
printf("\t-h this message\n");
@@ -1232,7 +1312,7 @@ int main(int ac, char **av)
page_size_mask = getpagesize() - 1;
while(1) {
- c = getopt(ac, av, "a:b:c:C:m:s:r:d:i:I:o:t:lnhOSxv");
+ c = getopt(ac, av, "a:b:c:C:m:s:r:d:i:I:o:t:lLnhOSxvu");
if (c < 0)
break;
@@ -1270,6 +1350,9 @@ int main(int ac, char **av)
case 'l':
latency_stats = 1;
break;
+ case 'L':
+ completion_latency_stats = 1;
+ break;
case 'm':
if (!strcmp(optarg, "shm")) {
fprintf(stderr, "using ipc shm\n");
@@ -1296,6 +1379,9 @@ int main(int ac, char **av)
case 'x':
stonewall = 0;
break;
+ case 'u':
+ unlink_files = 1;
+ break;
case 'v':
verify = 1;
break;
@@ -1379,7 +1465,6 @@ int main(int ac, char **av)
for (j = 0 ; j < num_contexts ; j++) {
thread_index = open_fds % num_threads;
open_fds++;
-// fprintf(stderr, "adding file %s thread %d\n", av[i], thread_index);
rwfd = open(av[i], O_CREAT | O_RDWR | o_direct | o_sync, 0600);
assert(rwfd != -1);
@@ -1407,25 +1492,21 @@ int main(int ac, char **av)
if (num_threads > 1){
printf("Running multi thread version num_threads:%d\n", num_threads);
run_workers(t, num_threads);
- }
- else {
+ } else {
printf("Running single thread version \n");
- status = worker(t);
+ status = worker(t);
}
-
-
- for (i = optind ; i < ac ; i++) {
- printf("Cleaning up file %s \n", av[i]);
- unlink(av[i]);
+ if (unlink_files) {
+ for (i = optind ; i < ac ; i++) {
+ printf("Cleaning up file %s \n", av[i]);
+ unlink(av[i]);
+ }
}
if (status) {
- printf("non zero return %d \n", status);
- }
- else{
- printf("aio-stress Completed successfully %d \n", status);
+ exit(1);
}
-
- exit(0);
+ return status;
}
+
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next reply other threads:[~2009-06-05 16:20 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-06-05 16:20 Eric Sandeen [this message]
2009-06-05 19:10 ` [PATCH] xfstests: update aio-stress.c, with copyright information intact Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4A2945DC.8040809@redhat.com \
--to=sandeen@redhat.com \
--cc=xfs@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.