| // SPDX-License-Identifier: MIT or LGPL-2.1-only |
| |
| /** |
| * @file ublksrv.h |
| * |
| * libublksrv APIs |
| * |
| * This header define the interfaces of libublksrv |
| */ |
| |
| #ifndef UBLKSRV_INC_H |
| #define UBLKSRV_INC_H |
| |
| #include <stdbool.h> |
| #include <assert.h> |
| |
| #include "liburing.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #include "ublk_cmd.h" |
| |
| #define MAX_NR_HW_QUEUES 32 |
| #define MAX_QD UBLK_MAX_QUEUE_DEPTH |
| #define MAX_BUF_SIZE (32U << 20) |
| |
| #define DEF_NR_HW_QUEUES 1 |
| #define DEF_QD 128 |
| #define DEF_BUF_SIZE (512 << 10) |
| |
| /************ stored in ublksrv_ctrl_dev_info->ublksrv_flags *******/ |
| /* |
| * target may not use io_uring for handling io, so eventfd is required |
| * for wakeup io command io_uring context |
| */ |
| #define UBLKSRV_F_NEED_EVENTFD (1UL << 1) |
| |
| struct io_uring; |
| struct io_uring_cqe; |
| struct ublksrv_aio_ctx; |
| struct ublksrv_ctrl_dev; |
| |
| /** |
| * Generic data for creating one ublk control device, which is used for |
| * sending control commands to /dev/ublk-control. |
| * |
| * Control commands(UBLK_CMD_*) are defined in ublk_cmd.h. |
| */ |
| struct ublksrv_dev_data { |
| int dev_id; |
| unsigned max_io_buf_bytes; |
| unsigned short nr_hw_queues; |
| unsigned short queue_depth; |
| const char *tgt_type; |
| const struct ublksrv_tgt_type *tgt_ops; |
| int tgt_argc; |
| char **tgt_argv; |
| const char *run_dir; |
| unsigned long flags; |
| unsigned long ublksrv_flags; |
| unsigned long reserved[7]; |
| }; |
| |
| /** |
| * IO data passed to target io handling callbacks, such as |
| * ->handle_io_async() and ->tgt_io_done(). |
| */ |
| struct ublk_io_data { |
| /** tag of this io data, unique in queue wide */ |
| int tag; |
| unsigned int pad; |
| |
| /** io description from ublk driver */ |
| const struct ublksrv_io_desc *iod; |
| |
| /** |
| * IO private data, created in ublksrv_queue_init(), |
| * data size is specified in ublksrv_tgt_info.io_data_size |
| */ |
| void *private_data; |
| }; |
| |
| /* queue state is only retrieved via ublksrv_queue_state() API */ |
| #define UBLKSRV_QUEUE_STOPPING (1U << 0) |
| #define UBLKSRV_QUEUE_IDLE (1U << 1) |
| #define UBLKSRV_QUEUE_IOCTL_OP (1U << 2) |
| #define UBLKSRV_USER_COPY (1U << 3) |
| |
| /** |
| * ublksrv_queue is 1:1 mapping with ublk driver's blk-mq queue, and |
| * has same queue depth with ublk driver's blk-mq queue. |
| */ |
| struct ublksrv_queue { |
| /** queue id */ |
| int q_id; |
| |
| /** So far, all queues in same device has same depth */ |
| int q_depth; |
| |
| /** io uring for handling io commands() from ublk driver */ |
| struct io_uring *ring_ptr; |
| |
| /** which device this queue belongs to */ |
| const struct ublksrv_dev *dev; |
| |
| /** queue's private data, passed from ublksrv_queue_init() */ |
| void *private_data; |
| }; |
| |
| struct ublksrv_tgt_type; |
| |
| #define UBLKSRV_TGT_MAX_FDS 32 |
| |
| /** |
| * |
| * ublksrv_tgt_info: target data |
| * |
| */ |
| struct ublksrv_tgt_info { |
| /** device size */ |
| unsigned long long dev_size; |
| |
| /** |
| * target ring depth, for handling target IOs |
| */ |
| unsigned int tgt_ring_depth; |
| |
| /** how many FDs regisgered */ |
| unsigned int nr_fds; |
| |
| /** file descriptor table */ |
| int fds[UBLKSRV_TGT_MAX_FDS]; |
| |
| /** target private data */ |
| void *tgt_data; |
| |
| /** |
| * Extra IO slots for each queue, target code can reserve some |
| * slots for handling internal IO, such as meta data IO, then |
| * ublk_io instances can be assigned for these extra IOs. |
| * |
| * IO slot is useful for storing coroutine data which is for |
| * handling this (meta) IO. |
| */ |
| unsigned int extra_ios; |
| |
| /** size of io private data */ |
| unsigned int io_data_size; |
| |
| /** |
| * target io handling type, target main job is to implement |
| * callbacks defined in this type |
| */ |
| const struct ublksrv_tgt_type *ops; |
| |
| /** |
| * If target needs to override default max workers for io_uring, |
| * initialize io_wq_max_workers with proper value, otherwise |
| * keep them as zero |
| */ |
| unsigned int iowq_max_workers[2]; |
| |
| unsigned long reserved[4]; |
| }; |
| |
| /** |
| * ublksrv device |
| */ |
| struct ublksrv_dev { |
| /** device data */ |
| struct ublksrv_tgt_info tgt; |
| }; |
| |
| /** |
| * |
| * ublksrv_tgt_type: target type |
| * |
| */ |
| struct ublksrv_tgt_type { |
| /** |
| * One IO request comes from /dev/ublkbN, so notify target code |
| * for handling the IO. Inside target code, the IO can be handled |
| * with our io_uring too, if this is true, ->tgt_io_done callback |
| * has to be implemented. Otherwise, target can implement |
| * ->handle_event() for processing io completion there. |
| * |
| * Required. |
| */ |
| int (*handle_io_async)(const struct ublksrv_queue *, |
| const struct ublk_io_data *io); |
| |
| /** |
| * target io is handled by our io_uring, and once the target io |
| * is completed, this callback is called. |
| * |
| * Optional, only required iff this target io is handled by ublksrv's |
| * io_uring. |
| */ |
| void (*tgt_io_done)(const struct ublksrv_queue *, |
| const struct ublk_io_data *io, |
| const struct io_uring_cqe *); |
| |
| /** |
| * Someone has written to our eventfd, so let target handle the |
| * event, most of times, it is for handling io completion by |
| * calling ublksrv_complete_io() which has to be run in ubq_daemon |
| * context. |
| * |
| * Follows the typical scenario: |
| * |
| * 1) one target io is completed in target pthread context, so |
| * target code calls ublksrv_queue_send_event for notifying ubq |
| * daemon |
| * |
| * 2) ubq daemon gets notified, so wakeup from io_uring_enter(), |
| * then found eventfd is completed, so call ->handle_event() |
| * |
| * 3) inside ->handle_event(), if any io represented by one io |
| * command is completed, ublksrv_complete_io() is called for |
| * this io. |
| * |
| * 4) after returning from ->handle_event(), ubq_daemon will |
| * queue & submit the eventfd io immediately for getting |
| * notification from future event. |
| * |
| * Optional. Only needed if target IO is handled by target its |
| * own pthread context. |
| */ |
| void (*handle_event)(const struct ublksrv_queue *); |
| |
| /** |
| * One typical use case is to flush meta data, which is usually done |
| * in background. So there isn't any tag from libublksrv for this kind |
| * of IOs, and the target code has to request for allocating extra ios |
| * by passing tgt_type->extra_ios and let this callback consume & handle |
| * these extra IOs. |
| * |
| * nr_queued_io: count of queued IOs in ublksrv_reap_events_uring of |
| * this time |
| * |
| * Optional. |
| */ |
| void (*handle_io_background)(const struct ublksrv_queue *, int |
| nr_queued_io); |
| |
| /** |
| * show target specific command line for adding new device |
| * |
| * Be careful: this callback is the only one which is not run from |
| * ublk device daemon task context. |
| */ |
| void (*usage_for_add)(void); |
| |
| /** |
| * initialize this new target, argc/argv includes target specific |
| * command line parameters |
| * |
| * Required. |
| */ |
| int (*init_tgt)(struct ublksrv_dev *, int type, int argc, |
| char *argv[]); |
| |
| /** |
| * Deinitialize this target |
| * |
| * Optional. |
| */ |
| void (*deinit_tgt)(const struct ublksrv_dev *); |
| |
| /** |
| * callback for allocating io buffer |
| * |
| * Optional. |
| */ |
| void *(*alloc_io_buf)(const struct ublksrv_queue *q, int tag, int size); |
| /** |
| * callback for freeing io buffer |
| * |
| * Optional. |
| */ |
| void (*free_io_buf)(const struct ublksrv_queue *q, void *buf, int tag); |
| |
| /** |
| * Called when the ublksrv io_uring is idle. |
| * |
| * Optional. |
| */ |
| void (*idle_fn)(const struct ublksrv_queue *q, bool enter); |
| |
| /** target type */ |
| int type; |
| |
| /** flags required for ublk driver */ |
| unsigned ublk_flags; |
| |
| /** flags required for ublksrv */ |
| unsigned ublksrv_flags; |
| unsigned pad; |
| |
| /** target name */ |
| const char *name; |
| |
| /** |
| * recovery callback for this target |
| * |
| * Required. |
| */ |
| int (*recovery_tgt)(struct ublksrv_dev *, int type); |
| |
| /** |
| * queue_data_ptr points to address of q->priviate_data, so that |
| * we still can pass 'const struct ublksrv_queue *', meantime |
| * queue data can be stored to q->private_data via queue_data_ptr. |
| * |
| * ->init_queue provides one chance to override/init the passed |
| * "queue_data" to ublksrv_queue_init(), "queue_data" is set to |
| * q->private_data before calling ->init_queue() |
| */ |
| int (*init_queue)(const struct ublksrv_queue *, void **queue_data_ptr); |
| |
| /** deinit queue data, counter pair of ->init_queue */ |
| void (*deinit_queue)(const struct ublksrv_queue *); |
| |
| unsigned long reserved[5]; |
| }; |
| |
| /** |
| * Build sqe->user_data. |
| * |
| * io_uring relies on ->user_data to map cqe to the submitted io represented by |
| * sqe, encodes ublk interested info into ->user_data for handling IO |
| * completion efficiently. |
| * |
| * @param tag ublk io tag |
| * @param op operation code of submitted io |
| * @param tgt_data target data for this io |
| * @param is_taget_io is this one target io, and it should be true for target, |
| * and false for ublksrv built uring command, which is for communicating |
| * with ublk_drv |
| */ |
| static inline __u64 build_user_data(unsigned tag, unsigned op, |
| unsigned tgt_data, unsigned is_target_io) |
| { |
| assert(!(tag >> 16) && !(op >> 8) && !(tgt_data >> 16)); |
| |
| return tag | (op << 16) | (tgt_data << 24) | (__u64)is_target_io << 63; |
| } |
| |
| static inline unsigned int user_data_to_tag(__u64 user_data) |
| { |
| return user_data & 0xffff; |
| } |
| |
| static inline unsigned int user_data_to_op(__u64 user_data) |
| { |
| return (user_data >> 16) & 0xff; |
| } |
| |
| static inline unsigned int user_data_to_tgt_data(__u64 user_data) |
| { |
| return (user_data >> 24) & 0xffff; |
| } |
| |
| static inline __u64 ublk_pos(__u16 q_id, __u16 tag, __u32 offset) |
| { |
| assert(!(offset & ~UBLK_IO_BUF_BITS_MASK)); |
| |
| return UBLKSRV_IO_BUF_OFFSET + |
| ((((__u64)q_id) << UBLK_QID_OFF) | |
| (((__u64)tag) << UBLK_TAG_OFF) | (__u64)offset); |
| } |
| |
| /** |
| * \defgroup ctrl_dev control device API |
| * |
| * Most of APIs are for sending command to ublk control device(/dev/ublk-control), |
| * and some of them are just for device management purpose, such as, retrieving |
| * device json buffer, run_dir, prepare for recovering, get cached device info ... |
| * |
| * Almost all these APIs can be called in random context by random io uring |
| * context |
| * |
| * @{ |
| */ |
| |
| /** |
| * Deinit one control device |
| * |
| * @param dev the ublksrv control device instance |
| * |
| */ |
| extern void ublksrv_ctrl_deinit(struct ublksrv_ctrl_dev *dev); |
| |
| /** |
| * Allocate and init one control device |
| * |
| * @param data data for allocating & initializing this control device |
| * |
| */ |
| extern struct ublksrv_ctrl_dev *ublksrv_ctrl_init(struct ublksrv_dev_data *data); |
| |
| /** |
| * Retrieve and store each queue's cpu affinity info into private data of the |
| * control device by sending commands to ublk control device |
| * |
| * @param ctrl_dev the ublksrv control device instance |
| * |
| */ |
| extern int ublksrv_ctrl_get_affinity(struct ublksrv_ctrl_dev *ctrl_dev); |
| |
| /** |
| * Add one ublk device by sending command to ublk driver |
| * |
| * @param dev the ublksrv control device instance |
| */ |
| extern int ublksrv_ctrl_add_dev(struct ublksrv_ctrl_dev *dev); |
| |
| /** |
| * Delete this ublk device by sending command to ublk driver |
| * |
| * @param dev the ublksrv control device instance |
| */ |
| extern int ublksrv_ctrl_del_dev(struct ublksrv_ctrl_dev *dev); |
| |
| /** |
| * Delete this ublk device asynchronously by sending command to ublk driver |
| * |
| * @param dev the ublksrv control device instance |
| */ |
| extern int ublksrv_ctrl_del_dev_async(struct ublksrv_ctrl_dev *dev); |
| |
| /** |
| * Retrieve ublk device info by sending command to ublk control device |
| * |
| * @param dev the ublksrv control device instance |
| */ |
| extern int ublksrv_ctrl_get_info(struct ublksrv_ctrl_dev *dev); |
| |
| /** |
| * Stop the specified ublk device by sending command to ublk control device |
| * |
| * @param dev the ublksrv control device instance |
| */ |
| extern int ublksrv_ctrl_stop_dev(struct ublksrv_ctrl_dev *dev); |
| |
| /** |
| * Dump this ublk device |
| * |
| * @param dev the ublksrv control device instance |
| * @param buf ublk device json buffer, optional |
| */ |
| extern void ublksrv_ctrl_dump(struct ublksrv_ctrl_dev *dev, const char *buf); |
| |
| /** |
| * Start this ublk device by sending command to ublk control device |
| * |
| * @param ctrl_dev the ublksrv control device instance |
| * @param daemon_pid pid of the ublksrv process |
| */ |
| extern int ublksrv_ctrl_start_dev(struct ublksrv_ctrl_dev *ctrl_dev, |
| int daemon_pid); |
| |
| /** |
| * Set specified device parameter by sending command to ublk control device |
| * |
| * @param dev the ublksrv control device instance |
| * @param params the specified parameter for setting device |
| */ |
| extern int ublksrv_ctrl_set_params(struct ublksrv_ctrl_dev *dev, |
| struct ublk_params *params); |
| |
| /** |
| * Get specified device parameter by sending command to ublk control device |
| * |
| * @param dev the ublksrv control device instance |
| * @param params the parameter buffer for storing the device parameter |
| */ |
| extern int ublksrv_ctrl_get_params(struct ublksrv_ctrl_dev *dev, |
| struct ublk_params *params); |
| |
| /** |
| * Start to recovery device by sending command to ublk control device |
| * |
| * @param dev the ublksrv control device instance |
| */ |
| extern int ublksrv_ctrl_start_recovery(struct ublksrv_ctrl_dev *dev); |
| |
| /** |
| * End recovery device by sending command to ublk control device |
| * |
| * Once this command is successful, the device is recovered to normal state |
| * |
| * @param dev the ublksrv control device instance |
| * @param daemon_pid pid of the new ublksrv process |
| */ |
| extern int ublksrv_ctrl_end_recovery(struct ublksrv_ctrl_dev *dev, |
| int daemon_pid); |
| |
| /** |
| * Return cached device info for this device |
| * |
| * @param dev the ublksrv control device instance |
| */ |
| extern const struct ublksrv_ctrl_dev_info *ublksrv_ctrl_get_dev_info( |
| const struct ublksrv_ctrl_dev *dev); |
| |
| /** |
| * Return feature set supported by ublk driver |
| * |
| * @features points to buffer for holding the returned features |
| */ |
| extern int ublksrv_ctrl_get_features(struct ublksrv_ctrl_dev *dev, |
| __u64 *features); |
| |
| /** |
| * Return run dir of ublk device |
| * |
| * Device pid file and json string stored under this dir |
| * |
| * @param dev the ublksrv control device instance |
| */ |
| extern const char *ublksrv_ctrl_get_run_dir(const struct ublksrv_ctrl_dev *dev); |
| |
| /** |
| * Prepare for starting to recovery device |
| * |
| * Setup target type, run_dir and json buffer before starting to recovery device. |
| * |
| * @param dev the ublksrv control device instance |
| * @param tgt_type target type name of this device |
| * @param tgt_ops target type of this devie |
| * @param recovery_jbuf points to device json buffer |
| */ |
| extern void ublksrv_ctrl_prep_recovery(struct ublksrv_ctrl_dev *dev, |
| const char *tgt_type, const struct ublksrv_tgt_type *tgt_ops, |
| const char *recovery_jbuf); |
| |
| /** |
| * Return device's json buffer |
| * |
| * Setup target type, run_dir and json buffer before starting to recovery device. |
| * |
| * @param dev the ublksrv control device instance |
| */ |
| extern const char *ublksrv_ctrl_get_recovery_jbuf(const struct ublksrv_ctrl_dev *dev); |
| |
| /** |
| * Return true if this control device is for recovering |
| * |
| * @param dev the ublksrv control device instance |
| */ |
| extern bool ublksrv_is_recovering(const struct ublksrv_ctrl_dev *ctrl_dev); |
| |
| /** @} */ // end of ctrl_dev group |
| |
| |
| /** |
| * \defgroup ublksrv_dev ublksrv device API |
| * |
| * ublksrv device ("/dev/ublkcN") level APIs, and ublksrv device focuses on |
| * IO handling related function |
| * |
| * All APIs in this group should be called in ublksrv daemon process context |
| * |
| * @{ |
| */ |
| |
| /** |
| * Allocate and initialize ublksrv device |
| * |
| * @param ctrl_dev the ublksrv control device instance |
| */ |
| extern const struct ublksrv_dev *ublksrv_dev_init(const struct ublksrv_ctrl_dev * |
| ctrl_dev); |
| |
| /** |
| * Deinitialize and free ublksrv device |
| * |
| * @param dev the ublksrv device instance |
| */ |
| extern void ublksrv_dev_deinit(const struct ublksrv_dev *dev); |
| |
| /** |
| * Return the associated ublksrv control device instance |
| * |
| * @param dev the ublksrv device instance |
| */ |
| extern const struct ublksrv_ctrl_dev *ublksrv_get_ctrl_dev( |
| const struct ublksrv_dev *dev); |
| |
| /** |
| * Return pid file FD of this ublksrv device |
| * |
| * @param dev the ublksrv device instance |
| */ |
| extern int ublksrv_get_pidfile_fd(const struct ublksrv_dev *dev); |
| |
| /** |
| * Set completion queue depth of this ublksrv device |
| * |
| * @param dev the ublksrv device instance |
| * @param cq_depth depth of the completion queue of io_uring |
| */ |
| extern void ublksrv_dev_set_cq_depth(struct ublksrv_dev *dev, int cq_depth); |
| |
| /** |
| * Get completion queue depth of this ublksrv device |
| * |
| * @param dev the ublksrv device instance |
| */ |
| extern int ublksrv_dev_get_cq_depth(struct ublksrv_dev *dev); |
| |
| /** |
| * |
| * Apply OOM porotection |
| */ |
| extern void ublksrv_apply_oom_protection(void); |
| |
| /** @} */ // end of ublksrv_dev group |
| |
| /* target json has to include the following key/value */ |
| #define UBLKSRV_TGT_NAME_MAX_LEN 32 |
| struct ublksrv_tgt_base_json { |
| char name[UBLKSRV_TGT_NAME_MAX_LEN]; |
| int type; |
| unsigned int pad; |
| unsigned long long dev_size; |
| unsigned long reserved[8]; |
| }; |
| |
| /** |
| * \defgroup ublksrv_json ublksrv json string API |
| * |
| * ublksrv json string APIs |
| * |
| * APIs for serializing/deserializing device data to/from json string |
| * |
| * @{ |
| */ |
| |
| /** |
| * Serialize json buffer from device's ublksrv_ctrl_dev_info data |
| * |
| * @param dev the ublksrv control device instance |
| * @param buf json buffer |
| * @param len length of json buffer |
| */ |
| extern int ublksrv_json_write_dev_info(const struct ublksrv_ctrl_dev *dev, |
| char *buf, int len); |
| |
| /** |
| * Deserialize json buffer to ublksrv_ctrl_dev_info instance |
| * |
| * @param json_buf json buffer |
| * @param info device info for storing the parsed ublksrv_ctrl_dev_info |
| */ |
| extern int ublksrv_json_read_dev_info(const char *json_buf, |
| struct ublksrv_ctrl_dev_info *info); |
| |
| /** |
| * Serialize json buffer from ublksrv queue |
| * |
| * @param dev the ublksrv control device instance |
| * @param jbuf json buffer |
| * @param len length of json buffer |
| * @param qid queue id |
| * @param ubq_daemon_tid queue pthread tid |
| */ |
| extern int ublksrv_json_write_queue_info(const struct ublksrv_ctrl_dev *dev, |
| char *jbuf, int len, int qid, int ubq_daemon_tid); |
| |
| /** |
| * Deserialize json buffer to ublksrv queue |
| * |
| * @param jbuf json buffer |
| * @param qid queue id |
| * @param tid queue pthread tid |
| * @param affinity_buf queue affinity buffer |
| * @param len length of json buffer |
| */ |
| extern int ublksrv_json_read_queue_info(const char *jbuf, int qid, |
| unsigned *tid, char *affinity_buf, int len); |
| |
| /** |
| * Deserialize json buffer to target data |
| * |
| * @param jbuf json buffer |
| * @param tgt_buf target buffer |
| * @param len length of json buffer |
| */ |
| extern int ublksrv_json_read_target_info(const char *jbuf, char *tgt_buf, |
| int len); |
| |
| /** |
| * Deserialize json buffer to target string field |
| * |
| * @param jbuf json buffer |
| * @param len length of json buffer |
| * @param name string name |
| * @param val string value |
| */ |
| extern int ublksrv_json_read_target_str_info(const char *jbuf, int len, |
| const char *name, char *val); |
| |
| /** |
| * Deserialize json buffer to target ulong field |
| * |
| * @param jbuf json buffer |
| * @param name field name with ulong type |
| * @param val field value with ulong type |
| */ |
| extern int ublksrv_json_read_target_ulong_info(const char *jbuf, |
| const char *name, long *val); |
| |
| /** |
| * Serialize json buffer from target field with string type |
| * |
| * @param jbuf json buffer |
| * @param len length of json buffer |
| * @param name field name with string type |
| * @param val field value with string type |
| */ |
| extern int ublksrv_json_write_target_str_info(char *jbuf, int len, |
| const char *name, const char *val); |
| |
| extern int ublksrv_json_write_target_long_info(char *jbuf, int len, |
| const char *name, long val); |
| |
| /** |
| * Serialize json buffer from target field with ulong type |
| * |
| * @param jbuf json buffer |
| * @param len length of json buffer |
| * @param name field name with ulong type |
| * @param val field value with ulong type |
| */ |
| extern int ublksrv_json_write_target_ulong_info(char *jbuf, int len, |
| const char *name, unsigned long val); |
| |
| extern void ublksrv_json_dump(const char *jbuf); |
| |
| /** |
| * Deserialize json buffer to ublksrv_tgt_base_json instance |
| * |
| * @param jbuf json buffer |
| * @param tgt ublksrv_tgt_base_json instance |
| */ |
| extern int ublksrv_json_read_target_base_info(const char *jbuf, |
| struct ublksrv_tgt_base_json *tgt); |
| |
| /** |
| * Serialize json buffer from ublksrv_tgt_base_json |
| * |
| * @param jbuf json buffer |
| * @param len length of json buffer |
| * @param tgt ublksrv_tgt_base_json instance |
| */ |
| extern int ublksrv_json_write_target_base_info(char *jbuf, int len, |
| const struct ublksrv_tgt_base_json *tgt); |
| |
| /** |
| * Deserialize json buffer to ublk_params instance |
| * |
| * @param p ublk_params instance |
| * @param jbuf json buffer |
| */ |
| extern int ublksrv_json_read_params(struct ublk_params *p, |
| const char *jbuf); |
| |
| /** |
| * Serialize json buffer from ublk_params instance |
| * |
| * @param p ublk_params instance |
| * @param jbuf json buffer |
| * @param len length of json buffer |
| */ |
| extern int ublksrv_json_write_params(const struct ublk_params *p, |
| char *jbuf, int len); |
| extern int ublksrv_json_dump_params(const char *jbuf); |
| |
| /** |
| * Return actual length of the json buffer |
| * |
| * @param jbuf json buffer |
| */ |
| extern int ublksrv_json_get_length(const char *jbuf); |
| |
| /** @} */ // end of ublksrv_json group |
| |
| /** |
| * \defgroup ublksrv_queue ublksrv queue API |
| * |
| * ublksrv queue level APIs |
| * |
| * All APIs in this group is supposed to be called in the queue context |
| * |
| * @{ |
| */ |
| |
| /** |
| * Return the specified io private data |
| * |
| * Each IO has unique tag, so we use tag to represent specified io. |
| * |
| * Inside ->init_tgt() callback, target code sets io private data |
| * size via dev->tgt.io_data_size, then io private data will be allocated |
| * in ublksrv_queue_init(). The allocated io private data is very useful |
| * to store target specific io data, then runtime memory allocation in io |
| * handling code path can be avoided. |
| * |
| * @param q the ublksrv queue instance |
| * @param tag tag for this io |
| */ |
| extern void *ublksrv_io_private_data(const struct ublksrv_queue *q, int tag); |
| |
| /** |
| * Return the specified io generic io data |
| * |
| * Each IO has unique tag, so we use tag to represent specified io. |
| * |
| * @param q the ublksrv queue instance |
| * @param tag tag for this io |
| * @return 'struct ublk_io_data' instance, which is for storing io descriptor, |
| * tag, and private data |
| */ |
| extern const struct ublk_io_data *ublksrv_queue_get_io_data( |
| const struct ublksrv_queue *q, int tag); |
| |
| /** |
| * Return pre-allocated io buffer |
| * |
| * Each IO has unique tag, so we use tag to represent specified io. |
| * |
| * @param q the ublksrv queue instance |
| * @param tag tag for this io |
| * @return pre-allocated io buffer for this io |
| */ |
| extern void *ublksrv_queue_get_io_buf(const struct ublksrv_queue *q, int tag); |
| |
| /** |
| * Return current queue state |
| * |
| * queue state is usually for debug purpose |
| * |
| * @param q the ublksrv queue instance |
| * @return queue current state |
| */ |
| extern unsigned int ublksrv_queue_state(const struct ublksrv_queue *q); |
| |
| /** |
| * Allocate and initialize ublksrv queue instance |
| * |
| * @param dev the ublksrv device instance |
| * @param q_id queue id |
| * @param queue_data queue private data |
| */ |
| extern const struct ublksrv_queue *ublksrv_queue_init(const struct ublksrv_dev *dev, |
| unsigned short q_id, void *queue_data); |
| |
| /** |
| * Deinit & free ublksrv queue instance |
| * |
| * @param q the ublksrv queue instance |
| */ |
| extern void ublksrv_queue_deinit(const struct ublksrv_queue *q); |
| |
| /** |
| * Return how many unconsumed cqes in CQ of queue uring |
| * |
| * @param q the ublksrv queue instance |
| * |
| * Return -1 if uring isn't setup correctly |
| */ |
| extern int ublksrv_queue_unconsumed_cqes(const struct ublksrv_queue *q); |
| |
| extern int ublksrv_queue_handled_event(const struct ublksrv_queue *q); |
| extern int ublksrv_queue_send_event(const struct ublksrv_queue *q); |
| |
| /** |
| * Return the specified queue instance by ublksrv device and qid |
| * |
| * Retrieve queue instance by ublksrv device and queue id |
| * |
| * @param dev the ublksrv device instance |
| * @param q_id queue id |
| */ |
| extern const struct ublksrv_queue *ublksrv_get_queue(const struct ublksrv_dev *dev, |
| int q_id); |
| |
| /** |
| * Process target IO & IO command from this queue's io_uring |
| * |
| * Handle incoming io command by calling target ->handle_io_async(), or |
| * call ->tgt_io_done() if target IO is completed. |
| * |
| * It is the engine of libulksrv, almost everything is driven by this |
| * API. |
| * |
| * @param q the ublksrv queue instance |
| */ |
| extern int ublksrv_process_io(const struct ublksrv_queue *q); |
| |
| /** |
| * Complete specified io with result of 'res' |
| * |
| * This API will tell ublk driver via /dev/ublkcN that this IO is completed. |
| * |
| * @param q the ublksrv queue instance |
| * @param tag the io to be completed |
| * @param res io result |
| */ |
| extern int ublksrv_complete_io(const struct ublksrv_queue *q, unsigned tag, int res); |
| /** @} */ // end of ublksrv_queue group |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| #endif |