1 /*
2  * Dump the contents of a verify state file in plain text
3  */
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <string.h>
12 #include "../log.h"
13 #include "../os/os.h"
14 #include "../verify-state.h"
15 #include "../crc/crc32c.h"
16 #include "debug.h"
17 
show_s(struct thread_io_list * s,unsigned int no_s)18 static void show_s(struct thread_io_list *s, unsigned int no_s)
19 {
20 	int i;
21 
22 	printf("Thread:\t\t%u\n", no_s);
23 	printf("Name:\t\t%s\n", s->name);
24 	printf("Completions:\t%llu\n", (unsigned long long) s->no_comps);
25 	printf("Depth:\t\t%llu\n", (unsigned long long) s->depth);
26 	printf("Number IOs:\t%llu\n", (unsigned long long) s->numberio);
27 	printf("Index:\t\t%llu\n", (unsigned long long) s->index);
28 
29 	printf("Completions:\n");
30 	if (!s->no_comps)
31 		return;
32 	for (i = s->no_comps - 1; i >= 0; i--) {
33 		printf("\t(file=%2llu) %llu\n",
34 				(unsigned long long) s->comps[i].fileno,
35 				(unsigned long long) s->comps[i].offset);
36 	}
37 }
38 
show(struct thread_io_list * s,size_t size)39 static void show(struct thread_io_list *s, size_t size)
40 {
41 	int no_s;
42 
43 	no_s = 0;
44 	do {
45 		int i;
46 
47 		s->no_comps = le64_to_cpu(s->no_comps);
48 		s->depth = le32_to_cpu(s->depth);
49 		s->nofiles = le32_to_cpu(s->nofiles);
50 		s->numberio = le64_to_cpu(s->numberio);
51 		s->index = le64_to_cpu(s->index);
52 
53 		for (i = 0; i < s->no_comps; i++) {
54 			s->comps[i].fileno = le64_to_cpu(s->comps[i].fileno);
55 			s->comps[i].offset = le64_to_cpu(s->comps[i].offset);
56 		}
57 
58 		show_s(s, no_s);
59 		no_s++;
60 		size -= __thread_io_list_sz(s->depth, s->nofiles);
61 		s = (struct thread_io_list *)((char *) s +
62 			__thread_io_list_sz(s->depth, s->nofiles));
63 	} while (size != 0);
64 }
65 
show_verify_state(void * buf,size_t size)66 static void show_verify_state(void *buf, size_t size)
67 {
68 	struct verify_state_hdr *hdr = buf;
69 	struct thread_io_list *s;
70 	uint32_t crc;
71 
72 	hdr->version = le64_to_cpu(hdr->version);
73 	hdr->size = le64_to_cpu(hdr->size);
74 	hdr->crc = le64_to_cpu(hdr->crc);
75 
76 	printf("Version:\t0x%x\n", (unsigned int) hdr->version);
77 	printf("Size:\t\t%u\n", (unsigned int) hdr->size);
78 	printf("CRC:\t\t0x%x\n", (unsigned int) hdr->crc);
79 
80 	size -= sizeof(*hdr);
81 	if (hdr->size != size) {
82 		log_err("Size mismatch\n");
83 		return;
84 	}
85 
86 	s = buf + sizeof(*hdr);
87 	crc = fio_crc32c((unsigned char *) s, hdr->size);
88 	if (crc != hdr->crc) {
89 		log_err("crc mismatch %x != %x\n", crc, (unsigned int) hdr->crc);
90 		return;
91 	}
92 
93 	if (hdr->version == 0x03)
94 		show(s, size);
95 	else
96 		log_err("Unsupported version %d\n", (int) hdr->version);
97 }
98 
show_file(const char * file)99 static int show_file(const char *file)
100 {
101 	struct stat sb;
102 	void *buf;
103 	int ret, fd;
104 
105 	fd = open(file, O_RDONLY);
106 	if (fd < 0) {
107 		log_err("open %s: %s\n", file, strerror(errno));
108 		return 1;
109 	}
110 
111 	if (fstat(fd, &sb) < 0) {
112 		log_err("stat: %s\n", strerror(errno));
113 		close(fd);
114 		return 1;
115 	}
116 
117 	buf = malloc(sb.st_size);
118 	ret = read(fd, buf, sb.st_size);
119 	if (ret < 0) {
120 		log_err("read: %s\n", strerror(errno));
121 		close(fd);
122 		free(buf);
123 		return 1;
124 	} else if (ret != sb.st_size) {
125 		log_err("Short read\n");
126 		close(fd);
127 		free(buf);
128 		return 1;
129 	}
130 
131 	close(fd);
132 	show_verify_state(buf, sb.st_size);
133 
134 	free(buf);
135 	return 0;
136 }
137 
main(int argc,char * argv[])138 int main(int argc, char *argv[])
139 {
140 	int i, ret;
141 
142 	debug_init();
143 
144 	if (argc < 2) {
145 		log_err("Usage: %s <state file>\n", argv[0]);
146 		return 1;
147 	}
148 
149 	ret = 0;
150 	for (i = 1; i < argc; i++) {
151 		ret = show_file(argv[i]);
152 		if (ret)
153 			break;
154 	}
155 
156 	return ret;
157 }
158