#include <linux/module.h>
#include <linux/moduleparam.h>
#include <generated/utsrelease.h>
#include <linux/utsname.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/kthread.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/configfs.h>
#include <linux/ctype.h>
#include <linux/compat.h>
#include <linux/eventfd.h>
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <linux/miscdevice.h>
#include <linux/blk_types.h>
#include <linux/bio.h>
#include <linux/unaligned.h>
#include <scsi/scsi_common.h>
#include <scsi/scsi_proto.h>
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
#include <linux/vhost.h>
#include <linux/virtio_scsi.h>
#include <linux/llist.h>
#include <linux/bitmap.h>
#include "vhost.h"
#define VHOST_SCSI_VERSION …
#define VHOST_SCSI_NAMELEN …
#define VHOST_SCSI_MAX_CDB_SIZE …
#define VHOST_SCSI_PREALLOC_SGLS …
#define VHOST_SCSI_PREALLOC_UPAGES …
#define VHOST_SCSI_PREALLOC_PROT_SGLS …
#define VHOST_SCSI_WEIGHT …
struct vhost_scsi_inflight { … };
struct vhost_scsi_cmd { … };
struct vhost_scsi_nexus { … };
struct vhost_scsi_tpg { … };
struct vhost_scsi_tport { … };
struct vhost_scsi_evt { … };
enum { … };
enum { … };
#define VHOST_SCSI_MAX_TARGET …
#define VHOST_SCSI_MAX_IO_VQ …
#define VHOST_SCSI_MAX_EVENT …
static unsigned vhost_scsi_max_io_vqs = …;
module_param_named(max_io_vqs, vhost_scsi_max_io_vqs, uint, 0644);
MODULE_PARM_DESC(…) …;
struct vhost_scsi_virtqueue { … };
struct vhost_scsi { … };
struct vhost_scsi_tmf { … };
struct vhost_scsi_ctx { … };
static DEFINE_MUTEX(vhost_scsi_mutex);
static LIST_HEAD(vhost_scsi_list);
static void vhost_scsi_done_inflight(struct kref *kref)
{ … }
static void vhost_scsi_init_inflight(struct vhost_scsi *vs,
struct vhost_scsi_inflight *old_inflight[])
{ … }
static struct vhost_scsi_inflight *
vhost_scsi_get_inflight(struct vhost_virtqueue *vq)
{ … }
static void vhost_scsi_put_inflight(struct vhost_scsi_inflight *inflight)
{ … }
static int vhost_scsi_check_true(struct se_portal_group *se_tpg)
{ … }
static char *vhost_scsi_get_fabric_wwn(struct se_portal_group *se_tpg)
{ … }
static u16 vhost_scsi_get_tpgt(struct se_portal_group *se_tpg)
{ … }
static int vhost_scsi_check_prot_fabric_only(struct se_portal_group *se_tpg)
{ … }
static void vhost_scsi_release_cmd_res(struct se_cmd *se_cmd)
{ … }
static void vhost_scsi_release_tmf_res(struct vhost_scsi_tmf *tmf)
{ … }
static void vhost_scsi_drop_cmds(struct vhost_scsi_virtqueue *svq)
{ … }
static void vhost_scsi_release_cmd(struct se_cmd *se_cmd)
{ … }
static int vhost_scsi_write_pending(struct se_cmd *se_cmd)
{ … }
static int vhost_scsi_queue_data_in(struct se_cmd *se_cmd)
{ … }
static int vhost_scsi_queue_status(struct se_cmd *se_cmd)
{ … }
static void vhost_scsi_queue_tm_rsp(struct se_cmd *se_cmd)
{ … }
static void vhost_scsi_aborted_task(struct se_cmd *se_cmd)
{ … }
static void vhost_scsi_free_evt(struct vhost_scsi *vs, struct vhost_scsi_evt *evt)
{ … }
static struct vhost_scsi_evt *
vhost_scsi_allocate_evt(struct vhost_scsi *vs,
u32 event, u32 reason)
{ … }
static int vhost_scsi_check_stop_free(struct se_cmd *se_cmd)
{ … }
static void
vhost_scsi_do_evt_work(struct vhost_scsi *vs, struct vhost_scsi_evt *evt)
{ … }
static void vhost_scsi_complete_events(struct vhost_scsi *vs, bool drop)
{ … }
static void vhost_scsi_evt_work(struct vhost_work *work)
{ … }
static int vhost_scsi_copy_sgl_to_iov(struct vhost_scsi_cmd *cmd)
{ … }
static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
{ … }
static struct vhost_scsi_cmd *
vhost_scsi_get_cmd(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg,
unsigned char *cdb, u64 scsi_tag, u16 lun, u8 task_attr,
u32 exp_data_len, int data_direction)
{ … }
static int
vhost_scsi_map_to_sgl(struct vhost_scsi_cmd *cmd,
struct iov_iter *iter,
struct scatterlist *sgl,
bool is_prot)
{ … }
static int
vhost_scsi_calc_sgls(struct iov_iter *iter, size_t bytes, int max_sgls)
{ … }
static int
vhost_scsi_copy_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter,
struct scatterlist *sg, int sg_count)
{ … }
static int
vhost_scsi_map_iov_to_sgl(struct vhost_scsi_cmd *cmd, struct iov_iter *iter,
struct scatterlist *sg, int sg_count, bool is_prot)
{ … }
static int
vhost_scsi_mapal(struct vhost_scsi_cmd *cmd,
size_t prot_bytes, struct iov_iter *prot_iter,
size_t data_bytes, struct iov_iter *data_iter)
{ … }
static int vhost_scsi_to_tcm_attr(int attr)
{ … }
static void vhost_scsi_target_queue_cmd(struct vhost_scsi_cmd *cmd)
{ … }
static void
vhost_scsi_send_bad_target(struct vhost_scsi *vs,
struct vhost_virtqueue *vq,
int head, unsigned out)
{ … }
static int
vhost_scsi_get_desc(struct vhost_scsi *vs, struct vhost_virtqueue *vq,
struct vhost_scsi_ctx *vc)
{ … }
static int
vhost_scsi_chk_size(struct vhost_virtqueue *vq, struct vhost_scsi_ctx *vc)
{ … }
static int
vhost_scsi_get_req(struct vhost_virtqueue *vq, struct vhost_scsi_ctx *vc,
struct vhost_scsi_tpg **tpgp)
{ … }
static u16 vhost_buf_to_lun(u8 *lun_buf)
{ … }
static void
vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
{ … }
static void
vhost_scsi_send_tmf_resp(struct vhost_scsi *vs, struct vhost_virtqueue *vq,
int in_iovs, int vq_desc, struct iovec *resp_iov,
int tmf_resp_code)
{ … }
static void vhost_scsi_tmf_resp_work(struct vhost_work *work)
{ … }
static void vhost_scsi_tmf_flush_work(struct work_struct *work)
{ … }
static void
vhost_scsi_handle_tmf(struct vhost_scsi *vs, struct vhost_scsi_tpg *tpg,
struct vhost_virtqueue *vq,
struct virtio_scsi_ctrl_tmf_req *vtmf,
struct vhost_scsi_ctx *vc)
{ … }
static void
vhost_scsi_send_an_resp(struct vhost_scsi *vs,
struct vhost_virtqueue *vq,
struct vhost_scsi_ctx *vc)
{ … }
static void
vhost_scsi_ctl_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
{ … }
static void vhost_scsi_ctl_handle_kick(struct vhost_work *work)
{ … }
static void
vhost_scsi_send_evt(struct vhost_scsi *vs, struct vhost_virtqueue *vq,
struct vhost_scsi_tpg *tpg, struct se_lun *lun,
u32 event, u32 reason)
{ … }
static void vhost_scsi_evt_handle_kick(struct vhost_work *work)
{ … }
static void vhost_scsi_handle_kick(struct vhost_work *work)
{ … }
static void vhost_scsi_flush(struct vhost_scsi *vs)
{ … }
static void vhost_scsi_destroy_vq_cmds(struct vhost_virtqueue *vq)
{ … }
static int vhost_scsi_setup_vq_cmds(struct vhost_virtqueue *vq, int max_cmds)
{ … }
static int
vhost_scsi_set_endpoint(struct vhost_scsi *vs,
struct vhost_scsi_target *t)
{ … }
static int
vhost_scsi_clear_endpoint(struct vhost_scsi *vs,
struct vhost_scsi_target *t)
{ … }
static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
{ … }
static int vhost_scsi_open(struct inode *inode, struct file *f)
{ … }
static int vhost_scsi_release(struct inode *inode, struct file *f)
{ … }
static long
vhost_scsi_ioctl(struct file *f,
unsigned int ioctl,
unsigned long arg)
{ … }
static const struct file_operations vhost_scsi_fops = …;
static struct miscdevice vhost_scsi_misc = …;
static int __init vhost_scsi_register(void)
{ … }
static void vhost_scsi_deregister(void)
{ … }
static char *vhost_scsi_dump_proto_id(struct vhost_scsi_tport *tport)
{ … }
static void
vhost_scsi_do_plug(struct vhost_scsi_tpg *tpg,
struct se_lun *lun, bool plug)
{ … }
static void vhost_scsi_hotplug(struct vhost_scsi_tpg *tpg, struct se_lun *lun)
{ … }
static void vhost_scsi_hotunplug(struct vhost_scsi_tpg *tpg, struct se_lun *lun)
{ … }
static int vhost_scsi_port_link(struct se_portal_group *se_tpg,
struct se_lun *lun)
{ … }
static void vhost_scsi_port_unlink(struct se_portal_group *se_tpg,
struct se_lun *lun)
{ … }
static ssize_t vhost_scsi_tpg_attrib_fabric_prot_type_store(
struct config_item *item, const char *page, size_t count)
{ … }
static ssize_t vhost_scsi_tpg_attrib_fabric_prot_type_show(
struct config_item *item, char *page)
{ … }
CONFIGFS_ATTR(…);
static struct configfs_attribute *vhost_scsi_tpg_attrib_attrs[] = …;
static int vhost_scsi_make_nexus(struct vhost_scsi_tpg *tpg,
const char *name)
{ … }
static int vhost_scsi_drop_nexus(struct vhost_scsi_tpg *tpg)
{ … }
static ssize_t vhost_scsi_tpg_nexus_show(struct config_item *item, char *page)
{ … }
static ssize_t vhost_scsi_tpg_nexus_store(struct config_item *item,
const char *page, size_t count)
{ … }
CONFIGFS_ATTR(…);
static struct configfs_attribute *vhost_scsi_tpg_attrs[] = …;
static struct se_portal_group *
vhost_scsi_make_tpg(struct se_wwn *wwn, const char *name)
{ … }
static void vhost_scsi_drop_tpg(struct se_portal_group *se_tpg)
{ … }
static struct se_wwn *
vhost_scsi_make_tport(struct target_fabric_configfs *tf,
struct config_group *group,
const char *name)
{ … }
static void vhost_scsi_drop_tport(struct se_wwn *wwn)
{ … }
static ssize_t
vhost_scsi_wwn_version_show(struct config_item *item, char *page)
{ … }
CONFIGFS_ATTR_RO(…);
static struct configfs_attribute *vhost_scsi_wwn_attrs[] = …;
static const struct target_core_fabric_ops vhost_scsi_ops = …;
static int __init vhost_scsi_init(void)
{
int ret = -ENOMEM;
pr_debug("TCM_VHOST fabric module %s on %s/%s"
" on "UTS_RELEASE"\n", VHOST_SCSI_VERSION, utsname()->sysname,
utsname()->machine);
ret = vhost_scsi_register();
if (ret < 0)
goto out;
ret = target_register_template(&vhost_scsi_ops);
if (ret < 0)
goto out_vhost_scsi_deregister;
return 0;
out_vhost_scsi_deregister:
vhost_scsi_deregister();
out:
return ret;
};
static void vhost_scsi_exit(void)
{
target_unregister_template(&vhost_scsi_ops);
vhost_scsi_deregister();
};
MODULE_DESCRIPTION(…) …;
MODULE_ALIAS(…) …;
MODULE_LICENSE(…) …;
module_init(…) …;
module_exit(vhost_scsi_exit);