Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2017 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/stdinc.h"
7 : :
8 : : #include "spdk/event.h"
9 : : #include "spdk/nvme.h"
10 : : #include "spdk/string.h"
11 : : #include "spdk/thread.h"
12 : :
13 : : static char g_path[256];
14 : : static struct spdk_poller *g_poller;
15 : : /* default sleep time in ms */
16 : : static uint32_t g_sleep_time = 1000;
17 : : static uint32_t g_io_queue_size;
18 : :
19 : : struct ctrlr_entry {
20 : : struct spdk_nvme_ctrlr *ctrlr;
21 : : TAILQ_ENTRY(ctrlr_entry) link;
22 : : };
23 : :
24 : : static TAILQ_HEAD(, ctrlr_entry) g_controllers = TAILQ_HEAD_INITIALIZER(g_controllers);
25 : :
26 : : static void
27 : 6 : cleanup(void)
28 : : {
29 : : struct ctrlr_entry *ctrlr_entry, *tmp;
30 : 6 : struct spdk_nvme_detach_ctx *detach_ctx = NULL;
31 : :
32 [ + + ]: 16 : TAILQ_FOREACH_SAFE(ctrlr_entry, &g_controllers, link, tmp) {
33 [ + + ]: 10 : TAILQ_REMOVE(&g_controllers, ctrlr_entry, link);
34 : 10 : spdk_nvme_cuse_unregister(ctrlr_entry->ctrlr);
35 : 10 : spdk_nvme_detach_async(ctrlr_entry->ctrlr, &detach_ctx);
36 : 10 : free(ctrlr_entry);
37 : : }
38 : :
39 [ + - ]: 6 : if (detach_ctx) {
40 : 6 : spdk_nvme_detach_poll(detach_ctx);
41 : : }
42 : 6 : }
43 : :
44 : : static void
45 : 0 : usage(char *executable_name)
46 : : {
47 [ # # ]: 0 : printf("%s [options]\n", executable_name);
48 [ # # ]: 0 : printf("options:\n");
49 [ # # ]: 0 : printf(" -i shared memory ID [required]\n");
50 [ # # ]: 0 : printf(" -m mask core mask for DPDK\n");
51 [ # # ]: 0 : printf(" -n channel number of memory channels used for DPDK\n");
52 [ # # ]: 0 : printf(" -p core main (primary) core for DPDK\n");
53 [ # # ]: 0 : printf(" -s size memory size in MB for DPDK\n");
54 [ # # ]: 0 : printf(" -t msec sleep time (ms) between checking for admin completions\n");
55 [ # # ]: 0 : printf(" -q size override default io_queue_size when attaching controllers\n");
56 [ # # ]: 0 : printf(" -H show this usage\n");
57 : 0 : }
58 : :
59 : : static bool
60 : 10 : probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
61 : : struct spdk_nvme_ctrlr_opts *opts)
62 : : {
63 [ - + ]: 10 : if (g_io_queue_size > 0) {
64 : 0 : opts->io_queue_size = g_io_queue_size;
65 : : }
66 : 10 : return true;
67 : : }
68 : :
69 : : static void
70 : 10 : attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
71 : : struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts)
72 : : {
73 : : struct ctrlr_entry *entry;
74 : :
75 : 10 : entry = malloc(sizeof(struct ctrlr_entry));
76 [ - + ]: 10 : if (entry == NULL) {
77 [ # # # # ]: 0 : fprintf(stderr, "Malloc error\n");
78 : 0 : exit(1);
79 : : }
80 : :
81 : 10 : entry->ctrlr = ctrlr;
82 : 10 : TAILQ_INSERT_TAIL(&g_controllers, entry, link);
83 [ - + ]: 10 : if (spdk_nvme_cuse_register(ctrlr) != 0) {
84 [ # # # # ]: 0 : fprintf(stderr, "could not register ctrlr with cuse\n");
85 : : }
86 : 10 : }
87 : :
88 : : static int
89 : 263 : stub_sleep(void *arg)
90 : : {
91 : : struct ctrlr_entry *ctrlr_entry, *tmp;
92 : :
93 : 263 : usleep(g_sleep_time * 1000);
94 [ + + ]: 763 : TAILQ_FOREACH_SAFE(ctrlr_entry, &g_controllers, link, tmp) {
95 : 500 : spdk_nvme_ctrlr_process_admin_completions(ctrlr_entry->ctrlr);
96 : : }
97 : 263 : return 0;
98 : : }
99 : :
100 : : static void
101 : 6 : stub_start(void *arg1)
102 : : {
103 : 6 : int shm_id = (intptr_t)arg1;
104 : :
105 [ - + ]: 6 : snprintf(g_path, sizeof(g_path), "/var/run/spdk_stub%d", shm_id);
106 : :
107 : : /* If sentinel file already exists from earlier crashed stub, delete
108 : : * it now to avoid mknod() failure after spdk_nvme_probe() completes.
109 : : */
110 [ - + ]: 6 : unlink(g_path);
111 : :
112 : 6 : spdk_unaffinitize_thread();
113 : :
114 [ - + ]: 6 : if (spdk_nvme_probe(NULL, NULL, probe_cb, attach_cb, NULL) != 0) {
115 [ # # # # ]: 0 : fprintf(stderr, "spdk_nvme_probe() failed\n");
116 : 0 : exit(1);
117 : : }
118 : :
119 [ - + - + ]: 6 : if (mknod(g_path, S_IFREG, 0) != 0) {
120 [ # # # # ]: 0 : fprintf(stderr, "could not create sentinel file %s\n", g_path);
121 : 0 : exit(1);
122 : : }
123 : :
124 : 6 : g_poller = SPDK_POLLER_REGISTER(stub_sleep, NULL, 0);
125 : 6 : }
126 : :
127 : : static void
128 : 6 : stub_shutdown(void)
129 : : {
130 : 6 : spdk_poller_unregister(&g_poller);
131 [ - + ]: 6 : unlink(g_path);
132 : 6 : spdk_app_stop(0);
133 : 6 : }
134 : :
135 : : int
136 : 6 : main(int argc, char **argv)
137 : : {
138 : : int ch;
139 : 6 : struct spdk_app_opts opts = {};
140 : : long int val;
141 : :
142 : : /* default value in opts structure */
143 : 6 : spdk_app_opts_init(&opts, sizeof(opts));
144 : :
145 : 6 : opts.name = "stub";
146 : 6 : opts.rpc_addr = NULL;
147 : 6 : opts.env_context = "--proc-type=primary";
148 : :
149 [ + + + + : 24 : while ((ch = getopt(argc, argv, "i:m:n:p:q:s:t:H")) != -1) {
+ + ]
150 [ + + ]: 18 : if (ch == 'm') {
151 : 6 : opts.reactor_mask = optarg;
152 [ + - - + ]: 12 : } else if (ch == '?' || ch == 'H') {
153 : 0 : usage(argv[0]);
154 : 0 : exit(EXIT_SUCCESS);
155 : : } else {
156 : 12 : val = spdk_strtol(optarg, 10);
157 [ - + ]: 12 : if (val < 0) {
158 [ # # # # ]: 0 : fprintf(stderr, "Converting a string to integer failed\n");
159 : 0 : exit(1);
160 : : }
161 [ + - - + : 12 : switch (ch) {
- - - ]
162 : 6 : case 'i':
163 : 6 : opts.shm_id = val;
164 : 6 : break;
165 : 0 : case 'n':
166 : 0 : opts.mem_channel = val;
167 : 0 : break;
168 : 0 : case 'p':
169 : 0 : opts.main_core = val;
170 : 0 : break;
171 : 6 : case 's':
172 : 6 : opts.mem_size = val;
173 : 6 : break;
174 : 0 : case 't':
175 : 0 : g_sleep_time = val;
176 : 0 : break;
177 : 0 : case 'q':
178 : 0 : g_io_queue_size = val;
179 : 0 : break;
180 : 0 : default:
181 : 0 : usage(argv[0]);
182 : 0 : exit(EXIT_FAILURE);
183 : : }
184 : : }
185 : : }
186 : :
187 [ - + ]: 6 : if (opts.shm_id < 0) {
188 [ # # # # ]: 0 : fprintf(stderr, "%s: -i shared memory ID must be specified\n", argv[0]);
189 : 0 : usage(argv[0]);
190 : 0 : exit(1);
191 : : }
192 : :
193 : 6 : opts.shutdown_cb = stub_shutdown;
194 : :
195 : 6 : ch = spdk_app_start(&opts, stub_start, (void *)(intptr_t)opts.shm_id);
196 : :
197 : 6 : cleanup();
198 : 6 : spdk_app_fini();
199 : :
200 : 6 : return ch;
201 : : }
|