Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 : : */
4 : :
5 : : #include "spdk/stdinc.h"
6 : : #include "spdk/thread.h"
7 : : #include "spdk/fsdev.h"
8 : : #include "spdk/env.h"
9 : : #include "spdk/event.h"
10 : : #include "spdk/log.h"
11 : : #include "spdk/string.h"
12 : :
13 : : #define TEST_FILENAME "hello_file"
14 : : #define DATA_SIZE 512
15 : : #define ROOT_NODEID 1
16 : :
17 : : static char *g_fsdev_name = "Fs0";
18 : : int g_result = 0;
19 : :
20 : : /*
21 : : * We'll use this struct to gather housekeeping hello_context to pass between
22 : : * our events and callbacks.
23 : : */
24 : : struct hello_context_t {
25 : : struct spdk_thread *app_thread;
26 : : struct spdk_fsdev_desc *fsdev_desc;
27 : : struct spdk_io_channel *fsdev_io_channel;
28 : : struct spdk_fsdev_file_object *root_fobject;
29 : : char *fsdev_name;
30 : : int thread_count;
31 : : };
32 : :
33 : : struct hello_thread_t {
34 : : struct hello_context_t *hello_context;
35 : : struct spdk_thread *thread;
36 : : struct spdk_io_channel *fsdev_io_channel;
37 : : uint64_t unique;
38 : : uint8_t *buf;
39 : : char *file_name;
40 : : struct spdk_fsdev_file_object *fobject;
41 : : struct spdk_fsdev_file_handle *fhandle;
42 : : struct iovec iov[2];
43 : : };
44 : :
45 : : /*
46 : : * Usage function for printing parameters that are specific to this application
47 : : */
48 : : static void
49 : 0 : hello_fsdev_usage(void)
50 : : {
51 [ # # ]: 0 : printf(" -f <fs> name of the fsdev to use\n");
52 : 0 : }
53 : :
54 : : /*
55 : : * This function is called to parse the parameters that are specific to this application
56 : : */
57 : : static int
58 : 0 : hello_fsdev_parse_arg(int ch, char *arg)
59 : : {
60 [ # # ]: 0 : switch (ch) {
61 : 0 : case 'f':
62 : 0 : g_fsdev_name = arg;
63 : 0 : break;
64 : 0 : default:
65 : 0 : return -EINVAL;
66 : : }
67 : 0 : return 0;
68 : : }
69 : :
70 : : static void
71 : 0 : hello_app_done(struct hello_context_t *hello_context, int rc)
72 : : {
73 : 0 : spdk_put_io_channel(hello_context->fsdev_io_channel);
74 : 0 : spdk_fsdev_close(hello_context->fsdev_desc);
75 : 0 : SPDK_NOTICELOG("Stopping app: rc %d\n", rc);
76 : 0 : spdk_app_stop(rc);
77 : 0 : }
78 : :
79 : : static void
80 : 0 : root_forget_complete(void *cb_arg, struct spdk_io_channel *ch, int status)
81 : : {
82 : 0 : struct hello_context_t *hello_context = cb_arg;
83 : :
84 : 0 : SPDK_NOTICELOG("Root forget complete (status=%d)\n", status);
85 [ # # ]: 0 : if (status) {
86 : 0 : SPDK_ERRLOG("Root forget failed: error %d\n", status);
87 : 0 : g_result = EINVAL;
88 : : }
89 : :
90 : 0 : hello_app_done(hello_context, g_result);
91 : 0 : }
92 : :
93 : : static void
94 : 0 : hello_root_release(struct hello_context_t *hello_context)
95 : : {
96 : : int res;
97 : :
98 : 0 : SPDK_NOTICELOG("Forget root\n");
99 : 0 : res = spdk_fsdev_forget(hello_context->fsdev_desc, hello_context->fsdev_io_channel, 0,
100 : : hello_context->root_fobject, 1,
101 : : root_forget_complete, hello_context);
102 [ # # ]: 0 : if (res) {
103 : 0 : SPDK_ERRLOG("Failed to forget root (err=%d)\n", res);
104 : 0 : hello_app_done(hello_context, EINVAL);
105 : : }
106 : 0 : }
107 : :
108 : : static void
109 : 0 : hello_app_notify_thread_done(void *ctx)
110 : : {
111 : 0 : struct hello_context_t *hello_context = (struct hello_context_t *)ctx;
112 : :
113 [ # # ]: 0 : assert(hello_context->thread_count > 0);
114 : 0 : hello_context->thread_count--;
115 [ # # ]: 0 : if (hello_context->thread_count == 0) {
116 : 0 : hello_root_release(hello_context);
117 : : }
118 : 0 : }
119 : :
120 : : static void
121 : 0 : hello_thread_done(struct hello_thread_t *hello_thread, int rc)
122 : : {
123 : 0 : struct hello_context_t *hello_context = hello_thread->hello_context;
124 : :
125 : 0 : spdk_put_io_channel(hello_thread->fsdev_io_channel);
126 : 0 : free(hello_thread->buf);
127 : 0 : free(hello_thread->file_name);
128 : 0 : SPDK_NOTICELOG("Thread %s done: rc %d\n",
129 : : spdk_thread_get_name(hello_thread->thread), rc);
130 : 0 : spdk_thread_exit(hello_thread->thread);
131 : 0 : free(hello_thread);
132 [ # # ]: 0 : if (rc) {
133 : 0 : g_result = rc;
134 : : }
135 : :
136 : 0 : spdk_thread_send_msg(hello_context->app_thread, hello_app_notify_thread_done, hello_context);
137 : 0 : }
138 : :
139 : : static bool
140 : 0 : hello_check_complete(struct hello_thread_t *hello_thread, int status, const char *op)
141 : : {
142 : 0 : hello_thread->unique++;
143 [ # # ]: 0 : if (status) {
144 : 0 : SPDK_ERRLOG("%s failed with %d\n", op, status);
145 : 0 : hello_thread_done(hello_thread, EIO);
146 : 0 : return false;
147 : : }
148 : :
149 : 0 : return true;
150 : : }
151 : :
152 : : static void
153 : 0 : unlink_complete(void *cb_arg, struct spdk_io_channel *ch, int status)
154 : : {
155 : 0 : struct hello_thread_t *hello_thread = cb_arg;
156 : :
157 : 0 : SPDK_NOTICELOG("Unlink complete (status=%d)\n", status);
158 [ # # ]: 0 : if (!hello_check_complete(hello_thread, status, "unlink")) {
159 : 0 : return;
160 : : }
161 : :
162 : 0 : hello_thread->fobject = NULL;
163 : 0 : hello_thread_done(hello_thread, 0);
164 : : }
165 : :
166 : : static void
167 : 0 : hello_unlink(struct hello_thread_t *hello_thread)
168 : : {
169 : 0 : struct hello_context_t *hello_context = hello_thread->hello_context;
170 : : int res;
171 : :
172 : 0 : SPDK_NOTICELOG("Unlink file %s\n", hello_thread->file_name);
173 : :
174 : 0 : res = spdk_fsdev_unlink(hello_context->fsdev_desc, hello_thread->fsdev_io_channel,
175 : 0 : hello_thread->unique, hello_context->root_fobject, hello_thread->file_name,
176 : : unlink_complete, hello_thread);
177 [ # # ]: 0 : if (res) {
178 : 0 : SPDK_ERRLOG("unlink failed with %d\n", res);
179 : 0 : hello_thread_done(hello_thread, EIO);
180 : : }
181 : 0 : }
182 : :
183 : : static void
184 : 0 : release_complete(void *cb_arg, struct spdk_io_channel *ch, int status)
185 : : {
186 : 0 : struct hello_thread_t *hello_thread = cb_arg;
187 : :
188 : 0 : SPDK_NOTICELOG("Release complete (status=%d)\n", status);
189 [ # # ]: 0 : if (!hello_check_complete(hello_thread, status, "release")) {
190 : 0 : return;
191 : : }
192 : :
193 : 0 : hello_thread->fhandle = NULL;
194 : 0 : hello_unlink(hello_thread);
195 : : }
196 : :
197 : : static void
198 : 0 : hello_release(struct hello_thread_t *hello_thread)
199 : : {
200 : 0 : struct hello_context_t *hello_context = hello_thread->hello_context;
201 : : int res;
202 : :
203 : 0 : SPDK_NOTICELOG("Release file handle %p\n", hello_thread->fhandle);
204 : :
205 : 0 : res = spdk_fsdev_release(hello_context->fsdev_desc, hello_thread->fsdev_io_channel,
206 : : hello_thread->unique, hello_thread->fobject, hello_thread->fhandle,
207 : : release_complete, hello_thread);
208 [ # # ]: 0 : if (res) {
209 : 0 : SPDK_ERRLOG("release failed with %d\n", res);
210 : 0 : hello_thread_done(hello_thread, EIO);
211 : : }
212 : 0 : }
213 : :
214 : : static void
215 : 0 : read_complete(void *cb_arg, struct spdk_io_channel *ch, int status, uint32_t data_size)
216 : : {
217 : 0 : struct hello_thread_t *hello_thread = cb_arg;
218 : 0 : uint8_t data = spdk_env_get_current_core();
219 : : uint32_t i;
220 : :
221 : 0 : SPDK_NOTICELOG("Read complete (status=%d, %" PRIu32 "bytes read)\n", status, data_size);
222 [ # # ]: 0 : if (!hello_check_complete(hello_thread, status, "read")) {
223 : 0 : return;
224 : : }
225 : :
226 [ # # ]: 0 : assert(data_size == DATA_SIZE);
227 : :
228 [ # # ]: 0 : for (i = 0; i < DATA_SIZE; ++i) {
229 [ # # ]: 0 : if (hello_thread->buf[i] != data) {
230 : 0 : SPDK_NOTICELOG("Bad read data at offset %d, 0x%02X != 0x%02X\n",
231 : : i, hello_thread->buf[i], data);
232 : 0 : break;
233 : : }
234 : : }
235 : :
236 : 0 : hello_release(hello_thread);
237 : : }
238 : :
239 : : static void
240 : 0 : hello_read(struct hello_thread_t *hello_thread)
241 : : {
242 : 0 : struct hello_context_t *hello_context = hello_thread->hello_context;
243 : : int res;
244 : :
245 : 0 : SPDK_NOTICELOG("Read from file handle %p\n", hello_thread->fhandle);
246 : :
247 [ # # ]: 0 : memset(hello_thread->buf, 0xFF, DATA_SIZE);
248 : :
249 : 0 : hello_thread->iov[0].iov_base = hello_thread->buf;
250 : 0 : hello_thread->iov[0].iov_len = DATA_SIZE / 4;
251 : 0 : hello_thread->iov[1].iov_base = hello_thread->buf + hello_thread->iov[0].iov_len;
252 : 0 : hello_thread->iov[1].iov_len = DATA_SIZE - hello_thread->iov[0].iov_len;
253 : :
254 : 0 : res = spdk_fsdev_read(hello_context->fsdev_desc, hello_thread->fsdev_io_channel,
255 : : hello_thread->unique, hello_thread->fobject, hello_thread->fhandle,
256 : 0 : DATA_SIZE, 0, 0, hello_thread->iov, 2, NULL,
257 : : read_complete, hello_thread);
258 [ # # ]: 0 : if (res) {
259 : 0 : SPDK_ERRLOG("write failed with %d\n", res);
260 : 0 : hello_thread_done(hello_thread, EIO);
261 : : }
262 : 0 : }
263 : :
264 : : static void
265 : 0 : write_complete(void *cb_arg, struct spdk_io_channel *ch, int status, uint32_t data_size)
266 : : {
267 : 0 : struct hello_thread_t *hello_thread = cb_arg;
268 : :
269 : 0 : SPDK_NOTICELOG("Write complete (status=%d, %" PRIu32 "bytes written)\n", status, data_size);
270 [ # # ]: 0 : if (!hello_check_complete(hello_thread, status, "write")) {
271 : 0 : return;
272 : : }
273 : :
274 [ # # ]: 0 : assert(data_size == DATA_SIZE);
275 : 0 : hello_read(hello_thread);
276 : : }
277 : :
278 : : static void
279 : 0 : hello_write(struct hello_thread_t *hello_thread)
280 : : {
281 : 0 : uint8_t data = spdk_env_get_current_core();
282 : 0 : struct hello_context_t *hello_context = hello_thread->hello_context;
283 : : int res;
284 : :
285 : 0 : SPDK_NOTICELOG("Write to file handle %p\n", hello_thread->fhandle);
286 : :
287 [ # # ]: 0 : memset(hello_thread->buf, data, DATA_SIZE);
288 : :
289 : 0 : hello_thread->iov[0].iov_base = hello_thread->buf;
290 : 0 : hello_thread->iov[0].iov_len = DATA_SIZE / 2;
291 : 0 : hello_thread->iov[1].iov_base = hello_thread->buf + hello_thread->iov[0].iov_len;
292 : 0 : hello_thread->iov[1].iov_len = DATA_SIZE - hello_thread->iov[0].iov_len;
293 : :
294 : 0 : res = spdk_fsdev_write(hello_context->fsdev_desc, hello_thread->fsdev_io_channel,
295 : : hello_thread->unique, hello_thread->fobject, hello_thread->fhandle,
296 : 0 : DATA_SIZE, 0, 0, hello_thread->iov, 2, NULL,
297 : : write_complete, hello_thread);
298 [ # # ]: 0 : if (res) {
299 : 0 : SPDK_ERRLOG("write failed with %d\n", res);
300 : 0 : hello_thread_done(hello_thread, EIO);
301 : : }
302 : 0 : }
303 : :
304 : : static void
305 : 0 : fopen_complete(void *cb_arg, struct spdk_io_channel *ch, int status,
306 : : struct spdk_fsdev_file_handle *fhandle)
307 : : {
308 : 0 : struct hello_thread_t *hello_thread = cb_arg;
309 : :
310 : 0 : SPDK_NOTICELOG("Open complete (status=%d)\n", status);
311 [ # # ]: 0 : if (!hello_check_complete(hello_thread, status, "open")) {
312 : 0 : return;
313 : : }
314 : :
315 : 0 : hello_thread->fhandle = fhandle;
316 : 0 : hello_write(hello_thread);
317 : : }
318 : :
319 : : static void
320 : 0 : hello_open(struct hello_thread_t *hello_thread)
321 : : {
322 : 0 : struct hello_context_t *hello_context = hello_thread->hello_context;
323 : : int res;
324 : :
325 : 0 : SPDK_NOTICELOG("Open fobject %p\n", hello_thread->fobject);
326 : :
327 : 0 : res = spdk_fsdev_fopen(hello_context->fsdev_desc, hello_thread->fsdev_io_channel,
328 : : hello_thread->unique, hello_thread->fobject, O_RDWR,
329 : : fopen_complete, hello_thread);
330 [ # # ]: 0 : if (res) {
331 : 0 : SPDK_ERRLOG("open failed with %d\n", res);
332 : 0 : hello_thread_done(hello_thread, EIO);
333 : : }
334 : 0 : }
335 : :
336 : : static void
337 : 0 : lookup_complete(void *cb_arg, struct spdk_io_channel *ch, int status,
338 : : struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr)
339 : : {
340 : 0 : struct hello_thread_t *hello_thread = cb_arg;
341 : :
342 : 0 : SPDK_NOTICELOG("Lookup complete (status=%d)\n", status);
343 [ # # ]: 0 : if (!hello_check_complete(hello_thread, status, "lookup")) {
344 : 0 : return;
345 : : }
346 : :
347 [ # # ]: 0 : assert(hello_thread->fobject == fobject);
348 : 0 : hello_open(hello_thread);
349 : : }
350 : :
351 : : static void
352 : 0 : hello_lookup(struct hello_thread_t *hello_thread)
353 : : {
354 : 0 : struct hello_context_t *hello_context = hello_thread->hello_context;
355 : : int res;
356 : :
357 : 0 : SPDK_NOTICELOG("Lookup file %s\n", hello_thread->file_name);
358 : :
359 : 0 : res = spdk_fsdev_lookup(hello_context->fsdev_desc, hello_thread->fsdev_io_channel,
360 : 0 : hello_thread->unique, hello_context->root_fobject, hello_thread->file_name,
361 : : lookup_complete, hello_thread);
362 [ # # ]: 0 : if (res) {
363 : 0 : SPDK_ERRLOG("lookup failed with %d\n", res);
364 : 0 : hello_thread_done(hello_thread, EIO);
365 : : }
366 : 0 : }
367 : :
368 : : static void
369 : 0 : mknod_complete(void *cb_arg, struct spdk_io_channel *ch, int status,
370 : : struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr)
371 : : {
372 : 0 : struct hello_thread_t *hello_thread = cb_arg;
373 : :
374 : 0 : SPDK_NOTICELOG("Mknod complete (status=%d)\n", status);
375 [ # # ]: 0 : if (!hello_check_complete(hello_thread, status, "mknod")) {
376 : 0 : return;
377 : : }
378 : :
379 : 0 : hello_thread->fobject = fobject;
380 : 0 : hello_lookup(hello_thread);
381 : : }
382 : :
383 : : static void
384 : 0 : hello_mknod(void *ctx)
385 : : {
386 : 0 : struct hello_thread_t *hello_thread = (struct hello_thread_t *)ctx;
387 : 0 : struct hello_context_t *hello_context = hello_thread->hello_context;
388 : : int res;
389 : :
390 : 0 : SPDK_NOTICELOG("Mknod file %s\n", hello_thread->file_name);
391 : :
392 : 0 : res = spdk_fsdev_mknod(hello_context->fsdev_desc, hello_thread->fsdev_io_channel,
393 : 0 : hello_thread->unique, hello_context->root_fobject, hello_thread->file_name,
394 : : S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO, 0, 0, 0, mknod_complete, hello_thread);
395 [ # # ]: 0 : if (res) {
396 : 0 : SPDK_ERRLOG("mknod failed with %d\n", res);
397 : 0 : hello_thread_done(hello_thread, EIO);
398 : : }
399 : 0 : }
400 : :
401 : : static void
402 : 0 : hello_start_thread(void *ctx)
403 : : {
404 : 0 : struct hello_context_t *hello_context = (struct hello_context_t *)ctx;
405 : : struct hello_thread_t *hello_thread;
406 : : /* File name size assumes that core number will fit into 3 characters */
407 : 0 : const int filename_size = strlen(TEST_FILENAME) + 5;
408 : :
409 : 0 : hello_thread = calloc(1, sizeof(struct hello_thread_t));
410 [ # # ]: 0 : if (!hello_thread) {
411 : 0 : SPDK_ERRLOG("Failed to allocate thread context\n");
412 : 0 : spdk_thread_send_msg(hello_context->app_thread, hello_app_notify_thread_done, hello_context);
413 : 0 : return;
414 : : }
415 : :
416 : 0 : hello_thread->hello_context = hello_context;
417 : 0 : hello_thread->thread = spdk_get_thread();
418 : 0 : hello_thread->unique = 1;
419 : 0 : hello_thread->buf = (char *)malloc(DATA_SIZE);
420 [ # # ]: 0 : if (!hello_thread->buf) {
421 : 0 : SPDK_ERRLOG("Could not allocate data buffer\n");
422 : 0 : hello_thread_done(hello_thread, ENOMEM);
423 : 0 : return;
424 : : }
425 : :
426 : 0 : hello_thread->file_name = (char *)malloc(filename_size);
427 [ # # ]: 0 : if (!hello_thread->file_name) {
428 : 0 : SPDK_ERRLOG("Could not allocate file name buffer\n");
429 : 0 : hello_thread_done(hello_thread, ENOMEM);
430 : 0 : return;
431 : : }
432 : :
433 [ # # # # ]: 0 : if (snprintf(hello_thread->file_name, filename_size, "%s_%u",
434 : : TEST_FILENAME, spdk_env_get_current_core()) >= filename_size) {
435 : 0 : SPDK_ERRLOG("File name size doesn't fit into buffer\n");
436 : 0 : hello_thread_done(hello_thread, ENOMEM);
437 : 0 : return;
438 : : }
439 : :
440 : 0 : hello_thread->fsdev_io_channel = spdk_fsdev_get_io_channel(hello_thread->hello_context->fsdev_desc);
441 [ # # ]: 0 : if (!hello_thread->fsdev_io_channel) {
442 : 0 : SPDK_ERRLOG("Could not create fsdev I/O channel!\n");
443 : 0 : hello_thread_done(hello_thread, ENOMEM);
444 : 0 : return;
445 : : }
446 : :
447 : 0 : SPDK_NOTICELOG("Started thread %s on core %u\n",
448 : : spdk_thread_get_name(hello_thread->thread),
449 : : spdk_env_get_current_core());
450 : 0 : spdk_thread_send_msg(hello_thread->thread, hello_mknod, hello_thread);
451 : : }
452 : :
453 : : static void
454 : 0 : hello_create_threads(struct hello_context_t *hello_context)
455 : : {
456 : : uint32_t cpu;
457 : 0 : char thread_name[32];
458 : 0 : struct spdk_cpuset mask = {};
459 : : struct spdk_thread *thread;
460 : :
461 [ # # ]: 0 : SPDK_ENV_FOREACH_CORE(cpu) {
462 [ # # ]: 0 : snprintf(thread_name, sizeof(thread_name), "hello_fsdev_%u", cpu);
463 : 0 : spdk_cpuset_zero(&mask);
464 : 0 : spdk_cpuset_set_cpu(&mask, cpu, true);
465 : 0 : thread = spdk_thread_create(thread_name, &mask);
466 [ # # ]: 0 : assert(thread != NULL);
467 : 0 : hello_context->thread_count++;
468 : 0 : spdk_thread_send_msg(thread, hello_start_thread, hello_context);
469 : : }
470 : 0 : }
471 : :
472 : :
473 : : static void
474 : 0 : root_lookup_complete(void *cb_arg, struct spdk_io_channel *ch, int status,
475 : : struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr)
476 : : {
477 : 0 : struct hello_context_t *hello_context = cb_arg;
478 : :
479 : 0 : SPDK_NOTICELOG("Root lookup complete (status=%d)\n", status);
480 [ # # ]: 0 : if (status) {
481 : 0 : SPDK_ERRLOG("Fuse init failed: error %d\n", status);
482 : 0 : hello_app_done(hello_context, status);
483 : 0 : return;
484 : : }
485 : :
486 : 0 : hello_context->root_fobject = fobject;
487 : :
488 : 0 : hello_create_threads(hello_context);
489 : : }
490 : :
491 : : static void
492 : 0 : root_lookup(struct hello_context_t *hello_context)
493 : : {
494 : : int res;
495 : :
496 : 0 : SPDK_NOTICELOG("Lookup for the root\n");
497 : :
498 : 0 : res = spdk_fsdev_lookup(hello_context->fsdev_desc, hello_context->fsdev_io_channel, 0,
499 : : NULL /* root */, "" /* will be ignored */, root_lookup_complete, hello_context);
500 [ # # ]: 0 : if (res) {
501 : 0 : SPDK_ERRLOG("Failed to initiate lookup for the root (err=%d)\n", res);
502 : 0 : hello_app_done(hello_context, res);
503 : 0 : return;
504 : : }
505 : : }
506 : :
507 : : static void
508 : 0 : hello_fsdev_event_cb(enum spdk_fsdev_event_type type, struct spdk_fsdev *fsdev, void *event_ctx)
509 : : {
510 : 0 : SPDK_NOTICELOG("Unsupported fsdev event: type %d\n", type);
511 : 0 : }
512 : :
513 : : /*
514 : : * Our initial event that kicks off everything from main().
515 : : */
516 : : static void
517 : 0 : hello_start(void *arg1)
518 : : {
519 : 0 : struct hello_context_t *hello_context = arg1;
520 : 0 : int rc = 0;
521 : 0 : hello_context->fsdev_desc = NULL;
522 : :
523 : 0 : SPDK_NOTICELOG("Successfully started the application\n");
524 : :
525 : 0 : hello_context->app_thread = spdk_get_thread();
526 : :
527 : : /*
528 : : * There can be many fsdevs configured, but this application will only use
529 : : * the one input by the user at runtime.
530 : : *
531 : : * Open the fs by calling spdk_fsdev_open() with its name.
532 : : * The function will return a descriptor
533 : : */
534 : 0 : SPDK_NOTICELOG("Opening the fsdev %s\n", hello_context->fsdev_name);
535 : 0 : rc = spdk_fsdev_open(hello_context->fsdev_name,
536 : : hello_fsdev_event_cb, NULL, NULL,
537 : : &hello_context->fsdev_desc);
538 [ # # ]: 0 : if (rc) {
539 : 0 : SPDK_ERRLOG("Could not open fsdev: %s\n", hello_context->fsdev_name);
540 : 0 : spdk_app_stop(-1);
541 : 0 : return;
542 : : }
543 : :
544 : 0 : SPDK_NOTICELOG("Opening io channel\n");
545 : : /* Open I/O channel */
546 : 0 : hello_context->fsdev_io_channel = spdk_fsdev_get_io_channel(hello_context->fsdev_desc);
547 [ # # ]: 0 : if (!hello_context->fsdev_io_channel) {
548 : 0 : SPDK_ERRLOG("Could not create fsdev I/O channel!\n");
549 : 0 : spdk_fsdev_close(hello_context->fsdev_desc);
550 : 0 : spdk_app_stop(-1);
551 : 0 : return;
552 : : }
553 : :
554 : 0 : root_lookup(hello_context);
555 : : }
556 : :
557 : : int
558 : 0 : main(int argc, char **argv)
559 : : {
560 : 0 : struct spdk_app_opts opts = {};
561 : 0 : int rc = 0;
562 : 0 : struct hello_context_t hello_context = {};
563 : :
564 : : /* Set default values in opts structure. */
565 : 0 : spdk_app_opts_init(&opts, sizeof(opts));
566 : 0 : opts.name = "hello_fsdev";
567 : :
568 : : /*
569 : : * Parse built-in SPDK command line parameters as well
570 : : * as our custom one(s).
571 : : */
572 [ # # ]: 0 : if ((rc = spdk_app_parse_args(argc, argv, &opts, "f:", NULL, hello_fsdev_parse_arg,
573 : : hello_fsdev_usage)) != SPDK_APP_PARSE_ARGS_SUCCESS) {
574 : 0 : exit(rc);
575 : : }
576 : 0 : hello_context.fsdev_name = g_fsdev_name;
577 : :
578 : : /*
579 : : * spdk_app_start() will initialize the SPDK framework, call hello_start(),
580 : : * and then block until spdk_app_stop() is called (or if an initialization
581 : : * error occurs, spdk_app_start() will return with rc even without calling
582 : : * hello_start().
583 : : */
584 : 0 : rc = spdk_app_start(&opts, hello_start, &hello_context);
585 [ # # ]: 0 : if (rc) {
586 : 0 : SPDK_ERRLOG("ERROR starting application\n");
587 : : }
588 : :
589 : : /* At this point either spdk_app_stop() was called, or spdk_app_start()
590 : : * failed because of internal error.
591 : : */
592 : :
593 : : /* Gracefully close out all of the SPDK subsystems. */
594 : 0 : spdk_app_fini();
595 : 0 : return rc;
596 : : }
|