2016-08-19 17:51:37 +00:00
|
|
|
/*-
|
|
|
|
* BSD LICENSE
|
|
|
|
*
|
|
|
|
* Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
|
|
|
|
* Copyright (c) Intel Corporation.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
*
|
|
|
|
* * Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
* distribution.
|
|
|
|
* * Neither the name of Intel Corporation nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** \file
|
|
|
|
* Block Device Module Interface
|
2018-05-25 19:52:32 +00:00
|
|
|
*
|
|
|
|
* For information on how to write a bdev module, see @ref bdev_module.
|
2016-08-19 17:51:37 +00:00
|
|
|
*/
|
|
|
|
|
2018-05-25 19:47:50 +00:00
|
|
|
#ifndef SPDK_BDEV_MODULE_H
|
|
|
|
#define SPDK_BDEV_MODULE_H
|
2016-08-19 17:51:37 +00:00
|
|
|
|
2017-05-02 18:18:25 +00:00
|
|
|
#include "spdk/stdinc.h"
|
2016-08-19 17:51:37 +00:00
|
|
|
|
|
|
|
#include "spdk/bdev.h"
|
|
|
|
#include "spdk/queue.h"
|
|
|
|
#include "spdk/scsi_spec.h"
|
2018-06-11 20:32:15 +00:00
|
|
|
#include "spdk/thread.h"
|
2018-03-02 01:27:44 +00:00
|
|
|
#include "spdk/uuid.h"
|
2016-08-19 17:51:37 +00:00
|
|
|
|
|
|
|
/** Block device module */
|
2018-03-09 22:20:21 +00:00
|
|
|
struct spdk_bdev_module {
|
2016-08-19 17:51:37 +00:00
|
|
|
/**
|
|
|
|
* Initialization function for the module. Called by the spdk
|
|
|
|
* application during startup.
|
|
|
|
*
|
|
|
|
* Modules are required to define this function.
|
|
|
|
*/
|
2017-07-13 17:36:19 +00:00
|
|
|
int (*module_init)(void);
|
2016-08-19 17:51:37 +00:00
|
|
|
|
2018-04-10 21:53:20 +00:00
|
|
|
/**
|
|
|
|
* Optional callback for modules that require notification of when
|
|
|
|
* the bdev subsystem has completed initialization.
|
|
|
|
*
|
|
|
|
* Modules are not required to define this function.
|
|
|
|
*/
|
|
|
|
void (*init_complete)(void);
|
|
|
|
|
2016-08-19 17:51:37 +00:00
|
|
|
/**
|
|
|
|
* Finish function for the module. Called by the spdk application
|
|
|
|
* before the spdk application exits to perform any necessary cleanup.
|
|
|
|
*
|
|
|
|
* Modules are not required to define this function.
|
|
|
|
*/
|
|
|
|
void (*module_fini)(void);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function called to return a text string representing the
|
|
|
|
* module's configuration options for inclusion in a configuration file.
|
|
|
|
*/
|
|
|
|
void (*config_text)(FILE *fp);
|
|
|
|
|
2018-02-22 12:48:13 +00:00
|
|
|
/**
|
|
|
|
* Function called to return a text string representing the
|
|
|
|
* module's configuration options for inclusion in a configuration file.
|
|
|
|
*
|
|
|
|
* \return 0 on success or Bdev specific negative error code.
|
|
|
|
*/
|
|
|
|
int (*config_json)(struct spdk_json_write_ctx *w);
|
|
|
|
|
2016-08-19 17:51:37 +00:00
|
|
|
/** Name for the modules being defined. */
|
2017-07-07 00:20:53 +00:00
|
|
|
const char *name;
|
2016-08-19 17:51:37 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the allocation size required for the backend for uses such as local
|
|
|
|
* command structs, local SGL, iovecs, or other user context.
|
|
|
|
*/
|
|
|
|
int (*get_ctx_size)(void);
|
|
|
|
|
2017-02-10 20:18:49 +00:00
|
|
|
/**
|
2017-07-11 07:04:40 +00:00
|
|
|
* Notification that a bdev should be examined by a virtual bdev module.
|
|
|
|
* Virtual bdev modules may use this to examine newly-added bdevs and automatically
|
2017-02-10 20:18:49 +00:00
|
|
|
* create their own vbdevs.
|
|
|
|
*/
|
2017-07-11 07:04:40 +00:00
|
|
|
void (*examine)(struct spdk_bdev *bdev);
|
2017-02-10 20:18:49 +00:00
|
|
|
|
2017-07-10 23:02:27 +00:00
|
|
|
/**
|
2017-08-24 15:36:25 +00:00
|
|
|
* Count of bdev inits/examinations in progress. Used by generic bdev
|
|
|
|
* layer and must not be modified by bdev modules.
|
2018-03-06 18:52:46 +00:00
|
|
|
*
|
|
|
|
* \note Used internally by bdev subsystem, don't change this value in bdev module.
|
2017-07-10 23:02:27 +00:00
|
|
|
*/
|
2017-08-24 15:36:25 +00:00
|
|
|
uint32_t action_in_progress;
|
2017-07-10 23:02:27 +00:00
|
|
|
|
2018-03-06 18:52:46 +00:00
|
|
|
/**
|
|
|
|
* Denotes if the module_init function may complete asynchronously. If set to true,
|
|
|
|
* the module initialization has to be explicitly completed by calling
|
|
|
|
* spdk_bdev_module_init_done().
|
|
|
|
*/
|
|
|
|
bool async_init;
|
|
|
|
|
2017-10-25 13:58:02 +00:00
|
|
|
/**
|
|
|
|
* Denotes if the module_fini function may complete asynchronously.
|
2018-03-06 18:52:46 +00:00
|
|
|
* If set to true finishing has to be explicitly completed by calling
|
|
|
|
* spdk_bdev_module_fini_done().
|
2017-10-25 13:58:02 +00:00
|
|
|
*/
|
|
|
|
bool async_fini;
|
|
|
|
|
2018-03-09 22:20:21 +00:00
|
|
|
TAILQ_ENTRY(spdk_bdev_module) tailq;
|
2016-08-19 17:51:37 +00:00
|
|
|
};
|
|
|
|
|
2017-10-25 09:11:59 +00:00
|
|
|
typedef void (*spdk_bdev_unregister_cb)(void *cb_arg, int rc);
|
|
|
|
|
2016-11-08 21:09:08 +00:00
|
|
|
/**
|
|
|
|
* Function table for a block device backend.
|
|
|
|
*
|
|
|
|
* The backend block device function table provides a set of APIs to allow
|
|
|
|
* communication with a backend. The main commands are read/write API
|
|
|
|
* calls for I/O via submit_request.
|
|
|
|
*/
|
|
|
|
struct spdk_bdev_fn_table {
|
|
|
|
/** Destroy the backend block device object */
|
2017-04-04 21:10:00 +00:00
|
|
|
int (*destruct)(void *ctx);
|
2016-11-08 21:09:08 +00:00
|
|
|
|
|
|
|
/** Process the IO. */
|
2017-05-04 20:18:03 +00:00
|
|
|
void (*submit_request)(struct spdk_io_channel *ch, struct spdk_bdev_io *);
|
2016-11-08 21:09:08 +00:00
|
|
|
|
|
|
|
/** Check if the block device supports a specific I/O type. */
|
2017-04-04 21:10:00 +00:00
|
|
|
bool (*io_type_supported)(void *ctx, enum spdk_bdev_io_type);
|
2016-11-08 21:09:08 +00:00
|
|
|
|
|
|
|
/** Get an I/O channel for the specific bdev for the calling thread. */
|
2017-05-18 17:48:04 +00:00
|
|
|
struct spdk_io_channel *(*get_io_channel)(void *ctx);
|
2016-11-18 17:22:58 +00:00
|
|
|
|
|
|
|
/**
|
2018-02-22 12:48:13 +00:00
|
|
|
* Output driver-specific information to a JSON stream. Optional - may be NULL.
|
2016-11-18 17:22:58 +00:00
|
|
|
*
|
|
|
|
* The JSON write context will be initialized with an open object, so the bdev
|
|
|
|
* driver should write a name (based on the driver name) followed by a JSON value
|
|
|
|
* (most likely another nested object).
|
|
|
|
*/
|
2018-02-22 12:48:13 +00:00
|
|
|
int (*dump_info_json)(void *ctx, struct spdk_json_write_ctx *w);
|
2017-06-15 16:59:02 +00:00
|
|
|
|
2018-02-22 12:48:13 +00:00
|
|
|
/**
|
|
|
|
* Output bdev-specific configuration to a JSON stream. Optional - may be NULL.
|
|
|
|
*
|
|
|
|
* The JSON write context will be initialized with an open object, so the bdev
|
|
|
|
* driver should write all data necessary to recreate this bdev by invoking
|
|
|
|
* constructor method. No other data should be written.
|
|
|
|
*/
|
|
|
|
void (*write_config_json)(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w);
|
|
|
|
|
2017-06-15 16:59:02 +00:00
|
|
|
/** Get spin-time per I/O channel in microseconds.
|
|
|
|
* Optional - may be NULL.
|
|
|
|
*/
|
|
|
|
uint64_t (*get_spin_time)(struct spdk_io_channel *ch);
|
2016-11-08 21:09:08 +00:00
|
|
|
};
|
2016-08-19 17:51:37 +00:00
|
|
|
|
2017-07-13 04:08:53 +00:00
|
|
|
/** bdev I/O completion status */
|
2017-05-16 20:25:03 +00:00
|
|
|
enum spdk_bdev_io_status {
|
bdev: add ENOMEM handling
At very high queue depths, bdev modules may not have enough
internal resources to track all of the incoming I/O. For example,
we allocate a finite number of nvme_request objects per allocated
queue pair. Currently if these resources are exhausted, the
bdev module will return failure (with no indication why) which
gets propagated all the way back to the application.
So instead, add SPDK_BDEV_IO_STATUS_NOMEM to allow bdev modules
to indicate this type of failure. Also add handling for this
status type in the generic bdev layer, involving queuing these
I/O for later retry after other I/O on the failing channel have
completed.
This does place an expectation on the bdev module that these
internal resources are allocated per io_channel. Otherwise we
cannot guarantee forward progress solely on reception of
completions. For example, without this guarantee, a bdev
module could theoretically return ENOMEM even if there were
no I/O oustanding for that io_channel. nvme, aio, rbd,
virtio and null drivers comply with this expectation already.
malloc only complies though when not using copy offload.
This patch will fix malloc w/ copy engine to at least
return ENOMEM when no copy descriptors are available. If the
condition above occurs, I/O waiting for resources will get
failed as part of a subsequent reset which matches the
behavior it has today.
Signed-off-by: Jim Harris <james.r.harris@intel.com>
Change-Id: Iea7cd51a611af8abe882794d0b2361fdbb74e84e
Reviewed-on: https://review.gerrithub.io/378853
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
2017-09-15 20:47:17 +00:00
|
|
|
/*
|
|
|
|
* NOMEM should be returned when a bdev module cannot start an I/O because of
|
|
|
|
* some lack of resources. It may not be returned for RESET I/O. I/O completed
|
|
|
|
* with NOMEM status will be retried after some I/O from the same channel have
|
|
|
|
* completed.
|
|
|
|
*/
|
|
|
|
SPDK_BDEV_IO_STATUS_NOMEM = -4,
|
2017-05-16 20:25:03 +00:00
|
|
|
SPDK_BDEV_IO_STATUS_SCSI_ERROR = -3,
|
|
|
|
SPDK_BDEV_IO_STATUS_NVME_ERROR = -2,
|
|
|
|
SPDK_BDEV_IO_STATUS_FAILED = -1,
|
|
|
|
SPDK_BDEV_IO_STATUS_PENDING = 0,
|
|
|
|
SPDK_BDEV_IO_STATUS_SUCCESS = 1,
|
|
|
|
};
|
|
|
|
|
2017-11-29 15:13:17 +00:00
|
|
|
struct spdk_bdev_alias {
|
|
|
|
char *alias;
|
|
|
|
TAILQ_ENTRY(spdk_bdev_alias) tailq;
|
|
|
|
};
|
|
|
|
|
2018-04-10 23:23:37 +00:00
|
|
|
typedef TAILQ_HEAD(, spdk_bdev_io) bdev_io_tailq_t;
|
|
|
|
typedef STAILQ_HEAD(, spdk_bdev_io) bdev_io_stailq_t;
|
|
|
|
|
2017-05-16 20:03:11 +00:00
|
|
|
struct spdk_bdev {
|
|
|
|
/** User context passed in by the backend */
|
|
|
|
void *ctxt;
|
|
|
|
|
|
|
|
/** Unique name for this block device. */
|
2017-06-02 17:25:43 +00:00
|
|
|
char *name;
|
2017-05-16 20:03:11 +00:00
|
|
|
|
2017-11-29 15:13:17 +00:00
|
|
|
/** Unique aliases for this block device. */
|
|
|
|
TAILQ_HEAD(spdk_bdev_aliases_list, spdk_bdev_alias) aliases;
|
|
|
|
|
2017-05-16 20:03:11 +00:00
|
|
|
/** Unique product name for this kind of block device. */
|
2017-06-02 17:25:43 +00:00
|
|
|
char *product_name;
|
2017-05-16 20:03:11 +00:00
|
|
|
|
|
|
|
/** Size in bytes of a logical block for the backend */
|
|
|
|
uint32_t blocklen;
|
|
|
|
|
|
|
|
/** Number of blocks */
|
|
|
|
uint64_t blockcnt;
|
|
|
|
|
2017-12-28 03:11:55 +00:00
|
|
|
/** Number of active channels on this bdev except the QoS bdev channel */
|
|
|
|
uint32_t channel_count;
|
|
|
|
|
2018-04-10 23:23:37 +00:00
|
|
|
/** Quality of service parameters */
|
2018-04-24 22:44:14 +00:00
|
|
|
struct spdk_bdev_qos *qos;
|
2018-04-10 23:23:37 +00:00
|
|
|
|
2018-04-24 22:44:14 +00:00
|
|
|
/** True if the state of the QoS is being modified */
|
|
|
|
bool qos_mod_in_progress;
|
2017-12-28 03:11:55 +00:00
|
|
|
|
2017-05-16 20:03:11 +00:00
|
|
|
/** write cache enabled, not used at the moment */
|
|
|
|
int write_cache;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This is used to make sure buffers are sector aligned.
|
|
|
|
* This causes double buffering on writes.
|
|
|
|
*/
|
|
|
|
int need_aligned_buffer;
|
|
|
|
|
2017-08-16 20:56:10 +00:00
|
|
|
/**
|
|
|
|
* Optimal I/O boundary in blocks, or 0 for no value reported.
|
|
|
|
*/
|
|
|
|
uint32_t optimal_io_boundary;
|
|
|
|
|
2018-03-02 01:27:44 +00:00
|
|
|
/**
|
|
|
|
* UUID for this bdev.
|
|
|
|
*
|
|
|
|
* Fill with zeroes if no uuid is available.
|
|
|
|
*/
|
|
|
|
struct spdk_uuid uuid;
|
|
|
|
|
2017-07-07 00:36:17 +00:00
|
|
|
/**
|
|
|
|
* Pointer to the bdev module that registered this bdev.
|
|
|
|
*/
|
2018-03-09 22:20:21 +00:00
|
|
|
struct spdk_bdev_module *module;
|
2017-07-07 00:36:17 +00:00
|
|
|
|
2017-05-16 20:03:11 +00:00
|
|
|
/** function table for all LUN ops */
|
|
|
|
const struct spdk_bdev_fn_table *fn_table;
|
|
|
|
|
|
|
|
/** Mutex protecting claimed */
|
|
|
|
pthread_mutex_t mutex;
|
|
|
|
|
|
|
|
/** The bdev status */
|
|
|
|
enum spdk_bdev_status status;
|
|
|
|
|
2018-03-23 19:35:21 +00:00
|
|
|
/** The array of block devices that this block device is built on top of (if any). */
|
|
|
|
struct spdk_bdev **base_bdevs;
|
|
|
|
size_t base_bdevs_cnt;
|
2017-06-29 20:16:26 +00:00
|
|
|
|
|
|
|
|
2018-03-23 19:35:21 +00:00
|
|
|
/** The array of virtual block devices built on top of this block device. */
|
|
|
|
struct spdk_bdev **vbdevs;
|
|
|
|
size_t vbdevs_cnt;
|
2017-06-29 20:16:26 +00:00
|
|
|
|
2017-07-13 04:06:22 +00:00
|
|
|
/**
|
|
|
|
* Pointer to the module that has claimed this bdev for purposes of creating virtual
|
|
|
|
* bdevs on top of it. Set to NULL if the bdev has not been claimed.
|
|
|
|
*/
|
2018-03-09 22:20:21 +00:00
|
|
|
struct spdk_bdev_module *claim_module;
|
2017-06-29 18:23:50 +00:00
|
|
|
|
2017-10-25 09:11:59 +00:00
|
|
|
/** Callback function that will be called after bdev destruct is completed. */
|
|
|
|
spdk_bdev_unregister_cb unregister_cb;
|
|
|
|
|
|
|
|
/** Unregister call context */
|
|
|
|
void *unregister_ctx;
|
|
|
|
|
2017-06-29 18:23:50 +00:00
|
|
|
/** List of open descriptors for this block device. */
|
|
|
|
TAILQ_HEAD(, spdk_bdev_desc) open_descs;
|
2017-05-16 20:03:11 +00:00
|
|
|
|
|
|
|
TAILQ_ENTRY(spdk_bdev) link;
|
2017-06-15 14:17:12 +00:00
|
|
|
|
2017-09-12 19:14:48 +00:00
|
|
|
/** points to a reset bdev_io if one is in progress. */
|
|
|
|
struct spdk_bdev_io *reset_in_progress;
|
2017-05-16 20:03:11 +00:00
|
|
|
};
|
|
|
|
|
2017-05-05 20:15:51 +00:00
|
|
|
typedef void (*spdk_bdev_io_get_buf_cb)(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io);
|
2017-05-04 20:18:03 +00:00
|
|
|
|
2017-05-04 20:46:50 +00:00
|
|
|
struct spdk_bdev_io {
|
|
|
|
/** The block device that this I/O belongs to. */
|
|
|
|
struct spdk_bdev *bdev;
|
|
|
|
|
2018-03-16 01:20:14 +00:00
|
|
|
/** Error information from a device */
|
|
|
|
union {
|
|
|
|
/** Only valid when status is SPDK_BDEV_IO_STATUS_NVME_ERROR */
|
|
|
|
struct {
|
|
|
|
/** NVMe status code type */
|
|
|
|
uint8_t sct;
|
|
|
|
/** NVMe status code */
|
|
|
|
uint8_t sc;
|
|
|
|
} nvme;
|
|
|
|
/** Only valid when status is SPDK_BDEV_IO_STATUS_SCSI_ERROR */
|
|
|
|
struct {
|
|
|
|
/** SCSI status code */
|
|
|
|
uint8_t sc;
|
|
|
|
/** SCSI sense key */
|
|
|
|
uint8_t sk;
|
|
|
|
/** SCSI additional sense code */
|
|
|
|
uint8_t asc;
|
|
|
|
/** SCSI additional sense code qualifier */
|
|
|
|
uint8_t ascq;
|
|
|
|
} scsi;
|
|
|
|
} error;
|
|
|
|
|
|
|
|
/** Enumerated value representing the I/O type. */
|
|
|
|
uint8_t type;
|
|
|
|
|
2017-05-04 20:46:50 +00:00
|
|
|
union {
|
|
|
|
struct {
|
2017-09-20 13:10:17 +00:00
|
|
|
/** For basic IO case, use our own iovec element. */
|
2017-05-04 20:46:50 +00:00
|
|
|
struct iovec iov;
|
|
|
|
|
|
|
|
/** For SG buffer cases, array of iovecs to transfer. */
|
|
|
|
struct iovec *iovs;
|
|
|
|
|
|
|
|
/** For SG buffer cases, number of iovecs in iovec array. */
|
|
|
|
int iovcnt;
|
|
|
|
|
2017-05-09 20:32:20 +00:00
|
|
|
/** Total size of data to be transferred. */
|
2017-08-29 00:15:53 +00:00
|
|
|
uint64_t num_blocks;
|
2017-05-04 20:46:50 +00:00
|
|
|
|
2017-08-29 00:15:53 +00:00
|
|
|
/** Starting offset (in blocks) of the bdev for this I/O. */
|
|
|
|
uint64_t offset_blocks;
|
2018-03-16 01:20:14 +00:00
|
|
|
|
|
|
|
/** stored user callback in case we split the I/O and use a temporary callback */
|
|
|
|
spdk_bdev_io_completion_cb stored_user_cb;
|
|
|
|
|
|
|
|
/** number of blocks remaining in a split i/o */
|
|
|
|
uint64_t split_remaining_num_blocks;
|
|
|
|
|
|
|
|
/** current offset of the split I/O in the bdev */
|
|
|
|
uint64_t split_current_offset_blocks;
|
2017-09-20 13:10:17 +00:00
|
|
|
} bdev;
|
2017-09-12 16:34:55 +00:00
|
|
|
struct {
|
|
|
|
/** Channel reference held while messages for this reset are in progress. */
|
|
|
|
struct spdk_io_channel *ch_ref;
|
|
|
|
} reset;
|
2017-05-13 20:12:13 +00:00
|
|
|
struct {
|
|
|
|
/* The NVMe command to execute */
|
|
|
|
struct spdk_nvme_cmd cmd;
|
|
|
|
|
|
|
|
/* The data buffer to transfer */
|
|
|
|
void *buf;
|
|
|
|
|
|
|
|
/* The number of bytes to transfer */
|
|
|
|
size_t nbytes;
|
2017-11-14 06:33:11 +00:00
|
|
|
|
|
|
|
/* The meta data buffer to transfer */
|
|
|
|
void *md_buf;
|
|
|
|
|
|
|
|
/* meta data buffer size to transfer */
|
|
|
|
size_t md_len;
|
2017-05-13 20:12:13 +00:00
|
|
|
} nvme_passthru;
|
2017-05-04 20:46:50 +00:00
|
|
|
} u;
|
|
|
|
|
2017-06-05 08:04:04 +00:00
|
|
|
/** It may be used by modules to put the bdev_io into its own list. */
|
|
|
|
TAILQ_ENTRY(spdk_bdev_io) module_link;
|
|
|
|
|
2018-06-18 14:54:39 +00:00
|
|
|
/** Fields that are used internally by the bdev subsystem. Bdev modules
|
|
|
|
* must not read or write to these fields.
|
|
|
|
*/
|
|
|
|
struct __bdev_io_internal_fields {
|
2018-06-20 17:54:48 +00:00
|
|
|
/** The bdev I/O channel that this was handled on. */
|
|
|
|
struct spdk_bdev_channel *ch;
|
|
|
|
|
|
|
|
/** The bdev I/O channel that this was submitted on. */
|
|
|
|
struct spdk_bdev_channel *io_submit_ch;
|
|
|
|
|
2018-06-19 23:57:20 +00:00
|
|
|
/** User function that will be called when this completes */
|
|
|
|
spdk_bdev_io_completion_cb cb;
|
|
|
|
|
|
|
|
/** Context that will be passed to the completion callback */
|
|
|
|
void *caller_ctx;
|
|
|
|
|
2018-06-19 23:27:19 +00:00
|
|
|
/** Current tsc at submit time. Used to calculate latency at completion. */
|
|
|
|
uint64_t submit_tsc;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set to true while the bdev module submit_request function is in progress.
|
|
|
|
*
|
|
|
|
* This is used to decide whether spdk_bdev_io_complete() can complete the I/O directly
|
|
|
|
* or if completion must be deferred via an event.
|
|
|
|
*/
|
|
|
|
bool in_submit_request;
|
|
|
|
|
2018-06-19 23:19:49 +00:00
|
|
|
/** Status for the IO */
|
|
|
|
int8_t status;
|
|
|
|
|
2018-06-19 22:08:31 +00:00
|
|
|
/** bdev allocated memory associated with this request */
|
|
|
|
void *buf;
|
|
|
|
|
|
|
|
/** requested size of the buffer associated with this I/O */
|
|
|
|
uint64_t buf_len;
|
|
|
|
|
|
|
|
/** Callback for when buf is allocated */
|
|
|
|
spdk_bdev_io_get_buf_cb get_buf_cb;
|
|
|
|
|
2018-06-20 20:58:59 +00:00
|
|
|
/** Member used for linking child I/Os together. */
|
|
|
|
TAILQ_ENTRY(spdk_bdev_io) link;
|
|
|
|
|
2018-05-31 17:06:30 +00:00
|
|
|
/** Entry to the list need_buf of struct spdk_bdev. */
|
|
|
|
STAILQ_ENTRY(spdk_bdev_io) buf_link;
|
|
|
|
} internal;
|
|
|
|
|
2017-06-15 14:17:12 +00:00
|
|
|
/**
|
2017-07-13 04:08:53 +00:00
|
|
|
* Per I/O context for use by the bdev module.
|
2017-06-15 14:17:12 +00:00
|
|
|
*/
|
2017-05-04 20:46:50 +00:00
|
|
|
uint8_t driver_ctx[0];
|
|
|
|
|
|
|
|
/* No members may be added after driver_ctx! */
|
|
|
|
};
|
|
|
|
|
2018-06-20 20:41:24 +00:00
|
|
|
/**
|
|
|
|
* Register a new bdev.
|
|
|
|
*
|
|
|
|
* \param bdev Block device to register.
|
|
|
|
*
|
|
|
|
* \return 0 on success.
|
|
|
|
* \return -EINVAL if the bdev name is NULL.
|
|
|
|
* \return -EEXIST if a bdev or bdev alias with the same name already exists.
|
|
|
|
*/
|
2017-11-20 09:31:39 +00:00
|
|
|
int spdk_bdev_register(struct spdk_bdev *bdev);
|
2018-06-20 20:41:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Unregister a bdev
|
|
|
|
*
|
|
|
|
* \param bdev Block device to unregister.
|
|
|
|
* \param cb_fn Callback function to be called when the unregister is complete.
|
|
|
|
* \param cb_arg Argument to be supplied to cb_fn
|
|
|
|
*/
|
2017-10-25 09:11:59 +00:00
|
|
|
void spdk_bdev_unregister(struct spdk_bdev *bdev, spdk_bdev_unregister_cb cb_fn, void *cb_arg);
|
2018-06-20 20:41:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Invokes the unregister callback of a bdev backing a virtual bdev.
|
|
|
|
*
|
|
|
|
* A Bdev with an asynchronous destruct path should return 1 from its
|
|
|
|
* destruct function and call this function at the conclusion of that path.
|
|
|
|
* Bdevs with synchronous destruct paths should return 0 from their destruct
|
|
|
|
* path.
|
|
|
|
*
|
|
|
|
* \param bdev Block device that was destroyed.
|
|
|
|
* \param bdeverrno Error code returned from bdev's destruct callback.
|
|
|
|
*/
|
2018-02-22 12:29:49 +00:00
|
|
|
void spdk_bdev_destruct_done(struct spdk_bdev *bdev, int bdeverrno);
|
2018-06-20 20:41:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Register a virtual bdev.
|
|
|
|
*
|
|
|
|
* \param vbdev Virtual bdev to register.
|
|
|
|
* \param base_bdevs Array of bdevs upon which this vbdev is based.
|
|
|
|
* \param base_bdev_count Number of bdevs in base_bdevs.
|
|
|
|
*
|
|
|
|
* \return 0 on success
|
|
|
|
* \return -EINVAL if the bdev name is NULL.
|
|
|
|
* \return -EEXIST if the bdev already exists.
|
|
|
|
* \return -ENOMEM if allocation of the base_bdevs array or the base bdevs vbdevs array fails.
|
|
|
|
*/
|
2017-11-20 09:31:39 +00:00
|
|
|
int spdk_vbdev_register(struct spdk_bdev *vbdev, struct spdk_bdev **base_bdevs,
|
|
|
|
int base_bdev_count);
|
2017-06-29 20:16:26 +00:00
|
|
|
|
2018-06-20 20:41:24 +00:00
|
|
|
/**
|
|
|
|
* Indicate to the bdev layer that the module is done examining a bdev.
|
|
|
|
*
|
|
|
|
* To be called synchronously or asynchronously in response to the
|
|
|
|
* module's examine function being called.
|
|
|
|
*
|
|
|
|
* \param module Pointer to the module completing the examination.
|
|
|
|
*/
|
2018-03-09 22:20:21 +00:00
|
|
|
void spdk_bdev_module_examine_done(struct spdk_bdev_module *module);
|
2018-06-20 20:41:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Indicate to the bdev layer that the module is done initializing.
|
|
|
|
*
|
|
|
|
* To be called synchronously or asynchronously in response to the
|
|
|
|
* module_init function being called.
|
|
|
|
*
|
|
|
|
* \param module Pointer to the module completing the initialization.
|
|
|
|
*/
|
2018-03-09 22:20:21 +00:00
|
|
|
void spdk_bdev_module_init_done(struct spdk_bdev_module *module);
|
2018-06-20 20:41:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Indicate to the bdev layer that the module is done cleaning up.
|
|
|
|
*
|
|
|
|
* To be called either synchronously or asynchronously
|
|
|
|
* in response to the module_fini function being called.
|
|
|
|
*
|
|
|
|
*/
|
2017-10-25 13:58:02 +00:00
|
|
|
void spdk_bdev_module_finish_done(void);
|
2018-06-20 20:41:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Called by a bdev module to lay exclusive write claim to a bdev.
|
|
|
|
*
|
|
|
|
* Also upgrades that bdev's descriptor to have write access.
|
|
|
|
*
|
|
|
|
* \param bdev Block device to be claimed.
|
|
|
|
* \param desc Descriptor for the above block device.
|
|
|
|
* \param module Bdev module attempting to claim bdev.
|
|
|
|
*
|
|
|
|
* \return 0 on success
|
|
|
|
* \return -EPERM if the bdev is already claimed by another module.
|
|
|
|
*/
|
2017-07-13 04:06:22 +00:00
|
|
|
int spdk_bdev_module_claim_bdev(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
|
2018-03-09 22:20:21 +00:00
|
|
|
struct spdk_bdev_module *module);
|
2018-06-20 20:41:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Called to release a write claim on a block device.
|
|
|
|
*
|
|
|
|
* \param bdev Block device to be released.
|
|
|
|
*/
|
2017-07-13 04:06:22 +00:00
|
|
|
void spdk_bdev_module_release_bdev(struct spdk_bdev *bdev);
|
2017-07-07 23:04:52 +00:00
|
|
|
|
2017-11-29 15:13:17 +00:00
|
|
|
/**
|
|
|
|
* Add alias to block device names list.
|
|
|
|
* Aliases can be add only to registered bdev.
|
|
|
|
*
|
|
|
|
* \param bdev Block device to query.
|
|
|
|
* \param alias Alias to be added to list.
|
|
|
|
*
|
|
|
|
* \return 0 on success
|
|
|
|
* \return -EEXIST if alias already exists as name or alias on any bdev
|
|
|
|
* \return -ENOMEM if memory cannot be allocated to store alias
|
|
|
|
* \return -EINVAL if passed alias is empty
|
|
|
|
*/
|
|
|
|
int spdk_bdev_alias_add(struct spdk_bdev *bdev, const char *alias);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes name from block device names list.
|
|
|
|
*
|
|
|
|
* \param bdev Block device to query.
|
|
|
|
* \param alias Alias to be deleted from list.
|
|
|
|
* \return 0 on success
|
|
|
|
* \return -ENOENT if alias does not exists
|
|
|
|
*/
|
|
|
|
int spdk_bdev_alias_del(struct spdk_bdev *bdev, const char *alias);
|
|
|
|
|
2017-12-07 10:40:18 +00:00
|
|
|
/**
|
|
|
|
* Get pointer to block device aliases list.
|
|
|
|
*
|
|
|
|
* \param bdev Block device to query.
|
|
|
|
* \return Pointer to bdev aliases list.
|
|
|
|
*/
|
|
|
|
const struct spdk_bdev_aliases_list *spdk_bdev_get_aliases(const struct spdk_bdev *bdev);
|
|
|
|
|
2017-09-22 20:59:55 +00:00
|
|
|
/**
|
|
|
|
* Allocate a buffer for given bdev_io. Allocation will happen
|
|
|
|
* only if the bdev_io has no assigned SGL yet. The buffer will be
|
|
|
|
* freed automatically on \c spdk_bdev_free_io() call. This call
|
|
|
|
* will never fail - in case of lack of memory given callback \c cb
|
|
|
|
* will be deferred until enough memory is freed.
|
|
|
|
*
|
|
|
|
* \param bdev_io I/O to allocate buffer for.
|
|
|
|
* \param cb callback to be called when the buffer is allocated
|
|
|
|
* or the bdev_io has an SGL assigned already.
|
2017-09-27 18:59:50 +00:00
|
|
|
* \param len size of the buffer to allocate. In case the bdev_io
|
|
|
|
* doesn't have an SGL assigned this field must be no bigger than
|
|
|
|
* \c SPDK_BDEV_LARGE_BUF_MAX_SIZE.
|
2017-09-22 20:59:55 +00:00
|
|
|
*/
|
|
|
|
void spdk_bdev_io_get_buf(struct spdk_bdev_io *bdev_io, spdk_bdev_io_get_buf_cb cb, uint64_t len);
|
|
|
|
|
2018-06-20 20:41:24 +00:00
|
|
|
/**
|
|
|
|
* Complete a bdev_io
|
|
|
|
*
|
|
|
|
* \param bdev_io I/O to complete.
|
|
|
|
* \param status The I/O completion status.
|
|
|
|
*/
|
2016-08-19 17:51:37 +00:00
|
|
|
void spdk_bdev_io_complete(struct spdk_bdev_io *bdev_io,
|
|
|
|
enum spdk_bdev_io_status status);
|
2017-01-18 21:43:15 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Complete a bdev_io with an NVMe status code.
|
|
|
|
*
|
|
|
|
* \param bdev_io I/O to complete.
|
|
|
|
* \param sct NVMe Status Code Type.
|
|
|
|
* \param sc NVMe Status Code.
|
|
|
|
*/
|
|
|
|
void spdk_bdev_io_complete_nvme_status(struct spdk_bdev_io *bdev_io, int sct, int sc);
|
|
|
|
|
2017-01-18 22:20:31 +00:00
|
|
|
/**
|
|
|
|
* Complete a bdev_io with a SCSI status code.
|
|
|
|
*
|
|
|
|
* \param bdev_io I/O to complete.
|
|
|
|
* \param sc SCSI Status Code.
|
|
|
|
* \param sk SCSI Sense Key.
|
|
|
|
* \param asc SCSI Additional Sense Code.
|
|
|
|
* \param ascq SCSI Additional Sense Code Qualifier.
|
|
|
|
*/
|
|
|
|
void spdk_bdev_io_complete_scsi_status(struct spdk_bdev_io *bdev_io, enum spdk_scsi_status sc,
|
|
|
|
enum spdk_scsi_sense sk, uint8_t asc, uint8_t ascq);
|
|
|
|
|
2017-10-11 16:47:52 +00:00
|
|
|
/**
|
|
|
|
* Get a thread that given bdev_io was submitted on.
|
|
|
|
*
|
|
|
|
* \param bdev_io I/O
|
|
|
|
* \return thread that submitted the I/O
|
|
|
|
*/
|
|
|
|
struct spdk_thread *spdk_bdev_io_get_thread(struct spdk_bdev_io *bdev_io);
|
2017-01-18 22:20:31 +00:00
|
|
|
|
2018-01-26 10:00:36 +00:00
|
|
|
/**
|
|
|
|
* Resize for a bdev.
|
|
|
|
*
|
|
|
|
* Change number of blocks for provided block device.
|
|
|
|
* It can only be called on a registered bdev.
|
|
|
|
*
|
|
|
|
* \param bdev Block device to change.
|
|
|
|
* \param size New size of bdev.
|
|
|
|
* \return 0 on success, negated errno on failure.
|
|
|
|
*/
|
|
|
|
int spdk_bdev_notify_blockcnt_change(struct spdk_bdev *bdev, uint64_t size);
|
|
|
|
|
2018-06-20 23:07:06 +00:00
|
|
|
/**
|
|
|
|
* Translates NVMe status codes to SCSI status information.
|
|
|
|
*
|
|
|
|
* The codes are stored in the user supplied integers.
|
|
|
|
*
|
|
|
|
* \param bdev_io I/O containing status codes to translate.
|
|
|
|
* \param sc SCSI Status Code will be stored here.
|
|
|
|
* \param sk SCSI Sense Key will be stored here.
|
|
|
|
* \param asc SCSI Additional Sense Code will be stored here.
|
|
|
|
* \param ascq SCSI Additional Sense Code Qualifier will be stored here.
|
|
|
|
*/
|
2017-01-18 22:15:35 +00:00
|
|
|
void spdk_scsi_nvme_translate(const struct spdk_bdev_io *bdev_io,
|
|
|
|
int *sc, int *sk, int *asc, int *ascq);
|
|
|
|
|
2018-06-20 23:07:06 +00:00
|
|
|
/**
|
|
|
|
* Add the given module to the list of registered modules.
|
|
|
|
* This function should be invoked by referencing the macro
|
|
|
|
* SPDK_BDEV_MODULE_REGISTER in the module c file.
|
|
|
|
*
|
|
|
|
* \param bdev_module Module to be added.
|
|
|
|
*/
|
2018-03-09 22:20:21 +00:00
|
|
|
void spdk_bdev_module_list_add(struct spdk_bdev_module *bdev_module);
|
2016-08-19 17:51:37 +00:00
|
|
|
|
2018-03-06 18:52:46 +00:00
|
|
|
/**
|
|
|
|
* Find registered module with name pointed by \c name.
|
|
|
|
*
|
|
|
|
* \param name name of module to be searched for.
|
|
|
|
* \return pointer to module or NULL if no module with \c name exist
|
|
|
|
*/
|
2018-03-09 22:20:21 +00:00
|
|
|
struct spdk_bdev_module *spdk_bdev_module_list_find(const char *name);
|
2018-03-06 18:52:46 +00:00
|
|
|
|
2016-08-19 17:51:37 +00:00
|
|
|
static inline struct spdk_bdev_io *
|
|
|
|
spdk_bdev_io_from_ctx(void *ctx)
|
|
|
|
{
|
|
|
|
return (struct spdk_bdev_io *)
|
|
|
|
((uintptr_t)ctx - offsetof(struct spdk_bdev_io, driver_ctx));
|
|
|
|
}
|
|
|
|
|
2017-09-14 18:34:36 +00:00
|
|
|
struct spdk_bdev_part_base;
|
|
|
|
|
|
|
|
typedef void (*spdk_bdev_part_base_free_fn)(struct spdk_bdev_part_base *base);
|
|
|
|
|
2017-08-29 05:24:52 +00:00
|
|
|
struct spdk_bdev_part_base {
|
|
|
|
struct spdk_bdev *bdev;
|
|
|
|
struct spdk_bdev_desc *desc;
|
|
|
|
uint32_t ref;
|
|
|
|
uint32_t channel_size;
|
2017-09-14 18:34:36 +00:00
|
|
|
spdk_bdev_part_base_free_fn base_free_fn;
|
2017-08-29 05:24:52 +00:00
|
|
|
bool claimed;
|
2018-03-09 22:20:21 +00:00
|
|
|
struct spdk_bdev_module *module;
|
2017-08-29 05:24:52 +00:00
|
|
|
struct spdk_bdev_fn_table *fn_table;
|
|
|
|
struct bdev_part_tailq *tailq;
|
|
|
|
spdk_io_channel_create_cb ch_create_cb;
|
|
|
|
spdk_io_channel_destroy_cb ch_destroy_cb;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct spdk_bdev_part {
|
|
|
|
struct spdk_bdev bdev;
|
|
|
|
struct spdk_bdev_part_base *base;
|
|
|
|
uint64_t offset_blocks;
|
|
|
|
TAILQ_ENTRY(spdk_bdev_part) tailq;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct spdk_bdev_part_channel {
|
|
|
|
struct spdk_bdev_part *part;
|
|
|
|
struct spdk_io_channel *base_ch;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef TAILQ_HEAD(bdev_part_tailq, spdk_bdev_part) SPDK_BDEV_PART_TAILQ;
|
|
|
|
|
2018-06-20 23:07:06 +00:00
|
|
|
/**
|
|
|
|
* Free the base corresponding to one or more spdk_bdev_part.
|
|
|
|
*
|
|
|
|
* \param base The base to free.
|
|
|
|
*/
|
2017-08-29 05:24:52 +00:00
|
|
|
void spdk_bdev_part_base_free(struct spdk_bdev_part_base *base);
|
2018-06-20 23:07:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Free an spdk_bdev_part context.
|
|
|
|
*
|
|
|
|
* \param part The part to free.
|
|
|
|
*
|
|
|
|
* \return 1 always. To indicate that the operation is asynchronous.
|
|
|
|
*/
|
2018-04-16 21:45:53 +00:00
|
|
|
int spdk_bdev_part_free(struct spdk_bdev_part *part);
|
2018-06-20 23:07:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Calls spdk_bdev_unregister on the bdev for each part associated with base_bdev.
|
|
|
|
*
|
|
|
|
* \param base_bdev The spdk_bdev upon which an spdk_bdev-part_base is built
|
|
|
|
* \param tailq The list of spdk_bdev_part bdevs associated with this base bdev.
|
|
|
|
*/
|
2017-08-29 05:24:52 +00:00
|
|
|
void spdk_bdev_part_base_hotremove(struct spdk_bdev *base_bdev, struct bdev_part_tailq *tailq);
|
2018-06-20 23:07:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Construct a new spdk_bdev_part_base on top of the provided bdev.
|
|
|
|
*
|
|
|
|
* \param base User allocated spdk_bdev_part_base to be filled by this function.
|
|
|
|
* \param bdev The spdk_bdev upon which this base will be built.
|
|
|
|
* \param remove_cb Function to be called upon hotremove of the bdev.
|
|
|
|
* \param module The module to which this bdev base belongs.
|
|
|
|
* \param fn_table Function table for communicating with the bdev backend.
|
|
|
|
* \param tailq The head of the list of all spdk_bdev_part structures registered to this base's module.
|
|
|
|
* \param free_fn User provided function to free base related context upon bdev removal or shutdown.
|
|
|
|
* \param channel_size Channel size in bytes.
|
|
|
|
* \param ch_create_cb Called after a new channel is allocated.
|
|
|
|
* \param ch_destroy_cb Called upon channel deletion.
|
|
|
|
*
|
|
|
|
* \return 0 on success
|
|
|
|
* \return -1 if the underlying bdev cannot be opened.
|
|
|
|
*/
|
2017-08-29 05:24:52 +00:00
|
|
|
int spdk_bdev_part_base_construct(struct spdk_bdev_part_base *base, struct spdk_bdev *bdev,
|
|
|
|
spdk_bdev_remove_cb_t remove_cb,
|
2018-03-09 22:20:21 +00:00
|
|
|
struct spdk_bdev_module *module,
|
2017-08-29 05:24:52 +00:00
|
|
|
struct spdk_bdev_fn_table *fn_table,
|
|
|
|
struct bdev_part_tailq *tailq,
|
2017-09-14 18:34:36 +00:00
|
|
|
spdk_bdev_part_base_free_fn free_fn,
|
2017-08-29 05:24:52 +00:00
|
|
|
uint32_t channel_size,
|
|
|
|
spdk_io_channel_create_cb ch_create_cb,
|
|
|
|
spdk_io_channel_destroy_cb ch_destroy_cb);
|
2018-06-20 23:07:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a logical spdk_bdev_part on top of a base.
|
|
|
|
*
|
|
|
|
* \param part The part object allocated by the user.
|
|
|
|
* \param base The base from which to create the part.
|
|
|
|
* \param name The name of the new spdk_bdev_part.
|
|
|
|
* \param offset_blocks The offset into the base bdev at which this part begins.
|
|
|
|
* \param num_blocks The number of blocks that this part will span.
|
|
|
|
* \param product_name Unique name for this type of block device.
|
|
|
|
*
|
|
|
|
* \return 0 on success.
|
|
|
|
* \return -1 if the bases underlying bdev cannot be claimed by the current module.
|
|
|
|
*/
|
2017-08-29 05:24:52 +00:00
|
|
|
int spdk_bdev_part_construct(struct spdk_bdev_part *part, struct spdk_bdev_part_base *base,
|
|
|
|
char *name, uint64_t offset_blocks, uint64_t num_blocks,
|
|
|
|
char *product_name);
|
2018-06-20 23:07:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Forwards I/O from an spdk_bdev_part to the underlying base bdev.
|
|
|
|
*
|
|
|
|
* This function will apply the offset_blocks the user provided to
|
|
|
|
* spdk_bdev_part_construct to the I/O. The user should not manually
|
|
|
|
* apply this offset before submitting any I/O through this function.
|
|
|
|
*
|
|
|
|
* \param ch The I/O channel associated with the spdk_bdev_part.
|
|
|
|
* \param bdev_io The I/O to be submitted to the underlying bdev.
|
|
|
|
*/
|
2017-08-29 05:24:52 +00:00
|
|
|
void spdk_bdev_part_submit_request(struct spdk_bdev_part_channel *ch, struct spdk_bdev_io *bdev_io);
|
|
|
|
|
2017-08-24 15:36:25 +00:00
|
|
|
|
|
|
|
/*
|
2018-03-06 18:52:46 +00:00
|
|
|
* Macro used to register module for later initialization.
|
2017-08-24 15:36:25 +00:00
|
|
|
*/
|
2018-03-06 18:52:46 +00:00
|
|
|
#define SPDK_BDEV_MODULE_REGISTER(_module) \
|
|
|
|
__attribute__((constructor)) static void \
|
|
|
|
SPDK_BDEV_MODULE_REGISTER_FN_NAME(__LINE__) (void) \
|
2017-08-24 15:36:25 +00:00
|
|
|
{ \
|
2018-03-06 18:52:46 +00:00
|
|
|
spdk_bdev_module_list_add(_module); \
|
2017-08-24 15:36:25 +00:00
|
|
|
}
|
2017-07-07 00:36:17 +00:00
|
|
|
|
2017-10-25 13:58:02 +00:00
|
|
|
/*
|
2018-03-06 18:52:46 +00:00
|
|
|
* This is helper macro for automatic function generation.
|
|
|
|
*
|
2017-10-25 13:58:02 +00:00
|
|
|
*/
|
2018-03-06 18:52:46 +00:00
|
|
|
#define SPDK_BDEV_MODULE_REGISTER_FN_NAME(line) SPDK_BDEV_MODULE_REGISTER_FN_NAME_(line)
|
2017-10-25 13:58:02 +00:00
|
|
|
|
2017-07-07 00:36:17 +00:00
|
|
|
/*
|
2018-03-06 18:52:46 +00:00
|
|
|
* Second helper macro for "stringize" trick to work.
|
2017-07-07 00:36:17 +00:00
|
|
|
*/
|
2018-03-09 22:20:21 +00:00
|
|
|
#define SPDK_BDEV_MODULE_REGISTER_FN_NAME_(line) spdk_bdev_module_register_ ## line
|
2017-07-07 00:36:17 +00:00
|
|
|
|
2018-05-25 19:47:50 +00:00
|
|
|
#endif /* SPDK_BDEV_MODULE_H */
|