Repository navigation
Expand file tree
/
Copy pathvscsi.h
More file actions
190 lines (164 loc) · 4.53 KB
/
Copy pathvscsi.h
File metadata and controls
190 lines (164 loc) · 4.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#pragma once
/**
* vscsi reader for vscsi trace
*
*/
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "libCacheSim/reader.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAX_TEST 2
typedef struct {
uint64_t ts;
uint32_t len;
uint64_t lbn;
uint16_t cmd;
} trace_item_t;
typedef struct {
uint32_t sn;
uint32_t len;
uint32_t nSG;
uint16_t cmd;
uint16_t ver;
uint64_t lbn;
uint64_t ts;
} trace_v1_record_t;
typedef struct {
uint16_t cmd;
uint16_t ver;
uint32_t sn;
uint32_t len;
uint32_t nSG;
uint64_t lbn;
uint64_t ts;
uint64_t rt;
} trace_v2_record_t;
typedef enum { VSCSI1 = 1, VSCSI2 = 2, UNKNOWN } vscsi_version_e;
typedef struct {
vscsi_version_e vscsi_ver;
} vscsi_params_t;
static inline bool test_version(const vscsi_version_e *test_buf,
vscsi_version_e version) {
for (int i = 0; i < MAX_TEST; i++) {
if (version != test_buf[i]) return (false);
}
return (true);
}
static inline vscsi_version_e to_vscsi_version(uint16_t ver) {
return ((vscsi_version_e)(ver >> 8));
}
static inline vscsi_version_e test_vscsi_version(void *trace) {
vscsi_version_e test_buf[MAX_TEST] = {0};
int i;
for (i = 0; i < MAX_TEST; i++) {
test_buf[i] = to_vscsi_version((((trace_v2_record_t *)trace)[i]).ver);
}
if (test_version(test_buf, VSCSI2))
return (VSCSI2);
else {
for (i = 0; i < MAX_TEST; i++) {
test_buf[i] = to_vscsi_version((((trace_v1_record_t *)trace)[i]).ver);
}
if (test_version(test_buf, VSCSI1)) return (VSCSI1);
}
return (UNKNOWN);
}
static inline size_t record_size(vscsi_version_e version) {
if (version == VSCSI1)
return (sizeof(trace_v1_record_t));
else if (version == VSCSI2)
return (sizeof(trace_v2_record_t));
else
return (-1);
}
static inline int vscsiReader_setup(reader_t *const reader) {
vscsi_params_t *params = malloc(sizeof(vscsi_params_t));
reader->reader_params = params;
reader->trace_format = BINARY_TRACE_FORMAT;
reader->obj_id_is_num = true;
/* Version 2 records are the bigger of the two */
if ((unsigned long long)reader->file_size <
(unsigned long long)sizeof(trace_v2_record_t) * MAX_TEST) {
ERROR("File too small, unable to read header.\n");
return -1;
}
vscsi_version_e ver = test_vscsi_version(reader->mapped_file);
switch (ver) {
case VSCSI1:
case VSCSI2:
reader->item_size = record_size(ver);
params->vscsi_ver = ver;
break;
case UNKNOWN:
default:
ERROR("Trace format unrecognized.\n");
return -1;
}
return 0;
}
static inline int vscsi_read_ver1(reader_t *reader, request_t *req) {
trace_v1_record_t *record =
(trace_v1_record_t *)(reader->mapped_file + reader->mmap_offset);
// trace uses microsec change to sec
req->clock_time = record->ts / 1000000;
req->obj_size = record->len;
uint16_t cmd = record->cmd;
if (cmd == 40 || cmd == 8 || cmd == 136 || cmd == 45 || cmd == 168) {
req->op = OP_READ;
} else if (cmd == 42 || cmd == 63 || cmd == 138 || cmd == 142 || cmd == 154 ||
cmd == 156 || cmd == 170 || cmd == 174) {
req->op = OP_WRITE;
} else {
req->op = OP_INVALID;
}
req->obj_id = record->lbn;
(reader->mmap_offset) += reader->item_size;
return 0;
}
static inline int vscsi_read_ver2(reader_t *reader, request_t *req) {
trace_v2_record_t *record =
(trace_v2_record_t *)(reader->mapped_file + reader->mmap_offset);
req->clock_time = record->ts / 1000000;
req->obj_size = record->len;
uint16_t cmd = record->cmd;
if (cmd == 40 || cmd == 8 || cmd == 136 || cmd == 45 || cmd == 168) {
req->op = OP_READ;
} else if (cmd == 42 || cmd == 63 || cmd == 138 || cmd == 142 || cmd == 154 ||
cmd == 156 || cmd == 170 || cmd == 174) {
req->op = OP_WRITE;
} else {
req->op = OP_INVALID;
}
req->obj_id = record->lbn;
(reader->mmap_offset) += reader->item_size;
return 0;
}
static inline int vscsi_read_one_req(reader_t *reader, request_t *req) {
if (reader->mmap_offset >= reader->n_total_req * reader->item_size) {
req->valid = false;
return 1;
}
vscsi_params_t *params = (vscsi_params_t *)reader->reader_params;
int (*fptr)(reader_t *, request_t *) = NULL;
switch (params->vscsi_ver) {
case VSCSI1:
fptr = vscsi_read_ver1;
break;
case VSCSI2:
fptr = vscsi_read_ver2;
break;
case UNKNOWN:
ERROR("unknown vscsi version encountered\n");
break;
}
return fptr(reader, req);
}
#ifdef __cplusplus
}
#endif