xref: /spdk/test/app/stub/stub.c (revision d8d29ec0b1a116941bdead09bedd58f456317566)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 
36 #include "spdk/event.h"
37 #include "spdk/nvme.h"
38 #include "spdk/string.h"
39 #include "spdk/thread.h"
40 
41 static char g_path[256];
42 static struct spdk_poller *g_poller;
43 /* default sleep time in ms */
44 static uint32_t g_sleep_time = 1000;
45 
46 struct ctrlr_entry {
47 	struct spdk_nvme_ctrlr *ctrlr;
48 	TAILQ_ENTRY(ctrlr_entry) link;
49 };
50 
51 static TAILQ_HEAD(, ctrlr_entry) g_controllers = TAILQ_HEAD_INITIALIZER(g_controllers);
52 
53 static void
54 cleanup(void)
55 {
56 	struct ctrlr_entry *ctrlr_entry, *tmp;
57 	struct spdk_nvme_detach_ctx *detach_ctx = NULL;
58 
59 	TAILQ_FOREACH_SAFE(ctrlr_entry, &g_controllers, link, tmp) {
60 		TAILQ_REMOVE(&g_controllers, ctrlr_entry, link);
61 		spdk_nvme_detach_async(ctrlr_entry->ctrlr, &detach_ctx);
62 		free(ctrlr_entry);
63 	}
64 
65 	if (detach_ctx) {
66 		spdk_nvme_detach_poll(detach_ctx);
67 	}
68 }
69 
70 static void
71 usage(char *executable_name)
72 {
73 	printf("%s [options]\n", executable_name);
74 	printf("options:\n");
75 	printf(" -i shared memory ID [required]\n");
76 	printf(" -m mask    core mask for DPDK\n");
77 	printf(" -n channel number of memory channels used for DPDK\n");
78 	printf(" -p core    main (primary) core for DPDK\n");
79 	printf(" -s size    memory size in MB for DPDK\n");
80 	printf(" -t msec    sleep time (ms) between checking for admin completions\n");
81 	printf(" -H         show this usage\n");
82 }
83 
84 static bool
85 probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
86 	 struct spdk_nvme_ctrlr_opts *opts)
87 {
88 	/*
89 	 * Set the io_queue_size to UINT16_MAX to initialize
90 	 * the controller with the possible largest queue size.
91 	 */
92 	opts->io_queue_size = UINT16_MAX;
93 	return true;
94 }
95 
96 static void
97 attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
98 	  struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_ctrlr_opts *opts)
99 {
100 	struct ctrlr_entry *entry;
101 
102 	entry = malloc(sizeof(struct ctrlr_entry));
103 	if (entry == NULL) {
104 		fprintf(stderr, "Malloc error\n");
105 		exit(1);
106 	}
107 
108 	entry->ctrlr = ctrlr;
109 	TAILQ_INSERT_TAIL(&g_controllers, entry, link);
110 }
111 
112 static int
113 stub_sleep(void *arg)
114 {
115 	struct ctrlr_entry *ctrlr_entry, *tmp;
116 
117 	usleep(g_sleep_time * 1000);
118 	TAILQ_FOREACH_SAFE(ctrlr_entry, &g_controllers, link, tmp) {
119 		spdk_nvme_ctrlr_process_admin_completions(ctrlr_entry->ctrlr);
120 	}
121 	return 0;
122 }
123 
124 static void
125 stub_start(void *arg1)
126 {
127 	int shm_id = (intptr_t)arg1;
128 
129 	spdk_unaffinitize_thread();
130 
131 	if (spdk_nvme_probe(NULL, NULL, probe_cb, attach_cb, NULL) != 0) {
132 		fprintf(stderr, "spdk_nvme_probe() failed\n");
133 		exit(1);
134 	}
135 
136 	snprintf(g_path, sizeof(g_path), "/var/run/spdk_stub%d", shm_id);
137 	if (mknod(g_path, S_IFREG, 0) != 0) {
138 		fprintf(stderr, "could not create sentinel file %s\n", g_path);
139 		exit(1);
140 	}
141 
142 	g_poller = SPDK_POLLER_REGISTER(stub_sleep, NULL, 0);
143 }
144 
145 static void
146 stub_shutdown(void)
147 {
148 	spdk_poller_unregister(&g_poller);
149 	unlink(g_path);
150 	spdk_app_stop(0);
151 }
152 
153 int
154 main(int argc, char **argv)
155 {
156 	int ch;
157 	struct spdk_app_opts opts = {};
158 	long int val;
159 
160 	/* default value in opts structure */
161 	spdk_app_opts_init(&opts, sizeof(opts));
162 
163 	opts.name = "stub";
164 	opts.rpc_addr = NULL;
165 
166 	while ((ch = getopt(argc, argv, "i:m:n:p:s:t:H")) != -1) {
167 		if (ch == 'm') {
168 			opts.reactor_mask = optarg;
169 		} else if (ch == '?' || ch == 'H') {
170 			usage(argv[0]);
171 			exit(EXIT_SUCCESS);
172 		} else {
173 			val = spdk_strtol(optarg, 10);
174 			if (val < 0) {
175 				fprintf(stderr, "Converting a string to integer failed\n");
176 				exit(1);
177 			}
178 			switch (ch) {
179 			case 'i':
180 				opts.shm_id = val;
181 				break;
182 			case 'n':
183 				opts.mem_channel = val;
184 				break;
185 			case 'p':
186 				opts.main_core = val;
187 				break;
188 			case 's':
189 				opts.mem_size = val;
190 				break;
191 			case 't':
192 				g_sleep_time = val;
193 				break;
194 			default:
195 				usage(argv[0]);
196 				exit(EXIT_FAILURE);
197 			}
198 		}
199 	}
200 
201 	if (opts.shm_id < 0) {
202 		fprintf(stderr, "%s: -i shared memory ID must be specified\n", argv[0]);
203 		usage(argv[0]);
204 		exit(1);
205 	}
206 
207 	opts.shutdown_cb = stub_shutdown;
208 
209 	ch = spdk_app_start(&opts, stub_start, (void *)(intptr_t)opts.shm_id);
210 
211 	cleanup();
212 	spdk_app_fini();
213 
214 	return ch;
215 }
216