* [RFC PATCH 13/19] Target_Core_Mod Storage Engine Object infrastructure
@ 2009-09-18 22:08 Nicholas A. Bellinger
0 siblings, 0 replies; 2+ messages in thread
From: Nicholas A. Bellinger @ 2009-09-18 22:08 UTC (permalink / raw)
To: LKML, linux-scsi
Cc: Andrew Morton, Greg KH, Douglas Gilbert, James Bottomley,
Hannes Reinecke, FUJITA Tomonori, Mike Christie, Joel Becker,
Martin K. Petersen, Christoph Hellwig, Linus Torvalds,
Alan Stern, Boaz Harrosh, Florian Haas, Philipp Reisner,
Lars Ellenberg, Daniel Walker
[RFC PATCH 13/19] Target_Core_Mod Storage Engine Object infrastructure
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@linux-iscsi.org>
diff --git a/drivers/target/target_core_seobj.c b/drivers/target/target_core_seobj.c
new file mode 100644
index 0000000..31fab2a
--- /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@kernel.org>
+ *
+ * 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, "TCM Device Object Plugin %s\n",
+ 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, NULL, NULL, &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@kernel.org>
+ *
+ * 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 */
^ permalink raw reply [flat|nested] 2+ messages in thread
* [RFC PATCH 13/19] Target_Core_Mod Storage Engine Object infrastructure
@ 2009-09-12 1:57 Nicholas A. Bellinger
0 siblings, 0 replies; 2+ messages in thread
From: Nicholas A. Bellinger @ 2009-09-12 1:57 UTC (permalink / raw)
To: LKML, linux-scsi
Cc: Andrew Morton, Greg KH, Douglas Gilbert, James Bottomley,
Hannes Reinecke, FUJITA Tomonori, Mike Christie, Joel Becker,
Martin K. Petersen, Christoph Hellwig, Linus Torvalds,
Alan Stern, Boaz Harrosh, Florian Haas, Philipp Reisner
[RFC PATCH 13/19] Target_Core_Mod Storage Engine Object infrastructure
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@linux-iscsi.org>
diff --git a/drivers/target/target_core_seobj.c b/drivers/target/target_core_seobj.c
new file mode 100644
index 0000000..e50f64c
--- /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@kernel.org>
+ *
+ * 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, NULL, NULL, &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@kernel.org>
+ *
+ * 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 */
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2009-09-18 22:13 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-18 22:08 [RFC PATCH 13/19] Target_Core_Mod Storage Engine Object infrastructure Nicholas A. Bellinger
-- strict thread matches above, loose matches on Subject: below --
2009-09-12 1:57 Nicholas A. Bellinger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®