Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2020 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/stdinc.h"
7 : : #include "spdk/thread.h"
8 : : #include "spdk/env.h"
9 : : #include "spdk/event.h"
10 : : #include "spdk/log.h"
11 : : #include "spdk/string.h"
12 : : #include "spdk/accel.h"
13 : : #include "spdk/crc32.h"
14 : : #include "spdk/util.h"
15 : : #include "spdk/xor.h"
16 : : #include "spdk/dif.h"
17 : :
18 : : #define DATA_PATTERN 0x5a
19 : : #define ALIGN_4K 0x1000
20 : : #define COMP_BUF_PAD_PERCENTAGE 1.1L
21 : :
22 : : static uint64_t g_tsc_rate;
23 : : static uint64_t g_tsc_end;
24 : : static int g_rc;
25 : : static int g_xfer_size_bytes = 4096;
26 : : static int g_block_size_bytes = 512;
27 : : static int g_md_size_bytes = 8;
28 : : static int g_queue_depth = 32;
29 : : /* g_allocate_depth indicates how many tasks we allocate per worker. It will
30 : : * be at least as much as the queue depth.
31 : : */
32 : : static int g_allocate_depth = 0;
33 : : static int g_threads_per_core = 1;
34 : : static int g_time_in_sec = 5;
35 : : static uint32_t g_crc32c_seed = 0;
36 : : static uint32_t g_chained_count = 1;
37 : : static int g_fail_percent_goal = 0;
38 : : static uint8_t g_fill_pattern = 255;
39 : : static uint32_t g_xor_src_count = 2;
40 : : static bool g_verify = false;
41 : : static const char *g_workload_type = NULL;
42 : : static enum spdk_accel_opcode g_workload_selection = SPDK_ACCEL_OPC_LAST;
43 : : static const char *g_module_name = NULL;
44 : : static struct worker_thread *g_workers = NULL;
45 : : static int g_num_workers = 0;
46 : : static char *g_cd_file_in_name = NULL;
47 : : static pthread_mutex_t g_workers_lock = PTHREAD_MUTEX_INITIALIZER;
48 : : static struct spdk_app_opts g_opts = {};
49 : :
50 : : struct ap_compress_seg {
51 : : void *uncompressed_data;
52 : : uint32_t uncompressed_len;
53 : : struct iovec *uncompressed_iovs;
54 : : uint32_t uncompressed_iovcnt;
55 : :
56 : : void *compressed_data;
57 : : uint32_t compressed_len;
58 : : uint32_t compressed_len_padded;
59 : : struct iovec *compressed_iovs;
60 : : uint32_t compressed_iovcnt;
61 : :
62 : : STAILQ_ENTRY(ap_compress_seg) link;
63 : : };
64 : :
65 : : static STAILQ_HEAD(, ap_compress_seg) g_compress_segs = STAILQ_HEAD_INITIALIZER(g_compress_segs);
66 : :
67 : : struct worker_thread;
68 : : static void accel_done(void *ref, int status);
69 : :
70 : : struct display_info {
71 : : int core;
72 : : int thread;
73 : : };
74 : :
75 : : struct ap_task {
76 : : void *src;
77 : : struct iovec *src_iovs;
78 : : uint32_t src_iovcnt;
79 : : void **sources;
80 : : struct iovec *dst_iovs;
81 : : uint32_t dst_iovcnt;
82 : : void *dst;
83 : : void *dst2;
84 : : uint32_t crc_dst;
85 : : uint32_t compressed_sz;
86 : : struct ap_compress_seg *cur_seg;
87 : : struct worker_thread *worker;
88 : : int expected_status; /* used for the compare operation */
89 : : uint32_t num_blocks; /* used for the DIF related operations */
90 : : struct spdk_dif_ctx dif_ctx;
91 : : struct spdk_dif_error dif_err;
92 : : TAILQ_ENTRY(ap_task) link;
93 : : };
94 : :
95 : : struct worker_thread {
96 : : struct spdk_io_channel *ch;
97 : : struct spdk_accel_opcode_stats stats;
98 : : uint64_t xfer_failed;
99 : : uint64_t injected_miscompares;
100 : : uint64_t current_queue_depth;
101 : : TAILQ_HEAD(, ap_task) tasks_pool;
102 : : struct worker_thread *next;
103 : : unsigned core;
104 : : struct spdk_thread *thread;
105 : : bool is_draining;
106 : : struct spdk_poller *is_draining_poller;
107 : : struct spdk_poller *stop_poller;
108 : : void *task_base;
109 : : struct display_info display;
110 : : enum spdk_accel_opcode workload;
111 : : };
112 : :
113 : : static void
114 : 774 : dump_user_config(void)
115 : : {
116 : 774 : const char *module_name = NULL;
117 : : int rc;
118 : :
119 : 774 : rc = spdk_accel_get_opc_module_name(g_workload_selection, &module_name);
120 [ + + ]: 774 : if (rc) {
121 [ # # ]: 0 : printf("error getting module name (%d)\n", rc);
122 : 0 : }
123 : :
124 [ - + ]: 774 : printf("\nSPDK Configuration:\n");
125 [ - + ]: 774 : printf("Core mask: %s\n\n", g_opts.reactor_mask);
126 [ - + ]: 774 : printf("Accel Perf Configuration:\n");
127 [ - + ]: 774 : printf("Workload Type: %s\n", g_workload_type);
128 [ + + + + ]: 774 : if (g_workload_selection == SPDK_ACCEL_OPC_CRC32C ||
129 [ + + ]: 698 : g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C) {
130 [ - + ]: 152 : printf("CRC-32C seed: %u\n", g_crc32c_seed);
131 [ + + ]: 630 : } else if (g_workload_selection == SPDK_ACCEL_OPC_FILL) {
132 [ - + ]: 38 : printf("Fill pattern: 0x%x\n", g_fill_pattern);
133 [ + + + + ]: 586 : } else if ((g_workload_selection == SPDK_ACCEL_OPC_COMPARE) && g_fail_percent_goal > 0) {
134 [ # # ]: 0 : printf("Failure inject: %u percent\n", g_fail_percent_goal);
135 [ + + ]: 584 : } else if (g_workload_selection == SPDK_ACCEL_OPC_XOR) {
136 [ - + ]: 76 : printf("Source buffers: %u\n", g_xor_src_count);
137 : 4 : }
138 [ + + + + ]: 806 : if (g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C ||
139 [ + + ]: 698 : g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY ||
140 [ + + ]: 660 : g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE ||
141 [ + + ]: 622 : g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE_COPY) {
142 [ - + ]: 190 : printf("Vector size: %u bytes\n", g_xfer_size_bytes);
143 [ - + ]: 190 : printf("Transfer size: %u bytes\n", g_xfer_size_bytes * g_chained_count);
144 : 10 : } else {
145 [ - + ]: 584 : printf("Transfer size: %u bytes\n", g_xfer_size_bytes);
146 : : }
147 [ + + + + ]: 774 : if (g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE ||
148 [ + + ]: 736 : g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY) {
149 [ - + ]: 76 : printf("Block size: %u bytes\n", g_block_size_bytes);
150 [ - + ]: 76 : printf("Metadata size: %u bytes\n", g_md_size_bytes);
151 : 4 : }
152 [ - + ]: 774 : printf("Vector count %u\n", g_chained_count);
153 [ - + ]: 774 : printf("Module: %s\n", module_name);
154 [ + + + + ]: 774 : if (g_workload_selection == SPDK_ACCEL_OPC_COMPRESS ||
155 [ + + ]: 734 : g_workload_selection == SPDK_ACCEL_OPC_DECOMPRESS) {
156 [ - + ]: 280 : printf("File Name: %s\n", g_cd_file_in_name);
157 : 14 : }
158 [ - + ]: 774 : printf("Queue depth: %u\n", g_queue_depth);
159 [ - + ]: 774 : printf("Allocate depth: %u\n", g_allocate_depth);
160 [ - + ]: 774 : printf("# threads/core: %u\n", g_threads_per_core);
161 [ - + ]: 774 : printf("Run time: %u seconds\n", g_time_in_sec);
162 [ + + + + : 774 : printf("Verify: %s\n\n", g_verify ? "Yes" : "No");
- + ]
163 : 774 : }
164 : :
165 : : static void
166 : 57 : usage(void)
167 : : {
168 [ - + ]: 57 : printf("accel_perf options:\n");
169 [ - + ]: 57 : printf("\t[-h help message]\n");
170 [ - + ]: 57 : printf("\t[-q queue depth per core]\n");
171 [ - + ]: 57 : printf("\t[-C for supported workloads, use this value to configure the io vector size to test (default 1)\n");
172 [ - + ]: 57 : printf("\t[-T number of threads per core\n");
173 [ - + ]: 57 : printf("\t[-o transfer size in bytes (default: 4KiB. For compress/decompress, 0 means the input file size)]\n");
174 [ - + ]: 57 : printf("\t[-t time in seconds]\n");
175 [ - + ]: 57 : printf("\t[-w workload type must be one of these: copy, fill, crc32c, copy_crc32c, compare, compress, decompress, dualcast, xor,\n");
176 [ - + ]: 57 : printf("\t[ dif_verify, , dif_generate, dif_generate_copy\n");
177 [ - + ]: 57 : printf("\t[-M assign module to the operation, not compatible with accel_assign_opc RPC\n");
178 [ - + ]: 57 : printf("\t[-l for compress/decompress workloads, name of uncompressed input file\n");
179 [ - + ]: 57 : printf("\t[-S for crc32c workload, use this seed value (default 0)\n");
180 [ - + ]: 57 : printf("\t[-P for compare workload, percentage of operations that should miscompare (percent, default 0)\n");
181 [ - + ]: 57 : printf("\t[-f for fill workload, use this BYTE value (default 255)\n");
182 [ - + ]: 57 : printf("\t[-x for xor workload, use this number of source buffers (default, minimum: 2)]\n");
183 [ - + ]: 57 : printf("\t[-y verify result if this switch is on]\n");
184 [ - + ]: 57 : printf("\t[-a tasks to allocate per core (default: same value as -q)]\n");
185 [ - + ]: 57 : printf("\t\tCan be used to spread operations across a wider range of memory.\n");
186 : 57 : }
187 : :
188 : : static int
189 : 3142 : parse_args(int ch, char *arg)
190 : : {
191 : 3142 : int argval = 0;
192 : :
193 [ + + ]: 3142 : switch (ch) {
194 : 1266 : case 'a':
195 : : case 'C':
196 : : case 'f':
197 : : case 'T':
198 : : case 'o':
199 : : case 'P':
200 : : case 'q':
201 : : case 'S':
202 : : case 't':
203 : : case 'x':
204 : 1335 : argval = spdk_strtol(optarg, 10);
205 [ + + ]: 1335 : if (argval < 0) {
206 [ - + ]: 19 : fprintf(stderr, "-%c option must be non-negative.\n", ch);
207 : 19 : usage();
208 : 19 : return 1;
209 : : }
210 : 1316 : break;
211 : 1714 : default:
212 : 1807 : break;
213 : : };
214 : :
215 [ + + + + : 3123 : switch (ch) {
+ + + + +
+ + + + +
- ]
216 : 36 : case 'a':
217 : 38 : g_allocate_depth = argval;
218 : 38 : break;
219 : 72 : case 'C':
220 : 76 : g_chained_count = argval;
221 : 76 : break;
222 : 284 : case 'l':
223 : 299 : g_cd_file_in_name = optarg;
224 : 299 : break;
225 : 36 : case 'f':
226 : 38 : g_fill_pattern = (uint8_t)argval;
227 : 38 : break;
228 : 76 : case 'T':
229 : 80 : g_threads_per_core = argval;
230 : 80 : break;
231 : 114 : case 'o':
232 : 120 : g_xfer_size_bytes = argval;
233 : 120 : break;
234 : 0 : case 'P':
235 : 0 : g_fail_percent_goal = argval;
236 : 0 : break;
237 : 36 : case 'q':
238 : 38 : g_queue_depth = argval;
239 : 38 : break;
240 : 36 : case 'S':
241 : 38 : g_crc32c_seed = argval;
242 : 38 : break;
243 : 806 : case 't':
244 : 850 : g_time_in_sec = argval;
245 : 850 : break;
246 : 36 : case 'x':
247 : 38 : g_xor_src_count = argval;
248 : 38 : break;
249 : 624 : case 'y':
250 : 658 : g_verify = true;
251 : 658 : break;
252 : 806 : case 'w':
253 : 850 : g_workload_type = optarg;
254 [ + + + + : 850 : if (!strcmp(g_workload_type, "copy")) {
+ + ]
255 : 38 : g_workload_selection = SPDK_ACCEL_OPC_COPY;
256 [ + + + + : 814 : } else if (!strcmp(g_workload_type, "fill")) {
+ + ]
257 : 38 : g_workload_selection = SPDK_ACCEL_OPC_FILL;
258 [ + + + + : 776 : } else if (!strcmp(g_workload_type, "crc32c")) {
+ + ]
259 : 76 : g_workload_selection = SPDK_ACCEL_OPC_CRC32C;
260 [ + + + + : 702 : } else if (!strcmp(g_workload_type, "copy_crc32c")) {
+ + ]
261 : 76 : g_workload_selection = SPDK_ACCEL_OPC_COPY_CRC32C;
262 [ + + + + : 626 : } else if (!strcmp(g_workload_type, "compare")) {
+ + ]
263 : 38 : g_workload_selection = SPDK_ACCEL_OPC_COMPARE;
264 [ + + + + : 586 : } else if (!strcmp(g_workload_type, "dualcast")) {
+ + ]
265 : 38 : g_workload_selection = SPDK_ACCEL_OPC_DUALCAST;
266 [ + + + + : 548 : } else if (!strcmp(g_workload_type, "compress")) {
+ + ]
267 : 78 : g_workload_selection = SPDK_ACCEL_OPC_COMPRESS;
268 [ + + + + : 472 : } else if (!strcmp(g_workload_type, "decompress")) {
+ + ]
269 : 240 : g_workload_selection = SPDK_ACCEL_OPC_DECOMPRESS;
270 [ + + + + : 240 : } else if (!strcmp(g_workload_type, "xor")) {
+ + ]
271 : 95 : g_workload_selection = SPDK_ACCEL_OPC_XOR;
272 [ + + + + : 138 : } else if (!strcmp(g_workload_type, "dif_verify")) {
+ + ]
273 : 38 : g_workload_selection = SPDK_ACCEL_OPC_DIF_VERIFY;
274 [ + + + + : 97 : } else if (!strcmp(g_workload_type, "dif_generate")) {
+ + ]
275 : 38 : g_workload_selection = SPDK_ACCEL_OPC_DIF_GENERATE;
276 [ + + + + : 59 : } else if (!strcmp(g_workload_type, "dif_generate_copy")) {
+ + ]
277 : 38 : g_workload_selection = SPDK_ACCEL_OPC_DIF_GENERATE_COPY;
278 : 2 : } else {
279 [ - + ]: 19 : fprintf(stderr, "Unsupported workload type: %s\n", optarg);
280 : 19 : usage();
281 : 19 : return 1;
282 : : }
283 : 831 : break;
284 : 0 : case 'M':
285 : 0 : g_module_name = optarg;
286 : 0 : break;
287 : :
288 : 0 : default:
289 : 0 : usage();
290 : 0 : return 1;
291 : : }
292 : :
293 : 3104 : return 0;
294 : 162 : }
295 : :
296 : : static int dump_result(void);
297 : : static void
298 : 1094 : unregister_worker(void *arg1)
299 : : {
300 : 1094 : struct worker_thread *worker = arg1;
301 : :
302 [ + - + - : 1094 : if (worker->ch) {
- + ]
303 [ + - + - : 1094 : spdk_accel_get_opcode_stats(worker->ch, worker->workload,
+ - + - ]
304 [ + - ]: 56 : &worker->stats, sizeof(worker->stats));
305 [ + - + - ]: 1094 : spdk_put_io_channel(worker->ch);
306 [ + - + - ]: 1094 : worker->ch = NULL;
307 : 56 : }
308 [ + - + - ]: 1094 : free(worker->task_base);
309 : 1094 : spdk_thread_exit(spdk_get_thread());
310 [ + + ]: 1094 : pthread_mutex_lock(&g_workers_lock);
311 [ + + # # ]: 1094 : assert(g_num_workers >= 1);
312 [ + + + + ]: 1094 : if (--g_num_workers == 0) {
313 [ + + ]: 774 : pthread_mutex_unlock(&g_workers_lock);
314 : : /* Only dump results on successful runs */
315 [ + + ]: 774 : if (g_rc == 0) {
316 : 774 : g_rc = dump_result();
317 : 40 : }
318 : 774 : spdk_app_stop(g_rc);
319 : 40 : } else {
320 [ + + ]: 320 : pthread_mutex_unlock(&g_workers_lock);
321 : : }
322 : 1094 : }
323 : :
324 : : static void
325 : 23799 : accel_perf_construct_iovs(void *buf, uint64_t sz, struct iovec *iovs, uint32_t iovcnt)
326 : : {
327 : : uint64_t ele_size;
328 : : uint8_t *data;
329 : : uint32_t i;
330 : :
331 : 23799 : ele_size = spdk_divide_round_up(sz, iovcnt);
332 : :
333 : 23799 : data = buf;
334 [ + + ]: 47597 : for (i = 0; i < iovcnt; i++) {
335 [ - + ]: 23798 : ele_size = spdk_min(ele_size, sz);
336 [ + + # # ]: 23798 : assert(ele_size > 0);
337 : :
338 [ + - + - : 23798 : iovs[i].iov_base = data;
+ - ]
339 [ + - + - : 23798 : iovs[i].iov_len = ele_size;
+ - ]
340 : :
341 [ + - ]: 23798 : data += ele_size;
342 : 23798 : sz -= ele_size;
343 : 1188 : }
344 [ + + # # ]: 23799 : assert(sz == 0);
345 : 23799 : }
346 : :
347 : : static int
348 : 36224 : _get_task_data_bufs(struct ap_task *task)
349 : : {
350 : 36224 : uint32_t align = 0;
351 : 36224 : uint32_t i = 0;
352 : 36224 : int src_buff_len = g_xfer_size_bytes;
353 : 36224 : int dst_buff_len = g_xfer_size_bytes;
354 : 14848 : struct spdk_dif_ctx_init_ext_opts dif_opts;
355 : : uint32_t num_blocks, transfer_size_with_md;
356 : : int rc;
357 : :
358 : : /* For dualcast, the DSA HW requires 4K alignment on destination addresses but
359 : : * we do this for all modules to keep it simple.
360 : : */
361 [ + + ]: 36224 : if (g_workload_selection == SPDK_ACCEL_OPC_DUALCAST) {
362 : 1216 : align = ALIGN_4K;
363 : 64 : }
364 : :
365 [ + + + + ]: 36224 : if (g_workload_selection == SPDK_ACCEL_OPC_COMPRESS ||
366 [ + + ]: 34943 : g_workload_selection == SPDK_ACCEL_OPC_DECOMPRESS) {
367 [ - + - + ]: 19200 : task->cur_seg = STAILQ_FIRST(&g_compress_segs);
368 : :
369 [ + + ]: 19200 : if (g_workload_selection == SPDK_ACCEL_OPC_COMPRESS) {
370 [ + - + - : 1280 : dst_buff_len = task->cur_seg->compressed_len_padded;
+ - + - ]
371 : 64 : }
372 : :
373 [ - + - + ]: 19200 : task->dst = spdk_dma_zmalloc(dst_buff_len, align, NULL);
374 [ - + - + : 19200 : if (task->dst == NULL) {
+ - ]
375 [ # # # # ]: 0 : fprintf(stderr, "Unable to alloc dst buffer\n");
376 : 0 : return -ENOMEM;
377 : : }
378 : :
379 [ + - + - ]: 19200 : task->dst_iovs = calloc(g_chained_count, sizeof(struct iovec));
380 [ + + + - : 19200 : if (!task->dst_iovs) {
- + ]
381 [ # # # # ]: 0 : fprintf(stderr, "cannot allocate task->dst_iovs for task=%p\n", task);
382 : 0 : return -ENOMEM;
383 : : }
384 [ - + - + ]: 19200 : task->dst_iovcnt = g_chained_count;
385 [ - + - + : 19200 : accel_perf_construct_iovs(task->dst, dst_buff_len, task->dst_iovs, task->dst_iovcnt);
- + - + -
+ - + ]
386 : :
387 : 19200 : return 0;
388 : : }
389 : :
390 [ + + ]: 17024 : if (g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE_COPY) {
391 [ + - + - ]: 1216 : task->dst_iovcnt = g_chained_count;
392 [ + - + - : 1216 : task->dst_iovs = calloc(task->dst_iovcnt, sizeof(struct iovec));
+ - + - ]
393 [ + + + - : 1216 : if (!task->dst_iovs) {
- + ]
394 [ # # # # ]: 0 : fprintf(stderr, "cannot allocate task->dst_iovs for task=%p\n", task);
395 : 0 : return -ENOMEM;
396 : : }
397 : :
398 [ + + ]: 1216 : num_blocks = g_xfer_size_bytes / g_block_size_bytes;
399 : : /* Add bytes for each block for metadata */
400 : 1216 : transfer_size_with_md = g_xfer_size_bytes + (num_blocks * g_md_size_bytes);
401 [ + - + - ]: 1216 : task->num_blocks = num_blocks;
402 : :
403 [ + + + - : 2432 : for (i = 0; i < task->dst_iovcnt; i++) {
+ + ]
404 [ - + - + : 1216 : task->dst_iovs[i].iov_base = spdk_dma_zmalloc(transfer_size_with_md, 0, NULL);
- + - + -
+ ]
405 [ - + - + : 1216 : if (task->dst_iovs[i].iov_base == NULL) {
- + - + -
+ - + ]
406 : 0 : return -ENOMEM;
407 : : }
408 [ + - + - : 1216 : task->dst_iovs[i].iov_len = transfer_size_with_md;
+ - + - +
- ]
409 : 64 : }
410 : :
411 : 1216 : dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
412 [ + - ]: 1216 : dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
413 : :
414 [ + - ]: 1280 : rc = spdk_dif_ctx_init(&task->dif_ctx,
415 [ + - ]: 1216 : g_block_size_bytes + g_md_size_bytes,
416 : 64 : g_md_size_bytes, true, true,
417 : : SPDK_DIF_TYPE1,
418 [ + - + - : 64 : SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | SPDK_DIF_FLAGS_REFTAG_CHECK,
+ - ]
419 : : 0x123, 0xFFFF, 0x234, 0, 0, &dif_opts);
420 [ - + ]: 1216 : if (rc != 0) {
421 [ # # # # ]: 0 : fprintf(stderr, "Initialization of DIF context failed\n");
422 : 0 : return rc;
423 : : }
424 : 64 : }
425 : :
426 [ + + + + ]: 17536 : if (g_workload_selection == SPDK_ACCEL_OPC_CRC32C ||
427 [ + + ]: 14592 : g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C ||
428 [ + + ]: 12160 : g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY ||
429 [ + + ]: 10944 : g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE ||
430 [ + + ]: 9728 : g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE_COPY) {
431 [ + + # # ]: 8512 : assert(g_chained_count > 0);
432 [ + - + - ]: 8512 : task->src_iovcnt = g_chained_count;
433 [ + - + - : 8512 : task->src_iovs = calloc(task->src_iovcnt, sizeof(struct iovec));
+ - + - ]
434 [ + + + - : 8512 : if (!task->src_iovs) {
+ - ]
435 [ # # # # ]: 0 : fprintf(stderr, "cannot allocated task->src_iovs fot task=%p\n", task);
436 : 0 : return -ENOMEM;
437 : : }
438 : :
439 [ + + ]: 8512 : if (g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C) {
440 : 2432 : dst_buff_len = g_xfer_size_bytes * g_chained_count;
441 : 128 : }
442 : :
443 [ + + + + ]: 8512 : if (g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE ||
444 [ + + ]: 7296 : g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY) {
445 [ - + - + : 2432 : src_buff_len += (g_xfer_size_bytes / g_block_size_bytes) * g_md_size_bytes;
- + ]
446 : 128 : }
447 : :
448 [ + + + - : 19456 : for (i = 0; i < task->src_iovcnt; i++) {
+ + ]
449 [ - + - + : 10944 : task->src_iovs[i].iov_base = spdk_dma_zmalloc(src_buff_len, 0, NULL);
- + - + -
+ ]
450 [ - + - + : 10944 : if (task->src_iovs[i].iov_base == NULL) {
- + - + -
+ - + ]
451 : 0 : return -ENOMEM;
452 : : }
453 [ - + - + : 10944 : memset(task->src_iovs[i].iov_base, DATA_PATTERN, src_buff_len);
- + - + -
+ - + ]
454 [ - + - + : 10944 : task->src_iovs[i].iov_len = src_buff_len;
- + - + -
+ ]
455 : 576 : }
456 [ + + ]: 8960 : } else if (g_workload_selection == SPDK_ACCEL_OPC_XOR) {
457 [ + + # # ]: 2432 : assert(g_xor_src_count > 1);
458 [ + - + - ]: 2432 : task->sources = calloc(g_xor_src_count, sizeof(*task->sources));
459 [ + + + - : 2432 : if (!task->sources) {
+ - ]
460 : 0 : return -ENOMEM;
461 : : }
462 : :
463 [ + + ]: 8512 : for (i = 0; i < g_xor_src_count; i++) {
464 [ + - + - : 6080 : task->sources[i] = spdk_dma_zmalloc(g_xfer_size_bytes, 0, NULL);
+ - + - ]
465 [ + + + - : 6080 : if (!task->sources[i]) {
+ - + - -
+ ]
466 : 0 : return -ENOMEM;
467 : : }
468 [ + + + - : 6080 : memset(task->sources[i], DATA_PATTERN, g_xfer_size_bytes);
+ - + - +
- ]
469 : 320 : }
470 : 128 : } else {
471 [ + - + - ]: 6080 : task->src = spdk_dma_zmalloc(g_xfer_size_bytes, 0, NULL);
472 [ + + + - : 6080 : if (task->src == NULL) {
+ - ]
473 [ # # # # ]: 0 : fprintf(stderr, "Unable to alloc src buffer\n");
474 : 0 : return -ENOMEM;
475 : : }
476 : :
477 : : /* For fill, set the entire src buffer so we can check if verify is enabled. */
478 [ + + ]: 6080 : if (g_workload_selection == SPDK_ACCEL_OPC_FILL) {
479 [ + + + - : 2432 : memset(task->src, g_fill_pattern, g_xfer_size_bytes);
+ - ]
480 : 128 : } else {
481 [ + + + - : 3648 : memset(task->src, DATA_PATTERN, g_xfer_size_bytes);
+ - ]
482 : : }
483 : : }
484 : :
485 [ + + + + ]: 17664 : if (g_workload_selection != SPDK_ACCEL_OPC_CRC32C &&
486 [ + + ]: 14592 : g_workload_selection != SPDK_ACCEL_OPC_DIF_VERIFY &&
487 [ + + ]: 13376 : g_workload_selection != SPDK_ACCEL_OPC_DIF_GENERATE &&
488 [ + + ]: 12160 : g_workload_selection != SPDK_ACCEL_OPC_DIF_GENERATE_COPY) {
489 [ + - + - ]: 10944 : task->dst = spdk_dma_zmalloc(dst_buff_len, align, NULL);
490 [ + + + - : 10944 : if (task->dst == NULL) {
- + ]
491 [ # # # # ]: 0 : fprintf(stderr, "Unable to alloc dst buffer\n");
492 : 0 : return -ENOMEM;
493 : : }
494 : :
495 : : /* For compare we want the buffers to match, otherwise not. */
496 [ + + ]: 10944 : if (g_workload_selection == SPDK_ACCEL_OPC_COMPARE) {
497 [ + + + - : 1216 : memset(task->dst, DATA_PATTERN, dst_buff_len);
+ - ]
498 : 64 : } else {
499 [ + + + - : 9728 : memset(task->dst, ~DATA_PATTERN, dst_buff_len);
+ - ]
500 : : }
501 : 576 : }
502 : :
503 : : /* For dualcast 2 buffers are needed for the operation. */
504 [ + + + - ]: 17152 : if (g_workload_selection == SPDK_ACCEL_OPC_DUALCAST ||
505 [ + + + + : 15808 : (g_workload_selection == SPDK_ACCEL_OPC_XOR && g_verify)) {
+ - ]
506 [ + - + - ]: 3648 : task->dst2 = spdk_dma_zmalloc(g_xfer_size_bytes, align, NULL);
507 [ + + + - : 3648 : if (task->dst2 == NULL) {
- + ]
508 [ # # # # ]: 0 : fprintf(stderr, "Unable to alloc dst buffer\n");
509 : 0 : return -ENOMEM;
510 : : }
511 [ - + - + : 3648 : memset(task->dst2, ~DATA_PATTERN, g_xfer_size_bytes);
- + ]
512 : 192 : }
513 : :
514 [ + + + + ]: 17024 : if (g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE ||
515 [ + + ]: 15808 : g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY) {
516 : 2432 : dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
517 [ + - ]: 2432 : dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
518 : :
519 [ + + + - : 2432 : task->num_blocks = (g_xfer_size_bytes * g_chained_count) / g_block_size_bytes;
+ - ]
520 : :
521 [ + - ]: 2560 : rc = spdk_dif_ctx_init(&task->dif_ctx,
522 [ + - ]: 2432 : g_block_size_bytes + g_md_size_bytes,
523 : 128 : g_md_size_bytes, true, true,
524 : : SPDK_DIF_TYPE1,
525 [ + - + - : 128 : SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | SPDK_DIF_FLAGS_REFTAG_CHECK,
+ - ]
526 : : 16, 0xFFFF, 10, 0, 0, &dif_opts);
527 [ - + ]: 2432 : if (rc != 0) {
528 [ # # # # ]: 0 : fprintf(stderr, "Initialization of DIF context failed, error (%d)\n", rc);
529 : 0 : return rc;
530 : : }
531 : :
532 [ + + ]: 2432 : if (g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY) {
533 [ + - + - : 1216 : rc = spdk_dif_generate(task->src_iovs, task->src_iovcnt, task->num_blocks, &task->dif_ctx);
+ - + - +
- + - +
- ]
534 [ - + ]: 1216 : if (rc != 0) {
535 [ # # # # ]: 0 : fprintf(stderr, "Generation of DIF failed, error (%d)\n", rc);
536 : 0 : return rc;
537 : : }
538 : 64 : }
539 : 128 : }
540 : :
541 : 17024 : return 0;
542 : 1856 : }
543 : :
544 : : inline static struct ap_task *
545 : 246783881 : _get_task(struct worker_thread *worker)
546 : : {
547 : : struct ap_task *task;
548 : :
549 [ + - + - : 246783881 : if (!TAILQ_EMPTY(&worker->tasks_pool)) {
+ - + - ]
550 [ + - + - : 246783881 : task = TAILQ_FIRST(&worker->tasks_pool);
+ - ]
551 [ + + + - : 246783881 : TAILQ_REMOVE(&worker->tasks_pool, task, link);
+ - + + +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - ]
552 : 15762282 : } else {
553 [ # # # # ]: 0 : fprintf(stderr, "Unable to get ap_task\n");
554 : 0 : return NULL;
555 : : }
556 : :
557 : 246783881 : return task;
558 : 15762282 : }
559 : :
560 : : /* Submit one operation using the same ap task that just completed. */
561 : : static void
562 : 246785647 : _submit_single(struct worker_thread *worker, struct ap_task *task)
563 : : {
564 : : int random_num;
565 : 246785647 : int rc = 0;
566 : 246785647 : int flags = 0;
567 : :
568 [ + + # # ]: 246785647 : assert(worker);
569 : :
570 [ + + + + : 246785647 : switch (worker->workload) {
+ + + + +
+ + + + +
- + + ]
571 : 19549056 : case SPDK_ACCEL_OPC_COPY:
572 [ + - + - : 20642624 : rc = spdk_accel_submit_copy(worker->ch, task->dst, task->src,
+ - + - +
- + - ]
573 : 1093568 : g_xfer_size_bytes, flags, accel_done, task);
574 : 20642624 : break;
575 : 28722944 : case SPDK_ACCEL_OPC_FILL:
576 : : /* For fill use the first byte of the task->dst buffer */
577 [ + - + - : 30672256 : rc = spdk_accel_submit_fill(worker->ch, task->dst, *(uint8_t *)task->src,
+ - + - +
- + - +
- ]
578 : 1949312 : g_xfer_size_bytes, flags, accel_done, task);
579 : 30672256 : break;
580 : 43265920 : case SPDK_ACCEL_OPC_CRC32C:
581 [ + - + - : 49115008 : rc = spdk_accel_submit_crc32cv(worker->ch, &task->crc_dst,
+ - ]
582 [ + - + - : 2924544 : task->src_iovs, task->src_iovcnt, g_crc32c_seed,
+ - + - ]
583 : 2924544 : accel_done, task);
584 : 46190464 : break;
585 : 23833568 : case SPDK_ACCEL_OPC_COPY_CRC32C:
586 [ + - + - : 25293632 : rc = spdk_accel_submit_copy_crc32cv(worker->ch, task->dst, task->src_iovs, task->src_iovcnt,
+ - + - +
- + - + -
+ - ]
587 [ + - ]: 1460064 : &task->crc_dst, g_crc32c_seed, flags, accel_done, task);
588 : 25293632 : break;
589 : 29009984 : case SPDK_ACCEL_OPC_COMPARE:
590 [ + - ]: 30650144 : random_num = rand() % 100;
591 [ - + ]: 30650144 : if (random_num < g_fail_percent_goal) {
592 [ # # # # ]: 0 : task->expected_status = -EILSEQ;
593 [ # # # # : 0 : *(uint8_t *)task->dst = ~DATA_PATTERN;
# # ]
594 : 0 : } else {
595 [ + - + - ]: 30650144 : task->expected_status = 0;
596 [ + - + - : 30650144 : *(uint8_t *)task->dst = DATA_PATTERN;
+ - ]
597 : : }
598 [ + - + - : 30650144 : rc = spdk_accel_submit_compare(worker->ch, task->dst, task->src,
+ - + - +
- + - ]
599 : 1640160 : g_xfer_size_bytes, accel_done, task);
600 : 30650144 : break;
601 : 20015072 : case SPDK_ACCEL_OPC_DUALCAST:
602 [ + - + - : 22512736 : rc = spdk_accel_submit_dualcast(worker->ch, task->dst, task->dst2,
+ - + - +
- + - ]
603 [ + - + - ]: 1248832 : task->src, g_xfer_size_bytes, flags, accel_done, task);
604 : 21263904 : break;
605 : 2372129 : case SPDK_ACCEL_OPC_COMPRESS:
606 [ + - + - : 2506241 : task->src_iovs = task->cur_seg->uncompressed_iovs;
+ - + - +
- + - ]
607 [ + - + - : 2506241 : task->src_iovcnt = task->cur_seg->uncompressed_iovcnt;
+ - + - +
- + - ]
608 [ + - + - : 4643074 : rc = spdk_accel_submit_compress(worker->ch, task->dst, task->cur_seg->compressed_len_padded,
+ - + - +
- + - + -
+ - ]
609 [ + - + - ]: 134112 : task->src_iovs,
610 [ + - + - : 2506241 : task->src_iovcnt, &task->compressed_sz, flags, accel_done, task);
+ - ]
611 : 2506241 : break;
612 : 16592222 : case SPDK_ACCEL_OPC_DECOMPRESS:
613 [ + - + - : 17635694 : task->src_iovs = task->cur_seg->compressed_iovs;
+ - + - +
- + - ]
614 [ + - + - : 17635694 : task->src_iovcnt = task->cur_seg->compressed_iovcnt;
+ - + - +
- + - ]
615 [ + - + - : 18679166 : rc = spdk_accel_submit_decompress(worker->ch, task->dst_iovs, task->dst_iovcnt, task->src_iovs,
+ - + - +
- + - + -
+ - ]
616 [ + - + - ]: 17635694 : task->src_iovcnt, NULL, flags, accel_done, task);
617 : 17635694 : break;
618 : 30921440 : case SPDK_ACCEL_OPC_XOR:
619 [ + - + - : 33685344 : rc = spdk_accel_submit_xor(worker->ch, task->dst, task->sources, g_xor_src_count,
+ - + - +
- + - ]
620 : 2763904 : g_xfer_size_bytes, accel_done, task);
621 : 33685344 : break;
622 : 5228960 : case SPDK_ACCEL_OPC_DIF_VERIFY:
623 [ + - + - : 9578624 : rc = spdk_accel_submit_dif_verify(worker->ch, task->src_iovs, task->src_iovcnt, task->num_blocks,
+ - + - +
- + - + -
+ - ]
624 [ + - + - ]: 5714208 : &task->dif_ctx, &task->dif_err, accel_done, task);
625 : 5714208 : break;
626 : 6588320 : case SPDK_ACCEL_OPC_DIF_GENERATE:
627 [ + - + - : 7163168 : rc = spdk_accel_submit_dif_generate(worker->ch, task->src_iovs, task->src_iovcnt, task->num_blocks,
+ - + - +
- + - + -
+ - ]
628 [ + - ]: 7163168 : &task->dif_ctx, accel_done, task);
629 : 7163168 : break;
630 : 4921984 : case SPDK_ACCEL_OPC_DIF_GENERATE_COPY:
631 [ + - + - : 9018368 : rc = spdk_accel_submit_dif_generate_copy(worker->ch, task->dst_iovs, task->dst_iovcnt,
+ - + - +
- + - ]
632 [ + - + - : 5367968 : task->src_iovs, task->src_iovcnt,
+ - + - ]
633 [ + - + - : 5367968 : task->num_blocks, &task->dif_ctx, accel_done, task);
+ - ]
634 : 5367968 : break;
635 : 0 : default:
636 [ # # ]: 0 : assert(false);
637 : : break;
638 : :
639 : : }
640 : :
641 [ + - ]: 246785647 : worker->current_queue_depth++;
642 [ + + ]: 246785647 : if (rc) {
643 : 0 : accel_done(task, rc);
644 : 0 : }
645 : 246785647 : }
646 : :
647 : : static void
648 : 36224 : _free_task_buffers(struct ap_task *task)
649 : : {
650 : : uint32_t i;
651 : :
652 [ + + + + ]: 36224 : if (g_workload_selection == SPDK_ACCEL_OPC_DECOMPRESS ||
653 [ + + ]: 18304 : g_workload_selection == SPDK_ACCEL_OPC_COMPRESS) {
654 [ + - + - ]: 19200 : free(task->dst_iovs);
655 [ + + + + ]: 18496 : } else if (g_workload_selection == SPDK_ACCEL_OPC_CRC32C ||
656 [ + + ]: 14592 : g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C ||
657 [ + + ]: 12160 : g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY ||
658 [ + + ]: 10944 : g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE ||
659 [ + + ]: 9728 : g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE_COPY) {
660 [ + - + - : 8512 : if (task->src_iovs) {
- + ]
661 [ + + + - : 19456 : for (i = 0; i < task->src_iovcnt; i++) {
+ + ]
662 [ + - + - : 10944 : if (task->src_iovs[i].iov_base) {
+ - + - +
- - + ]
663 [ + - + - : 10944 : spdk_dma_free(task->src_iovs[i].iov_base);
+ - + - +
- ]
664 : 576 : }
665 : 576 : }
666 [ + - + - ]: 8512 : free(task->src_iovs);
667 : 448 : }
668 [ + + ]: 8960 : } else if (g_workload_selection == SPDK_ACCEL_OPC_XOR) {
669 [ + - + - : 2432 : if (task->sources) {
- + ]
670 [ + + ]: 8512 : for (i = 0; i < g_xor_src_count; i++) {
671 [ + - + - : 6080 : spdk_dma_free(task->sources[i]);
+ - + - ]
672 : 320 : }
673 [ - + - + ]: 2432 : free(task->sources);
674 : 128 : }
675 : 128 : } else {
676 [ + - + - ]: 6080 : spdk_dma_free(task->src);
677 : : }
678 : :
679 [ + - + - ]: 36224 : spdk_dma_free(task->dst);
680 [ + + + + ]: 36224 : if (g_workload_selection == SPDK_ACCEL_OPC_DUALCAST || g_workload_selection == SPDK_ACCEL_OPC_XOR) {
681 [ + - + - ]: 3648 : spdk_dma_free(task->dst2);
682 : 192 : }
683 : :
684 [ + + ]: 36224 : if (g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE_COPY) {
685 [ + - + - : 1216 : if (task->dst_iovs) {
- + ]
686 [ + + + - : 2432 : for (i = 0; i < task->dst_iovcnt; i++) {
+ + ]
687 [ + - + - : 1216 : if (task->dst_iovs[i].iov_base) {
+ - + - +
- - + ]
688 [ + - + - : 1216 : spdk_dma_free(task->dst_iovs[i].iov_base);
+ - + - +
- ]
689 : 64 : }
690 : 64 : }
691 [ + - + - ]: 1216 : free(task->dst_iovs);
692 : 64 : }
693 : 64 : }
694 : 36224 : }
695 : :
696 : : static int
697 : 25293632 : _vector_memcmp(void *_dst, struct iovec *src_src_iovs, uint32_t iovcnt)
698 : : {
699 : : uint32_t i;
700 : 25293632 : uint32_t ttl_len = 0;
701 : 25293632 : uint8_t *dst = (uint8_t *)_dst;
702 : :
703 [ + + ]: 60907264 : for (i = 0; i < iovcnt; i++) {
704 [ + + + + : 35613632 : if (memcmp(dst, src_src_iovs[i].iov_base, src_src_iovs[i].iov_len)) {
+ + + - +
- + - + -
+ - + - ]
705 : 0 : return -1;
706 : : }
707 [ - + - + : 35613632 : dst += src_src_iovs[i].iov_len;
- + - + ]
708 [ - + - + : 35613632 : ttl_len += src_src_iovs[i].iov_len;
- + ]
709 : 2061920 : }
710 : :
711 [ - + ]: 25293632 : if (ttl_len != iovcnt * g_xfer_size_bytes) {
712 : 0 : return -1;
713 : : }
714 : :
715 : 25293632 : return 0;
716 : 1460064 : }
717 : :
718 : : static int _worker_stop(void *arg);
719 : :
720 : : static void
721 : 246782179 : accel_done(void *arg1, int status)
722 : : {
723 : 246782179 : struct ap_task *task = arg1;
724 [ + - + - ]: 246782179 : struct worker_thread *worker = task->worker;
725 : : uint32_t sw_crc32c;
726 : 83400800 : struct spdk_dif_error err_blk;
727 : :
728 [ + + # # ]: 246782179 : assert(worker);
729 [ + + + - : 246782179 : assert(worker->current_queue_depth > 0);
+ - # # ]
730 : :
731 [ + + + + : 246782179 : if (g_verify && status == 0) {
+ + ]
732 [ + + + + : 226028285 : switch (worker->workload) {
+ + + + +
+ - + - -
- + - ]
733 : 23833568 : case SPDK_ACCEL_OPC_COPY_CRC32C:
734 [ + - + - : 25293632 : sw_crc32c = spdk_crc32c_iov_update(task->src_iovs, task->src_iovcnt, ~g_crc32c_seed);
+ - + - ]
735 [ + + + - : 25293632 : if (task->crc_dst != sw_crc32c) {
+ - ]
736 : 0 : SPDK_NOTICELOG("CRC-32C miscompare\n");
737 [ # # ]: 0 : worker->xfer_failed++;
738 : 0 : }
739 [ + + + - : 25293632 : if (_vector_memcmp(task->dst, task->src_iovs, task->src_iovcnt)) {
+ - + - +
- + - +
- ]
740 : 0 : SPDK_NOTICELOG("Data miscompare\n");
741 [ # # ]: 0 : worker->xfer_failed++;
742 : 0 : }
743 : 25293632 : break;
744 : 43265920 : case SPDK_ACCEL_OPC_CRC32C:
745 [ + - + - : 46190464 : sw_crc32c = spdk_crc32c_iov_update(task->src_iovs, task->src_iovcnt, ~g_crc32c_seed);
+ - + - ]
746 [ + + + - : 46190464 : if (task->crc_dst != sw_crc32c) {
+ - ]
747 : 0 : SPDK_NOTICELOG("CRC-32C miscompare\n");
748 [ # # ]: 0 : worker->xfer_failed++;
749 : 0 : }
750 : 46190464 : break;
751 : 19549056 : case SPDK_ACCEL_OPC_COPY:
752 [ + + + + : 20642624 : if (memcmp(task->src, task->dst, g_xfer_size_bytes)) {
+ + + - +
- + - -
+ ]
753 : 0 : SPDK_NOTICELOG("Data miscompare\n");
754 [ # # ]: 0 : worker->xfer_failed++;
755 : 0 : }
756 : 20642624 : break;
757 : 20015072 : case SPDK_ACCEL_OPC_DUALCAST:
758 [ + + + + : 21263904 : if (memcmp(task->src, task->dst, g_xfer_size_bytes)) {
+ + + - +
- + - +
- ]
759 : 0 : SPDK_NOTICELOG("Data miscompare, first destination\n");
760 [ # # ]: 0 : worker->xfer_failed++;
761 : 0 : }
762 [ + + + + : 21263904 : if (memcmp(task->src, task->dst2, g_xfer_size_bytes)) {
+ + + - +
- + - +
- ]
763 : 0 : SPDK_NOTICELOG("Data miscompare, second destination\n");
764 [ # # ]: 0 : worker->xfer_failed++;
765 : 0 : }
766 : 21263904 : break;
767 : 28722944 : case SPDK_ACCEL_OPC_FILL:
768 [ + + + + : 30672256 : if (memcmp(task->dst, task->src, g_xfer_size_bytes)) {
+ + + - +
- + - +
- ]
769 : 0 : SPDK_NOTICELOG("Data miscompare\n");
770 [ # # ]: 0 : worker->xfer_failed++;
771 : 0 : }
772 : 30672256 : break;
773 : 29009984 : case SPDK_ACCEL_OPC_COMPARE:
774 : 30650144 : break;
775 : 0 : case SPDK_ACCEL_OPC_COMPRESS:
776 : 0 : break;
777 : 16592222 : case SPDK_ACCEL_OPC_DECOMPRESS:
778 [ + + + + : 17629917 : if (memcmp(task->dst, task->cur_seg->uncompressed_data, task->cur_seg->uncompressed_len)) {
+ + + - +
- + - + -
+ - + - +
- + - + -
+ - ]
779 : 0 : SPDK_NOTICELOG("Data miscompare on decompression\n");
780 [ # # ]: 0 : worker->xfer_failed++;
781 : 0 : }
782 : 17629917 : break;
783 : 30921440 : case SPDK_ACCEL_OPC_XOR:
784 [ + + + - : 33685344 : if (spdk_xor_gen(task->dst2, task->sources, g_xor_src_count,
+ - + - -
+ - + -
+ ]
785 : 5527808 : g_xfer_size_bytes) != 0) {
786 : 0 : SPDK_ERRLOG("Failed to generate xor for verification\n");
787 [ - + - + : 33685344 : } else if (memcmp(task->dst, task->dst2, g_xfer_size_bytes)) {
- + - + -
+ - + +
- ]
788 : 0 : SPDK_NOTICELOG("Data miscompare\n");
789 [ # # ]: 0 : worker->xfer_failed++;
790 : 0 : }
791 : 33685344 : break;
792 : 0 : case SPDK_ACCEL_OPC_DIF_VERIFY:
793 : 0 : break;
794 : 0 : case SPDK_ACCEL_OPC_DIF_GENERATE:
795 [ # # # # : 0 : if (spdk_dif_verify(task->src_iovs, task->src_iovcnt, task->num_blocks,
# # # # #
# # # # #
# # ]
796 [ # # ]: 0 : &task->dif_ctx, &err_blk) != 0) {
797 [ # # # # : 0 : SPDK_NOTICELOG("Data miscompare, "
# # ]
798 : : "err_type %u, expected %lu, actual %lu, err_offset %u\n",
799 : : err_blk.err_type, err_blk.expected,
800 : : err_blk.actual, err_blk.err_offset);
801 [ # # ]: 0 : worker->xfer_failed++;
802 : 0 : }
803 : 0 : break;
804 : 0 : case SPDK_ACCEL_OPC_DIF_GENERATE_COPY:
805 [ # # # # : 0 : if (spdk_dif_verify(task->dst_iovs, task->dst_iovcnt, task->num_blocks,
# # # # #
# # # # #
# # ]
806 [ # # ]: 0 : &task->dif_ctx, &err_blk) != 0) {
807 [ # # # # : 0 : SPDK_NOTICELOG("Data miscompare, "
# # ]
808 : : "err_type %u, expected %lu, actual %lu, err_offset %u\n",
809 : : err_blk.err_type, err_blk.expected,
810 : : err_blk.actual, err_blk.err_offset);
811 [ # # ]: 0 : worker->xfer_failed++;
812 : 0 : }
813 : 0 : break;
814 : 0 : default:
815 [ # # ]: 0 : assert(false);
816 : : break;
817 : : }
818 : 14118079 : }
819 : :
820 [ + + + - : 246782179 : if (worker->workload == SPDK_ACCEL_OPC_COMPRESS ||
+ + + + ]
821 [ + + ]: 244279304 : g_workload_selection == SPDK_ACCEL_OPC_DECOMPRESS) {
822 : : /* Advance the task to the next segment */
823 [ + - + - : 20139322 : task->cur_seg = STAILQ_NEXT(task->cur_seg, link);
+ - + - +
- + - +
- ]
824 [ + + + - : 20139322 : if (task->cur_seg == NULL) {
+ + ]
825 [ + - + - ]: 2137659 : task->cur_seg = STAILQ_FIRST(&g_compress_segs);
826 : 109500 : }
827 : 1174971 : }
828 : :
829 [ + + + - : 246782179 : if (task->expected_status == -EILSEQ) {
- + ]
830 [ # # # # ]: 0 : assert(status != 0);
831 [ # # ]: 0 : worker->injected_miscompares++;
832 : 0 : status = 0;
833 [ + + ]: 246782179 : } else if (status) {
834 : : /* Expected to pass but the accel module reported an error (ex: COMPARE operation). */
835 [ # # ]: 0 : worker->xfer_failed++;
836 : 0 : }
837 : :
838 [ + - ]: 246782179 : worker->current_queue_depth--;
839 : :
840 [ + + + + : 246782179 : if (!worker->is_draining && status == 0) {
+ - + + +
+ ]
841 [ + - + - : 246750914 : TAILQ_INSERT_TAIL(&worker->tasks_pool, task, link);
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - ]
842 : 246750914 : task = _get_task(worker);
843 : 246750914 : _submit_single(worker, task);
844 : 15763683 : } else {
845 [ + - + - : 44821 : TAILQ_INSERT_TAIL(&worker->tasks_pool, task, link);
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - ]
846 : : }
847 : 246795735 : }
848 : :
849 : : static int
850 : 774 : dump_result(void)
851 : : {
852 : 774 : uint64_t total_completed = 0;
853 : 774 : uint64_t total_failed = 0;
854 : 774 : uint64_t total_miscompared = 0;
855 : : uint64_t total_xfer_per_sec, total_bw_in_MiBps;
856 : 774 : struct worker_thread *worker = g_workers;
857 : 320 : char tmp[64];
858 : :
859 [ - + ]: 774 : printf("\n%-12s %20s %16s %16s %16s\n",
860 : : "Core,Thread", "Transfers", "Bandwidth", "Failed", "Miscompares");
861 [ - + ]: 774 : printf("------------------------------------------------------------------------------------\n");
862 [ + + ]: 1868 : while (worker != NULL) {
863 : :
864 [ + + + - : 1094 : uint64_t xfer_per_sec = worker->stats.executed / g_time_in_sec;
+ - + - ]
865 [ + + + - : 1150 : uint64_t bw_in_MiBps = worker->stats.num_bytes /
+ - + - ]
866 [ + - + - ]: 1094 : (g_time_in_sec * 1024 * 1024);
867 : :
868 [ + - + - : 1094 : total_completed += worker->stats.executed;
+ - ]
869 [ + - + - ]: 1094 : total_failed += worker->xfer_failed;
870 [ + - + - ]: 1094 : total_miscompared += worker->injected_miscompares;
871 : :
872 [ + + + - : 1094 : snprintf(tmp, sizeof(tmp), "%u,%u", worker->display.core, worker->display.thread);
+ - + - +
- + - ]
873 [ + + ]: 1094 : if (xfer_per_sec) {
874 [ - + ]: 1094 : printf("%-12s %18" PRIu64 "/s %10" PRIu64 " MiB/s %16"PRIu64 " %16" PRIu64 "\n",
875 [ + - + - ]: 56 : tmp, xfer_per_sec, bw_in_MiBps, worker->xfer_failed,
876 [ + - + - ]: 56 : worker->injected_miscompares);
877 : 56 : }
878 : :
879 [ + - + - ]: 1094 : worker = worker->next;
880 : : }
881 : :
882 [ + + ]: 774 : total_xfer_per_sec = total_completed / g_time_in_sec;
883 [ + - ]: 200 : total_bw_in_MiBps = (total_completed * g_xfer_size_bytes) /
884 [ + + + - ]: 774 : (g_time_in_sec * 1024 * 1024);
885 : :
886 [ - + ]: 774 : printf("====================================================================================\n");
887 [ - + ]: 774 : printf("%-12s %18" PRIu64 "/s %10" PRIu64 " MiB/s %16"PRIu64 " %16" PRIu64 "\n",
888 : 40 : "Total", total_xfer_per_sec, total_bw_in_MiBps, total_failed, total_miscompared);
889 : :
890 : 774 : return total_failed ? 1 : 0;
891 : : }
892 : :
893 : : static inline void
894 : 1094 : _free_task_buffers_in_pool(struct worker_thread *worker)
895 : : {
896 : : struct ap_task *task;
897 : :
898 [ + + # # ]: 1094 : assert(worker);
899 [ + + + - : 37318 : while ((task = TAILQ_FIRST(&worker->tasks_pool))) {
+ - + + ]
900 [ + + + - : 36224 : TAILQ_REMOVE(&worker->tasks_pool, task, link);
+ - + + +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - ]
901 : 36224 : _free_task_buffers(task);
902 : : }
903 : 1094 : }
904 : :
905 : : static int
906 : 4636 : _check_draining(void *arg)
907 : : {
908 : 4636 : struct worker_thread *worker = arg;
909 : :
910 [ + + # # ]: 4636 : assert(worker);
911 : :
912 [ + + + - : 4636 : if (worker->current_queue_depth == 0) {
+ + ]
913 : 1094 : _free_task_buffers_in_pool(worker);
914 [ + - ]: 1094 : spdk_poller_unregister(&worker->is_draining_poller);
915 : 1094 : unregister_worker(worker);
916 : 56 : }
917 : :
918 : 4636 : return SPDK_POLLER_BUSY;
919 : : }
920 : :
921 : : static int
922 : 1094 : _worker_stop(void *arg)
923 : : {
924 : 1094 : struct worker_thread *worker = arg;
925 : :
926 [ + + # # ]: 1094 : assert(worker);
927 : :
928 [ + - ]: 1094 : spdk_poller_unregister(&worker->stop_poller);
929 : :
930 : : /* now let the worker drain and check it's outstanding IO with a poller */
931 [ + - + - ]: 1094 : worker->is_draining = true;
932 [ + - + - ]: 1094 : worker->is_draining_poller = SPDK_POLLER_REGISTER(_check_draining, worker, 0);
933 : :
934 : 1094 : return SPDK_POLLER_BUSY;
935 : : }
936 : :
937 : : static void shutdown_cb(void);
938 : :
939 : : static void
940 : 1094 : _init_thread(void *arg1)
941 : : {
942 : : struct worker_thread *worker;
943 : : struct ap_task *task;
944 : 1094 : int i, num_tasks = g_allocate_depth;
945 : 1094 : struct display_info *display = arg1;
946 : :
947 : 1094 : worker = calloc(1, sizeof(*worker));
948 [ + + ]: 1094 : if (worker == NULL) {
949 [ # # # # ]: 0 : fprintf(stderr, "Unable to allocate worker\n");
950 : 0 : free(display);
951 : 0 : spdk_thread_exit(spdk_get_thread());
952 : 0 : goto no_worker;
953 : : }
954 : :
955 [ + - + - ]: 1094 : worker->workload = g_workload_selection;
956 [ + - + - : 1094 : worker->display.core = display->core;
+ - + - +
- ]
957 [ + - + - : 1094 : worker->display.thread = display->thread;
+ - + - +
- ]
958 : 1094 : free(display);
959 [ + - + - ]: 1094 : worker->core = spdk_env_get_current_core();
960 [ + - + - ]: 1094 : worker->thread = spdk_get_thread();
961 [ + + ]: 1094 : pthread_mutex_lock(&g_workers_lock);
962 [ + - ]: 1094 : g_num_workers++;
963 [ + - + - ]: 1094 : worker->next = g_workers;
964 : 1094 : g_workers = worker;
965 [ + + ]: 1094 : pthread_mutex_unlock(&g_workers_lock);
966 [ + - + - ]: 1094 : worker->ch = spdk_accel_get_io_channel();
967 [ + + + - : 1094 : if (worker->ch == NULL) {
+ - ]
968 [ # # # # ]: 0 : fprintf(stderr, "Unable to get an accel channel\n");
969 : 0 : goto error;
970 : : }
971 : :
972 [ + - + - : 1094 : TAILQ_INIT(&worker->tasks_pool);
+ - + - +
- + - + -
+ - ]
973 : :
974 [ + - + - ]: 1094 : worker->task_base = calloc(num_tasks, sizeof(struct ap_task));
975 [ + + + - : 1094 : if (worker->task_base == NULL) {
+ - ]
976 [ # # # # ]: 0 : fprintf(stderr, "Could not allocate task base.\n");
977 : 0 : goto error;
978 : : }
979 : :
980 [ + - + - ]: 1094 : task = worker->task_base;
981 [ + + + - ]: 37317 : for (i = 0; i < num_tasks; i++) {
982 [ + - + - : 36223 : TAILQ_INSERT_TAIL(&worker->tasks_pool, task, link);
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - ]
983 [ + - + - ]: 36223 : task->worker = worker;
984 [ + + ]: 36223 : if (_get_task_data_bufs(task)) {
985 [ # # # # ]: 0 : fprintf(stderr, "Unable to get data bufs\n");
986 : 0 : goto error;
987 : : }
988 [ + - ]: 36223 : task++;
989 : 1855 : }
990 : :
991 : : /* Register a poller that will stop the worker at time elapsed */
992 [ + - + - ]: 1094 : worker->stop_poller = SPDK_POLLER_REGISTER(_worker_stop, worker,
993 : : g_time_in_sec * 1000000ULL);
994 : :
995 : : /* Load up queue depth worth of operations. */
996 [ + + + - ]: 37317 : for (i = 0; i < g_queue_depth; i++) {
997 : 36223 : task = _get_task(worker);
998 [ + + ]: 36223 : if (task == NULL) {
999 : 0 : goto error;
1000 : : }
1001 : :
1002 : 36223 : _submit_single(worker, task);
1003 : 1855 : }
1004 : 1094 : return;
1005 : 0 : error:
1006 : :
1007 : 0 : _free_task_buffers_in_pool(worker);
1008 [ # # # # ]: 0 : free(worker->task_base);
1009 : 0 : no_worker:
1010 : 0 : shutdown_cb();
1011 : 0 : g_rc = -1;
1012 : 56 : }
1013 : :
1014 : : static void
1015 : 774 : accel_perf_start(void *arg1)
1016 : : {
1017 : 774 : struct spdk_cpuset tmp_cpumask = {};
1018 : 320 : char thread_name[32];
1019 : : uint32_t i;
1020 : : int j;
1021 : : struct spdk_thread *thread;
1022 : : struct display_info *display;
1023 : :
1024 : 774 : g_tsc_rate = spdk_get_ticks_hz();
1025 : 774 : g_tsc_end = spdk_get_ticks() + g_time_in_sec * g_tsc_rate;
1026 : :
1027 : 774 : dump_user_config();
1028 : :
1029 [ - + ]: 774 : printf("Running for %d seconds...\n", g_time_in_sec);
1030 : 774 : fflush(stdout);
1031 : :
1032 : : /* Create worker threads for each core that was specified. */
1033 [ + + ]: 1788 : SPDK_ENV_FOREACH_CORE(i) {
1034 [ + + - + ]: 2108 : for (j = 0; j < g_threads_per_core; j++) {
1035 [ - + ]: 1094 : snprintf(thread_name, sizeof(thread_name), "ap_worker_%u_%u", i, j);
1036 : 1094 : spdk_cpuset_zero(&tmp_cpumask);
1037 : 1094 : spdk_cpuset_set_cpu(&tmp_cpumask, i, true);
1038 : 1094 : thread = spdk_thread_create(thread_name, &tmp_cpumask);
1039 : 1094 : display = calloc(1, sizeof(*display));
1040 [ + + ]: 1094 : if (display == NULL) {
1041 [ # # # # ]: 0 : fprintf(stderr, "Unable to allocate memory\n");
1042 : 0 : spdk_app_stop(-1);
1043 : 0 : return;
1044 : : }
1045 [ - + - + ]: 1094 : display->core = i;
1046 [ - + - + ]: 1094 : display->thread = j;
1047 : 1094 : spdk_thread_send_msg(thread, _init_thread, display);
1048 : 56 : }
1049 : 52 : }
1050 : 40 : }
1051 : :
1052 : : static void
1053 : 812 : accel_perf_free_compress_segs(void)
1054 : : {
1055 : : struct ap_compress_seg *seg, *tmp;
1056 : :
1057 [ + + + - : 5412 : STAILQ_FOREACH_SAFE(seg, &g_compress_segs, link, tmp) {
+ - + - +
+ ]
1058 [ + - + - ]: 4600 : free(seg->uncompressed_iovs);
1059 [ + - + - ]: 4600 : free(seg->compressed_iovs);
1060 [ + - + - ]: 4600 : spdk_dma_free(seg->compressed_data);
1061 [ + - + - ]: 4600 : spdk_dma_free(seg->uncompressed_data);
1062 [ + + + - : 4600 : STAILQ_REMOVE_HEAD(&g_compress_segs, link);
+ - + + -
+ ]
1063 : 4600 : free(seg);
1064 : 230 : }
1065 : 812 : }
1066 : :
1067 : : struct accel_perf_prep_ctx {
1068 : : FILE *file;
1069 : : long remaining;
1070 : : struct spdk_io_channel *ch;
1071 : : struct ap_compress_seg *cur_seg;
1072 : : };
1073 : :
1074 : : static void accel_perf_prep_process_seg(struct accel_perf_prep_ctx *ctx);
1075 : :
1076 : : static void
1077 : 4600 : accel_perf_prep_process_seg_cpl(void *ref, int status)
1078 : : {
1079 : 4600 : struct accel_perf_prep_ctx *ctx = ref;
1080 : : struct ap_compress_seg *seg;
1081 : :
1082 [ - + ]: 4600 : if (status != 0) {
1083 [ # # # # ]: 0 : fprintf(stderr, "error (%d) on initial compress completion\n", status);
1084 [ # # # # : 0 : spdk_dma_free(ctx->cur_seg->compressed_data);
# # # # ]
1085 [ # # # # : 0 : spdk_dma_free(ctx->cur_seg->uncompressed_data);
# # # # ]
1086 [ # # # # ]: 0 : free(ctx->cur_seg);
1087 [ # # # # ]: 0 : spdk_put_io_channel(ctx->ch);
1088 [ # # # # : 0 : fclose(ctx->file);
# # ]
1089 : 0 : free(ctx);
1090 [ # # ]: 0 : spdk_app_stop(-status);
1091 : 0 : return;
1092 : : }
1093 : :
1094 [ + - + - ]: 4600 : seg = ctx->cur_seg;
1095 : :
1096 [ + + ]: 4600 : if (g_workload_selection == SPDK_ACCEL_OPC_DECOMPRESS) {
1097 [ + - + - ]: 3480 : seg->compressed_iovs = calloc(g_chained_count, sizeof(struct iovec));
1098 [ + + + - : 3480 : if (seg->compressed_iovs == NULL) {
+ - ]
1099 [ # # # # ]: 0 : fprintf(stderr, "unable to allocate iovec\n");
1100 [ # # # # ]: 0 : spdk_dma_free(seg->compressed_data);
1101 [ # # # # ]: 0 : spdk_dma_free(seg->uncompressed_data);
1102 : 0 : free(seg);
1103 [ # # # # ]: 0 : spdk_put_io_channel(ctx->ch);
1104 [ # # # # : 0 : fclose(ctx->file);
# # ]
1105 : 0 : free(ctx);
1106 : 0 : spdk_app_stop(-ENOMEM);
1107 : 0 : return;
1108 : : }
1109 [ + - + - ]: 3480 : seg->compressed_iovcnt = g_chained_count;
1110 : :
1111 [ + - + - : 3654 : accel_perf_construct_iovs(seg->compressed_data, seg->compressed_len, seg->compressed_iovs,
+ - + - +
- + - ]
1112 [ + - + - ]: 174 : seg->compressed_iovcnt);
1113 : 174 : }
1114 : :
1115 [ + - + - : 4600 : STAILQ_INSERT_TAIL(&g_compress_segs, seg, link);
+ - + - +
- + - + -
+ - ]
1116 [ + - + - : 4600 : ctx->remaining -= seg->uncompressed_len;
+ - + - +
- ]
1117 : :
1118 : 4600 : accel_perf_prep_process_seg(ctx);
1119 : 230 : }
1120 : :
1121 : : static void
1122 : 4880 : accel_perf_prep_process_seg(struct accel_perf_prep_ctx *ctx)
1123 : : {
1124 : : struct ap_compress_seg *seg;
1125 : : int sz, sz_read, sz_padded;
1126 : : void *ubuf, *cbuf;
1127 : 1952 : struct iovec iov[1];
1128 : : int rc;
1129 : :
1130 [ + + + - : 4880 : if (ctx->remaining == 0) {
+ + ]
1131 [ + - + - ]: 280 : spdk_put_io_channel(ctx->ch);
1132 [ + + + - : 280 : fclose(ctx->file);
+ - ]
1133 : 280 : free(ctx);
1134 : 280 : accel_perf_start(NULL);
1135 : 2810 : return;
1136 : : }
1137 : :
1138 [ + - + - : 4600 : sz = spdk_min(ctx->remaining, g_xfer_size_bytes);
+ + + - +
- ]
1139 : : /* Add 10% pad to the compress buffer for incompressible data. Note that a real app
1140 : : * would likely either deal with the failure of not having a large enough buffer
1141 : : * by submitting another operation with a larger one. Or, like the vbdev module
1142 : : * does, just accept the error and use the data uncompressed marking it as such in
1143 : : * its own metadata so that in the future it doesn't try to decompress uncompressed
1144 : : * data, etc.
1145 : : */
1146 [ + - ]: 4600 : sz_padded = sz * COMP_BUF_PAD_PERCENTAGE;
1147 : :
1148 : 4600 : ubuf = spdk_dma_zmalloc(sz, ALIGN_4K, NULL);
1149 [ - + ]: 4600 : if (!ubuf) {
1150 [ # # ]: 0 : fprintf(stderr, "unable to allocate uncompress buffer\n");
1151 : 0 : rc = -ENOMEM;
1152 : 0 : goto error;
1153 : : }
1154 : :
1155 : 4600 : cbuf = spdk_dma_malloc(sz_padded, ALIGN_4K, NULL);
1156 [ + + ]: 4600 : if (!cbuf) {
1157 [ # # ]: 0 : fprintf(stderr, "unable to allocate compress buffer\n");
1158 : 0 : rc = -ENOMEM;
1159 : 0 : spdk_dma_free(ubuf);
1160 : 0 : goto error;
1161 : : }
1162 : :
1163 : 4600 : seg = calloc(1, sizeof(*seg));
1164 [ + + ]: 4600 : if (!seg) {
1165 [ # # ]: 0 : fprintf(stderr, "unable to allocate comp/decomp segment\n");
1166 : 0 : spdk_dma_free(ubuf);
1167 : 0 : spdk_dma_free(cbuf);
1168 : 0 : rc = -ENOMEM;
1169 : 0 : goto error;
1170 : : }
1171 : :
1172 [ + + + - ]: 4600 : sz_read = fread(ubuf, sizeof(uint8_t), sz, ctx->file);
1173 [ - + ]: 4600 : if (sz_read != sz) {
1174 [ # # ]: 0 : fprintf(stderr, "unable to read input file\n");
1175 : 0 : free(seg);
1176 : 0 : spdk_dma_free(ubuf);
1177 : 0 : spdk_dma_free(cbuf);
1178 [ # # # # ]: 0 : rc = -errno;
1179 : 0 : goto error;
1180 : : }
1181 : :
1182 [ + + ]: 4600 : if (g_workload_selection == SPDK_ACCEL_OPC_COMPRESS) {
1183 [ + - + - ]: 1120 : seg->uncompressed_iovs = calloc(g_chained_count, sizeof(struct iovec));
1184 [ + + + - : 1120 : if (seg->uncompressed_iovs == NULL) {
+ - ]
1185 [ # # ]: 0 : fprintf(stderr, "unable to allocate iovec\n");
1186 : 0 : free(seg);
1187 : 0 : spdk_dma_free(ubuf);
1188 : 0 : spdk_dma_free(cbuf);
1189 : 0 : rc = -ENOMEM;
1190 : 0 : goto error;
1191 : : }
1192 [ + - + - ]: 1120 : seg->uncompressed_iovcnt = g_chained_count;
1193 [ + - + - : 1120 : accel_perf_construct_iovs(ubuf, sz, seg->uncompressed_iovs, seg->uncompressed_iovcnt);
+ - + - ]
1194 : 56 : }
1195 : :
1196 [ + - + - ]: 4600 : seg->uncompressed_data = ubuf;
1197 [ + - + - ]: 4600 : seg->uncompressed_len = sz;
1198 [ + - + - ]: 4600 : seg->compressed_data = cbuf;
1199 [ + - + - ]: 4600 : seg->compressed_len = sz;
1200 [ + - + - ]: 4600 : seg->compressed_len_padded = sz_padded;
1201 : :
1202 [ + - + - ]: 4600 : ctx->cur_seg = seg;
1203 [ + - + - : 4600 : iov[0].iov_base = seg->uncompressed_data;
+ - + - ]
1204 [ + - + - : 4600 : iov[0].iov_len = seg->uncompressed_len;
+ - + - +
- ]
1205 : : /* Note that anytime a call is made to spdk_accel_submit_compress() there's a chance
1206 : : * it will fail with -ENOMEM in the event that the destination buffer is not large enough
1207 : : * to hold the compressed data. This example app simply adds 10% buffer for compressed data
1208 : : * but real applications may want to consider a more sophisticated method.
1209 : : */
1210 [ + - + - : 4600 : rc = spdk_accel_submit_compress(ctx->ch, seg->compressed_data, seg->compressed_len_padded, iov, 1,
+ - + - +
- + - ]
1211 [ + - ]: 230 : &seg->compressed_len, 0, accel_perf_prep_process_seg_cpl, ctx);
1212 [ + + ]: 4600 : if (rc < 0) {
1213 [ # # ]: 0 : fprintf(stderr, "error (%d) on initial compress submission\n", rc);
1214 : 0 : goto error;
1215 : : }
1216 : :
1217 : 4600 : return;
1218 : :
1219 : 0 : error:
1220 [ # # # # ]: 0 : spdk_put_io_channel(ctx->ch);
1221 [ # # # # : 0 : fclose(ctx->file);
# # ]
1222 : 0 : free(ctx);
1223 : 0 : spdk_app_stop(rc);
1224 : 244 : }
1225 : :
1226 : : static void
1227 : 812 : accel_perf_prep(void *arg1)
1228 : : {
1229 : : struct accel_perf_prep_ctx *ctx;
1230 : 812 : const char *module_name = NULL;
1231 : 812 : int rc = 0;
1232 : :
1233 [ + + ]: 812 : if (g_module_name) {
1234 : 0 : rc = spdk_accel_get_opc_module_name(g_workload_selection, &module_name);
1235 [ # # # # : 0 : if (rc != 0 || strcmp(g_module_name, module_name) != 0) {
# # # # ]
1236 [ # # ]: 0 : fprintf(stderr, "Module '%s' was assigned via JSON config or RPC, instead of '%s'\n",
1237 : 0 : module_name, g_module_name);
1238 [ # # ]: 0 : fprintf(stderr, "-M option is not compatible with accel_assign_opc RPC\n");
1239 : 0 : rc = -EINVAL;
1240 : 0 : goto error_end;
1241 : : }
1242 : 0 : }
1243 : :
1244 [ + + + + ]: 812 : if (g_workload_selection != SPDK_ACCEL_OPC_COMPRESS &&
1245 [ + + ]: 734 : g_workload_selection != SPDK_ACCEL_OPC_DECOMPRESS) {
1246 : 494 : accel_perf_start(arg1);
1247 : 648 : return;
1248 : : }
1249 : :
1250 [ + + ]: 318 : if (g_cd_file_in_name == NULL) {
1251 [ - + ]: 19 : fprintf(stdout, "A filename is required.\n");
1252 : 19 : rc = -EINVAL;
1253 : 19 : goto error_end;
1254 : : }
1255 : :
1256 [ + + + + : 299 : if (g_workload_selection == SPDK_ACCEL_OPC_COMPRESS && g_verify) {
+ + ]
1257 [ - + ]: 19 : fprintf(stdout, "\nCompression does not support the verify option, aborting.\n");
1258 : 19 : rc = -ENOTSUP;
1259 : 19 : goto error_end;
1260 : : }
1261 : :
1262 : 280 : printf("Preparing input file...\n");
1263 : :
1264 : 280 : ctx = calloc(1, sizeof(*ctx));
1265 [ + + ]: 280 : if (ctx == NULL) {
1266 : 0 : rc = -ENOMEM;
1267 : 0 : goto error_end;
1268 : : }
1269 : :
1270 [ + - + - ]: 280 : ctx->file = fopen(g_cd_file_in_name, "r");
1271 [ + + + - : 280 : if (ctx->file == NULL) {
+ - ]
1272 [ # # ]: 0 : fprintf(stderr, "Could not open file %s.\n", g_cd_file_in_name);
1273 [ # # # # ]: 0 : rc = -errno;
1274 : 0 : goto error_ctx;
1275 : : }
1276 : :
1277 [ + + + - ]: 280 : fseek(ctx->file, 0L, SEEK_END);
1278 [ + + + - : 280 : ctx->remaining = ftell(ctx->file);
+ - + - ]
1279 [ + + + - ]: 280 : fseek(ctx->file, 0L, SEEK_SET);
1280 : :
1281 [ + - + - ]: 280 : ctx->ch = spdk_accel_get_io_channel();
1282 [ + + + - : 280 : if (ctx->ch == NULL) {
+ - ]
1283 : 0 : rc = -EAGAIN;
1284 : 0 : goto error_file;
1285 : : }
1286 : :
1287 [ + + ]: 280 : if (g_xfer_size_bytes == 0) {
1288 : : /* size of 0 means "file at a time" */
1289 [ + - + - ]: 120 : g_xfer_size_bytes = ctx->remaining;
1290 : 6 : }
1291 : :
1292 : 280 : accel_perf_prep_process_seg(ctx);
1293 : 280 : return;
1294 : :
1295 : 0 : error_file:
1296 [ # # # # : 0 : fclose(ctx->file);
# # ]
1297 : 0 : error_ctx:
1298 : 0 : free(ctx);
1299 : 36 : error_end:
1300 : 38 : spdk_app_stop(rc);
1301 : 42 : }
1302 : :
1303 : : static void
1304 : 0 : worker_shutdown(void *ctx)
1305 : : {
1306 : 0 : _worker_stop(ctx);
1307 : 0 : }
1308 : :
1309 : : static void
1310 : 0 : shutdown_cb(void)
1311 : : {
1312 : : struct worker_thread *worker;
1313 : :
1314 [ # # ]: 0 : pthread_mutex_lock(&g_workers_lock);
1315 [ # # ]: 0 : if (!g_workers) {
1316 : 0 : spdk_app_stop(1);
1317 : 0 : goto unlock;
1318 : : }
1319 : :
1320 : 0 : worker = g_workers;
1321 [ # # ]: 0 : while (worker) {
1322 [ # # # # ]: 0 : spdk_thread_send_msg(worker->thread, worker_shutdown, worker);
1323 [ # # # # ]: 0 : worker = worker->next;
1324 : : }
1325 : 0 : unlock:
1326 [ # # ]: 0 : pthread_mutex_unlock(&g_workers_lock);
1327 : 0 : }
1328 : :
1329 : : int
1330 : 869 : main(int argc, char **argv)
1331 : : {
1332 : : struct worker_thread *worker, *tmp;
1333 : : int rc;
1334 : :
1335 [ + + ]: 869 : pthread_mutex_init(&g_workers_lock, NULL);
1336 : 869 : spdk_app_opts_init(&g_opts, sizeof(g_opts));
1337 : 869 : g_opts.name = "accel_perf";
1338 : 869 : g_opts.reactor_mask = "0x1";
1339 : 869 : g_opts.shutdown_cb = shutdown_cb;
1340 : :
1341 : 869 : rc = spdk_app_parse_args(argc, argv, &g_opts, "a:C:o:q:t:yw:M:P:f:T:l:S:x:", NULL,
1342 : : parse_args, usage);
1343 [ + + ]: 869 : if (rc != SPDK_APP_PARSE_ARGS_SUCCESS) {
1344 : 57 : return rc == SPDK_APP_PARSE_ARGS_HELP ? 0 : 1;
1345 : : }
1346 : :
1347 [ - + ]: 812 : if (g_workload_selection == SPDK_ACCEL_OPC_LAST) {
1348 [ # # # # ]: 0 : fprintf(stderr, "Must provide a workload type\n");
1349 : 0 : usage();
1350 : 0 : return -1;
1351 : : }
1352 : :
1353 [ + + + + ]: 812 : if (g_allocate_depth > 0 && g_queue_depth > g_allocate_depth) {
1354 [ # # # # ]: 0 : fprintf(stdout, "allocate depth must be at least as big as queue depth\n");
1355 : 0 : usage();
1356 : 0 : return -1;
1357 : : }
1358 : :
1359 [ + + ]: 812 : if (g_allocate_depth == 0) {
1360 : 774 : g_allocate_depth = g_queue_depth;
1361 : 40 : }
1362 : :
1363 [ + + - + ]: 850 : if ((g_workload_selection == SPDK_ACCEL_OPC_CRC32C ||
1364 [ + + ]: 736 : g_workload_selection == SPDK_ACCEL_OPC_COPY_CRC32C ||
1365 [ + + ]: 660 : g_workload_selection == SPDK_ACCEL_OPC_DIF_VERIFY ||
1366 [ + + ]: 622 : g_workload_selection == SPDK_ACCEL_OPC_DIF_GENERATE) &&
1367 [ - + ]: 258 : g_chained_count == 0) {
1368 : 0 : usage();
1369 : 0 : return -1;
1370 : : }
1371 : :
1372 [ + + + + ]: 812 : if (g_workload_selection == SPDK_ACCEL_OPC_XOR && g_xor_src_count < 2) {
1373 : 0 : usage();
1374 : 0 : return -1;
1375 : : }
1376 : :
1377 [ - + - - ]: 812 : if (g_module_name && spdk_accel_assign_opc(g_workload_selection, g_module_name)) {
1378 [ # # # # ]: 0 : fprintf(stderr, "Was not able to assign '%s' module to the workload\n", g_module_name);
1379 : 0 : usage();
1380 : 0 : return -1;
1381 : : }
1382 : :
1383 : 812 : g_rc = spdk_app_start(&g_opts, accel_perf_prep, NULL);
1384 [ + + ]: 812 : if (g_rc) {
1385 : 38 : SPDK_ERRLOG("ERROR starting application\n");
1386 : 2 : }
1387 : :
1388 [ + + ]: 812 : pthread_mutex_destroy(&g_workers_lock);
1389 : :
1390 : 812 : worker = g_workers;
1391 [ + + ]: 1906 : while (worker) {
1392 [ + - + - ]: 1094 : tmp = worker->next;
1393 : 1094 : free(worker);
1394 : 1094 : worker = tmp;
1395 : : }
1396 : 812 : accel_perf_free_compress_segs();
1397 : 812 : spdk_app_fini();
1398 : 812 : return g_rc;
1399 : 45 : }
|