[RFC PATCH 15/19] Target_Core_Mod Storage Engine Objectinfrastructure

From: Nicholas A. Bellinger
Date: Sun Apr 05 2009 - 00:09:16 EST


This patch adds the storage engine object (SEObject) infrastructure used by
target_core_mod for accessing allocated se_device_t objects.

Signed-off-by: Nicholas A. Bellinger <nab@xxxxxxxxxxxxxxx>

diff --git a/drivers/target/target_core_seobj.c b/drivers/target/target_core_seobj.c
new file mode 100644
index 0000000..519749b
--- /dev/null
+++ b/drivers/target/target_core_seobj.c
@@ -0,0 +1,679 @@
+/*******************************************************************************
+ * Filename: target_core_seobj.c
+ *
+ * Copyright (c) 2006-2007 SBE, Inc. All Rights Reserved.
+ * Copyright (c) 2007-2009 Rising Tide Software, Inc.
+ * Copyright (c) 2008-2009 Linux-iSCSI.org
+ *
+ * Nicholas A. Bellinger <nab@xxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ ******************************************************************************/
+
+
+#define TARGET_CORE_SEOBJ_C
+
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
+#include <linux/in.h>
+#include <scsi/scsi.h>
+
+#include <target/target_core_base.h>
+#include <target/target_core_device.h>
+#include <target/target_core_hba.h>
+#include <target/target_core_tpg.h>
+#include <target/target_core_transport.h>
+#include <target/target_core_plugin.h>
+#include <target/target_core_seobj.h>
+#include <target/target_core_fabric_ops.h>
+#include <target/target_core_configfs.h>
+
+#undef TARGET_CORE_SEOBJ_C
+
+#define MAKE_OBJ_TYPE(type, op1, op2) \
+void type##_obj_##op1##_count(struct se_obj_s *obj) \
+{ \
+ atomic_##op2(&obj->obj_access_count); \
+}
+
+#define MAKE_OBJ_TYPE_RET(type) \
+int type##_obj_check_count(struct se_obj_s *obj) \
+{ \
+ return atomic_read(&obj->obj_access_count); \
+}
+
+MAKE_OBJ_TYPE(dev, inc, inc);
+MAKE_OBJ_TYPE(dev, dec, dec);
+MAKE_OBJ_TYPE_RET(dev);
+
+void dev_obj_get_obj_info(
+ void *p,
+ se_lun_t *lun,
+ unsigned long long bytes,
+ int state,
+ char *b,
+ int *bl)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ if (state)
+ transport_dump_dev_state(dev, b, bl);
+ transport_dump_dev_info((se_device_t *)p, lun, bytes, b, bl);
+}
+
+void dev_obj_get_plugin_info(void *p, char *b, int *bl)
+{
+ *bl += sprintf(b + *bl, "%s Device Object Plugin %s\n",
+ PYX_ISCSI_VENDOR, DEV_OBJ_VERSION);
+}
+
+void *dev_obj_get_obj(void *p)
+{
+ return p;
+}
+
+se_queue_obj_t *dev_obj_get_queue_obj(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ return dev->dev_queue_obj;
+}
+
+int dev_obj_claim_obj(void *p)
+{
+ return transport_generic_claim_phydevice((se_device_t *)p);
+}
+
+void dev_obj_release_obj(void *p)
+{
+ transport_generic_release_phydevice((se_device_t *)p, 1);
+}
+
+void dev_access_obj(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ DEV_OBJ_API(dev)->inc_count(&dev->dev_access_obj);
+}
+
+void dev_deaccess_obj(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ DEV_OBJ_API(dev)->dec_count(&dev->dev_access_obj);
+}
+
+void dev_put_obj(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ core_put_hba(dev->se_hba);
+}
+
+int dev_obj_export(void *p, se_portal_group_t *tpg, se_lun_t *lun)
+{
+ se_device_t *dev = (se_device_t *)p;
+ se_port_t *port;
+
+ port = core_alloc_port(dev);
+ if (!(port))
+ return -1;
+
+ lun->se_dev = dev;
+ if (DEV_OBJ_API(dev)->activate(p) < 0) {
+ lun->se_dev = NULL;
+ kfree(port);
+ return -1;
+ }
+
+ DEV_OBJ_API(dev)->inc_count(&dev->dev_export_obj);
+
+ core_export_port(dev, tpg, port, lun);
+ return 0;
+}
+
+void dev_obj_unexport(void *p, se_portal_group_t *tpg, se_lun_t *lun)
+{
+ se_device_t *dev = (se_device_t *)p;
+ se_port_t *port = lun->lun_sep;
+
+ spin_lock(&dev->se_port_lock);
+ spin_lock(&lun->lun_sep_lock);
+ if (lun->lun_type_ptr == NULL) {
+ spin_unlock(&dev->se_port_lock);
+ spin_unlock(&lun->lun_sep_lock);
+ return;
+ }
+ spin_unlock(&lun->lun_sep_lock);
+
+ DEV_OBJ_API(dev)->dec_count(&dev->dev_export_obj);
+
+ core_release_port(dev, port);
+ spin_unlock(&dev->se_port_lock);
+
+ DEV_OBJ_API(dev)->deactivate(p);
+ lun->se_dev = NULL;
+}
+
+int dev_obj_transport_setup_cmd(void *p, se_cmd_t *cmd)
+{
+ transport_device_setup_cmd(cmd);
+ return 0;
+}
+
+int dev_obj_active_tasks(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ return atomic_read(&dev->execute_tasks);
+}
+
+int dev_obj_add_tasks(void *p, se_cmd_t *cmd)
+{
+ transport_add_tasks_from_cmd(cmd);
+ return 0;
+}
+
+int dev_obj_execute_tasks(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ __transport_execute_tasks(dev);
+ return 0;
+}
+
+int dev_obj_depth_left(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ return atomic_read(&dev->depth_left);
+}
+
+int dev_obj_queue_depth(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ return dev->queue_depth;
+}
+
+int dev_obj_blocksize(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ return DEV_ATTRIB(dev)->block_size;
+}
+
+int dev_obj_max_sectors(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ if (TRANSPORT(dev)->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
+ return (DEV_ATTRIB(dev)->max_sectors >
+ TRANSPORT(dev)->get_max_sectors(dev) ?
+ TRANSPORT(dev)->get_max_sectors(dev) :
+ DEV_ATTRIB(dev)->max_sectors);
+ } else
+ return DEV_ATTRIB(dev)->max_sectors;
+}
+
+unsigned long long dev_obj_end_lba(void *p, int zero_lba)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ return dev->dev_sectors_total + ((zero_lba) ? 1 : 0);
+}
+
+unsigned long long dev_obj_get_next_lba(void *p, unsigned long long lba)
+{
+ return lba;
+}
+
+unsigned long long dev_obj_total_sectors(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ return dev->dev_sectors_total + 1;
+}
+
+int dev_obj_do_se_mem_map(
+ void *p,
+ se_task_t *task,
+ struct list_head *se_mem_list,
+ void *in_mem,
+ se_mem_t *in_se_mem,
+ se_mem_t **out_se_mem,
+ u32 *se_mem_cnt,
+ u32 *task_offset)
+{
+ se_device_t *dev = (se_device_t *)p;
+ u32 tmp_task_offset = *task_offset;
+ int ret = 0;
+
+ /*
+ * se_subsystem_api_t->do_se_mem_map is used when internal allocation
+ * has been done by the transport plugin.
+ */
+ if (TRANSPORT(dev)->do_se_mem_map) {
+ ret = TRANSPORT(dev)->do_se_mem_map(task, se_mem_list,
+ in_mem, in_se_mem, out_se_mem, se_mem_cnt,
+ task_offset);
+ if (ret == 0)
+ T_TASK(task->task_se_cmd)->t_task_se_num += *se_mem_cnt;
+
+ return ret;
+ }
+
+ /*
+ * Assume default that transport plugin speaks preallocated
+ * scatterlists.
+ */
+ if (!(transport_calc_sg_num(task, in_se_mem, tmp_task_offset)))
+ return -1;
+
+ /*
+ * se_task_t->task_sg now contains the struct scatterlist array.
+ */
+ return transport_map_mem_to_sg(task, se_mem_list, task->task_sg,
+ in_se_mem, out_se_mem, se_mem_cnt, task_offset);
+}
+
+int dev_obj_get_mem_buf(void *p, se_cmd_t *cmd)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ cmd->transport_allocate_resources = (TRANSPORT(dev)->allocate_buf) ?
+ TRANSPORT(dev)->allocate_buf : &transport_generic_allocate_buf;
+ cmd->transport_free_resources = (TRANSPORT(dev)->free_buf) ?
+ TRANSPORT(dev)->free_buf : NULL;
+
+ return 0;
+}
+
+int dev_obj_get_mem_SG(void *p, se_cmd_t *cmd)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ cmd->transport_allocate_resources = (TRANSPORT(dev)->allocate_DMA) ?
+ TRANSPORT(dev)->allocate_DMA : &transport_generic_get_mem;
+ cmd->transport_free_resources = (TRANSPORT(dev)->free_DMA) ?
+ TRANSPORT(dev)->free_DMA : NULL;
+
+ return 0;
+}
+
+map_func_t dev_obj_get_map_SG(void *p, int rw)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ return (rw == SE_DIRECTION_WRITE) ? dev->transport->spc->write_SG :
+ dev->transport->spc->read_SG;
+}
+
+map_func_t dev_obj_get_map_non_SG(void *p, int rw)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ return (rw == SE_DIRECTION_WRITE) ? dev->transport->spc->write_non_SG :
+ dev->transport->spc->read_non_SG;
+}
+
+map_func_t dev_obj_get_map_none(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ return dev->transport->spc->none;
+}
+
+void *dev_obj_get_transport_req(void *p, se_task_t *task)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ task->se_dev = dev;
+
+ return dev->transport->allocate_request(task, dev);
+}
+
+void dev_obj_free_tasks(void *p, se_cmd_t *cmd)
+{
+ transport_free_dev_tasks(cmd);
+}
+
+int dev_obj_activate(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ se_dev_start(dev);
+ return 0;
+}
+
+void dev_obj_deactivate(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ se_dev_stop(dev);
+}
+
+void dev_obj_notify_obj(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ wake_up_interruptible(&dev->dev_queue_obj->thread_wq);
+}
+
+int dev_obj_check_online(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+ int ret;
+
+ spin_lock(&dev->dev_status_lock);
+ ret = ((dev->dev_status & TRANSPORT_DEVICE_ACTIVATED) ||
+ (dev->dev_status & TRANSPORT_DEVICE_DEACTIVATED)) ? 0 : 1;
+ spin_unlock(&dev->dev_status_lock);
+
+ return ret;
+}
+
+int dev_obj_check_shutdown(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+ int ret;
+
+ spin_lock(&dev->dev_status_lock);
+ ret = (dev->dev_status & TRANSPORT_DEVICE_SHUTDOWN);
+ spin_unlock(&dev->dev_status_lock);
+
+ return ret;
+}
+
+void dev_obj_signal_shutdown(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ spin_lock(&dev->dev_status_lock);
+ if ((dev->dev_status & TRANSPORT_DEVICE_ACTIVATED) ||
+ (dev->dev_status & TRANSPORT_DEVICE_DEACTIVATED) ||
+ (dev->dev_status & TRANSPORT_DEVICE_OFFLINE_ACTIVATED) ||
+ (dev->dev_status & TRANSPORT_DEVICE_OFFLINE_DEACTIVATED)) {
+ dev->dev_status |= TRANSPORT_DEVICE_SHUTDOWN;
+ dev->dev_status &= ~TRANSPORT_DEVICE_ACTIVATED;
+ dev->dev_status &= ~TRANSPORT_DEVICE_DEACTIVATED;
+ dev->dev_status &= ~TRANSPORT_DEVICE_OFFLINE_ACTIVATED;
+ dev->dev_status &= ~TRANSPORT_DEVICE_OFFLINE_DEACTIVATED;
+
+ wake_up_interruptible(&dev->dev_queue_obj->thread_wq);
+ }
+ spin_unlock(&dev->dev_status_lock);
+}
+
+void dev_obj_clear_shutdown(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ spin_lock(&dev->dev_status_lock);
+ if (dev->dev_status & TRANSPORT_DEVICE_SHUTDOWN) {
+ dev->dev_status &= ~TRANSPORT_DEVICE_SHUTDOWN;
+ dev->dev_status |= TRANSPORT_DEVICE_DEACTIVATED;
+ }
+ spin_unlock(&dev->dev_status_lock);
+}
+
+unsigned char *dev_obj_get_cdb(
+ void *p,
+ se_task_t *task)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ return dev->transport->get_cdb(task);
+}
+
+int dev_obj_start(
+ void *p,
+ se_transform_info_t *ti,
+ unsigned long long starting_lba)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ return transport_generic_obj_start(ti, DEV_OBJ_API(dev),
+ p, starting_lba);
+}
+
+u32 dev_obj_get_cdb_count(
+ void *p,
+ se_transform_info_t *ti,
+ unsigned long long lba,
+ u32 sectors,
+ se_mem_t *se_mem_in,
+ se_mem_t **se_mem_out,
+ u32 *task_offset_in)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ ti->ti_dev = dev;
+ return transport_generic_get_cdb_count(ti->ti_se_cmd, ti,
+ DEV_OBJ_API(dev), p, lba, sectors, se_mem_in, se_mem_out,
+ task_offset_in);
+}
+
+u32 dev_obj_get_cdb_size(
+ void *p,
+ u32 sectors,
+ unsigned char *cdb)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ if (TRANSPORT(dev)->get_device_type(dev) == TYPE_TAPE) {
+ if (cdb[1] & 1) { /* sectors */
+ return DEV_ATTRIB(dev)->block_size * sectors;
+ } else /* bytes */
+ return sectors;
+ }
+
+ /* sectors */
+#if 0
+ printk(KERN_INFO "Returning block_size: %u, sectors: %u == %u for"
+ " %s object\n", DEV_ATTRIB(dev)->block_size, sectors,
+ DEV_ATTRIB(dev)->block_size * sectors,
+ TRANSPORT(dev)->name);
+#endif
+ return DEV_ATTRIB(dev)->block_size * sectors;
+}
+
+void dev_obj_generate_cdb(
+ void *p,
+ unsigned long long lba,
+ u32 *sectors,
+ unsigned char *cdb,
+ int rw)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ dev->dev_generate_cdb(lba, sectors, cdb, rw);
+}
+
+int dev_obj_get_device_access(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ return (dev->dev_flags & DF_READ_ONLY) ? 0 : 1;
+}
+
+int dev_obj_get_device_type(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ return TRANSPORT(dev)->get_device_type(dev);
+}
+
+int dev_obj_check_DMA_handler(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ if (!dev->transport) {
+ printk(KERN_ERR "se_device_t->transport is NULL!\n");
+ BUG();
+ }
+
+ return (TRANSPORT(dev)->allocate_DMA != NULL);
+}
+
+t10_wwn_t *dev_obj_get_t10_wwn(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ return DEV_T10_WWN(dev);
+}
+
+int dev_obj_get_task_timeout(void *p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ return DEV_ATTRIB(dev)->task_timeout;
+}
+
+int dev_add_obj_to_lun(se_portal_group_t *tpg, se_lun_t *lun)
+{
+ return 0;
+}
+
+int dev_del_obj_from_lun(se_portal_group_t *tpg, se_lun_t *lun)
+{
+ return core_dev_del_lun(tpg, lun->unpacked_lun);
+}
+
+se_obj_lun_type_t *dev_get_next_obj_api(void *p, void **next_p)
+{
+ se_device_t *dev = (se_device_t *)p;
+
+ *next_p = dev;
+ return DEV_OBJ_API(dev);
+}
+
+int dev_obtain_obj_lock(void *p)
+{
+ return 0;
+}
+
+int dev_release_obj_lock(void *p)
+{
+ return 0;
+}
+
+se_obj_lun_type_t dev_obj_template = {
+ .se_obj_type = TRANSPORT_LUN_TYPE_DEVICE,
+ .get_obj_info = dev_obj_get_obj_info,
+ .get_plugin_info = dev_obj_get_plugin_info,
+ .get_obj = dev_obj_get_obj,
+ .get_queue_obj = dev_obj_get_queue_obj,
+ .claim_obj = dev_obj_claim_obj,
+ .release_obj = dev_obj_release_obj,
+ .inc_count = dev_obj_inc_count,
+ .dec_count = dev_obj_dec_count,
+ .check_count = dev_obj_check_count,
+ .access_obj = dev_access_obj,
+ .deaccess_obj = dev_deaccess_obj,
+ .put_obj = dev_put_obj,
+ .export_obj = dev_obj_export,
+ .unexport_obj = dev_obj_unexport,
+ .transport_setup_cmd = dev_obj_transport_setup_cmd,
+ .active_tasks = dev_obj_active_tasks,
+ .add_tasks = dev_obj_add_tasks,
+ .execute_tasks = dev_obj_execute_tasks,
+ .depth_left = dev_obj_depth_left,
+ .queue_depth = dev_obj_queue_depth,
+ .blocksize = dev_obj_blocksize,
+ .max_sectors = dev_obj_max_sectors,
+ .end_lba = dev_obj_end_lba,
+ .get_next_lba = dev_obj_get_next_lba,
+ .total_sectors = dev_obj_total_sectors,
+ .do_se_mem_map = dev_obj_do_se_mem_map,
+ .get_mem_buf = dev_obj_get_mem_buf,
+ .get_mem_SG = dev_obj_get_mem_SG,
+ .get_map_SG = dev_obj_get_map_SG,
+ .get_map_non_SG = dev_obj_get_map_non_SG,
+ .get_map_none = dev_obj_get_map_none,
+ .get_transport_req = dev_obj_get_transport_req,
+ .free_tasks = dev_obj_free_tasks,
+ .activate = dev_obj_activate,
+ .deactivate = dev_obj_deactivate,
+ .notify_obj = dev_obj_notify_obj,
+ .check_online = dev_obj_check_online,
+ .check_shutdown = dev_obj_check_shutdown,
+ .signal_shutdown = dev_obj_signal_shutdown,
+ .clear_shutdown = dev_obj_clear_shutdown,
+ .get_cdb = dev_obj_get_cdb,
+ .obj_start = dev_obj_start,
+ .get_cdb_count = dev_obj_get_cdb_count,
+ .get_cdb_size = dev_obj_get_cdb_size,
+ .generate_cdb = dev_obj_generate_cdb,
+ .get_device_access = dev_obj_get_device_access,
+ .get_device_type = dev_obj_get_device_type,
+ .check_DMA_handler = dev_obj_check_DMA_handler,
+ .get_t10_wwn = dev_obj_get_t10_wwn,
+ .get_task_timeout = dev_obj_get_task_timeout,
+ .add_obj_to_lun = dev_add_obj_to_lun,
+ .del_obj_from_lun = dev_del_obj_from_lun,
+ .get_next_obj_api = dev_get_next_obj_api,
+ .obtain_obj_lock = dev_obtain_obj_lock,
+ .release_obj_lock = dev_release_obj_lock,
+};
+
+se_obj_lun_type_t *se_obj_get_api(u32 plugin_loc)
+{
+ se_plugin_class_t *pc;
+ se_plugin_t *p;
+
+ pc = plugin_get_class(PLUGIN_TYPE_OBJ);
+ if (!(pc))
+ return NULL;
+
+ spin_lock(&pc->plugin_lock);
+ if (plugin_loc > pc->max_plugins) {
+ printk(KERN_ERR "Passed plugin_loc: %u exceeds pc->max_plugins:"
+ " %d\n", plugin_loc, pc->max_plugins);
+ goto out;
+ }
+
+ p = &pc->plugin_array[plugin_loc];
+ if (!p->plugin_obj) {
+ printk(KERN_ERR "Passed plugin_loc: %u does not exist!\n",
+ plugin_loc);
+ goto out;
+ }
+ spin_unlock(&pc->plugin_lock);
+
+ return (se_obj_lun_type_t *)p->plugin_obj;
+out:
+ spin_unlock(&pc->plugin_lock);
+ return NULL;
+}
+
+
+int se_obj_load_plugins(void)
+{
+ int ret = 0;
+
+ dev_obj_template.obj_plugin = plugin_register((void *)&dev_obj_template,
+ TRANSPORT_LUN_TYPE_DEVICE, "dev", PLUGIN_TYPE_OBJ,
+ dev_obj_template.get_plugin_info, &ret);
+ if (ret)
+ printk(KERN_ERR "plugin_register() failures\n");
+
+ return ret;
+}
diff --git a/include/target/target_core_seobj.h b/include/target/target_core_seobj.h
new file mode 100644
index 0000000..fad3b4e
--- /dev/null
+++ b/include/target/target_core_seobj.h
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Filename: target_core_seobj.h
+ *
+ * Copyright (c) 2006-2007 SBE, Inc. All Rights Reserved.
+ * Copyright (c) 2007-2009 Rising Tide Software, Inc.
+ * Copyright (c) 2008-2009 Linux-iSCSI.org
+ *
+ * Nicholas A. Bellinger <nab@xxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ ******************************************************************************/
+
+
+#ifndef TARGET_CORE_SEOBJ_H
+#define TARGET_CORE_SEOBJ_H
+
+extern struct se_obj_lun_type_s *se_obj_get_api(u32);
+extern int se_obj_load_plugins(void);
+
+#define DEV_OBJ_VERSION "v3.0"
+
+typedef int (*map_func_t)(struct se_task_s *, u32);
+
+typedef struct se_obj_lun_type_s {
+ int se_obj_type;
+ struct se_plugin_s *obj_plugin;
+ void (*get_obj_info)(void *, struct se_lun_s *, unsigned long long,
+ int, char *, int *);
+ void (*get_plugin_info)(void *, char *, int *);
+ void *(*get_obj)(void *);
+ struct se_queue_obj_s *(*get_queue_obj)(void *);
+ int (*claim_obj)(void *);
+ void (*release_obj)(void *);
+ void (*inc_count)(struct se_obj_s *);
+ void (*dec_count)(struct se_obj_s *);
+ int (*check_count)(struct se_obj_s *);
+ void (*access_obj)(void *);
+ void (*deaccess_obj)(void *);
+ void (*put_obj)(void *);
+ int (*export_obj)(void *, struct se_portal_group_s *,
+ struct se_lun_s *);
+ void (*unexport_obj)(void *, struct se_portal_group_s *,
+ struct se_lun_s *);
+ int (*transport_setup_cmd)(void *, struct se_cmd_s *);
+ int (*active_tasks)(void *);
+ int (*add_tasks)(void *, struct se_cmd_s *);
+ int (*execute_tasks)(void *);
+ int (*depth_left)(void *);
+ int (*queue_depth)(void *);
+ int (*blocksize)(void *);
+ int (*max_sectors)(void *);
+ unsigned long long (*end_lba)(void *, int);
+ unsigned long long (*free_sectors)(void *);
+ unsigned long long (*get_next_lba)(void *, unsigned long long);
+ unsigned long long (*total_sectors)(void *);
+ int (*do_se_mem_map)(void *, struct se_task_s *, struct list_head *,
+ void *, struct se_mem_s *, struct se_mem_s **,
+ u32 *, u32 *);
+ int (*get_mem_buf)(void *, struct se_cmd_s *);
+ int (*get_mem_SG)(void *, struct se_cmd_s *);
+ map_func_t (*get_map_SG)(void *, int);
+ map_func_t (*get_map_non_SG)(void *, int);
+ map_func_t (*get_map_none)(void *);
+ void *(*get_transport_req)(void *, struct se_task_s *);
+ void (*free_tasks)(void *, struct se_cmd_s *);
+ int (*activate)(void *);
+ void (*deactivate)(void *);
+ void (*notify_obj)(void *);
+ int (*check_export)(void *);
+ int (*check_online)(void *);
+ int (*check_shutdown)(void *);
+ void (*signal_shutdown)(void *);
+ void (*clear_shutdown)(void *);
+ int (*obj_start)(void *, struct se_transform_info_s *,
+ unsigned long long);
+ unsigned char *(*get_cdb)(void *, struct se_task_s *);
+ u32 (*get_cdb_count)(void *, struct se_transform_info_s *,
+ unsigned long long, u32, struct se_mem_s *,
+ struct se_mem_s **, u32 *);
+ u32 (*get_cdb_size)(void *, u32, unsigned char *);
+ void (*generate_cdb)(void *, unsigned long long, u32 *,
+ unsigned char *, int);
+ int (*get_device_access)(void *);
+ int (*get_device_type)(void *);
+ int (*check_DMA_handler)(void *);
+ t10_wwn_t *(*get_t10_wwn)(void *);
+ int (*get_task_timeout)(void *);
+ int (*task_failure_complete)(void *, struct se_cmd_s *);
+ int (*add_obj_to_lun)(struct se_portal_group_s *, struct se_lun_s *);
+ int (*del_obj_from_lun)(struct se_portal_group_s *, struct se_lun_s *);
+ struct se_obj_lun_type_s *(*get_next_obj_api)(void *, void **);
+ int (*obtain_obj_lock)(void *);
+ int (*release_obj_lock)(void *);
+} se_obj_lun_type_t;
+
+/*
+ * object template for se_device_t storage objects
+ */
+extern se_obj_lun_type_t dev_obj_template;
+
+#endif /* TARGET_CORE_SEOBJ_H */


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/