From 89a5b7257e6779ff7a52b7abeef639033e9f1ca6 Mon Sep 17 00:00:00 2001
From: wangdi <wangdi>
Date: Fri, 4 Jul 2008 22:25:35 +0000
Subject: [PATCH] Branch: HEAD add stride read-ahead test case b=16172
 i=adilger,nikita

---
 lustre/tests/Makefile.am                 |  2 +-
 lustre/tests/{random-reads.c => reads.c} | 94 ++++++++++++++++++++----
 lustre/tests/sanity.sh                   | 76 ++++++++++++++++++-
 3 files changed, 155 insertions(+), 17 deletions(-)
 rename lustre/tests/{random-reads.c => reads.c} (63%)

diff --git a/lustre/tests/Makefile.am b/lustre/tests/Makefile.am
index 4d4017baa8..f2b2c65240 100644
--- a/lustre/tests/Makefile.am
+++ b/lustre/tests/Makefile.am
@@ -34,7 +34,7 @@ noinst_PROGRAMS += wantedi statone runas openfile getdents o_directory rmdirmany
 noinst_PROGRAMS += small_write multiop sleeptest ll_sparseness_verify cmknod
 noinst_PROGRAMS += ll_sparseness_write mrename ll_dirstripe_verify mkdirmany
 noinst_PROGRAMS += openfilleddirunlink rename_many memhog iopentest1 iopentest2
-noinst_PROGRAMS += mmap_sanity flock_test writemany random-reads flocks_test
+noinst_PROGRAMS += mmap_sanity flock_test writemany reads flocks_test
 noinst_PROGRAMS += ll_getstripe_info write_time_limit
 if MPITESTS
 noinst_PROGRAMS += parallel_grouplock write_append_truncate createmany_mpi
diff --git a/lustre/tests/random-reads.c b/lustre/tests/reads.c
similarity index 63%
rename from lustre/tests/random-reads.c
rename to lustre/tests/reads.c
index 1722afb34f..77ebeaaa56 100644
--- a/lustre/tests/random-reads.c
+++ b/lustre/tests/reads.c
@@ -1,7 +1,8 @@
 /*
- * Lustre Random Reads test
+ * Lustre Reads test
  *
  * Copyright (c) 2005 Cluster File Systems, Inc.
+ * Copyright (c) 2008 SUN Microsystems.
  *
  * Author: Nikita Danilov <nikita@clusterfs.com>
  *
@@ -34,13 +35,14 @@
 #include <sys/types.h>
 #include <sys/time.h>
 
-long long atoll(const char *nptr);
-
 static void usage(void)
 {
-	printf("random-reads: read random chunks of a file.\n");
+	printf("reads: read random or stride chunks of a file.\n");
 	printf("Usage:\n\n");
-	printf("random-reads -f <filename> -s <filesize> -b <buffersize> -a <adjacent reads> [-v] [-h] [-C] [-S <seed>] [-n <iterations>] [-w <width>] [-t <timelimit>]\n");
+	printf("reads -f <filename> -s <filesize> -b <buffersize>"
+	       "-a <adjacent reads> [-v] [-h] [-C] [-l <stride_length> ] "
+	       "[ -o <stride_offset> ] [-S <seed>] [-n <iterations>]"
+	       "[-w <width>] [-t <timelimit>]\n");
 }
 
 enum {
@@ -82,6 +84,8 @@ int main(int argc, char **argv)
 	unsigned int seed = 0;
 	unsigned long iterations = 0;
 	unsigned long timelimit = 24 * 3600;
+	unsigned long stride_length = 0;
+	unsigned long stride_offset = 0;
 
 	int opt;
 	int fd;
@@ -95,9 +99,10 @@ int main(int argc, char **argv)
 	double usecs;
 
 	char *buf;
+	char *term;
 
 	do {
-		opt = getopt(argc, argv, "f:s:b:va:hCS:n:t:w:");
+		opt = getopt(argc, argv, "f:s:b:va:hCS:n:t:l:o:w:");
 		switch (opt) {
 		case -1:
 			break;
@@ -113,28 +118,81 @@ int main(int argc, char **argv)
 			fname = strdup(optarg);
 			break;
 		case 's':
-			size = atoll(optarg);
+			size = strtol(optarg, &term, 0);
+			if (term == optarg) {
+				fprintf (stderr, "Can't parse size %s\n", optarg);
+				usage();
+				return RR_SET;
+			}
 			break;
 		case 'b':
-			bsize = atol(optarg);
+			bsize = strtol(optarg, &term, 0);
+			if (term == optarg) {
+				fprintf (stderr, "Can't parse bsize %s\n", optarg);
+				usage();
+				return RR_SET;
+			}
 			break;
 		case 'a':
-			ad = atoi(optarg);
+			ad = (int)strtol(optarg, &term, 0);
+			if (term == optarg) {
+				fprintf (stderr, "Can't parse ad %s\n", optarg);
+				usage();
+				return RR_SET;
+			}
 			break;
 		case 'C':
 			preclean = 1;
 			break;
 		case 'S':
-			seed = atol(optarg);
+			seed = strtol(optarg, &term, 0);
+			if (term == optarg) {
+				fprintf (stderr, "Can't parse seed %s\n", optarg);
+				usage();
+				return RR_SET;
+			}
 			break;
 		case 'n':
-			iterations = atoll(optarg);
+			iterations = strtol(optarg, &term, 0);
+			if (term == optarg) {
+				fprintf (stderr, "Can't parse seed %s\n", optarg);
+				usage();
+				return RR_SET;
+			}
+			break;
+
 			break;
 		case 't':
-			timelimit = atoll(optarg);
+			timelimit = strtol(optarg, &term, 0);
+			if (term == optarg) {
+				fprintf (stderr, "Can't parse seed %s\n", optarg);
+				usage();
+				return RR_SET;
+			}
+			break;
+                case 'l':
+                        stride_length = strtol(optarg, &term, 0);
+			if (term == optarg) {
+				fprintf (stderr, "Can't parse seed %s\n", optarg);
+				usage();
+				return RR_SET;
+			}
+	       		break;
+		case 'o':
+			stride_offset = strtol(optarg, &term, 0);
+			if (term == optarg) {
+				fprintf (stderr, "Can't parse seed %s\n", optarg);
+				usage();
+				return RR_SET;
+			}
 			break;
 		case 'w':
-			width = atoi(optarg);
+			width = (int)strtol(optarg, &term, 0);
+			if (term == optarg) {
+				fprintf (stderr, "Can't parse seed %s\n", optarg);
+				usage();
+				return RR_SET;
+			}
 			break;
 		}
 	} while (opt != -1);
@@ -171,6 +229,7 @@ int main(int argc, char **argv)
 			if (ret < 0) {
 				LOG(LOG_CRIT, "write() failure: %s\n",
 				    strerror(errno));
+				close(fd);
 				return RR_PRECLEAN;
 			}
 		}
@@ -183,7 +242,12 @@ int main(int argc, char **argv)
 		unsigned long block_nr;
 		int j;
 
-		block_nr = (int) ((double)nblocks*rand()/(RAND_MAX+1.0));
+		if (stride_length) 
+			block_nr = (unsigned long)(i*stride_length + 
+						   stride_offset) % nblocks;
+		else
+			block_nr = (unsigned long)((double)nblocks*rand()/
+						   (RAND_MAX+1.0));
 		if (i % width == 0)
 			LOG(LOG_INFO, "\n%9lu: ", i);
 		LOG(LOG_INFO, "%7lu ", block_nr);
@@ -193,6 +257,7 @@ int main(int argc, char **argv)
 				LOG(LOG_CRIT,
 				    "pread(...%zi, %li) got: %zi, %s\n", bsize,
 				    block_nr * bsize, ret, strerror(errno));
+				close(fd);
 				return RR_READ;
 			}
 		}
@@ -200,6 +265,7 @@ int main(int argc, char **argv)
 		if (stop.tv_sec > timelimit)
 			break;
 	}
+	close(fd);
 	usecs = (stop.tv_sec - start.tv_sec) * 1000000. +
 		stop.tv_usec - start.tv_usec;
 	printf("\n%fs, %gMB/s\n", usecs / 1000000.,
diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh
index 33dba9c393..f2fc49d410 100644
--- a/lustre/tests/sanity.sh
+++ b/lustre/tests/sanity.sh
@@ -45,7 +45,7 @@ LCTL=${LCTL:-lctl}
 MCREATE=${MCREATE:-mcreate}
 OPENFILE=${OPENFILE:-openfile}
 OPENUNLINK=${OPENUNLINK:-openunlink}
-RANDOM_READS=${RANDOM_READS:-"random-reads"}
+READS=${READS:-"reads"}
 TOEXCL=${TOEXCL:-toexcl}
 TRUNCATE=${TRUNCATE:-truncate}
 MUNLINK=${MUNLINK:-munlink}
@@ -3655,7 +3655,7 @@ test_101() {
 	# randomly read 10000 of 64K chunks from file 3x 32MB in size
 	#
 	echo "nreads: $nreads file size: $((cache_limit * 3))MB"
-	$RANDOM_READS -f $DIR/$tfile -s$((cache_limit * 3192 * 1024)) -b65536 -C -n$nreads -t 180
+	$READS -f $DIR/$tfile -s$((cache_limit * 3192 * 1024)) -b65536 -C -n$nreads -t 180
 
 	discard=0
 	for s in `lctl get_param -n llite.*.read_ahead_stats | get_named_value 'read but discarded'`; do
@@ -3672,6 +3672,78 @@ test_101() {
 }
 run_test 101 "check read-ahead for random reads ================"
 
+export SETUP_TEST101=no
+setup_test101() {
+	[ "$SETUP_TEST101" = "yes" ] && return
+	mkdir -p $DIR/$tdir
+	STRIPE_SIZE=1048576
+	STRIPE_COUNT=$OSTCOUNT
+	STRIPE_OFFSET=0
+
+	trap cleanup_test101 EXIT
+	# prepare the read-ahead file
+	$SETSTRIPE $DIR/$tfile -s $STRIPE_SIZE -i $STRIPE_OFFSET -c $OSTCOUNT
+
+	dd if=/dev/zero of=$DIR/$tfile bs=1024k count=100 2> /dev/null
+	SETUP_TEST102=yes
+}
+
+cleanup_test101() {
+	[ "$SETUP_TEST101" = "yes" ] || return
+	trap 0
+	rm -rf $DIR/$tdir
+	SETUP_TEST102=no
+}
+
+calc_total() {
+	awk 'BEGIN{total=0}; {total+=$1}; END{print total}'
+}
+
+ra_check_101() {
+	local READ_SIZE=$1
+	local STRIPE_SIZE=1048576
+	local RA_INC=1048576
+	local STRIDE_LENGTH=$((STRIPE_SIZE/READ_SIZE))
+	local FILE_LENGTH=$((64*100))
+	local discard_limit=$(((((((STRIDE_LENGTH - 1))*3)/(STRIDE_LENGTH*OSTCOUNT))* \
+			     (STRIDE_LENGTH*OSTCOUNT - STRIDE_LENGTH))))
+	DISCARD=`$LCTL get_param -n llite.*.read_ahead_stats |   \
+			 get_named_value 'read but discarded' | calc_total`
+
+	if [ $DISCARD -gt $discard_limit ]; then
+		lctl get_param llite.*.read_ahead_stats
+		error "Too many ($DISCARD) discarded pages with size (${READ_SIZE})"
+	else
+		echo "Read-ahead success for size ${READ_SIZE}"
+	fi
+}
+
+test_101b() {
+	[ "$OSTCOUNT" -lt "2" ] && skip "skipping stride IO stride-ahead test" && return
+	local STRIPE_SIZE=1048576
+	local STRIDE_SIZE=$((STRIPE_SIZE*OSTCOUNT))
+	local FILE_LENGTH=$((STRIPE_SIZE*100))
+	local ITERATION=$((FILE_LENGTH/STRIDE_SIZE))
+	# prepare the read-ahead file
+	setup_test101
+	cancel_lru_locks osc 
+	for BIDX in 2 4 8 16 32 64 128 256
+	do
+		local BSIZE=$((BIDX*4096))
+		local READ_COUNT=$((STRIPE_SIZE/BSIZE))
+		local STRIDE_LENGTH=$((STRIDE_SIZE/BSIZE))
+		local OFFSET=$((STRIPE_SIZE/BSIZE*(OSTCOUNT - 1)))
+		$LCTL set_param -n llite.*.read_ahead_stats 0
+		$READS -f $DIR/$tfile  -l $STRIDE_LENGTH -o $OFFSET \
+			      -s $FILE_LENGTH -b $STRIPE_SIZE -a $READ_COUNT -n $ITERATION
+		cancel_lru_locks osc
+		ra_check_101 $BSIZE
+	done
+	cleanup_test101
+	true
+}
+run_test 101b "check stride-io mode read-ahead ================="
+
 export SETUP_TEST102=no
 setup_test102() {
 	[ "$SETUP_TEST102" = "yes" ] && return
-- 
GitLab