1c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee/*
2c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * Copyright 2010 by Garmin Ltd. or its subsidiaries
3c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee *
4c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * Licensed under the Apache License, Version 2.0 (the "License");
5c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * you may not use this file except in compliance with the License.
6c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * You may obtain a copy of the License at
7c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee *
8c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee *      http://www.apache.org/licenses/LICENSE-2.0
9c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee *
10c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * Unless required by applicable law or agreed to in writing, software
11c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * distributed under the License is distributed on an "AS IS" BASIS,
12c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * See the License for the specific language governing permissions and
14c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * limitations under the License.
15c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee *
16c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * Performs a simple write/readback test to verify correct functionality
17c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * of direct i/o on a block device node.
18c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee */
19c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
20c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee/* For large-file support */
21c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#define _FILE_OFFSET_BITS 64
22c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#define _LARGEFILE_SOURCE
23c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#define _LARGEFILE64_SOURCE
24c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
25c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee/* For O_DIRECT */
26c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#define _GNU_SOURCE
27c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
28c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#include <stdio.h>
29c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#include <stdlib.h>
30c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#include <stdint.h>
31c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#include <string.h>
32c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#include <ctype.h>
33c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#include <errno.h>
34c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#include <limits.h>
35c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#include <fcntl.h>
36c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#include <unistd.h>
37c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#include <sys/stat.h>
38c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#include <sys/types.h>
39c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#include <sys/ioctl.h>
40c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#include <sys/mman.h>
41c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
42c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#include <linux/fs.h>
43c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
44c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee#define NUM_TEST_BLKS 128
45c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
46c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee/*
47c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * Allocate page-aligned memory.  Could use posix_memalign(3), but some
48c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * systems don't support it.  Also pre-faults memory since we'll be using
49c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * it all right away anyway.
50c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee */
51c610219fe9441f673e3aee12cf9479ae57feae25Seth Forsheestatic void *pagealign_alloc(size_t size)
52c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee{
53c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	void *ret = mmap(NULL, size, PROT_READ | PROT_WRITE,
54c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE | MAP_LOCKED,
55c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			-1, 0);
56c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	if (ret == MAP_FAILED) {
57c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		perror("mmap");
58c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		ret = NULL;
59c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	}
60c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	return ret;
61c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee}
62c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
63c610219fe9441f673e3aee12cf9479ae57feae25Seth Forsheestatic void pagealign_free(void *addr, size_t size)
64c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee{
65c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	int ret = munmap(addr, size);
66c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	if (ret == -1)
67c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		perror("munmap");
68c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee}
69c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
70c610219fe9441f673e3aee12cf9479ae57feae25Seth Forsheestatic ssize_t do_read(int fd, void *buf, off64_t start, size_t count)
71c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee{
72c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	ssize_t ret;
73c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	size_t bytes_read = 0;
74c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
75c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	lseek64(fd, start, SEEK_SET);
76c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
77c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	do {
78c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		ret = read(fd, (char *)buf + bytes_read, count - bytes_read);
79c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		if (ret == -1) {
80c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			perror("read");
81c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			return -1;
82c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		} else if (ret == 0) {
83c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			fprintf(stderr, "Unexpected end-of-file\n");
84c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			return -1;
85c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		}
86c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		bytes_read += ret;
87c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	} while (bytes_read < count);
88c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
89c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	return bytes_read;
90c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee}
91c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
92c610219fe9441f673e3aee12cf9479ae57feae25Seth Forsheestatic ssize_t do_write(int fd, const void *buf, off64_t start, size_t count)
93c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee{
94c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	ssize_t ret;
95c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	size_t bytes_out = 0;
96c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
97c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	lseek64(fd, start, SEEK_SET);
98c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
99c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	do {
100c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		ret = write(fd, (char *)buf + bytes_out, count - bytes_out);
101c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		if (ret == -1) {
102c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			perror("write");
103c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			return -1;
104c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		} else if (ret == 0) {
105c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			fprintf(stderr, "write returned 0\n");
106c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			return -1;
107c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		}
108c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		bytes_out += ret;
109c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	} while (bytes_out < count);
110c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
111c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	return bytes_out;
112c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee}
113c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
114c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee/*
115c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * Initializes test buffer with locally-unique test pattern.  High 16-bits of
116c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * each 32-bit word contain first disk block number of the test area, low
117c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * 16-bits contain word offset into test area.  The goal is that a given test
118c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * area should never contain the same data as a nearby test area, and that the
119c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * data for a given test area be easily reproducable given the start block and
120c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee * test area size.
121c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee */
122c610219fe9441f673e3aee12cf9479ae57feae25Seth Forsheestatic void init_test_buf(void *buf, uint64_t start_blk, size_t len)
123c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee{
124c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	uint32_t *data = buf;
125c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	size_t i;
126c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
127c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	len /= sizeof(uint32_t);
128c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	for (i = 0; i < len; i++)
129c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		data[i] = (start_blk & 0xFFFF) << 16 | (i & 0xFFFF);
130c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee}
131c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
132c610219fe9441f673e3aee12cf9479ae57feae25Seth Forsheestatic void dump_hex(const void *buf, int len)
133c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee{
134c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	const uint8_t *data = buf;
135c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	int i;
136c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	char ascii_buf[17];
137c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
138c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	ascii_buf[16] = '\0';
139c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
140c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	for (i = 0; i < len; i++) {
141c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		int val = data[i];
142c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		int off = i % 16;
143c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
144c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		if (off == 0)
145c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			printf("%08x  ", i);
146c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		printf("%02x ", val);
147c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		ascii_buf[off] = isprint(val) ? val : '.';
148c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		if (off == 15)
149c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			printf(" %-16s\n", ascii_buf);
150c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	}
151c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
152c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	i %= 16;
153c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	if (i) {
154c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		ascii_buf[i] = '\0';
155c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		while (i++ < 16)
156c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			printf("   ");
157c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		printf(" %-16s\n", ascii_buf);
158c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	}
159c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee}
160c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
161c610219fe9441f673e3aee12cf9479ae57feae25Seth Forsheestatic void update_progress(int current, int total)
162c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee{
163c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	double pct_done = (double)current * 100 / total;
164c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	printf("Testing area %d/%d (%6.2f%% complete)\r", current, total,
165c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			pct_done);
166c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	fflush(stdout);
167c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee}
168c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
169c610219fe9441f673e3aee12cf9479ae57feae25Seth Forsheeint main(int argc, const char *argv[])
170c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee{
171c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	int ret = 1;
172c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	const char *path;
173c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	int fd;
174c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	struct stat stat;
175c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	void *read_buf = NULL, *write_buf = NULL;
176c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	int blk_size;
177c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	uint64_t num_blks;
178c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	size_t test_size;
179c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	int test_areas, i;
180c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
181c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	if (argc != 2) {
182c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		printf("Usage: directiotest blkdev_path\n");
183c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		exit(1);
184c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	}
185c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
186c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	path = argv[1];
187c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	fd = open(path, O_RDWR | O_DIRECT | O_LARGEFILE);
188c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	if (fd == -1) {
189c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		perror("open");
190c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		exit(1);
191c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	}
192c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	if (fstat(fd, &stat) == -1) {
193c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		perror("stat");
194c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		goto cleanup;
195c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	} else if (!S_ISBLK(stat.st_mode)) {
196c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		fprintf(stderr, "%s is not a block device\n", path);
197c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		goto cleanup;
198c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	}
199c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
200c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	if (ioctl(fd, BLKSSZGET, &blk_size) == -1) {
201c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		perror("ioctl");
202c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		goto cleanup;
203c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	}
204c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	if (ioctl(fd, BLKGETSIZE64, &num_blks) == -1) {
205c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		perror("ioctl");
206c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		goto cleanup;
207c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	}
208c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	num_blks /= blk_size;
209c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
210c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	test_size = (size_t)blk_size * NUM_TEST_BLKS;
211c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	read_buf = pagealign_alloc(test_size);
212c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	write_buf = pagealign_alloc(test_size);
213c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	if (!read_buf || !write_buf) {
214c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		fprintf(stderr, "Error allocating test buffers\n");
215c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		goto cleanup;
216c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	}
217c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
218c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	/*
219c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	 * Start the actual test.  Go through the entire device, writing
220c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	 * locally-unique patern to each test block and then reading it
221c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	 * back.
222c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	 */
223c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	if (num_blks / NUM_TEST_BLKS > INT_MAX) {
224c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		printf("Warning: Device too large for test variables\n");
225c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		printf("Entire device will not be tested\n");
226c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		test_areas = INT_MAX;
227c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	} else {
228c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		test_areas = num_blks / NUM_TEST_BLKS;
229c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	}
230c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
231c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	printf("Starting test\n");
232c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
233c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	for (i = 0; i < test_areas; i++) {
234c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		uint64_t cur_blk = (uint64_t)i * NUM_TEST_BLKS;
235c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
236c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		update_progress(i + 1, test_areas);
237c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
238c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		init_test_buf(write_buf, cur_blk, test_size);
239c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
240c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		if (do_write(fd, write_buf, cur_blk * blk_size, test_size) !=
241c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee				(ssize_t)test_size) {
242c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			fprintf(stderr, "write failed, aborting test\n");
243c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			goto cleanup;
244c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		}
245c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		if (do_read(fd, read_buf, cur_blk * blk_size, test_size) !=
246c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee				(ssize_t)test_size) {
247c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			fprintf(stderr, "read failed, aborting test\n");
248c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			goto cleanup;
249c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		}
250c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
251c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		if (memcmp(write_buf, read_buf, test_size)) {
252c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			printf("Readback verification failed at block %llu\n\n",
253c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee					cur_blk);
254c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			printf("Written data:\n");
255c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			dump_hex(write_buf, test_size);
256c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			printf("\nRead data:\n");
257c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			dump_hex(read_buf, test_size);
258c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee			goto cleanup;
259c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		}
260c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	}
261c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
262c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	printf("\nTest complete\n");
263c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	ret = 0;
264c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee
265c610219fe9441f673e3aee12cf9479ae57feae25Seth Forsheecleanup:
266c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	if (read_buf)
267c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		pagealign_free(read_buf, test_size);
268c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	if (write_buf)
269c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee		pagealign_free(write_buf, test_size);
270c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	close(fd);
271c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee	return ret;
272c610219fe9441f673e3aee12cf9479ae57feae25Seth Forshee}
273