4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 #include "spdk/stdinc.h"
35 #include "spdk/thread.h"
36 #include "spdk/bdev.h"
38 #include "spdk/event.h"
40 #include "spdk/string.h"
41 #include "spdk/bdev_module.h"
43 static char *g_bdev_name
= "Malloc0";
46 * We'll use this struct to gather housekeeping hello_context to pass between
47 * our events and callbacks.
49 struct hello_context_t
{
50 struct spdk_bdev
*bdev
;
51 struct spdk_bdev_desc
*bdev_desc
;
52 struct spdk_io_channel
*bdev_io_channel
;
55 struct spdk_bdev_io_wait_entry bdev_io_wait
;
59 * Usage function for printing parameters that are specific to this application
62 hello_bdev_usage(void)
64 printf(" -b <bdev> name of the bdev to use\n");
68 * This function is called to parse the parameters that are specific to this application
70 static void hello_bdev_parse_arg(int ch
, char *arg
)
80 * Callback function for read io completion.
83 read_complete(struct spdk_bdev_io
*bdev_io
, bool success
, void *cb_arg
)
85 struct hello_context_t
*hello_context
= cb_arg
;
88 SPDK_NOTICELOG("Read string from bdev : %s\n", hello_context
->buff
);
90 SPDK_ERRLOG("bdev io read error\n");
93 /* Complete the bdev io and close the channel */
94 spdk_bdev_free_io(bdev_io
);
95 spdk_put_io_channel(hello_context
->bdev_io_channel
);
96 spdk_bdev_close(hello_context
->bdev_desc
);
97 SPDK_NOTICELOG("Stopping app\n");
98 spdk_app_stop(success
? 0 : -1);
102 hello_read(void *arg
)
104 struct hello_context_t
*hello_context
= arg
;
106 uint32_t length
= spdk_bdev_get_block_size(hello_context
->bdev
);
108 SPDK_NOTICELOG("Reading io\n");
109 rc
= spdk_bdev_read(hello_context
->bdev_desc
, hello_context
->bdev_io_channel
,
110 hello_context
->buff
, 0, length
, read_complete
, hello_context
);
113 SPDK_NOTICELOG("Queueing io\n");
114 /* In case we cannot perform I/O now, queue I/O */
115 hello_context
->bdev_io_wait
.bdev
= hello_context
->bdev
;
116 hello_context
->bdev_io_wait
.cb_fn
= hello_read
;
117 hello_context
->bdev_io_wait
.cb_arg
= hello_context
;
118 spdk_bdev_queue_io_wait(hello_context
->bdev
, hello_context
->bdev_io_channel
,
119 &hello_context
->bdev_io_wait
);
121 SPDK_ERRLOG("%s error while reading from bdev: %d\n", spdk_strerror(-rc
), rc
);
122 spdk_put_io_channel(hello_context
->bdev_io_channel
);
123 spdk_bdev_close(hello_context
->bdev_desc
);
129 * Callback function for write io completion.
132 write_complete(struct spdk_bdev_io
*bdev_io
, bool success
, void *cb_arg
)
134 struct hello_context_t
*hello_context
= cb_arg
;
137 /* Complete the I/O */
138 spdk_bdev_free_io(bdev_io
);
141 SPDK_NOTICELOG("bdev io write completed successfully\n");
143 SPDK_ERRLOG("bdev io write error: %d\n", EIO
);
144 spdk_put_io_channel(hello_context
->bdev_io_channel
);
145 spdk_bdev_close(hello_context
->bdev_desc
);
150 /* Zero the buffer so that we can use it for reading */
151 length
= spdk_bdev_get_block_size(hello_context
->bdev
);
152 memset(hello_context
->buff
, 0, length
);
154 hello_read(hello_context
);
158 hello_write(void *arg
)
160 struct hello_context_t
*hello_context
= arg
;
162 uint32_t length
= spdk_bdev_get_block_size(hello_context
->bdev
);
164 SPDK_NOTICELOG("Writing to the bdev\n");
165 rc
= spdk_bdev_write(hello_context
->bdev_desc
, hello_context
->bdev_io_channel
,
166 hello_context
->buff
, 0, length
, write_complete
, hello_context
);
169 SPDK_NOTICELOG("Queueing io\n");
170 /* In case we cannot perform I/O now, queue I/O */
171 hello_context
->bdev_io_wait
.bdev
= hello_context
->bdev
;
172 hello_context
->bdev_io_wait
.cb_fn
= hello_write
;
173 hello_context
->bdev_io_wait
.cb_arg
= hello_context
;
174 spdk_bdev_queue_io_wait(hello_context
->bdev
, hello_context
->bdev_io_channel
,
175 &hello_context
->bdev_io_wait
);
177 SPDK_ERRLOG("%s error while writing to bdev: %d\n", spdk_strerror(-rc
), rc
);
178 spdk_put_io_channel(hello_context
->bdev_io_channel
);
179 spdk_bdev_close(hello_context
->bdev_desc
);
185 * Our initial event that kicks off everything from main().
188 hello_start(void *arg1
, void *arg2
)
190 struct hello_context_t
*hello_context
= arg1
;
191 uint32_t blk_size
, buf_align
;
193 hello_context
->bdev
= NULL
;
194 hello_context
->bdev_desc
= NULL
;
196 SPDK_NOTICELOG("Successfully started the application\n");
199 * Get the bdev. There can be many bdevs configured in
200 * in the configuration file but this application will only
201 * use the one input by the user at runtime so we get it via its name.
203 hello_context
->bdev
= spdk_bdev_get_by_name(hello_context
->bdev_name
);
204 if (hello_context
->bdev
== NULL
) {
205 SPDK_ERRLOG("Could not find the bdev: %s\n", hello_context
->bdev_name
);
211 * Open the bdev by calling spdk_bdev_open()
212 * The function will return a descriptor
214 SPDK_NOTICELOG("Opening the bdev %s\n", hello_context
->bdev_name
);
215 rc
= spdk_bdev_open(hello_context
->bdev
, true, NULL
, NULL
, &hello_context
->bdev_desc
);
217 SPDK_ERRLOG("Could not open bdev: %s\n", hello_context
->bdev_name
);
222 SPDK_NOTICELOG("Opening io channel\n");
223 /* Open I/O channel */
224 hello_context
->bdev_io_channel
= spdk_bdev_get_io_channel(hello_context
->bdev_desc
);
225 if (hello_context
->bdev_io_channel
== NULL
) {
226 SPDK_ERRLOG("Could not create bdev I/O channel!!\n");
227 spdk_bdev_close(hello_context
->bdev_desc
);
232 /* Allocate memory for the write buffer.
233 * Initialize the write buffer with the string "Hello World!"
235 blk_size
= spdk_bdev_get_block_size(hello_context
->bdev
);
236 buf_align
= spdk_bdev_get_buf_align(hello_context
->bdev
);
237 hello_context
->buff
= spdk_dma_zmalloc(blk_size
, buf_align
, NULL
);
238 if (!hello_context
->buff
) {
239 SPDK_ERRLOG("Failed to allocate buffer\n");
240 spdk_put_io_channel(hello_context
->bdev_io_channel
);
241 spdk_bdev_close(hello_context
->bdev_desc
);
245 snprintf(hello_context
->buff
, blk_size
, "%s", "Hello World!\n");
247 hello_write(hello_context
);
251 main(int argc
, char **argv
)
253 struct spdk_app_opts opts
= {};
255 struct hello_context_t hello_context
= {};
257 /* Set default values in opts structure. */
258 spdk_app_opts_init(&opts
);
259 opts
.name
= "hello_bdev";
260 opts
.config_file
= "bdev.conf";
263 * The user can provide the config file and bdev name at run time.
264 * For example, to use Malloc0 in file bdev.conf run with params
265 * ./hello_bdev -c bdev.conf -b Malloc0
266 * To use passthru bdev PT0 run with params
267 * ./hello_bdev -c bdev.conf -b PT0
268 * If none of the parameters are provide the application will use the
269 * default parameters(-c bdev.conf -b Malloc0).
271 if ((rc
= spdk_app_parse_args(argc
, argv
, &opts
, "b:", NULL
, hello_bdev_parse_arg
,
272 hello_bdev_usage
)) != SPDK_APP_PARSE_ARGS_SUCCESS
) {
275 hello_context
.bdev_name
= g_bdev_name
;
278 * spdk_app_start() will block running hello_start() until
279 * spdk_app_stop() is called by someone (not simply when
280 * hello_start() returns), or if an error occurs during
281 * spdk_app_start() before hello_start() runs.
283 rc
= spdk_app_start(&opts
, hello_start
, &hello_context
, NULL
);
285 SPDK_ERRLOG("ERROR starting application\n");
288 /* When the app stops, free up memory that we allocated. */
289 spdk_dma_free(hello_context
.buff
);
291 /* Gracefully close out all of the SPDK subsystems. */