All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] xfstests: update aio-stress.c, with copyright information intact
@ 2009-06-05 16:20 Eric Sandeen
  2009-06-05 19:10 ` Christoph Hellwig
  0 siblings, 1 reply; 2+ messages in thread
From: Eric Sandeen @ 2009-06-05 16:20 UTC (permalink / raw)
  To: xfs mailing list

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

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] xfstests: update aio-stress.c, with copyright information intact
  2009-06-05 16:20 [PATCH] xfstests: update aio-stress.c, with copyright information intact Eric Sandeen
@ 2009-06-05 19:10 ` Christoph Hellwig
  0 siblings, 0 replies; 2+ messages in thread
From: Christoph Hellwig @ 2009-06-05 19:10 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs mailing list

On Fri, Jun 05, 2009 at 11:20:44AM -0500, Eric Sandeen wrote:
> 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>


Looks good,


Reviewed-by: Christoph Hellwig <hch@lst.de>

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2009-06-05 19:10 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-05 16:20 [PATCH] xfstests: update aio-stress.c, with copyright information intact Eric Sandeen
2009-06-05 19:10 ` Christoph Hellwig

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.