1fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe/*
2fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe * blktrace support code for fio
3fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe */
4fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe#include <stdio.h>
5fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe#include <stdlib.h>
65e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe#include <sys/stat.h>
75e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe#include <dirent.h>
88c1fdf044083522504685e3009e356c70d003ef0Jens Axboe
901743ee1718e7ec4b16ae3e53c8f64900c6052ccJens Axboe#include "flist.h"
10fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe#include "fio.h"
11fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe#include "blktrace_api.h"
12fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe
132da7df1d7d002d11161374ac4f0144521f7be0f0Jens Axboe#define TRACE_FIFO_SIZE	8192
14e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe
15e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe/*
16e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * fifo refill frontend, to avoid reading data in trace sized bites
17e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe */
18e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboestatic int refill_fifo(struct thread_data *td, struct fifo *fifo, int fd)
19e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe{
20e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe	char buf[TRACE_FIFO_SIZE];
21f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe	unsigned int total;
22e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe	int ret;
23e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe
24f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe	total = sizeof(buf);
25f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe	if (total > fifo_room(fifo))
26f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe		total = fifo_room(fifo);
27e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe
28f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe	ret = read(fd, buf, total);
29f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe	if (ret < 0) {
30f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe		td_verror(td, errno, "read blktrace file");
31f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe		return -1;
32e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe	}
33e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe
34f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe	if (ret > 0)
35f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe		ret = fifo_put(fifo, buf, ret);
36f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe
37bd6f78b2f0b6375383948f126368804612ec0035Jens Axboe	dprint(FD_BLKTRACE, "refill: filled %d bytes\n", ret);
38f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe	return ret;
39e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe}
40e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe
41e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe/*
42e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * Retrieve 'len' bytes from the fifo, refilling if necessary.
43e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe */
44e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboestatic int trace_fifo_get(struct thread_data *td, struct fifo *fifo, int fd,
45e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe			  void *buf, unsigned int len)
46e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe{
47f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe	if (fifo_len(fifo) < len) {
48f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe		int ret = refill_fifo(td, fifo, fd);
49e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe
50f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe		if (ret < 0)
51f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe			return ret;
52f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe	}
53e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe
54e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe	return fifo_get(fifo, buf, len);
55e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe}
56e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe
578c1fdf044083522504685e3009e356c70d003ef0Jens Axboe/*
588c1fdf044083522504685e3009e356c70d003ef0Jens Axboe * Just discard the pdu by seeking past it.
598c1fdf044083522504685e3009e356c70d003ef0Jens Axboe */
60f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboestatic int discard_pdu(struct thread_data *td, struct fifo *fifo, int fd,
61f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe		       struct blk_io_trace *t)
62fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe{
63fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	if (t->pdu_len == 0)
64fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe		return 0;
65fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe
66bd6f78b2f0b6375383948f126368804612ec0035Jens Axboe	dprint(FD_BLKTRACE, "discard pdu len %u\n", t->pdu_len);
67f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe	return trace_fifo_get(td, fifo, fd, NULL, t->pdu_len);
68fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe}
69fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe
708c1fdf044083522504685e3009e356c70d003ef0Jens Axboe/*
718c1fdf044083522504685e3009e356c70d003ef0Jens Axboe * Check if this is a blktrace binary data file. We read a single trace
728c1fdf044083522504685e3009e356c70d003ef0Jens Axboe * into memory and check for the magic signature.
738c1fdf044083522504685e3009e356c70d003ef0Jens Axboe */
74d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboeint is_blktrace(const char *filename, int *need_swap)
75fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe{
76fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	struct blk_io_trace t;
77fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	int fd, ret;
78fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe
79fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	fd = open(filename, O_RDONLY);
804dced40768378754a156bb3327b10df53cf7eb8cJens Axboe	if (fd < 0)
81fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe		return 0;
82fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe
83fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	ret = read(fd, &t, sizeof(t));
84fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	close(fd);
85fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe
86fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	if (ret < 0) {
87fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe		perror("read blktrace");
88fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe		return 0;
89fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	} else if (ret != sizeof(t)) {
90fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe		log_err("fio: short read on blktrace file\n");
91fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe		return 0;
92fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	}
93fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe
94d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	if ((t.magic & 0xffffff00) == BLK_IO_TRACE_MAGIC) {
95d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe		*need_swap = 0;
96fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe		return 1;
97d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	}
98d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe
99d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	/*
100d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	 * Maybe it needs to be endian swapped...
101d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	 */
102d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	t.magic = fio_swap32(t.magic);
103d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	if ((t.magic & 0xffffff00) == BLK_IO_TRACE_MAGIC) {
104d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe		*need_swap = 1;
105d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe		return 1;
106d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	}
107fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe
108fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	return 0;
109fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe}
110fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe
111d1c46c049cfba2028abc45246e2609bcee52d0f3David Nellansstatic int lookup_device(struct thread_data *td, char *path, unsigned int maj,
112d1c46c049cfba2028abc45246e2609bcee52d0f3David Nellans			 unsigned int min)
1135e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe{
1145e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	struct dirent *dir;
1155e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	struct stat st;
1165e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	int found = 0;
1175e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	DIR *D;
1185e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe
1195e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	D = opendir(path);
1205e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	if (!D)
1215e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe		return 0;
1225e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe
1235e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	while ((dir = readdir(D)) != NULL) {
1245e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe		char full_path[256];
1255e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe
1265e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe		if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))
1275e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe			continue;
1285e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe
129b9fd788f0e8adacc33316107594e9eb0463743d7Bruce Cran		sprintf(full_path, "%s%s%s", path, FIO_OS_PATH_SEPARATOR, dir->d_name);
1305e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe		if (lstat(full_path, &st) == -1) {
1315e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe			perror("lstat");
1325e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe			break;
1335e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe		}
1345e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe
1355e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe		if (S_ISDIR(st.st_mode)) {
136d1c46c049cfba2028abc45246e2609bcee52d0f3David Nellans			found = lookup_device(td, full_path, maj, min);
1375e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe			if (found) {
1385e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe				strcpy(path, full_path);
1395e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe				break;
1405e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe			}
1415e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe		}
1425e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe
1435e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe		if (!S_ISBLK(st.st_mode))
1445e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe			continue;
1455e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe
146d1c46c049cfba2028abc45246e2609bcee52d0f3David Nellans		/*
147d1c46c049cfba2028abc45246e2609bcee52d0f3David Nellans		 * If replay_redirect is set then always return this device
148d1c46c049cfba2028abc45246e2609bcee52d0f3David Nellans		 * upon lookup which overrides the device lookup based on
149d1c46c049cfba2028abc45246e2609bcee52d0f3David Nellans		 * major minor in the actual blktrace
150d1c46c049cfba2028abc45246e2609bcee52d0f3David Nellans		 */
151d1c46c049cfba2028abc45246e2609bcee52d0f3David Nellans		if (td->o.replay_redirect) {
152d1c46c049cfba2028abc45246e2609bcee52d0f3David Nellans			dprint(FD_BLKTRACE, "device lookup: %d/%d\n overridden"
15325a4e78bf7a20802fc64dc4368a821be7dc529c3Jens Axboe					" with: %s\n", maj, min,
154d1c46c049cfba2028abc45246e2609bcee52d0f3David Nellans					td->o.replay_redirect);
155d1c46c049cfba2028abc45246e2609bcee52d0f3David Nellans			strcpy(path, td->o.replay_redirect);
156d1c46c049cfba2028abc45246e2609bcee52d0f3David Nellans			found = 1;
157d1c46c049cfba2028abc45246e2609bcee52d0f3David Nellans			break;
158d1c46c049cfba2028abc45246e2609bcee52d0f3David Nellans		}
159d1c46c049cfba2028abc45246e2609bcee52d0f3David Nellans
1605e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe		if (maj == major(st.st_rdev) && min == minor(st.st_rdev)) {
1615ec10eaad3b09875b91e19a20bbdfa06f2117562Jens Axboe			dprint(FD_BLKTRACE, "device lookup: %d/%d\n", maj, min);
1625e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe			strcpy(path, full_path);
1635e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe			found = 1;
1645e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe			break;
1655e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe		}
1665e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	}
1675e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe
1685e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	closedir(D);
1695e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	return found;
1705e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe}
1715e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe
172c69aa91fa88fe1f0372afe2a56c4e79c62fc49e0Jens Axboe#define FMINORBITS	20
173c69aa91fa88fe1f0372afe2a56c4e79c62fc49e0Jens Axboe#define FMINORMASK	((1U << FMINORBITS) - 1)
174c69aa91fa88fe1f0372afe2a56c4e79c62fc49e0Jens Axboe#define FMAJOR(dev)	((unsigned int) ((dev) >> FMINORBITS))
175c69aa91fa88fe1f0372afe2a56c4e79c62fc49e0Jens Axboe#define FMINOR(dev)	((unsigned int) ((dev) & FMINORMASK))
176eeb9c2aa5439dd6615ad69324f402f774173f6e5Jens Axboe
17789ac1d48971578ccb0645c292d4a058340aeb909Shaohua Listatic void trace_add_open_close_event(struct thread_data *td, int fileno, enum file_log_act action)
178691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe{
179691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe	struct io_piece *ipo;
180691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe
181691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe	ipo = calloc(1, sizeof(*ipo));
1820d29de831183dfd049c97a03008d425ce21e2fa4Jens Axboe	init_ipo(ipo);
183691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe
184691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe	ipo->ddir = DDIR_INVAL;
185691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe	ipo->fileno = fileno;
18689ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li	ipo->file_action = action;
18701743ee1718e7ec4b16ae3e53c8f64900c6052ccJens Axboe	flist_add_tail(&ipo->list, &td->io_log_list);
188691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe}
189691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe
19089ac1d48971578ccb0645c292d4a058340aeb909Shaohua Listatic int trace_add_file(struct thread_data *td, __u32 device)
1915e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe{
19289ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li	static unsigned int last_maj, last_min, last_fileno;
193c69aa91fa88fe1f0372afe2a56c4e79c62fc49e0Jens Axboe	unsigned int maj = FMAJOR(device);
194c69aa91fa88fe1f0372afe2a56c4e79c62fc49e0Jens Axboe	unsigned int min = FMINOR(device);
1955e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	struct fio_file *f;
1965e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	char dev[256];
1975e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	unsigned int i;
1985e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe
1995e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	if (last_maj == maj && last_min == min)
20089ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li		return last_fileno;
2015e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe
2025e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	last_maj = maj;
2035e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	last_min = min;
2045e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe
2055e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	/*
2065e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	 * check for this file in our list
2075e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	 */
2085e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	for_each_file(td, f, i)
20989ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li		if (f->major == maj && f->minor == min) {
21089ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li			last_fileno = f->fileno;
21189ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li			return last_fileno;
21289ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li		}
2135e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe
2145e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe	strcpy(dev, "/dev");
215d1c46c049cfba2028abc45246e2609bcee52d0f3David Nellans	if (lookup_device(td, dev, maj, min)) {
216691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe		int fileno;
217691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe
218bd6f78b2f0b6375383948f126368804612ec0035Jens Axboe		dprint(FD_BLKTRACE, "add devices %s\n", dev);
21949ffb4a2e1ac3026d77d9e1c03edc2753fcec41bJens Axboe		fileno = add_file_exclusive(td, dev);
220b53f2c545d8335380b507bd7281178c25d27ddf0Jens Axboe		td->o.open_files++;
2215903e7b7907854014478b6febfc5645a203ff59eJens Axboe		td->files[fileno]->major = maj;
2225903e7b7907854014478b6febfc5645a203ff59eJens Axboe		td->files[fileno]->minor = min;
22389ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li		trace_add_open_close_event(td, fileno, FIO_LOG_OPEN_FILE);
22489ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li		last_fileno = fileno;
225bd6f78b2f0b6375383948f126368804612ec0035Jens Axboe	}
226f01b34ae759afccf39c1bf47972e45d91448e7bbJens Axboe
22789ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li	return last_fileno;
2285e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe}
2295e6c20673be9f46332f47ede0e3b657b2cc35ec4Jens Axboe
2308c1fdf044083522504685e3009e356c70d003ef0Jens Axboe/*
2318c1fdf044083522504685e3009e356c70d003ef0Jens Axboe * Store blk_io_trace data in an ipo for later retrieval.
2328c1fdf044083522504685e3009e356c70d003ef0Jens Axboe */
233fdefd987d7ba284c7a9e101911c4b8e72fe326adJens Axboestatic void store_ipo(struct thread_data *td, unsigned long long offset,
23489ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li		      unsigned int bytes, int rw, unsigned long long ttime,
23589ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li		      int fileno)
236fdefd987d7ba284c7a9e101911c4b8e72fe326adJens Axboe{
237fdefd987d7ba284c7a9e101911c4b8e72fe326adJens Axboe	struct io_piece *ipo = malloc(sizeof(*ipo));
238fdefd987d7ba284c7a9e101911c4b8e72fe326adJens Axboe
2390d29de831183dfd049c97a03008d425ce21e2fa4Jens Axboe	init_ipo(ipo);
2400d29de831183dfd049c97a03008d425ce21e2fa4Jens Axboe
241a2eea81b53fc1a71b91b20d82bcadffdd4ecb6cdJens Axboe	/*
242a2eea81b53fc1a71b91b20d82bcadffdd4ecb6cdJens Axboe	 * the 512 is wrong here, it should be the hardware sector size...
243a2eea81b53fc1a71b91b20d82bcadffdd4ecb6cdJens Axboe	 */
244a2eea81b53fc1a71b91b20d82bcadffdd4ecb6cdJens Axboe	ipo->offset = offset * 512;
245fdefd987d7ba284c7a9e101911c4b8e72fe326adJens Axboe	ipo->len = bytes;
2468c1fdf044083522504685e3009e356c70d003ef0Jens Axboe	ipo->delay = ttime / 1000;
247fdefd987d7ba284c7a9e101911c4b8e72fe326adJens Axboe	if (rw)
248fdefd987d7ba284c7a9e101911c4b8e72fe326adJens Axboe		ipo->ddir = DDIR_WRITE;
249fdefd987d7ba284c7a9e101911c4b8e72fe326adJens Axboe	else
250fdefd987d7ba284c7a9e101911c4b8e72fe326adJens Axboe		ipo->ddir = DDIR_READ;
25189ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li	ipo->fileno = fileno;
252fdefd987d7ba284c7a9e101911c4b8e72fe326adJens Axboe
253bd6f78b2f0b6375383948f126368804612ec0035Jens Axboe	dprint(FD_BLKTRACE, "store ddir=%d, off=%llu, len=%lu, delay=%lu\n",
254bd6f78b2f0b6375383948f126368804612ec0035Jens Axboe							ipo->ddir, ipo->offset,
255bd6f78b2f0b6375383948f126368804612ec0035Jens Axboe							ipo->len, ipo->delay);
256691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe	queue_io_piece(td, ipo);
257fdefd987d7ba284c7a9e101911c4b8e72fe326adJens Axboe}
258fdefd987d7ba284c7a9e101911c4b8e72fe326adJens Axboe
2590b9d69ecb14045cf3b2622ae922756b9889b25e6Jens Axboestatic void handle_trace_notify(struct blk_io_trace *t)
260cd991b9e36b18903f1564a4bfafdc83a9f165219Jens Axboe{
261691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe	switch (t->action) {
262691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe	case BLK_TN_PROCESS:
263d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe		log_info("blktrace: got process notify: %x, %d\n",
264d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe				t->action, t->pid);
265691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe		break;
266691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe	case BLK_TN_TIMESTAMP:
267d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe		log_info("blktrace: got timestamp notify: %x, %d\n",
268d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe				t->action, t->pid);
269691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe		break;
270ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe	case BLK_TN_MESSAGE:
271ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe		break;
272691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe	default:
273691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe		dprint(FD_BLKTRACE, "unknown trace act %x\n", t->action);
274691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe		break;
275691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe	}
276691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe}
2775b3023b818d5127504b4889f8f718c3cef62700bJens Axboe
278ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboestatic void handle_trace_discard(struct thread_data *td, struct blk_io_trace *t,
279ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe				 unsigned long long ttime, unsigned long *ios)
280ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe{
281ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe	struct io_piece *ipo = malloc(sizeof(*ipo));
28289ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li	int fileno;
283ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe
2840d29de831183dfd049c97a03008d425ce21e2fa4Jens Axboe	init_ipo(ipo);
28589ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li	fileno = trace_add_file(td, t->device);
286ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe
287ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe	ios[DDIR_WRITE]++;
288ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe	td->o.size += t->bytes;
289ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe
290ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe	memset(ipo, 0, sizeof(*ipo));
291ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe	INIT_FLIST_HEAD(&ipo->list);
292ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe
293ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe	/*
294ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe	 * the 512 is wrong here, it should be the hardware sector size...
295ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe	 */
296ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe	ipo->offset = t->sector * 512;
297ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe	ipo->len = t->bytes;
298ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe	ipo->delay = ttime / 1000;
299ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe	ipo->ddir = DDIR_TRIM;
30089ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li	ipo->fileno = fileno;
301ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe
302ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe	dprint(FD_BLKTRACE, "store discard, off=%llu, len=%lu, delay=%lu\n",
303ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe							ipo->offset, ipo->len,
304ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe							ipo->delay);
305ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe	queue_io_piece(td, ipo);
306ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe}
307ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe
308691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboestatic void handle_trace_fs(struct thread_data *td, struct blk_io_trace *t,
309691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe			    unsigned long long ttime, unsigned long *ios,
310691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe			    unsigned int *bs)
311691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe{
312691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe	int rw;
31389ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li	int fileno;
3145b3023b818d5127504b4889f8f718c3cef62700bJens Axboe
31589ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li	fileno = trace_add_file(td, t->device);
3165b3023b818d5127504b4889f8f718c3cef62700bJens Axboe
3175b3023b818d5127504b4889f8f718c3cef62700bJens Axboe	rw = (t->action & BLK_TC_ACT(BLK_TC_WRITE)) != 0;
3185b3023b818d5127504b4889f8f718c3cef62700bJens Axboe
3195b3023b818d5127504b4889f8f718c3cef62700bJens Axboe	if (t->bytes > bs[rw])
3205b3023b818d5127504b4889f8f718c3cef62700bJens Axboe		bs[rw] = t->bytes;
3215b3023b818d5127504b4889f8f718c3cef62700bJens Axboe
3225b3023b818d5127504b4889f8f718c3cef62700bJens Axboe	ios[rw]++;
3235b3023b818d5127504b4889f8f718c3cef62700bJens Axboe	td->o.size += t->bytes;
32489ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li	store_ipo(td, t->sector, t->bytes, rw, ttime, fileno);
325cd991b9e36b18903f1564a4bfafdc83a9f165219Jens Axboe}
326cd991b9e36b18903f1564a4bfafdc83a9f165219Jens Axboe
327cd991b9e36b18903f1564a4bfafdc83a9f165219Jens Axboe/*
328691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe * We only care for queue traces, most of the others are side effects
329691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe * due to internal workings of the block layer.
330691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe */
331691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboestatic void handle_trace(struct thread_data *td, struct blk_io_trace *t,
332691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe			 unsigned long long ttime, unsigned long *ios,
333691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe			 unsigned int *bs)
334691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe{
335691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe	if ((t->action & 0xffff) != __BLK_TA_QUEUE)
336691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe		return;
337691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe	if (t->action & BLK_TC_ACT(BLK_TC_PC))
338691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe		return;
339691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe
340691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe	if (t->action & BLK_TC_ACT(BLK_TC_NOTIFY))
341aec2de209564a6951e6c91d653fc99a75508607dJens Axboe		handle_trace_notify(t);
342ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe	else if (t->action & BLK_TC_ACT(BLK_TC_DISCARD))
343ff58fcede39d16a2c642897cbe5a7f28b2da1950Jens Axboe		handle_trace_discard(td, t, ttime, ios);
344691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe	else
345691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe		handle_trace_fs(td, t, ttime, ios, bs);
346691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe}
347691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe
348d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboestatic void byteswap_trace(struct blk_io_trace *t)
349d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe{
350d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	t->magic = fio_swap32(t->magic);
351d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	t->sequence = fio_swap32(t->sequence);
352d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	t->time = fio_swap64(t->time);
353d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	t->sector = fio_swap64(t->sector);
354d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	t->bytes = fio_swap32(t->bytes);
355d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	t->action = fio_swap32(t->action);
356d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	t->pid = fio_swap32(t->pid);
357d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	t->device = fio_swap32(t->device);
358d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	t->cpu = fio_swap32(t->cpu);
359d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	t->error = fio_swap16(t->error);
360d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe	t->pdu_len = fio_swap16(t->pdu_len);
361d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe}
362d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe
363691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe/*
3648c1fdf044083522504685e3009e356c70d003ef0Jens Axboe * Load a blktrace file by reading all the blk_io_trace entries, and storing
3658c1fdf044083522504685e3009e356c70d003ef0Jens Axboe * them as io_pieces like the fio text version would do.
3668c1fdf044083522504685e3009e356c70d003ef0Jens Axboe */
367d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboeint load_blktrace(struct thread_data *td, const char *filename, int need_swap)
368fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe{
369a61eddecca21d19f3f4c297400d6c5d93dc29259Jens Axboe	unsigned long long ttime, delay;
370fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	struct blk_io_trace t;
3714241ea8fb0606f9bd5b7ed1278d3b7825883acf6Jens Axboe	unsigned long ios[2], skipped_writes;
372a61eddecca21d19f3f4c297400d6c5d93dc29259Jens Axboe	unsigned int cpu;
373d84f8d4931be0c7519bd9f97f9914b07578a9854Jens Axboe	unsigned int rw_bs[2];
374e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe	struct fifo *fifo;
3755903e7b7907854014478b6febfc5645a203ff59eJens Axboe	int fd, i, old_state;
37689ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li	struct fio_file *f;
377eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe	int this_depth, depth;
378fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe
379fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	fd = open(filename, O_RDONLY);
380fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	if (fd < 0) {
381fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe		td_verror(td, errno, "open blktrace file");
382fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe		return 1;
383fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	}
384fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe
385e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe	fifo = fifo_alloc(TRACE_FIFO_SIZE);
386e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe
3878edd973d57a311d4c590d7385796bbdf111ed04cJens Axboe	old_state = td_bump_runstate(td, TD_SETTING_UP);
3885903e7b7907854014478b6febfc5645a203ff59eJens Axboe
3896df8adaaadb71340b47f2c3e971297b656082ca5Jens Axboe	td->o.size = 0;
3906df8adaaadb71340b47f2c3e971297b656082ca5Jens Axboe
391a61eddecca21d19f3f4c297400d6c5d93dc29259Jens Axboe	cpu = 0;
392d84f8d4931be0c7519bd9f97f9914b07578a9854Jens Axboe	ttime = 0;
393d84f8d4931be0c7519bd9f97f9914b07578a9854Jens Axboe	ios[0] = ios[1] = 0;
394d84f8d4931be0c7519bd9f97f9914b07578a9854Jens Axboe	rw_bs[0] = rw_bs[1] = 0;
3954241ea8fb0606f9bd5b7ed1278d3b7825883acf6Jens Axboe	skipped_writes = 0;
396eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe	this_depth = depth = 0;
397fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	do {
398e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe		int ret = trace_fifo_get(td, fifo, fd, &t, sizeof(t));
399fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe
400e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe		if (ret < 0)
4018c1fdf044083522504685e3009e356c70d003ef0Jens Axboe			goto err;
402e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe		else if (!ret)
403e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe			break;
404e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe		else if (ret < (int) sizeof(t)) {
405e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe			log_err("fio: short fifo get\n");
406fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe			break;
407fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe		}
408fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe
409d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe		if (need_swap)
410d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe			byteswap_trace(&t);
411d95b34a61ec3fc305fe53c0132bfe82e2e5fcc04Jens Axboe
412fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe		if ((t.magic & 0xffffff00) != BLK_IO_TRACE_MAGIC) {
4135ec10eaad3b09875b91e19a20bbdfa06f2117562Jens Axboe			log_err("fio: bad magic in blktrace data: %x\n",
4145ec10eaad3b09875b91e19a20bbdfa06f2117562Jens Axboe								t.magic);
4158c1fdf044083522504685e3009e356c70d003ef0Jens Axboe			goto err;
416fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe		}
417fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe		if ((t.magic & 0xff) != BLK_IO_TRACE_VERSION) {
4185ec10eaad3b09875b91e19a20bbdfa06f2117562Jens Axboe			log_err("fio: bad blktrace version %d\n",
4195ec10eaad3b09875b91e19a20bbdfa06f2117562Jens Axboe								t.magic & 0xff);
4208c1fdf044083522504685e3009e356c70d003ef0Jens Axboe			goto err;
421fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe		}
422f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe		ret = discard_pdu(td, fifo, fd, &t);
423f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe		if (ret < 0) {
424fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe			td_verror(td, ret, "blktrace lseek");
4258c1fdf044083522504685e3009e356c70d003ef0Jens Axboe			goto err;
426f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe		} else if (t.pdu_len != ret) {
427f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe			log_err("fio: discarded %d of %d\n", ret, t.pdu_len);
428f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe			goto err;
429fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe		}
430691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe		if ((t.action & BLK_TC_ACT(BLK_TC_NOTIFY)) == 0) {
431eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe			if ((t.action & 0xffff) == __BLK_TA_QUEUE)
432eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe				this_depth++;
433eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe			else if ((t.action & 0xffff) == __BLK_TA_COMPLETE) {
434eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe				depth = max(depth, this_depth);
435eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe				this_depth = 0;
436eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe			}
437691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe			if (!ttime) {
438691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe				ttime = t.time;
439691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe				cpu = t.cpu;
440691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe			}
441691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe
442691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe			delay = 0;
443691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe			if (cpu == t.cpu)
444691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe				delay = t.time - ttime;
445691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe			if ((t.action & BLK_TC_ACT(BLK_TC_WRITE)) && read_only)
446691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe				skipped_writes++;
44764bbb86598ada3fa401c61aab5ef6c37bec6d6f3David Nellans			else {
44864bbb86598ada3fa401c61aab5ef6c37bec6d6f3David Nellans				/*
44964bbb86598ada3fa401c61aab5ef6c37bec6d6f3David Nellans				 * set delay to zero if no_stall enabled for
45064bbb86598ada3fa401c61aab5ef6c37bec6d6f3David Nellans				 * fast replay
45164bbb86598ada3fa401c61aab5ef6c37bec6d6f3David Nellans				 */
45264bbb86598ada3fa401c61aab5ef6c37bec6d6f3David Nellans				if (td->o.no_stall)
45364bbb86598ada3fa401c61aab5ef6c37bec6d6f3David Nellans					delay = 0;
45464bbb86598ada3fa401c61aab5ef6c37bec6d6f3David Nellans
455691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe				handle_trace(td, &t, delay, ios, rw_bs);
45664bbb86598ada3fa401c61aab5ef6c37bec6d6f3David Nellans			}
457691c8fb014da9dd82e999a90b5511423f4eee188Jens Axboe
4588c1fdf044083522504685e3009e356c70d003ef0Jens Axboe			ttime = t.time;
459a61eddecca21d19f3f4c297400d6c5d93dc29259Jens Axboe			cpu = t.cpu;
460a6edd6383bfa6f85f24080b43722c8af6d80106cJens Axboe		} else {
461a6edd6383bfa6f85f24080b43722c8af6d80106cJens Axboe			delay = 0;
4624241ea8fb0606f9bd5b7ed1278d3b7825883acf6Jens Axboe			handle_trace(td, &t, delay, ios, rw_bs);
463a6edd6383bfa6f85f24080b43722c8af6d80106cJens Axboe		}
464fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	} while (1);
465fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe
46685a47ca2eeac70bad992556d077f18752098e44fJens Axboe	for (i = 0; i < td->files_index; i++) {
467f01b34ae759afccf39c1bf47972e45d91448e7bbJens Axboe		f = td->files[i];
46889ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li		trace_add_open_close_event(td, f->fileno, FIO_LOG_CLOSE_FILE);
46985a47ca2eeac70bad992556d077f18752098e44fJens Axboe	}
47089ac1d48971578ccb0645c292d4a058340aeb909Shaohua Li
47138470f85fa4acddab4339db9c8805a19bc87578eJens Axboe	fifo_free(fifo);
472fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	close(fd);
4738c1fdf044083522504685e3009e356c70d003ef0Jens Axboe
4748edd973d57a311d4c590d7385796bbdf111ed04cJens Axboe	td_restore_runstate(td, old_state);
4755903e7b7907854014478b6febfc5645a203ff59eJens Axboe
476f01b34ae759afccf39c1bf47972e45d91448e7bbJens Axboe	if (!td->files_index) {
477f01b34ae759afccf39c1bf47972e45d91448e7bbJens Axboe		log_err("fio: did not find replay device(s)\n");
478f01b34ae759afccf39c1bf47972e45d91448e7bbJens Axboe		return 1;
479f01b34ae759afccf39c1bf47972e45d91448e7bbJens Axboe	}
480f01b34ae759afccf39c1bf47972e45d91448e7bbJens Axboe
481eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe	/*
482eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe	 * For stacked devices, we don't always get a COMPLETE event so
483eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe	 * the depth grows to insane values. Limit it to something sane(r).
484eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe	 */
485eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe	if (!depth || depth > 1024)
486eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe		depth = 1024;
487eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe
4884241ea8fb0606f9bd5b7ed1278d3b7825883acf6Jens Axboe	if (skipped_writes)
4895ec10eaad3b09875b91e19a20bbdfa06f2117562Jens Axboe		log_err("fio: %s skips replay of %lu writes due to read-only\n",
4905ec10eaad3b09875b91e19a20bbdfa06f2117562Jens Axboe						td->o.name, skipped_writes);
4914241ea8fb0606f9bd5b7ed1278d3b7825883acf6Jens Axboe
4928c1fdf044083522504685e3009e356c70d003ef0Jens Axboe	if (!ios[DDIR_READ] && !ios[DDIR_WRITE]) {
4938c1fdf044083522504685e3009e356c70d003ef0Jens Axboe		log_err("fio: found no ios in blktrace data\n");
4948c1fdf044083522504685e3009e356c70d003ef0Jens Axboe		return 1;
495d84f8d4931be0c7519bd9f97f9914b07578a9854Jens Axboe	} else if (ios[DDIR_READ] && !ios[DDIR_READ]) {
4968c1fdf044083522504685e3009e356c70d003ef0Jens Axboe		td->o.td_ddir = TD_DDIR_READ;
497d84f8d4931be0c7519bd9f97f9914b07578a9854Jens Axboe		td->o.max_bs[DDIR_READ] = rw_bs[DDIR_READ];
498d84f8d4931be0c7519bd9f97f9914b07578a9854Jens Axboe	} else if (!ios[DDIR_READ] && ios[DDIR_WRITE]) {
4998c1fdf044083522504685e3009e356c70d003ef0Jens Axboe		td->o.td_ddir = TD_DDIR_WRITE;
500d84f8d4931be0c7519bd9f97f9914b07578a9854Jens Axboe		td->o.max_bs[DDIR_WRITE] = rw_bs[DDIR_WRITE];
501d84f8d4931be0c7519bd9f97f9914b07578a9854Jens Axboe	} else {
5028c1fdf044083522504685e3009e356c70d003ef0Jens Axboe		td->o.td_ddir = TD_DDIR_RW;
503d84f8d4931be0c7519bd9f97f9914b07578a9854Jens Axboe		td->o.max_bs[DDIR_READ] = rw_bs[DDIR_READ];
504d84f8d4931be0c7519bd9f97f9914b07578a9854Jens Axboe		td->o.max_bs[DDIR_WRITE] = rw_bs[DDIR_WRITE];
505d84f8d4931be0c7519bd9f97f9914b07578a9854Jens Axboe	}
5068c1fdf044083522504685e3009e356c70d003ef0Jens Axboe
5078c1fdf044083522504685e3009e356c70d003ef0Jens Axboe	/*
5088c1fdf044083522504685e3009e356c70d003ef0Jens Axboe	 * We need to do direct/raw ios to the device, to avoid getting
5098c1fdf044083522504685e3009e356c70d003ef0Jens Axboe	 * read-ahead in our way.
5108c1fdf044083522504685e3009e356c70d003ef0Jens Axboe	 */
5118c1fdf044083522504685e3009e356c70d003ef0Jens Axboe	td->o.odirect = 1;
5128c1fdf044083522504685e3009e356c70d003ef0Jens Axboe
513eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe	/*
514eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe	 * we don't know if this option was set or not. it defaults to 1,
515eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe	 * so we'll just guess that we should override it if it's still 1
516eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe	 */
517eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe	if (td->o.iodepth != 1)
518eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe		td->o.iodepth = depth;
519eb5fdcf1b045242a6bf4a9b225346c80418f3ab1Jens Axboe
520fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe	return 0;
5218c1fdf044083522504685e3009e356c70d003ef0Jens Axboeerr:
5228c1fdf044083522504685e3009e356c70d003ef0Jens Axboe	close(fd);
52338470f85fa4acddab4339db9c8805a19bc87578eJens Axboe	fifo_free(fifo);
5248c1fdf044083522504685e3009e356c70d003ef0Jens Axboe	return 1;
525fb7b71a3c99b7ead2055439bfea421579aae2691Jens Axboe}
526