diff options
Diffstat (limited to 'drivers/target/target_core_configfs.c')
| -rw-r--r-- | drivers/target/target_core_configfs.c | 1673 |
1 files changed, 830 insertions, 843 deletions
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index a5f44a6e6e1..bf55c5a04cf 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -3,8 +3,7 @@ * * This file contains ConfigFS logic for the Generic Target Engine project. * - * Copyright (c) 2008-2011 Rising Tide Systems - * Copyright (c) 2008-2011 Linux-iSCSI.org + * (c) Copyright 2008-2013 Datera, Inc. * * Nicholas A. Bellinger <nab@kernel.org> * @@ -23,7 +22,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/version.h> #include <generated/utsrelease.h> #include <linux/utsname.h> #include <linux/init.h> @@ -37,23 +35,25 @@ #include <linux/parser.h> #include <linux/syscalls.h> #include <linux/configfs.h> +#include <linux/spinlock.h> #include <target/target_core_base.h> -#include <target/target_core_device.h> -#include <target/target_core_transport.h> -#include <target/target_core_fabric_ops.h> +#include <target/target_core_backend.h> +#include <target/target_core_fabric.h> #include <target/target_core_fabric_configfs.h> #include <target/target_core_configfs.h> #include <target/configfs_macros.h> +#include "target_core_internal.h" #include "target_core_alua.h" -#include "target_core_hba.h" #include "target_core_pr.h" #include "target_core_rd.h" -#include "target_core_stat.h" +#include "target_core_xcopy.h" -static struct list_head g_tf_list; -static struct mutex g_tf_lock; +extern struct t10_alua_lu_gp *default_lu_gp; + +static LIST_HEAD(g_tf_list); +static DEFINE_MUTEX(g_tf_lock); struct target_core_configfs_attribute { struct configfs_attribute attr; @@ -61,6 +61,10 @@ struct target_core_configfs_attribute { ssize_t (*store)(void *, const char *, size_t); }; +static struct config_group target_core_hbagroup; +static struct config_group alua_group; +static struct config_group alua_lu_gps_group; + static inline struct se_hba * item_to_hba(struct config_item *item) { @@ -94,12 +98,12 @@ static struct target_fabric_configfs *target_core_get_fabric( { struct target_fabric_configfs *tf; - if (!(name)) + if (!name) return NULL; mutex_lock(&g_tf_lock); list_for_each_entry(tf, &g_tf_list, tf_list) { - if (!(strcmp(tf->tf_name, name))) { + if (!strcmp(tf->tf_name, name)) { atomic_inc(&tf->tf_access_cnt); mutex_unlock(&g_tf_lock); return tf; @@ -120,17 +124,9 @@ static struct config_group *target_core_register_fabric( struct target_fabric_configfs *tf; int ret; - printk(KERN_INFO "Target_Core_ConfigFS: REGISTER -> group: %p name:" + pr_debug("Target_Core_ConfigFS: REGISTER -> group: %p name:" " %s\n", group, name); /* - * Ensure that TCM subsystem plugins are loaded at this point for - * using the RAMDISK_DR virtual LUN 0 and all other struct se_port - * LUN symlinks. - */ - if (transport_subsystem_check_init() < 0) - return ERR_PTR(-EINVAL); - - /* * Below are some hardcoded request_module() calls to automatically * local fabric modules when the following is called: * @@ -140,7 +136,7 @@ static struct config_group *target_core_register_fabric( * registered, but simply provids auto loading logic for modules with * mkdir(2) system calls with known TCM fabric modules. */ - if (!(strncmp(name, "iscsi", 5))) { + if (!strncmp(name, "iscsi", 5)) { /* * Automatically load the LIO Target fabric module when the * following is called: @@ -149,11 +145,11 @@ static struct config_group *target_core_register_fabric( */ ret = request_module("iscsi_target_mod"); if (ret < 0) { - printk(KERN_ERR "request_module() failed for" + pr_err("request_module() failed for" " iscsi_target_mod.ko: %d\n", ret); return ERR_PTR(-EINVAL); } - } else if (!(strncmp(name, "loopback", 8))) { + } else if (!strncmp(name, "loopback", 8)) { /* * Automatically load the tcm_loop fabric module when the * following is called: @@ -162,44 +158,44 @@ static struct config_group *target_core_register_fabric( */ ret = request_module("tcm_loop"); if (ret < 0) { - printk(KERN_ERR "request_module() failed for" + pr_err("request_module() failed for" " tcm_loop.ko: %d\n", ret); return ERR_PTR(-EINVAL); } } tf = target_core_get_fabric(name); - if (!(tf)) { - printk(KERN_ERR "target_core_get_fabric() failed for %s\n", + if (!tf) { + pr_err("target_core_get_fabric() failed for %s\n", name); return ERR_PTR(-EINVAL); } - printk(KERN_INFO "Target_Core_ConfigFS: REGISTER -> Located fabric:" + pr_debug("Target_Core_ConfigFS: REGISTER -> Located fabric:" " %s\n", tf->tf_name); /* * On a successful target_core_get_fabric() look, the returned * struct target_fabric_configfs *tf will contain a usage reference. */ - printk(KERN_INFO "Target_Core_ConfigFS: REGISTER tfc_wwn_cit -> %p\n", - &TF_CIT_TMPL(tf)->tfc_wwn_cit); + pr_debug("Target_Core_ConfigFS: REGISTER tfc_wwn_cit -> %p\n", + &tf->tf_cit_tmpl.tfc_wwn_cit); tf->tf_group.default_groups = tf->tf_default_groups; tf->tf_group.default_groups[0] = &tf->tf_disc_group; tf->tf_group.default_groups[1] = NULL; config_group_init_type_name(&tf->tf_group, name, - &TF_CIT_TMPL(tf)->tfc_wwn_cit); + &tf->tf_cit_tmpl.tfc_wwn_cit); config_group_init_type_name(&tf->tf_disc_group, "discovery_auth", - &TF_CIT_TMPL(tf)->tfc_discovery_cit); + &tf->tf_cit_tmpl.tfc_discovery_cit); - printk(KERN_INFO "Target_Core_ConfigFS: REGISTER -> Allocated Fabric:" + pr_debug("Target_Core_ConfigFS: REGISTER -> Allocated Fabric:" " %s\n", tf->tf_group.cg_item.ci_name); /* * Setup tf_ops.tf_subsys pointer for usage with configfs_depend_item() */ tf->tf_ops.tf_subsys = tf->tf_subsys; tf->tf_fabric = &tf->tf_group.cg_item; - printk(KERN_INFO "Target_Core_ConfigFS: REGISTER -> Set tf->tf_fabric" + pr_debug("Target_Core_ConfigFS: REGISTER -> Set tf->tf_fabric" " for %s\n", name); return &tf->tf_group; @@ -218,18 +214,18 @@ static void target_core_deregister_fabric( struct config_item *df_item; int i; - printk(KERN_INFO "Target_Core_ConfigFS: DEREGISTER -> Looking up %s in" + pr_debug("Target_Core_ConfigFS: DEREGISTER -> Looking up %s in" " tf list\n", config_item_name(item)); - printk(KERN_INFO "Target_Core_ConfigFS: DEREGISTER -> located fabric:" + pr_debug("Target_Core_ConfigFS: DEREGISTER -> located fabric:" " %s\n", tf->tf_name); atomic_dec(&tf->tf_access_cnt); - printk(KERN_INFO "Target_Core_ConfigFS: DEREGISTER -> Releasing" + pr_debug("Target_Core_ConfigFS: DEREGISTER -> Releasing" " tf->tf_fabric for %s\n", tf->tf_name); tf->tf_fabric = NULL; - printk(KERN_INFO "Target_Core_ConfigFS: DEREGISTER -> Releasing ci" + pr_debug("Target_Core_ConfigFS: DEREGISTER -> Releasing ci" " %s\n", config_item_name(item)); tf_group = &tf->tf_group; @@ -273,7 +269,7 @@ static struct configfs_subsystem target_core_fabrics = { }, }; -static struct configfs_subsystem *target_core_subsystem[] = { +struct configfs_subsystem *target_core_subsystem[] = { &target_core_fabrics, NULL, }; @@ -296,22 +292,18 @@ struct target_fabric_configfs *target_fabric_configfs_init( { struct target_fabric_configfs *tf; - if (!(fabric_mod)) { - printk(KERN_ERR "Missing struct module *fabric_mod pointer\n"); - return NULL; - } if (!(name)) { - printk(KERN_ERR "Unable to locate passed fabric name\n"); - return NULL; + pr_err("Unable to locate passed fabric name\n"); + return ERR_PTR(-EINVAL); } - if (strlen(name) > TARGET_FABRIC_NAME_SIZE) { - printk(KERN_ERR "Passed name: %s exceeds TARGET_FABRIC" + if (strlen(name) >= TARGET_FABRIC_NAME_SIZE) { + pr_err("Passed name: %s exceeds TARGET_FABRIC" "_NAME_SIZE\n", name); - return NULL; + return ERR_PTR(-EINVAL); } tf = kzalloc(sizeof(struct target_fabric_configfs), GFP_KERNEL); - if (!(tf)) + if (!tf) return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&tf->tf_list); @@ -330,9 +322,9 @@ struct target_fabric_configfs *target_fabric_configfs_init( list_add_tail(&tf->tf_list, &g_tf_list); mutex_unlock(&g_tf_lock); - printk(KERN_INFO "<<<<<<<<<<<<<<<<<<<<<< BEGIN FABRIC API >>>>>>>>" + pr_debug("<<<<<<<<<<<<<<<<<<<<<< BEGIN FABRIC API >>>>>>>>" ">>>>>>>>>>>>>>\n"); - printk(KERN_INFO "Initialized struct target_fabric_configfs: %p for" + pr_debug("Initialized struct target_fabric_configfs: %p for" " %s\n", tf, tf->tf_name); return tf; } @@ -361,144 +353,112 @@ static int target_fabric_tf_ops_check( { struct target_core_fabric_ops *tfo = &tf->tf_ops; - if (!(tfo->get_fabric_name)) { - printk(KERN_ERR "Missing tfo->get_fabric_name()\n"); - return -EINVAL; - } - if (!(tfo->get_fabric_proto_ident)) { - printk(KERN_ERR "Missing tfo->get_fabric_proto_ident()\n"); - return -EINVAL; - } - if (!(tfo->tpg_get_wwn)) { - printk(KERN_ERR "Missing tfo->tpg_get_wwn()\n"); - return -EINVAL; - } - if (!(tfo->tpg_get_tag)) { - printk(KERN_ERR "Missing tfo->tpg_get_tag()\n"); - return -EINVAL; - } - if (!(tfo->tpg_get_default_depth)) { - printk(KERN_ERR "Missing tfo->tpg_get_default_depth()\n"); - return -EINVAL; - } - if (!(tfo->tpg_get_pr_transport_id)) { - printk(KERN_ERR "Missing tfo->tpg_get_pr_transport_id()\n"); + if (!tfo->get_fabric_name) { + pr_err("Missing tfo->get_fabric_name()\n"); return -EINVAL; } - if (!(tfo->tpg_get_pr_transport_id_len)) { - printk(KERN_ERR "Missing tfo->tpg_get_pr_transport_id_len()\n"); + if (!tfo->get_fabric_proto_ident) { + pr_err("Missing tfo->get_fabric_proto_ident()\n"); return -EINVAL; } - if (!(tfo->tpg_check_demo_mode)) { - printk(KERN_ERR "Missing tfo->tpg_check_demo_mode()\n"); + if (!tfo->tpg_get_wwn) { + pr_err("Missing tfo->tpg_get_wwn()\n"); return -EINVAL; } - if (!(tfo->tpg_check_demo_mode_cache)) { - printk(KERN_ERR "Missing tfo->tpg_check_demo_mode_cache()\n"); + if (!tfo->tpg_get_tag) { + pr_err("Missing tfo->tpg_get_tag()\n"); return -EINVAL; } - if (!(tfo->tpg_check_demo_mode_write_protect)) { - printk(KERN_ERR "Missing tfo->tpg_check_demo_mode_write_protect()\n"); + if (!tfo->tpg_get_default_depth) { + pr_err("Missing tfo->tpg_get_default_depth()\n"); return -EINVAL; } - if (!(tfo->tpg_check_prod_mode_write_protect)) { - printk(KERN_ERR "Missing tfo->tpg_check_prod_mode_write_protect()\n"); + if (!tfo->tpg_get_pr_transport_id) { + pr_err("Missing tfo->tpg_get_pr_transport_id()\n"); return -EINVAL; } - if (!(tfo->tpg_alloc_fabric_acl)) { - printk(KERN_ERR "Missing tfo->tpg_alloc_fabric_acl()\n"); + if (!tfo->tpg_get_pr_transport_id_len) { + pr_err("Missing tfo->tpg_get_pr_transport_id_len()\n"); return -EINVAL; } - if (!(tfo->tpg_release_fabric_acl)) { - printk(KERN_ERR "Missing tfo->tpg_release_fabric_acl()\n"); + if (!tfo->tpg_check_demo_mode) { + pr_err("Missing tfo->tpg_check_demo_mode()\n"); return -EINVAL; } - if (!(tfo->tpg_get_inst_index)) { - printk(KERN_ERR "Missing tfo->tpg_get_inst_index()\n"); + if (!tfo->tpg_check_demo_mode_cache) { + pr_err("Missing tfo->tpg_check_demo_mode_cache()\n"); return -EINVAL; } - if (!(tfo->release_cmd_to_pool)) { - printk(KERN_ERR "Missing tfo->release_cmd_to_pool()\n"); + if (!tfo->tpg_check_demo_mode_write_protect) { + pr_err("Missing tfo->tpg_check_demo_mode_write_protect()\n"); return -EINVAL; } - if (!(tfo->release_cmd_direct)) { - printk(KERN_ERR "Missing tfo->release_cmd_direct()\n"); + if (!tfo->tpg_check_prod_mode_write_protect) { + pr_err("Missing tfo->tpg_check_prod_mode_write_protect()\n"); return -EINVAL; } - if (!(tfo->shutdown_session)) { - printk(KERN_ERR "Missing tfo->shutdown_session()\n"); + if (!tfo->tpg_alloc_fabric_acl) { + pr_err("Missing tfo->tpg_alloc_fabric_acl()\n"); return -EINVAL; } - if (!(tfo->close_session)) { - printk(KERN_ERR "Missing tfo->close_session()\n"); + if (!tfo->tpg_release_fabric_acl) { + pr_err("Missing tfo->tpg_release_fabric_acl()\n"); return -EINVAL; } - if (!(tfo->stop_session)) { - printk(KERN_ERR "Missing tfo->stop_session()\n"); + if (!tfo->tpg_get_inst_index) { + pr_err("Missing tfo->tpg_get_inst_index()\n"); return -EINVAL; } - if (!(tfo->fall_back_to_erl0)) { - printk(KERN_ERR "Missing tfo->fall_back_to_erl0()\n"); + if (!tfo->release_cmd) { + pr_err("Missing tfo->release_cmd()\n"); return -EINVAL; } - if (!(tfo->sess_logged_in)) { - printk(KERN_ERR "Missing tfo->sess_logged_in()\n"); + if (!tfo->shutdown_session) { + pr_err("Missing tfo->shutdown_session()\n"); return -EINVAL; } - if (!(tfo->sess_get_index)) { - printk(KERN_ERR "Missing tfo->sess_get_index()\n"); + if (!tfo->close_session) { + pr_err("Missing tfo->close_session()\n"); return -EINVAL; } - if (!(tfo->write_pending)) { - printk(KERN_ERR "Missing tfo->write_pending()\n"); + if (!tfo->sess_get_index) { + pr_err("Missing tfo->sess_get_index()\n"); return -EINVAL; } - if (!(tfo->write_pending_status)) { - printk(KERN_ERR "Missing tfo->write_pending_status()\n"); + if (!tfo->write_pending) { + pr_err("Missing tfo->write_pending()\n"); return -EINVAL; } - if (!(tfo->set_default_node_attributes)) { - printk(KERN_ERR "Missing tfo->set_default_node_attributes()\n"); + if (!tfo->write_pending_status) { + pr_err("Missing tfo->write_pending_status()\n"); return -EINVAL; } - if (!(tfo->get_task_tag)) { - printk(KERN_ERR "Missing tfo->get_task_tag()\n"); + if (!tfo->set_default_node_attributes) { + pr_err("Missing tfo->set_default_node_attributes()\n"); return -EINVAL; } - if (!(tfo->get_cmd_state)) { - printk(KERN_ERR "Missing tfo->get_cmd_state()\n"); + if (!tfo->get_task_tag) { + pr_err("Missing tfo->get_task_tag()\n"); return -EINVAL; } - if (!(tfo->new_cmd_failure)) { - printk(KERN_ERR "Missing tfo->new_cmd_failure()\n"); + if (!tfo->get_cmd_state) { + pr_err("Missing tfo->get_cmd_state()\n"); return -EINVAL; } - if (!(tfo->queue_data_in)) { - printk(KERN_ERR "Missing tfo->queue_data_in()\n"); + if (!tfo->queue_data_in) { + pr_err("Missing tfo->queue_data_in()\n"); return -EINVAL; } - if (!(tfo->queue_status)) { - printk(KERN_ERR "Missing tfo->queue_status()\n"); + if (!tfo->queue_status) { + pr_err("Missing tfo->queue_status()\n"); return -EINVAL; } - if (!(tfo->queue_tm_rsp)) { - printk(KERN_ERR "Missing tfo->queue_tm_rsp()\n"); + if (!tfo->queue_tm_rsp) { + pr_err("Missing tfo->queue_tm_rsp()\n"); return -EINVAL; } - if (!(tfo->set_fabric_sense_len)) { - printk(KERN_ERR "Missing tfo->set_fabric_sense_len()\n"); - return -EINVAL; - } - if (!(tfo->get_fabric_sense_len)) { - printk(KERN_ERR "Missing tfo->get_fabric_sense_len()\n"); - return -EINVAL; - } - if (!(tfo->is_state_remove)) { - printk(KERN_ERR "Missing tfo->is_state_remove()\n"); - return -EINVAL; - } - if (!(tfo->pack_lun)) { - printk(KERN_ERR "Missing tfo->pack_lun()\n"); + if (!tfo->aborted_task) { + pr_err("Missing tfo->aborted_task()\n"); return -EINVAL; } /* @@ -506,20 +466,20 @@ static int target_fabric_tf_ops_check( * tfo->fabric_make_tpg() and tfo->fabric_drop_tpg() in * target_core_fabric_configfs.c WWN+TPG group context code. */ - if (!(tfo->fabric_make_wwn)) { - printk(KERN_ERR "Missing tfo->fabric_make_wwn()\n"); + if (!tfo->fabric_make_wwn) { + pr_err("Missing tfo->fabric_make_wwn()\n"); return -EINVAL; } - if (!(tfo->fabric_drop_wwn)) { - printk(KERN_ERR "Missing tfo->fabric_drop_wwn()\n"); + if (!tfo->fabric_drop_wwn) { + pr_err("Missing tfo->fabric_drop_wwn()\n"); return -EINVAL; } - if (!(tfo->fabric_make_tpg)) { - printk(KERN_ERR "Missing tfo->fabric_make_tpg()\n"); + if (!tfo->fabric_make_tpg) { + pr_err("Missing tfo->fabric_make_tpg()\n"); return -EINVAL; } - if (!(tfo->fabric_drop_tpg)) { - printk(KERN_ERR "Missing tfo->fabric_drop_tpg()\n"); + if (!tfo->fabric_drop_tpg) { + pr_err("Missing tfo->fabric_drop_tpg()\n"); return -EINVAL; } @@ -537,22 +497,15 @@ static int target_fabric_tf_ops_check( int target_fabric_configfs_register( struct target_fabric_configfs *tf) { - struct config_group *su_group; int ret; - if (!(tf)) { - printk(KERN_ERR "Unable to locate target_fabric_configfs" + if (!tf) { + pr_err("Unable to locate target_fabric_configfs" " pointer\n"); return -EINVAL; } - if (!(tf->tf_subsys)) { - printk(KERN_ERR "Unable to target struct config_subsystem" - " pointer\n"); - return -EINVAL; - } - su_group = &tf->tf_subsys->su_group; - if (!(su_group)) { - printk(KERN_ERR "Unable to locate target struct config_group" + if (!tf->tf_subsys) { + pr_err("Unable to target struct config_subsystem" " pointer\n"); return -EINVAL; } @@ -560,7 +513,7 @@ int target_fabric_configfs_register( if (ret < 0) return ret; - printk(KERN_INFO "<<<<<<<<<<<<<<<<<<<<<< END FABRIC API >>>>>>>>>>>>" + pr_debug("<<<<<<<<<<<<<<<<<<<<<< END FABRIC API >>>>>>>>>>>>" ">>>>>>>>>>\n"); return 0; } @@ -569,48 +522,39 @@ EXPORT_SYMBOL(target_fabric_configfs_register); void target_fabric_configfs_deregister( struct target_fabric_configfs *tf) { - struct config_group *su_group; struct configfs_subsystem *su; - if (!(tf)) { - printk(KERN_ERR "Unable to locate passed target_fabric_" + if (!tf) { + pr_err("Unable to locate passed target_fabric_" "configfs\n"); return; } su = tf->tf_subsys; - if (!(su)) { - printk(KERN_ERR "Unable to locate passed tf->tf_subsys" - " pointer\n"); - return; - } - su_group = &tf->tf_subsys->su_group; - if (!(su_group)) { - printk(KERN_ERR "Unable to locate target struct config_group" + if (!su) { + pr_err("Unable to locate passed tf->tf_subsys" " pointer\n"); return; } - - printk(KERN_INFO "<<<<<<<<<<<<<<<<<<<<<< BEGIN FABRIC API >>>>>>>>>>" + pr_debug("<<<<<<<<<<<<<<<<<<<<<< BEGIN FABRIC API >>>>>>>>>>" ">>>>>>>>>>>>\n"); mutex_lock(&g_tf_lock); if (atomic_read(&tf->tf_access_cnt)) { mutex_unlock(&g_tf_lock); - printk(KERN_ERR "Non zero tf->tf_access_cnt for fabric %s\n", + pr_err("Non zero tf->tf_access_cnt for fabric %s\n", tf->tf_name); BUG(); } list_del(&tf->tf_list); mutex_unlock(&g_tf_lock); - printk(KERN_INFO "Target_Core_ConfigFS: DEREGISTER -> Releasing tf:" + pr_debug("Target_Core_ConfigFS: DEREGISTER -> Releasing tf:" " %s\n", tf->tf_name); tf->tf_module = NULL; tf->tf_subsys = NULL; kfree(tf); - printk("<<<<<<<<<<<<<<<<<<<<<< END FABRIC API >>>>>>>>>>>>>>>>>" + pr_debug("<<<<<<<<<<<<<<<<<<<<<< END FABRIC API >>>>>>>>>>>>>>>>>" ">>>>>\n"); - return; } EXPORT_SYMBOL(target_fabric_configfs_deregister); @@ -625,20 +569,8 @@ static ssize_t target_core_dev_show_attr_##_name( \ struct se_dev_attrib *da, \ char *page) \ { \ - struct se_device *dev; \ - struct se_subsystem_dev *se_dev = da->da_sub_dev; \ - ssize_t rb; \ - \ - spin_lock(&se_dev->se_dev_lock); \ - dev = se_dev->se_dev_ptr; \ - if (!(dev)) { \ - spin_unlock(&se_dev->se_dev_lock); \ - return -ENODEV; \ - } \ - rb = snprintf(page, PAGE_SIZE, "%u\n", (u32)DEV_ATTRIB(dev)->_name); \ - spin_unlock(&se_dev->se_dev_lock); \ - \ - return rb; \ + return snprintf(page, PAGE_SIZE, "%u\n", \ + (u32)da->da_dev->dev_attrib._name); \ } #define DEF_DEV_ATTRIB_STORE(_name) \ @@ -647,26 +579,16 @@ static ssize_t target_core_dev_store_attr_##_name( \ const char *page, \ size_t count) \ { \ - struct se_device *dev; \ - struct se_subsystem_dev *se_dev = da->da_sub_dev; \ unsigned long val; \ int ret; \ \ - spin_lock(&se_dev->se_dev_lock); \ - dev = se_dev->se_dev_ptr; \ - if (!(dev)) { \ - spin_unlock(&se_dev->se_dev_lock); \ - return -ENODEV; \ - } \ - ret = strict_strtoul(page, 0, &val); \ + ret = kstrtoul(page, 0, &val); \ if (ret < 0) { \ - spin_unlock(&se_dev->se_dev_lock); \ - printk(KERN_ERR "strict_strtoul() failed with" \ + pr_err("kstrtoul() failed with" \ " ret: %d\n", ret); \ return -EINVAL; \ } \ - ret = se_dev_set_##_name(dev, (u32)val); \ - spin_unlock(&se_dev->se_dev_lock); \ + ret = se_dev_set_##_name(da->da_dev, (u32)val); \ \ return (!ret) ? count : -EINVAL; \ } @@ -692,6 +614,9 @@ static struct target_core_dev_attrib_attribute \ __CONFIGFS_EATTR_RO(_name, \ target_core_dev_show_attr_##_name); +DEF_DEV_ATTRIB(emulate_model_alias); +SE_DEV_ATTR(emulate_model_alias, S_IRUGO | S_IWUSR); + DEF_DEV_ATTRIB(emulate_dpo); SE_DEV_ATTR(emulate_dpo, S_IRUGO | S_IWUSR); @@ -716,9 +641,30 @@ SE_DEV_ATTR(emulate_tpu, S_IRUGO | S_IWUSR); DEF_DEV_ATTRIB(emulate_tpws); SE_DEV_ATTR(emulate_tpws, S_IRUGO | S_IWUSR); +DEF_DEV_ATTRIB(emulate_caw); +SE_DEV_ATTR(emulate_caw, S_IRUGO | S_IWUSR); + +DEF_DEV_ATTRIB(emulate_3pc); +SE_DEV_ATTR(emulate_3pc, S_IRUGO | S_IWUSR); + +DEF_DEV_ATTRIB(pi_prot_type); +SE_DEV_ATTR(pi_prot_type, S_IRUGO | S_IWUSR); + +DEF_DEV_ATTRIB_RO(hw_pi_prot_type); +SE_DEV_ATTR_RO(hw_pi_prot_type); + +DEF_DEV_ATTRIB(pi_prot_format); +SE_DEV_ATTR(pi_prot_format, S_IRUGO | S_IWUSR); + DEF_DEV_ATTRIB(enforce_pr_isids); SE_DEV_ATTR(enforce_pr_isids, S_IRUGO | S_IWUSR); +DEF_DEV_ATTRIB(is_nonrot); +SE_DEV_ATTR(is_nonrot, S_IRUGO | S_IWUSR); + +DEF_DEV_ATTRIB(emulate_rest_reord); +SE_DEV_ATTR(emulate_rest_reord, S_IRUGO | S_IWUSR); + DEF_DEV_ATTRIB_RO(hw_block_size); SE_DEV_ATTR_RO(hw_block_size); @@ -728,8 +674,8 @@ SE_DEV_ATTR(block_size, S_IRUGO | S_IWUSR); DEF_DEV_ATTRIB_RO(hw_max_sectors); SE_DEV_ATTR_RO(hw_max_sectors); -DEF_DEV_ATTRIB(max_sectors); -SE_DEV_ATTR(max_sectors, S_IRUGO | S_IWUSR); +DEF_DEV_ATTRIB(fabric_max_sectors); +SE_DEV_ATTR(fabric_max_sectors, S_IRUGO | S_IWUSR); DEF_DEV_ATTRIB(optimal_sectors); SE_DEV_ATTR(optimal_sectors, S_IRUGO | S_IWUSR); @@ -740,9 +686,6 @@ SE_DEV_ATTR_RO(hw_queue_depth); DEF_DEV_ATTRIB(queue_depth); SE_DEV_ATTR(queue_depth, S_IRUGO | S_IWUSR); -DEF_DEV_ATTRIB(task_timeout); -SE_DEV_ATTR(task_timeout, S_IRUGO | S_IWUSR); - DEF_DEV_ATTRIB(max_unmap_lba_count); SE_DEV_ATTR(max_unmap_lba_count, S_IRUGO | S_IWUSR); @@ -755,9 +698,13 @@ SE_DEV_ATTR(unmap_granularity, S_IRUGO | S_IWUSR); DEF_DEV_ATTRIB(unmap_granularity_alignment); SE_DEV_ATTR(unmap_granularity_alignment, S_IRUGO | S_IWUSR); +DEF_DEV_ATTRIB(max_write_same_len); +SE_DEV_ATTR(max_write_same_len, S_IRUGO | S_IWUSR); + CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group); static struct configfs_attribute *target_core_dev_attrib_attrs[] = { + &target_core_dev_attrib_emulate_model_alias.attr, &target_core_dev_attrib_emulate_dpo.attr, &target_core_dev_attrib_emulate_fua_write.attr, &target_core_dev_attrib_emulate_fua_read.attr, @@ -766,19 +713,26 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = { &target_core_dev_attrib_emulate_tas.attr, &target_core_dev_attrib_emulate_tpu.attr, &target_core_dev_attrib_emulate_tpws.attr, + &target_core_dev_attrib_emulate_caw.attr, + &target_core_dev_attrib_emulate_3pc.attr, + &target_core_dev_attrib_pi_prot_type.attr, + &target_core_dev_attrib_hw_pi_prot_type.attr, + &target_core_dev_attrib_pi_prot_format.attr, &target_core_dev_attrib_enforce_pr_isids.attr, + &target_core_dev_attrib_is_nonrot.attr, + &target_core_dev_attrib_emulate_rest_reord.attr, &target_core_dev_attrib_hw_block_size.attr, &target_core_dev_attrib_block_size.attr, &target_core_dev_attrib_hw_max_sectors.attr, - &target_core_dev_attrib_max_sectors.attr, + &target_core_dev_attrib_fabric_max_sectors.attr, &target_core_dev_attrib_optimal_sectors.attr, &target_core_dev_attrib_hw_queue_depth.attr, &target_core_dev_attrib_queue_depth.attr, - &target_core_dev_attrib_task_timeout.attr, &target_core_dev_attrib_max_unmap_lba_count.attr, &target_core_dev_attrib_max_unmap_block_desc_count.attr, &target_core_dev_attrib_unmap_granularity.attr, &target_core_dev_attrib_unmap_granularity_alignment.attr, + &target_core_dev_attrib_max_write_same_len.attr, NULL, }; @@ -819,13 +773,6 @@ static ssize_t target_core_dev_wwn_show_attr_vpd_unit_serial( struct t10_wwn *t10_wwn, char *page) { - struct se_subsystem_dev *se_dev = t10_wwn->t10_sub_dev; - struct se_device *dev; - - dev = se_dev->se_dev_ptr; - if (!(dev)) - return -ENODEV; - return sprintf(page, "T10 VPD Unit Serial Number: %s\n", &t10_wwn->unit_serial[0]); } @@ -835,8 +782,7 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial( const char *page, size_t count) { - struct se_subsystem_dev *su_dev = t10_wwn->t10_sub_dev; - struct se_device *dev; + struct se_device *dev = t10_wwn->t10_dev; unsigned char buf[INQUIRY_VPD_SERIAL_LEN]; /* @@ -849,14 +795,14 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial( * it is doing 'the right thing' wrt a world wide unique * VPD Unit Serial Number that OS dependent multipath can depend on. */ - if (su_dev->su_dev_flags & SDF_FIRMWARE_VPD_UNIT_SERIAL) { - printk(KERN_ERR "Underlying SCSI device firmware provided VPD" + if (dev->dev_flags & DF_FIRMWARE_VPD_UNIT_SERIAL) { + pr_err("Underlying SCSI device firmware provided VPD" " Unit Serial, ignoring request\n"); return -EOPNOTSUPP; } - if ((strlen(page) + 1) > INQUIRY_VPD_SERIAL_LEN) { - printk(KERN_ERR "Emulated VPD Unit Serial exceeds" + if (strlen(page) >= INQUIRY_VPD_SERIAL_LEN) { + pr_err("Emulated VPD Unit Serial exceeds" " INQUIRY_VPD_SERIAL_LEN: %d\n", INQUIRY_VPD_SERIAL_LEN); return -EOVERFLOW; } @@ -866,15 +812,13 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial( * (underneath the initiator side OS dependent multipath code) * could cause negative effects. */ - dev = su_dev->se_dev_ptr; - if ((dev)) { - if (atomic_read(&dev->dev_export_obj.obj_access_count)) { - printk(KERN_ERR "Unable to set VPD Unit Serial while" - " active %d $FABRIC_MOD exports exist\n", - atomic_read(&dev->dev_export_obj.obj_access_count)); - return -EINVAL; - } + if (dev->export_count) { + pr_err("Unable to set VPD Unit Serial while" + " active %d $FABRIC_MOD exports exist\n", + dev->export_count); + return -EINVAL; } + /* * This currently assumes ASCII encoding for emulated VPD Unit Serial. * @@ -883,12 +827,12 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial( */ memset(buf, 0, INQUIRY_VPD_SERIAL_LEN); snprintf(buf, INQUIRY_VPD_SERIAL_LEN, "%s", page); - snprintf(su_dev->t10_wwn.unit_serial, INQUIRY_VPD_SERIAL_LEN, + snprintf(dev->t10_wwn.unit_serial, INQUIRY_VPD_SERIAL_LEN, "%s", strstrip(buf)); - su_dev->su_dev_flags |= SDF_EMULATED_VPD_UNIT_SERIAL; + dev->dev_flags |= DF_EMULATED_VPD_UNIT_SERIAL; - printk(KERN_INFO "Target_Core_ConfigFS: Set emulated VPD Unit Serial:" - " %s\n", su_dev->t10_wwn.unit_serial); + pr_debug("Target_Core_ConfigFS: Set emulated VPD Unit Serial:" + " %s\n", dev->t10_wwn.unit_serial); return count; } @@ -902,26 +846,20 @@ static ssize_t target_core_dev_wwn_show_attr_vpd_protocol_identifier( struct t10_wwn *t10_wwn, char *page) { - struct se_subsystem_dev *se_dev = t10_wwn->t10_sub_dev; - struct se_device *dev; struct t10_vpd *vpd; unsigned char buf[VPD_TMP_BUF_SIZE]; ssize_t len = 0; - dev = se_dev->se_dev_ptr; - if (!(dev)) - return -ENODEV; - memset(buf, 0, VPD_TMP_BUF_SIZE); spin_lock(&t10_wwn->t10_vpd_lock); list_for_each_entry(vpd, &t10_wwn->t10_vpd_list, vpd_list) { - if (!(vpd->protocol_identifier_set)) + if (!vpd->protocol_identifier_set) continue; transport_dump_vpd_proto_id(vpd, buf, VPD_TMP_BUF_SIZE); - if ((len + strlen(buf) > PAGE_SIZE)) + if (len + strlen(buf) >= PAGE_SIZE) break; len += sprintf(page+len, "%s", buf); @@ -949,16 +887,10 @@ static ssize_t target_core_dev_wwn_show_attr_##_name( \ struct t10_wwn *t10_wwn, \ char *page) \ { \ - struct se_subsystem_dev *se_dev = t10_wwn->t10_sub_dev; \ - struct se_device *dev; \ struct t10_vpd *vpd; \ unsigned char buf[VPD_TMP_BUF_SIZE]; \ ssize_t len = 0; \ \ - dev = se_dev->se_dev_ptr; \ - if (!(dev)) \ - return -ENODEV; \ - \ spin_lock(&t10_wwn->t10_vpd_lock); \ list_for_each_entry(vpd, &t10_wwn->t10_vpd_list, vpd_list) { \ if (vpd->association != _assoc) \ @@ -966,19 +898,19 @@ static ssize_t target_core_dev_wwn_show_attr_##_name( \ \ memset(buf, 0, VPD_TMP_BUF_SIZE); \ transport_dump_vpd_assoc(vpd, buf, VPD_TMP_BUF_SIZE); \ - if ((len + strlen(buf) > PAGE_SIZE)) \ + if (len + strlen(buf) >= PAGE_SIZE) \ break; \ len += sprintf(page+len, "%s", buf); \ \ memset(buf, 0, VPD_TMP_BUF_SIZE); \ transport_dump_vpd_ident_type(vpd, buf, VPD_TMP_BUF_SIZE); \ - if ((len + strlen(buf) > PAGE_SIZE)) \ + if (len + strlen(buf) >= PAGE_SIZE) \ break; \ len += sprintf(page+len, "%s", buf); \ \ memset(buf, 0, VPD_TMP_BUF_SIZE); \ transport_dump_vpd_ident(vpd, buf, VPD_TMP_BUF_SIZE); \ - if ((len + strlen(buf) > PAGE_SIZE)) \ + if (len + strlen(buf) >= PAGE_SIZE) \ break; \ len += sprintf(page+len, "%s", buf); \ } \ @@ -988,7 +920,7 @@ static ssize_t target_core_dev_wwn_show_attr_##_name( \ } /* - * VPD page 0x83 Assoication: Logical Unit + * VPD page 0x83 Association: Logical Unit */ DEF_DEV_WWN_ASSOC_SHOW(vpd_assoc_logical_unit, 0x00); @@ -1058,7 +990,7 @@ static struct config_item_type target_core_dev_wwn_cit = { /* Start functions for struct config_item_type target_core_dev_pr_cit */ -CONFIGFS_EATTR_STRUCT(target_core_dev_pr, se_subsystem_dev); +CONFIGFS_EATTR_STRUCT(target_core_dev_pr, se_device); #define SE_DEV_PR_ATTR(_name, _mode) \ static struct target_core_dev_pr_attribute target_core_dev_pr_##_name = \ __CONFIGFS_EATTR(_name, _mode, \ @@ -1070,149 +1002,90 @@ static struct target_core_dev_pr_attribute target_core_dev_pr_##_name = \ __CONFIGFS_EATTR_RO(_name, \ target_core_dev_pr_show_attr_##_name); -/* - * res_holder - */ -static ssize_t target_core_dev_pr_show_spc3_res( - struct se_device *dev, - char *page, - ssize_t *len) +static ssize_t target_core_dev_pr_show_spc3_res(struct se_device *dev, + char *page) { struct se_node_acl *se_nacl; struct t10_pr_registration *pr_reg; char i_buf[PR_REG_ISID_ID_LEN]; - int prf_isid; memset(i_buf, 0, PR_REG_ISID_ID_LEN); - spin_lock(&dev->dev_reservation_lock); pr_reg = dev->dev_pr_res_holder; - if (!(pr_reg)) { - *len += sprintf(page + *len, "No SPC-3 Reservation holder\n"); - spin_unlock(&dev->dev_reservation_lock); - return *len; - } - se_nacl = pr_reg->pr_reg_nacl; - prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], - PR_REG_ISID_ID_LEN); + if (!pr_reg) + return sprintf(page, "No SPC-3 Reservation holder\n"); - *len += sprintf(page + *len, "SPC-3 Reservation: %s Initiator: %s%s\n", - TPG_TFO(se_nacl->se_tpg)->get_fabric_name(), - se_nacl->initiatorname, (prf_isid) ? &i_buf[0] : ""); - spin_unlock(&dev->dev_reservation_lock); + se_nacl = pr_reg->pr_reg_nacl; + core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); - return *len; + return sprintf(page, "SPC-3 Reservation: %s Initiator: %s%s\n", + se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(), + se_nacl->initiatorname, i_buf); } -static ssize_t target_core_dev_pr_show_spc2_res( - struct se_device *dev, - char *page, - ssize_t *len) +static ssize_t target_core_dev_pr_show_spc2_res(struct se_device *dev, + char *page) { struct se_node_acl *se_nacl; + ssize_t len; - spin_lock(&dev->dev_reservation_lock); se_nacl = dev->dev_reserved_node_acl; - if (!(se_nacl)) { - *len += sprintf(page + *len, "No SPC-2 Reservation holder\n"); - spin_unlock(&dev->dev_reservation_lock); - return *len; - } - *len += sprintf(page + *len, "SPC-2 Reservation: %s Initiator: %s\n", - TPG_TFO(se_nacl->se_tpg)->get_fabric_name(), - se_nacl->initiatorname); - spin_unlock(&dev->dev_reservation_lock); - - return *len; + if (se_nacl) { + len = sprintf(page, + "SPC-2 Reservation: %s Initiator: %s\n", + se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(), + se_nacl->initiatorname); + } else { + len = sprintf(page, "No SPC-2 Reservation holder\n"); + } + return len; } -static ssize_t target_core_dev_pr_show_attr_res_holder( - struct se_subsystem_dev *su_dev, - char *page) +static ssize_t target_core_dev_pr_show_attr_res_holder(struct se_device *dev, + char *page) { - ssize_t len = 0; - - if (!(su_dev->se_dev_ptr)) - return -ENODEV; + int ret; - switch (T10_RES(su_dev)->res_type) { - case SPC3_PERSISTENT_RESERVATIONS: - target_core_dev_pr_show_spc3_res(su_dev->se_dev_ptr, - page, &len); - break; - case SPC2_RESERVATIONS: - target_core_dev_pr_show_spc2_res(su_dev->se_dev_ptr, - page, &len); - break; - case SPC_PASSTHROUGH: - len += sprintf(page+len, "Passthrough\n"); - break; - default: - len += sprintf(page+len, "Unknown\n"); - break; - } + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + return sprintf(page, "Passthrough\n"); - return len; + spin_lock(&dev->dev_reservation_lock); + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) + ret = target_core_dev_pr_show_spc2_res(dev, page); + else + ret = target_core_dev_pr_show_spc3_res(dev, page); + spin_unlock(&dev->dev_reservation_lock); + return ret; } SE_DEV_PR_ATTR_RO(res_holder); -/* - * res_pr_all_tgt_pts - */ static ssize_t target_core_dev_pr_show_attr_res_pr_all_tgt_pts( - struct se_subsystem_dev *su_dev, - char *page) + struct se_device *dev, char *page) { - struct se_device *dev; - struct t10_pr_registration *pr_reg; ssize_t len = 0; - dev = su_dev->se_dev_ptr; - if (!(dev)) - return -ENODEV; - - if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS) - return len; - spin_lock(&dev->dev_reservation_lock); - pr_reg = dev->dev_pr_res_holder; - if (!(pr_reg)) { + if (!dev->dev_pr_res_holder) { len = sprintf(page, "No SPC-3 Reservation holder\n"); - spin_unlock(&dev->dev_reservation_lock); - return len; - } - /* - * See All Target Ports (ALL_TG_PT) bit in spcr17, section 6.14.3 - * Basic PERSISTENT RESERVER OUT parameter list, page 290 - */ - if (pr_reg->pr_reg_all_tg_pt) + } else if (dev->dev_pr_res_holder->pr_reg_all_tg_pt) { len = sprintf(page, "SPC-3 Reservation: All Target" " Ports registration\n"); - else + } else { len = sprintf(page, "SPC-3 Reservation: Single" " Target Port registration\n"); - spin_unlock(&dev->dev_reservation_lock); + } + spin_unlock(&dev->dev_reservation_lock); return len; } SE_DEV_PR_ATTR_RO(res_pr_all_tgt_pts); -/* - * res_pr_generation - */ static ssize_t target_core_dev_pr_show_attr_res_pr_generation( - struct se_subsystem_dev *su_dev, - char *page) + struct se_device *dev, char *page) { - if (!(su_dev->se_dev_ptr)) - return -ENODEV; - - if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS) - return 0; - - return sprintf(page, "0x%08x\n", T10_RES(su_dev)->pr_generation); + return sprintf(page, "0x%08x\n", dev->t10_pr.pr_generation); } SE_DEV_PR_ATTR_RO(res_pr_generation); @@ -1221,10 +1094,8 @@ SE_DEV_PR_ATTR_RO(res_pr_generation); * res_pr_holder_tg_port */ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port( - struct se_subsystem_dev *su_dev, - char *page) + struct se_device *dev, char *page) { - struct se_device *dev; struct se_node_acl *se_nacl; struct se_lun *lun; struct se_portal_group *se_tpg; @@ -1232,86 +1103,69 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port( struct target_core_fabric_ops *tfo; ssize_t len = 0; - dev = su_dev->se_dev_ptr; - if (!(dev)) - return -ENODEV; - - if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS) - return len; - spin_lock(&dev->dev_reservation_lock); pr_reg = dev->dev_pr_res_holder; - if (!(pr_reg)) { + if (!pr_reg) { len = sprintf(page, "No SPC-3 Reservation holder\n"); - spin_unlock(&dev->dev_reservation_lock); - return len; + goto out_unlock; } + se_nacl = pr_reg->pr_reg_nacl; se_tpg = se_nacl->se_tpg; lun = pr_reg->pr_reg_tg_pt_lun; - tfo = TPG_TFO(se_tpg); + tfo = se_tpg->se_tpg_tfo; len += sprintf(page+len, "SPC-3 Reservation: %s" " Target Node Endpoint: %s\n", tfo->get_fabric_name(), tfo->tpg_get_wwn(se_tpg)); len += sprintf(page+len, "SPC-3 Reservation: Relative Port" - " Identifer Tag: %hu %s Portal Group Tag: %hu" + " Identifier Tag: %hu %s Portal Group Tag: %hu" " %s Logical Unit: %u\n", lun->lun_sep->sep_rtpi, tfo->get_fabric_name(), tfo->tpg_get_tag(se_tpg), tfo->get_fabric_name(), lun->unpacked_lun); - spin_unlock(&dev->dev_reservation_lock); +out_unlock: + spin_unlock(&dev->dev_reservation_lock); return len; } SE_DEV_PR_ATTR_RO(res_pr_holder_tg_port); -/* - * res_pr_registered_i_pts - */ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts( - struct se_subsystem_dev *su_dev, - char *page) + struct se_device *dev, char *page) { struct target_core_fabric_ops *tfo; struct t10_pr_registration *pr_reg; unsigned char buf[384]; char i_buf[PR_REG_ISID_ID_LEN]; ssize_t len = 0; - int reg_count = 0, prf_isid; - - if (!(su_dev->se_dev_ptr)) - return -ENODEV; - - if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS) - return len; + int reg_count = 0; len += sprintf(page+len, "SPC-3 PR Registrations:\n"); - spin_lock(&T10_RES(su_dev)->registration_lock); - list_for_each_entry(pr_reg, &T10_RES(su_dev)->registration_list, + spin_lock(&dev->t10_pr.registration_lock); + list_for_each_entry(pr_reg, &dev->t10_pr.registration_list, pr_reg_list) { memset(buf, 0, 384); memset(i_buf, 0, PR_REG_ISID_ID_LEN); tfo = pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo; - prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], + core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); sprintf(buf, "%s Node: %s%s Key: 0x%016Lx PRgen: 0x%08x\n", tfo->get_fabric_name(), - pr_reg->pr_reg_nacl->initiatorname, (prf_isid) ? - &i_buf[0] : "", pr_reg->pr_res_key, + pr_reg->pr_reg_nacl->initiatorname, i_buf, pr_reg->pr_res_key, pr_reg->pr_res_generation); - if ((len + strlen(buf) > PAGE_SIZE)) + if (len + strlen(buf) >= PAGE_SIZE) break; len += sprintf(page+len, "%s", buf); reg_count++; } - spin_unlock(&T10_RES(su_dev)->registration_lock); + spin_unlock(&dev->t10_pr.registration_lock); - if (!(reg_count)) + if (!reg_count) len += sprintf(page+len, "None\n"); return len; @@ -1319,88 +1173,48 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts( SE_DEV_PR_ATTR_RO(res_pr_registered_i_pts); -/* - * res_pr_type - */ static ssize_t target_core_dev_pr_show_attr_res_pr_type( - struct se_subsystem_dev *su_dev, - char *page) + struct se_device *dev, char *page) { - struct se_device *dev; struct t10_pr_registration *pr_reg; ssize_t len = 0; - dev = su_dev->se_dev_ptr; - if (!(dev)) - return -ENODEV; - - if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS) - return len; - spin_lock(&dev->dev_reservation_lock); pr_reg = dev->dev_pr_res_holder; - if (!(pr_reg)) { + if (pr_reg) { + len = sprintf(page, "SPC-3 Reservation Type: %s\n", + core_scsi3_pr_dump_type(pr_reg->pr_res_type)); + } else { len = sprintf(page, "No SPC-3 Reservation holder\n"); - spin_unlock(&dev->dev_reservation_lock); - return len; } - len = sprintf(page, "SPC-3 Reservation Type: %s\n", - core_scsi3_pr_dump_type(pr_reg->pr_res_type)); - spin_unlock(&dev->dev_reservation_lock); + spin_unlock(&dev->dev_reservation_lock); return len; } SE_DEV_PR_ATTR_RO(res_pr_type); -/* - * res_type - */ static ssize_t target_core_dev_pr_show_attr_res_type( - struct se_subsystem_dev *su_dev, - char *page) + struct se_device *dev, char *page) { - ssize_t len = 0; - - if (!(su_dev->se_dev_ptr)) - return -ENODEV; - - switch (T10_RES(su_dev)->res_type) { - case SPC3_PERSISTENT_RESERVATIONS: - len = sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n"); - break; - case SPC2_RESERVATIONS: - len = sprintf(page, "SPC2_RESERVATIONS\n"); - break; - case SPC_PASSTHROUGH: - len = sprintf(page, "SPC_PASSTHROUGH\n"); - break; - default: - len = sprintf(page, "UNKNOWN\n"); - break; - } - - return len; + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + return sprintf(page, "SPC_PASSTHROUGH\n"); + else if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) + return sprintf(page, "SPC2_RESERVATIONS\n"); + else + return sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n"); } SE_DEV_PR_ATTR_RO(res_type); -/* - * res_aptpl_active - */ - static ssize_t target_core_dev_pr_show_attr_res_aptpl_active( - struct se_subsystem_dev *su_dev, - char *page) + struct se_device *dev, char *page) { - if (!(su_dev->se_dev_ptr)) - return -ENODEV; - - if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) return 0; return sprintf(page, "APTPL Bit Status: %s\n", - (T10_RES(su_dev)->pr_aptpl_active) ? "Activated" : "Disabled"); + (dev->t10_pr.pr_aptpl_active) ? "Activated" : "Disabled"); } SE_DEV_PR_ATTR_RO(res_aptpl_active); @@ -1409,13 +1223,9 @@ SE_DEV_PR_ATTR_RO(res_aptpl_active); * res_aptpl_metadata */ static ssize_t target_core_dev_pr_show_attr_res_aptpl_metadata( - struct se_subsystem_dev *su_dev, - char *page) + struct se_device *dev, char *page) { - if (!(su_dev->se_dev_ptr)) - return -ENODEV; - - if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) return 0; return sprintf(page, "Ready to process PR APTPL metadata..\n"); @@ -1447,11 +1257,10 @@ static match_table_t tokens = { }; static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( - struct se_subsystem_dev *su_dev, + struct se_device *dev, const char *page, size_t count) { - struct se_device *dev; unsigned char *i_fabric = NULL, *i_port = NULL, *isid = NULL; unsigned char *t_fabric = NULL, *t_port = NULL; char *orig, *ptr, *arg_p, *opts; @@ -1463,15 +1272,13 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( u16 port_rpti = 0, tpgt = 0; u8 type = 0, scope; - dev = su_dev->se_dev_ptr; - if (!(dev)) - return -ENODEV; - - if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS) + if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) + return 0; + if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) return 0; - if (atomic_read(&dev->dev_export_obj.obj_access_count)) { - printk(KERN_INFO "Unable to process APTPL metadata while" + if (dev->export_count) { + pr_debug("Unable to process APTPL metadata while" " active fabric exports exist\n"); return -EINVAL; } @@ -1481,7 +1288,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( return -ENOMEM; orig = opts; - while ((ptr = strsep(&opts, ",")) != NULL) { + while ((ptr = strsep(&opts, ",\n")) != NULL) { if (!*ptr) continue; @@ -1500,8 +1307,8 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( ret = -ENOMEM; goto out; } - if (strlen(i_port) > PR_APTPL_MAX_IPORT_LEN) { - printk(KERN_ERR "APTPL metadata initiator_node=" + if (strlen(i_port) >= PR_APTPL_MAX_IPORT_LEN) { + pr_err("APTPL metadata initiator_node=" " exceeds PR_APTPL_MAX_IPORT_LEN: %d\n", PR_APTPL_MAX_IPORT_LEN); ret = -EINVAL; @@ -1514,8 +1321,8 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( ret = -ENOMEM; goto out; } - if (strlen(isid) > PR_REG_ISID_LEN) { - printk(KERN_ERR "APTPL metadata initiator_isid" + if (strlen(isid) >= PR_REG_ISID_LEN) { + pr_err("APTPL metadata initiator_isid" "= exceeds PR_REG_ISID_LEN: %d\n", PR_REG_ISID_LEN); ret = -EINVAL; @@ -1528,9 +1335,9 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( ret = -ENOMEM; goto out; } - ret = strict_strtoull(arg_p, 0, &tmp_ll); + ret = kstrtoull(arg_p, 0, &tmp_ll); if (ret < 0) { - printk(KERN_ERR "strict_strtoull() failed for" + pr_err("kstrtoull() failed for" " sa_res_key=\n"); goto out; } @@ -1575,8 +1382,8 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( ret = -ENOMEM; goto out; } - if (strlen(t_port) > PR_APTPL_MAX_TPORT_LEN) { - printk(KERN_ERR "APTPL metadata target_node=" + if (strlen(t_port) >= PR_APTPL_MAX_TPORT_LEN) { + pr_err("APTPL metadata target_node=" " exceeds PR_APTPL_MAX_TPORT_LEN: %d\n", PR_APTPL_MAX_TPORT_LEN); ret = -EINVAL; @@ -1600,20 +1407,20 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( } } - if (!(i_port) || !(t_port) || !(sa_res_key)) { - printk(KERN_ERR "Illegal parameters for APTPL registration\n"); + if (!i_port || !t_port || !sa_res_key) { + pr_err("Illegal parameters for APTPL registration\n"); ret = -EINVAL; goto out; } if (res_holder && !(type)) { - printk(KERN_ERR "Illegal PR type: 0x%02x for reservation" + pr_err("Illegal PR type: 0x%02x for reservation" " holder\n", type); ret = -EINVAL; goto out; } - ret = core_scsi3_alloc_aptpl_registration(T10_RES(su_dev), sa_res_key, + ret = core_scsi3_alloc_aptpl_registration(&dev->t10_pr, sa_res_key, i_port, isid, mapped_lun, t_port, tpgt, target_lun, res_holder, all_tg_pt, type); out: @@ -1628,7 +1435,7 @@ out: SE_DEV_PR_ATTR(res_aptpl_metadata, S_IRUGO | S_IWUSR); -CONFIGFS_EATTR_OPS(target_core_dev_pr, se_subsystem_dev, se_dev_pr_group); +CONFIGFS_EATTR_OPS(target_core_dev_pr, se_device, dev_pr_group); static struct configfs_attribute *target_core_dev_pr_attrs[] = { &target_core_dev_pr_res_holder.attr, @@ -1660,18 +1467,14 @@ static struct config_item_type target_core_dev_pr_cit = { static ssize_t target_core_show_dev_info(void *p, char *page) { - struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p; - struct se_hba *hba = se_dev->se_dev_hba; - struct se_subsystem_api *t = hba->transport; + struct se_device *dev = p; + struct se_subsystem_api *t = dev->transport; int bl = 0; ssize_t read_bytes = 0; - if (!(se_dev->se_dev_ptr)) - return -ENODEV; - - transport_dump_dev_state(se_dev->se_dev_ptr, page, &bl); + transport_dump_dev_state(dev, page, &bl); read_bytes += bl; - read_bytes += t->show_configfs_dev_params(hba, se_dev, page+read_bytes); + read_bytes += t->show_configfs_dev_params(dev, page+read_bytes); return read_bytes; } @@ -1688,17 +1491,10 @@ static ssize_t target_core_store_dev_control( const char *page, size_t count) { - struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p; - struct se_hba *hba = se_dev->se_dev_hba; - struct se_subsystem_api *t = hba->transport; - - if (!(se_dev->se_dev_su_ptr)) { - printk(KERN_ERR "Unable to locate struct se_subsystem_dev>se" - "_dev_su_ptr\n"); - return -EINVAL; - } + struct se_device *dev = p; + struct se_subsystem_api *t = dev->transport; - return t->set_configfs_dev_params(hba, se_dev, page, count); + return t->set_configfs_dev_params(dev, page, count); } static struct target_core_configfs_attribute target_core_attr_dev_control = { @@ -1711,12 +1507,12 @@ static struct target_core_configfs_attribute target_core_attr_dev_control = { static ssize_t target_core_show_dev_alias(void *p, char *page) { - struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p; + struct se_device *dev = p; - if (!(se_dev->su_dev_flags & SDF_USING_ALIAS)) + if (!(dev->dev_flags & DF_USING_ALIAS)) return 0; - return snprintf(page, PAGE_SIZE, "%s\n", se_dev->se_dev_alias); + return snprintf(page, PAGE_SIZE, "%s\n", dev->dev_alias); } static ssize_t target_core_store_dev_alias( @@ -1724,25 +1520,29 @@ static ssize_t target_core_store_dev_alias( const char *page, size_t count) { - struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p; - struct se_hba *hba = se_dev->se_dev_hba; + struct se_device *dev = p; + struct se_hba *hba = dev->se_hba; ssize_t read_bytes; if (count > (SE_DEV_ALIAS_LEN-1)) { - printk(KERN_ERR "alias count: %d exceeds" + pr_err("alias count: %d exceeds" " SE_DEV_ALIAS_LEN-1: %u\n", (int)count, SE_DEV_ALIAS_LEN-1); return -EINVAL; } - se_dev->su_dev_flags |= SDF_USING_ALIAS; - read_bytes = snprintf(&se_dev->se_dev_alias[0], SE_DEV_ALIAS_LEN, - "%s", page); + read_bytes = snprintf(&dev->dev_alias[0], SE_DEV_ALIAS_LEN, "%s", page); + if (!read_bytes) + return -EINVAL; + if (dev->dev_alias[read_bytes - 1] == '\n') + dev->dev_alias[read_bytes - 1] = '\0'; + + dev->dev_flags |= DF_USING_ALIAS; - printk(KERN_INFO "Target_Core_ConfigFS: %s/%s set alias: %s\n", + pr_debug("Target_Core_ConfigFS: %s/%s set alias: %s\n", config_item_name(&hba->hba_group.cg_item), - config_item_name(&se_dev->se_dev_group.cg_item), - se_dev->se_dev_alias); + config_item_name(&dev->dev_group.cg_item), + dev->dev_alias); return read_bytes; } @@ -1757,12 +1557,12 @@ static struct target_core_configfs_attribute target_core_attr_dev_alias = { static ssize_t target_core_show_dev_udev_path(void *p, char *page) { - struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p; + struct se_device *dev = p; - if (!(se_dev->su_dev_flags & SDF_USING_UDEV_PATH)) + if (!(dev->dev_flags & DF_USING_UDEV_PATH)) return 0; - return snprintf(page, PAGE_SIZE, "%s\n", se_dev->se_dev_udev_path); + return snprintf(page, PAGE_SIZE, "%s\n", dev->udev_path); } static ssize_t target_core_store_dev_udev_path( @@ -1770,25 +1570,30 @@ static ssize_t target_core_store_dev_udev_path( const char *page, size_t count) { - struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p; - struct se_hba *hba = se_dev->se_dev_hba; + struct se_device *dev = p; + struct se_hba *hba = dev->se_hba; ssize_t read_bytes; if (count > (SE_UDEV_PATH_LEN-1)) { - printk(KERN_ERR "udev_path count: %d exceeds" + pr_err("udev_path count: %d exceeds" " SE_UDEV_PATH_LEN-1: %u\n", (int)count, SE_UDEV_PATH_LEN-1); return -EINVAL; } - se_dev->su_dev_flags |= SDF_USING_UDEV_PATH; - read_bytes = snprintf(&se_dev->se_dev_udev_path[0], SE_UDEV_PATH_LEN, + read_bytes = snprintf(&dev->udev_path[0], SE_UDEV_PATH_LEN, "%s", page); + if (!read_bytes) + return -EINVAL; + if (dev->udev_path[read_bytes - 1] == '\n') + dev->udev_path[read_bytes - 1] = '\0'; + + dev->dev_flags |= DF_USING_UDEV_PATH; - printk(KERN_INFO "Target_Core_ConfigFS: %s/%s set udev_path: %s\n", + pr_debug("Target_Core_ConfigFS: %s/%s set udev_path: %s\n", config_item_name(&hba->hba_group.cg_item), - config_item_name(&se_dev->se_dev_group.cg_item), - se_dev->se_dev_udev_path); + config_item_name(&dev->dev_group.cg_item), + dev->udev_path); return read_bytes; } @@ -1801,79 +1606,58 @@ static struct target_core_configfs_attribute target_core_attr_dev_udev_path = { .store = target_core_store_dev_udev_path, }; +static ssize_t target_core_show_dev_enable(void *p, char *page) +{ + struct se_device *dev = p; + + return snprintf(page, PAGE_SIZE, "%d\n", !!(dev->dev_flags & DF_CONFIGURED)); +} + static ssize_t target_core_store_dev_enable( void *p, const char *page, size_t count) { - struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p; - struct se_device *dev; - struct se_hba *hba = se_dev->se_dev_hba; - struct se_subsystem_api *t = hba->transport; + struct se_device *dev = p; char *ptr; + int ret; ptr = strstr(page, "1"); - if (!(ptr)) { - printk(KERN_ERR "For dev_enable ops, only valid value" + if (!ptr) { + pr_err("For dev_enable ops, only valid value" " is \"1\"\n"); return -EINVAL; } - if ((se_dev->se_dev_ptr)) { - printk(KERN_ERR "se_dev->se_dev_ptr already set for storage" - " object\n"); - return -EEXIST; - } - - if (t->check_configfs_dev_params(hba, se_dev) < 0) - return -EINVAL; - - dev = t->create_virtdevice(hba, se_dev, se_dev->se_dev_su_ptr); - if (IS_ERR(dev)) - return PTR_ERR(dev); - else if (!dev) - return -EINVAL; - - se_dev->se_dev_ptr = dev; - printk(KERN_INFO "Target_Core_ConfigFS: Registered se_dev->se_dev_ptr:" - " %p\n", se_dev->se_dev_ptr); + ret = target_configure_device(dev); + if (ret) + return ret; return count; } static struct target_core_configfs_attribute target_core_attr_dev_enable = { .attr = { .ca_owner = THIS_MODULE, .ca_name = "enable", - .ca_mode = S_IWUSR }, - .show = NULL, + .ca_mode = S_IRUGO | S_IWUSR }, + .show = target_core_show_dev_enable, .store = target_core_store_dev_enable, }; static ssize_t target_core_show_alua_lu_gp(void *p, char *page) { - struct se_device *dev; - struct se_subsystem_dev *su_dev = (struct se_subsystem_dev *)p; + struct se_device *dev = p; struct config_item *lu_ci; struct t10_alua_lu_gp *lu_gp; struct t10_alua_lu_gp_member *lu_gp_mem; ssize_t len = 0; - dev = su_dev->se_dev_ptr; - if (!(dev)) - return -ENODEV; - - if (T10_ALUA(su_dev)->alua_type != SPC3_ALUA_EMULATED) - return len; - lu_gp_mem = dev->dev_alua_lu_gp_mem; - if (!(lu_gp_mem)) { - printk(KERN_ERR "NULL struct se_device->dev_alua_lu_gp_mem" - " pointer\n"); - return -EINVAL; - } + if (!lu_gp_mem) + return 0; spin_lock(&lu_gp_mem->lu_gp_mem_lock); lu_gp = lu_gp_mem->lu_gp; - if ((lu_gp)) { + if (lu_gp) { lu_ci = &lu_gp->lu_gp_group.cg_item; len += sprintf(page, "LU Group Alias: %s\nLU Group ID: %hu\n", config_item_name(lu_ci), lu_gp->lu_gp_id); @@ -1888,26 +1672,19 @@ static ssize_t target_core_store_alua_lu_gp( const char *page, size_t count) { - struct se_device *dev; - struct se_subsystem_dev *su_dev = (struct se_subsystem_dev *)p; - struct se_hba *hba = su_dev->se_dev_hba; + struct se_device *dev = p; + struct se_hba *hba = dev->se_hba; struct t10_alua_lu_gp *lu_gp = NULL, *lu_gp_new = NULL; struct t10_alua_lu_gp_member *lu_gp_mem; unsigned char buf[LU_GROUP_NAME_BUF]; int move = 0; - dev = su_dev->se_dev_ptr; - if (!(dev)) - return -ENODEV; + lu_gp_mem = dev->dev_alua_lu_gp_mem; + if (!lu_gp_mem) + return 0; - if (T10_ALUA(su_dev)->alua_type != SPC3_ALUA_EMULATED) { - printk(KERN_WARNING "SPC3_ALUA_EMULATED not enabled for %s/%s\n", - config_item_name(&hba->hba_group.cg_item), - config_item_name(&su_dev->se_dev_group.cg_item)); - return -EINVAL; - } if (count > LU_GROUP_NAME_BUF) { - printk(KERN_ERR "ALUA LU Group Alias too large!\n"); + pr_err("ALUA LU Group Alias too large!\n"); return -EINVAL; } memset(buf, 0, LU_GROUP_NAME_BUF); @@ -1923,31 +1700,23 @@ static ssize_t target_core_store_alua_lu_gp( * core_alua_get_lu_gp_by_name below(). */ lu_gp_new = core_alua_get_lu_gp_by_name(strstrip(buf)); - if (!(lu_gp_new)) + if (!lu_gp_new) return -ENODEV; } - lu_gp_mem = dev->dev_alua_lu_gp_mem; - if (!(lu_gp_mem)) { - if (lu_gp_new) - core_alua_put_lu_gp_from_name(lu_gp_new); - printk(KERN_ERR "NULL struct se_device->dev_alua_lu_gp_mem" - " pointer\n"); - return -EINVAL; - } spin_lock(&lu_gp_mem->lu_gp_mem_lock); lu_gp = lu_gp_mem->lu_gp; - if ((lu_gp)) { + if (lu_gp) { /* * Clearing an existing lu_gp association, and replacing * with NULL */ - if (!(lu_gp_new)) { - printk(KERN_INFO "Target_Core_ConfigFS: Releasing %s/%s" + if (!lu_gp_new) { + pr_debug("Target_Core_ConfigFS: Releasing %s/%s" " from ALUA LU Group: core/alua/lu_gps/%s, ID:" " %hu\n", config_item_name(&hba->hba_group.cg_item), - config_item_name(&su_dev->se_dev_group.cg_item), + config_item_name(&dev->dev_group.cg_item), config_item_name(&lu_gp->lu_gp_group.cg_item), lu_gp->lu_gp_id); @@ -1968,11 +1737,11 @@ static ssize_t target_core_store_alua_lu_gp( __core_alua_attach_lu_gp_mem(lu_gp_mem, lu_gp_new); spin_unlock(&lu_gp_mem->lu_gp_mem_lock); - printk(KERN_INFO "Target_Core_ConfigFS: %s %s/%s to ALUA LU Group:" + pr_debug("Target_Core_ConfigFS: %s %s/%s to ALUA LU Group:" " core/alua/lu_gps/%s, ID: %hu\n", (move) ? "Moving" : "Adding", config_item_name(&hba->hba_group.cg_item), - config_item_name(&su_dev->se_dev_group.cg_item), + config_item_name(&dev->dev_group.cg_item), config_item_name(&lu_gp_new->lu_gp_group.cg_item), lu_gp_new->lu_gp_id); @@ -1988,6 +1757,176 @@ static struct target_core_configfs_attribute target_core_attr_dev_alua_lu_gp = { .store = target_core_store_alua_lu_gp, }; +static ssize_t target_core_show_dev_lba_map(void *p, char *page) +{ + struct se_device *dev = p; + struct t10_alua_lba_map *map; + struct t10_alua_lba_map_member *mem; + char *b = page; + int bl = 0; + char state; + + spin_lock(&dev->t10_alua.lba_map_lock); + if (!list_empty(&dev->t10_alua.lba_map_list)) + bl += sprintf(b + bl, "%u %u\n", + dev->t10_alua.lba_map_segment_size, + dev->t10_alua.lba_map_segment_multiplier); + list_for_each_entry(map, &dev->t10_alua.lba_map_list, lba_map_list) { + bl += sprintf(b + bl, "%llu %llu", + map->lba_map_first_lba, map->lba_map_last_lba); + list_for_each_entry(mem, &map->lba_map_mem_list, + lba_map_mem_list) { + switch (mem->lba_map_mem_alua_state) { + case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED: + state = 'O'; + break; + case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: + state = 'A'; + break; + case ALUA_ACCESS_STATE_STANDBY: + state = 'S'; + break; + case ALUA_ACCESS_STATE_UNAVAILABLE: + state = 'U'; + break; + default: + state = '.'; + break; + } + bl += sprintf(b + bl, " %d:%c", + mem->lba_map_mem_alua_pg_id, state); + } + bl += sprintf(b + bl, "\n"); + } + spin_unlock(&dev->t10_alua.lba_map_lock); + return bl; +} + +static ssize_t target_core_store_dev_lba_map( + void *p, + const char *page, + size_t count) +{ + struct se_device *dev = p; + struct t10_alua_lba_map *lba_map = NULL; + struct list_head lba_list; + char *map_entries, *ptr; + char state; + int pg_num = -1, pg; + int ret = 0, num = 0, pg_id, alua_state; + unsigned long start_lba = -1, end_lba = -1; + unsigned long segment_size = -1, segment_mult = -1; + + map_entries = kstrdup(page, GFP_KERNEL); + if (!map_entries) + return -ENOMEM; + + INIT_LIST_HEAD(&lba_list); + while ((ptr = strsep(&map_entries, "\n")) != NULL) { + if (!*ptr) + continue; + + if (num == 0) { + if (sscanf(ptr, "%lu %lu\n", + &segment_size, &segment_mult) != 2) { + pr_err("Invalid line %d\n", num); + ret = -EINVAL; + break; + } + num++; + continue; + } + if (sscanf(ptr, "%lu %lu", &start_lba, &end_lba) != 2) { + pr_err("Invalid line %d\n", num); + ret = -EINVAL; + break; + } + ptr = strchr(ptr, ' '); + if (!ptr) { + pr_err("Invalid line %d, missing end lba\n", num); + ret = -EINVAL; + break; + } + ptr++; + ptr = strchr(ptr, ' '); + if (!ptr) { + pr_err("Invalid line %d, missing state definitions\n", + num); + ret = -EINVAL; + break; + } + ptr++; + lba_map = core_alua_allocate_lba_map(&lba_list, + start_lba, end_lba); + if (IS_ERR(lba_map)) { + ret = PTR_ERR(lba_map); + break; + } + pg = 0; + while (sscanf(ptr, "%d:%c", &pg_id, &state) == 2) { + switch (state) { + case 'O': + alua_state = ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED; + break; + case 'A': + alua_state = ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED; + break; + case 'S': + alua_state = ALUA_ACCESS_STATE_STANDBY; + break; + case 'U': + alua_state = ALUA_ACCESS_STATE_UNAVAILABLE; + break; + default: + pr_err("Invalid ALUA state '%c'\n", state); + ret = -EINVAL; + goto out; + } + + ret = core_alua_allocate_lba_map_mem(lba_map, + pg_id, alua_state); + if (ret) { + pr_err("Invalid target descriptor %d:%c " + "at line %d\n", + pg_id, state, num); + break; + } + pg++; + ptr = strchr(ptr, ' '); + if (ptr) + ptr++; + else + break; + } + if (pg_num == -1) + pg_num = pg; + else if (pg != pg_num) { + pr_err("Only %d from %d port groups definitions " + "at line %d\n", pg, pg_num, num); + ret = -EINVAL; + break; + } + num++; + } +out: + if (ret) { + core_alua_free_lba_map(&lba_list); + count = ret; + } else + core_alua_set_lba_map(dev, &lba_list, + segment_size, segment_mult); + kfree(map_entries); + return count; +} + +static struct target_core_configfs_attribute target_core_attr_dev_lba_map = { + .attr = { .ca_owner = THIS_MODULE, + .ca_name = "lba_map", + .ca_mode = S_IRUGO | S_IWUSR }, + .show = target_core_show_dev_lba_map, + .store = target_core_store_dev_lba_map, +}; + static struct configfs_attribute *lio_core_dev_attrs[] = { &target_core_attr_dev_info.attr, &target_core_attr_dev_control.attr, @@ -1995,74 +1934,50 @@ static struct configfs_attribute *lio_core_dev_attrs[] = { &target_core_attr_dev_udev_path.attr, &target_core_attr_dev_enable.attr, &target_core_attr_dev_alua_lu_gp.attr, + &target_core_attr_dev_lba_map.attr, NULL, }; static void target_core_dev_release(struct config_item *item) { - struct se_subsystem_dev *se_dev = container_of(to_config_group(item), - struct se_subsystem_dev, se_dev_group); - struct se_hba *hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item); - struct se_subsystem_api *t = hba->transport; - struct config_group *dev_cg = &se_dev->se_dev_group; + struct config_group *dev_cg = to_config_group(item); + struct se_device *dev = + container_of(dev_cg, struct se_device, dev_group); kfree(dev_cg->default_groups); - /* - * This pointer will set when the storage is enabled with: - *`echo 1 > $CONFIGFS/core/$HBA/$DEV/dev_enable` - */ - if (se_dev->se_dev_ptr) { - printk(KERN_INFO "Target_Core_ConfigFS: Calling se_free_" - "virtual_device() for se_dev_ptr: %p\n", - se_dev->se_dev_ptr); - - se_free_virtual_device(se_dev->se_dev_ptr, hba); - } else { - /* - * Release struct se_subsystem_dev->se_dev_su_ptr.. - */ - printk(KERN_INFO "Target_Core_ConfigFS: Calling t->free_" - "device() for se_dev_su_ptr: %p\n", - se_dev->se_dev_su_ptr); - - t->free_device(se_dev->se_dev_su_ptr); - } - - printk(KERN_INFO "Target_Core_ConfigFS: Deallocating se_subsystem" - "_dev_t: %p\n", se_dev); - kfree(se_dev); + target_free_device(dev); } static ssize_t target_core_dev_show(struct config_item *item, struct configfs_attribute *attr, char *page) { - struct se_subsystem_dev *se_dev = container_of( - to_config_group(item), struct se_subsystem_dev, - se_dev_group); + struct config_group *dev_cg = to_config_group(item); + struct se_device *dev = + container_of(dev_cg, struct se_device, dev_group); struct target_core_configfs_attribute *tc_attr = container_of( attr, struct target_core_configfs_attribute, attr); - if (!(tc_attr->show)) + if (!tc_attr->show) return -EINVAL; - return tc_attr->show((void *)se_dev, page); + return tc_attr->show(dev, page); } static ssize_t target_core_dev_store(struct config_item *item, struct configfs_attribute *attr, const char *page, size_t count) { - struct se_subsystem_dev *se_dev = container_of( - to_config_group(item), struct se_subsystem_dev, - se_dev_group); + struct config_group *dev_cg = to_config_group(item); + struct se_device *dev = + container_of(dev_cg, struct se_device, dev_group); struct target_core_configfs_attribute *tc_attr = container_of( attr, struct target_core_configfs_attribute, attr); - if (!(tc_attr->store)) + if (!tc_attr->store) return -EINVAL; - return tc_attr->store((void *)se_dev, page, count); + return tc_attr->store(dev, page, count); } static struct configfs_item_operations target_core_dev_item_ops = { @@ -2102,7 +2017,7 @@ static ssize_t target_core_alua_lu_gp_show_attr_lu_gp_id( struct t10_alua_lu_gp *lu_gp, char *page) { - if (!(lu_gp->lu_gp_valid_id)) + if (!lu_gp->lu_gp_valid_id) return 0; return sprintf(page, "%hu\n", lu_gp->lu_gp_id); @@ -2117,14 +2032,14 @@ static ssize_t target_core_alua_lu_gp_store_attr_lu_gp_id( unsigned long lu_gp_id; int ret; - ret = strict_strtoul(page, 0, &lu_gp_id); + ret = kstrtoul(page, 0, &lu_gp_id); if (ret < 0) { - printk(KERN_ERR "strict_strtoul() returned %d for" + pr_err("kstrtoul() returned %d for" " lu_gp_id\n", ret); - return -EINVAL; + return ret; } if (lu_gp_id > 0x0000ffff) { - printk(KERN_ERR "ALUA lu_gp_id: %lu exceeds maximum:" + pr_err("ALUA lu_gp_id: %lu exceeds maximum:" " 0x0000ffff\n", lu_gp_id); return -EINVAL; } @@ -2133,7 +2048,7 @@ static ssize_t target_core_alua_lu_gp_store_attr_lu_gp_id( if (ret < 0) return -EINVAL; - printk(KERN_INFO "Target_Core_ConfigFS: Set ALUA Logical Unit" + pr_debug("Target_Core_ConfigFS: Set ALUA Logical Unit" " Group: core/alua/lu_gps/%s to ID: %hu\n", config_item_name(&alua_lu_gp_cg->cg_item), lu_gp->lu_gp_id); @@ -2152,7 +2067,6 @@ static ssize_t target_core_alua_lu_gp_show_attr_members( { struct se_device *dev; struct se_hba *hba; - struct se_subsystem_dev *su_dev; struct t10_alua_lu_gp_member *lu_gp_mem; ssize_t len = 0, cur_len; unsigned char buf[LU_GROUP_NAME_BUF]; @@ -2162,16 +2076,15 @@ static ssize_t target_core_alua_lu_gp_show_attr_members( spin_lock(&lu_gp->lu_gp_lock); list_for_each_entry(lu_gp_mem, &lu_gp->lu_gp_mem_list, lu_gp_mem_list) { dev = lu_gp_mem->lu_gp_mem_dev; - su_dev = dev->se_sub_dev; - hba = su_dev->se_dev_hba; + hba = dev->se_hba; cur_len = snprintf(buf, LU_GROUP_NAME_BUF, "%s/%s\n", config_item_name(&hba->hba_group.cg_item), - config_item_name(&su_dev->se_dev_group.cg_item)); + config_item_name(&dev->dev_group.cg_item)); cur_len++; /* Extra byte for NULL terminator */ if ((cur_len + len) > PAGE_SIZE) { - printk(KERN_WARNING "Ran out of lu_gp_show_attr" + pr_warn("Ran out of lu_gp_show_attr" "_members buffer\n"); break; } @@ -2235,7 +2148,7 @@ static struct config_group *target_core_alua_create_lu_gp( config_group_init_type_name(alua_lu_gp_cg, name, &target_core_alua_lu_gp_cit); - printk(KERN_INFO "Target_Core_ConfigFS: Allocated ALUA Logical Unit" + pr_debug("Target_Core_ConfigFS: Allocated ALUA Logical Unit" " Group: core/alua/lu_gps/%s\n", config_item_name(alua_lu_gp_ci)); @@ -2250,7 +2163,7 @@ static void target_core_alua_drop_lu_gp( struct t10_alua_lu_gp *lu_gp = container_of(to_config_group(item), struct t10_alua_lu_gp, lu_gp_group); - printk(KERN_INFO "Target_Core_ConfigFS: Releasing ALUA Logical Unit" + pr_debug("Target_Core_ConfigFS: Releasing ALUA Logical Unit" " Group: core/alua/lu_gps/%s, ID: %hu\n", config_item_name(item), lu_gp->lu_gp_id); /* @@ -2305,31 +2218,43 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state( const char *page, size_t count) { - struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev; + struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; unsigned long tmp; int new_state, ret; - if (!(tg_pt_gp->tg_pt_gp_valid_id)) { - printk(KERN_ERR "Unable to do implict ALUA on non valid" + if (!tg_pt_gp->tg_pt_gp_valid_id) { + pr_err("Unable to do implicit ALUA on non valid" " tg_pt_gp ID: %hu\n", tg_pt_gp->tg_pt_gp_valid_id); return -EINVAL; } + if (!(dev->dev_flags & DF_CONFIGURED)) { + pr_err("Unable to set alua_access_state while device is" + " not configured\n"); + return -ENODEV; + } - ret = strict_strtoul(page, 0, &tmp); + ret = kstrtoul(page, 0, &tmp); if (ret < 0) { - printk("Unable to extract new ALUA access state from" + pr_err("Unable to extract new ALUA access state from" " %s\n", page); - return -EINVAL; + return ret; } new_state = (int)tmp; - if (!(tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICT_ALUA)) { - printk(KERN_ERR "Unable to process implict configfs ALUA" - " transition while TPGS_IMPLICT_ALUA is diabled\n"); + if (!(tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICIT_ALUA)) { + pr_err("Unable to process implicit configfs ALUA" + " transition while TPGS_IMPLICIT_ALUA is disabled\n"); + return -EINVAL; + } + if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA && + new_state == ALUA_ACCESS_STATE_LBA_DEPENDENT) { + /* LBA DEPENDENT is only allowed with implicit ALUA */ + pr_err("Unable to process implicit configfs ALUA transition" + " while explicit ALUA management is enabled\n"); return -EINVAL; } - ret = core_alua_do_port_transition(tg_pt_gp, su_dev->se_dev_ptr, + ret = core_alua_do_port_transition(tg_pt_gp, dev, NULL, NULL, new_state, 0); return (!ret) ? count : -EINVAL; } @@ -2355,25 +2280,25 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_status( unsigned long tmp; int new_status, ret; - if (!(tg_pt_gp->tg_pt_gp_valid_id)) { - printk(KERN_ERR "Unable to do set ALUA access status on non" + if (!tg_pt_gp->tg_pt_gp_valid_id) { + pr_err("Unable to do set ALUA access status on non" " valid tg_pt_gp ID: %hu\n", tg_pt_gp->tg_pt_gp_valid_id); return -EINVAL; } - ret = strict_strtoul(page, 0, &tmp); + ret = kstrtoul(page, 0, &tmp); if (ret < 0) { - printk(KERN_ERR "Unable to extract new ALUA access status" + pr_err("Unable to extract new ALUA access status" " from %s\n", page); - return -EINVAL; + return ret; } new_status = (int)tmp; if ((new_status != ALUA_STATUS_NONE) && - (new_status != ALUA_STATUS_ALTERED_BY_EXPLICT_STPG) && - (new_status != ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA)) { - printk(KERN_ERR "Illegal ALUA access status: 0x%02x\n", + (new_status != ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG) && + (new_status != ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA)) { + pr_err("Illegal ALUA access status: 0x%02x\n", new_status); return -EINVAL; } @@ -2405,6 +2330,90 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_type( SE_DEV_ALUA_TG_PT_ATTR(alua_access_type, S_IRUGO | S_IWUSR); /* + * alua_supported_states + */ + +#define SE_DEV_ALUA_SUPPORT_STATE_SHOW(_name, _var, _bit) \ +static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_support_##_name( \ + struct t10_alua_tg_pt_gp *t, char *p) \ +{ \ + return sprintf(p, "%d\n", !!(t->_var & _bit)); \ +} + +#define SE_DEV_ALUA_SUPPORT_STATE_STORE(_name, _var, _bit) \ +static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_support_##_name(\ + struct t10_alua_tg_pt_gp *t, const char *p, size_t c) \ +{ \ + unsigned long tmp; \ + int ret; \ + \ + if (!t->tg_pt_gp_valid_id) { \ + pr_err("Unable to do set ##_name ALUA state on non" \ + " valid tg_pt_gp ID: %hu\n", \ + t->tg_pt_gp_valid_id); \ + return -EINVAL; \ + } \ + \ + ret = kstrtoul(p, 0, &tmp); \ + if (ret < 0) { \ + pr_err("Invalid value '%s', must be '0' or '1'\n", p); \ + return -EINVAL; \ + } \ + if (tmp > 1) { \ + pr_err("Invalid value '%ld', must be '0' or '1'\n", tmp); \ + return -EINVAL; \ + } \ + if (!tmp) \ + t->_var |= _bit; \ + else \ + t->_var &= ~_bit; \ + \ + return c; \ +} + +SE_DEV_ALUA_SUPPORT_STATE_SHOW(transitioning, + tg_pt_gp_alua_supported_states, ALUA_T_SUP); +SE_DEV_ALUA_SUPPORT_STATE_STORE(transitioning, + tg_pt_gp_alua_supported_states, ALUA_T_SUP); +SE_DEV_ALUA_TG_PT_ATTR(alua_support_transitioning, S_IRUGO | S_IWUSR); + +SE_DEV_ALUA_SUPPORT_STATE_SHOW(offline, + tg_pt_gp_alua_supported_states, ALUA_O_SUP); +SE_DEV_ALUA_SUPPORT_STATE_STORE(offline, + tg_pt_gp_alua_supported_states, ALUA_O_SUP); +SE_DEV_ALUA_TG_PT_ATTR(alua_support_offline, S_IRUGO | S_IWUSR); + +SE_DEV_ALUA_SUPPORT_STATE_SHOW(lba_dependent, + tg_pt_gp_alua_supported_states, ALUA_LBD_SUP); +SE_DEV_ALUA_SUPPORT_STATE_STORE(lba_dependent, + tg_pt_gp_alua_supported_states, ALUA_LBD_SUP); +SE_DEV_ALUA_TG_PT_ATTR(alua_support_lba_dependent, S_IRUGO); + +SE_DEV_ALUA_SUPPORT_STATE_SHOW(unavailable, + tg_pt_gp_alua_supported_states, ALUA_U_SUP); +SE_DEV_ALUA_SUPPORT_STATE_STORE(unavailable, + tg_pt_gp_alua_supported_states, ALUA_U_SUP); +SE_DEV_ALUA_TG_PT_ATTR(alua_support_unavailable, S_IRUGO | S_IWUSR); + +SE_DEV_ALUA_SUPPORT_STATE_SHOW(standby, + tg_pt_gp_alua_supported_states, ALUA_S_SUP); +SE_DEV_ALUA_SUPPORT_STATE_STORE(standby, + tg_pt_gp_alua_supported_states, ALUA_S_SUP); +SE_DEV_ALUA_TG_PT_ATTR(alua_support_standby, S_IRUGO | S_IWUSR); + +SE_DEV_ALUA_SUPPORT_STATE_SHOW(active_optimized, + tg_pt_gp_alua_supported_states, ALUA_AO_SUP); +SE_DEV_ALUA_SUPPORT_STATE_STORE(active_optimized, + tg_pt_gp_alua_supported_states, ALUA_AO_SUP); +SE_DEV_ALUA_TG_PT_ATTR(alua_support_active_optimized, S_IRUGO | S_IWUSR); + +SE_DEV_ALUA_SUPPORT_STATE_SHOW(active_nonoptimized, + tg_pt_gp_alua_supported_states, ALUA_AN_SUP); +SE_DEV_ALUA_SUPPORT_STATE_STORE(active_nonoptimized, + tg_pt_gp_alua_supported_states, ALUA_AN_SUP); +SE_DEV_ALUA_TG_PT_ATTR(alua_support_active_nonoptimized, S_IRUGO | S_IWUSR); + +/* * alua_write_metadata */ static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_write_metadata( @@ -2422,14 +2431,14 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_write_metadata( unsigned long tmp; int ret; - ret = strict_strtoul(page, 0, &tmp); + ret = kstrtoul(page, 0, &tmp); if (ret < 0) { - printk(KERN_ERR "Unable to extract alua_write_metadata\n"); - return -EINVAL; + pr_err("Unable to extract alua_write_metadata\n"); + return ret; } if ((tmp != 0) && (tmp != 1)) { - printk(KERN_ERR "Illegal value for alua_write_metadata:" + pr_err("Illegal value for alua_write_metadata:" " %lu\n", tmp); return -EINVAL; } @@ -2484,6 +2493,26 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_trans_delay_msecs( SE_DEV_ALUA_TG_PT_ATTR(trans_delay_msecs, S_IRUGO | S_IWUSR); /* + * implicit_trans_secs + */ +static ssize_t target_core_alua_tg_pt_gp_show_attr_implicit_trans_secs( + struct t10_alua_tg_pt_gp *tg_pt_gp, + char *page) +{ + return core_alua_show_implicit_trans_secs(tg_pt_gp, page); +} + +static ssize_t target_core_alua_tg_pt_gp_store_attr_implicit_trans_secs( + struct t10_alua_tg_pt_gp *tg_pt_gp, + const char *page, + size_t count) +{ + return core_alua_store_implicit_trans_secs(tg_pt_gp, page, count); +} + +SE_DEV_ALUA_TG_PT_ATTR(implicit_trans_secs, S_IRUGO | S_IWUSR); + +/* * preferred */ @@ -2511,7 +2540,7 @@ static ssize_t target_core_alua_tg_pt_gp_show_attr_tg_pt_gp_id( struct t10_alua_tg_pt_gp *tg_pt_gp, char *page) { - if (!(tg_pt_gp->tg_pt_gp_valid_id)) + if (!tg_pt_gp->tg_pt_gp_valid_id) return 0; return sprintf(page, "%hu\n", tg_pt_gp->tg_pt_gp_id); @@ -2526,14 +2555,14 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_tg_pt_gp_id( unsigned long tg_pt_gp_id; int ret; - ret = strict_strtoul(page, 0, &tg_pt_gp_id); + ret = kstrtoul(page, 0, &tg_pt_gp_id); if (ret < 0) { - printk(KERN_ERR "strict_strtoul() returned %d for" + pr_err("kstrtoul() returned %d for" " tg_pt_gp_id\n", ret); - return -EINVAL; + return ret; } if (tg_pt_gp_id > 0x0000ffff) { - printk(KERN_ERR "ALUA tg_pt_gp_id: %lu exceeds maximum:" + pr_err("ALUA tg_pt_gp_id: %lu exceeds maximum:" " 0x0000ffff\n", tg_pt_gp_id); return -EINVAL; } @@ -2542,7 +2571,7 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_tg_pt_gp_id( if (ret < 0) return -EINVAL; - printk(KERN_INFO "Target_Core_ConfigFS: Set ALUA Target Port Group: " + pr_debug("Target_Core_ConfigFS: Set ALUA Target Port Group: " "core/alua/tg_pt_gps/%s to ID: %hu\n", config_item_name(&alua_tg_pt_gp_cg->cg_item), tg_pt_gp->tg_pt_gp_id); @@ -2576,14 +2605,14 @@ static ssize_t target_core_alua_tg_pt_gp_show_attr_members( lun = port->sep_lun; cur_len = snprintf(buf, TG_PT_GROUP_NAME_BUF, "%s/%s/tpgt_%hu" - "/%s\n", TPG_TFO(tpg)->get_fabric_name(), - TPG_TFO(tpg)->tpg_get_wwn(tpg), - TPG_TFO(tpg)->tpg_get_tag(tpg), + "/%s\n", tpg->se_tpg_tfo->get_fabric_name(), + tpg->se_tpg_tfo->tpg_get_wwn(tpg), + tpg->se_tpg_tfo->tpg_get_tag(tpg), config_item_name(&lun->lun_group.cg_item)); cur_len++; /* Extra byte for NULL terminator */ if ((cur_len + len) > PAGE_SIZE) { - printk(KERN_WARNING "Ran out of lu_gp_show_attr" + pr_warn("Ran out of lu_gp_show_attr" "_members buffer\n"); break; } @@ -2604,9 +2633,17 @@ static struct configfs_attribute *target_core_alua_tg_pt_gp_attrs[] = { &target_core_alua_tg_pt_gp_alua_access_state.attr, &target_core_alua_tg_pt_gp_alua_access_status.attr, &target_core_alua_tg_pt_gp_alua_access_type.attr, + &target_core_alua_tg_pt_gp_alua_support_transitioning.attr, + &target_core_alua_tg_pt_gp_alua_support_offline.attr, + &target_core_alua_tg_pt_gp_alua_support_lba_dependent.attr, + &target_core_alua_tg_pt_gp_alua_support_unavailable.attr, + &target_core_alua_tg_pt_gp_alua_support_standby.attr, + &target_core_alua_tg_pt_gp_alua_support_active_nonoptimized.attr, + &target_core_alua_tg_pt_gp_alua_support_active_optimized.attr, &target_core_alua_tg_pt_gp_alua_write_metadata.attr, &target_core_alua_tg_pt_gp_nonop_delay_msecs.attr, &target_core_alua_tg_pt_gp_trans_delay_msecs.attr, + &target_core_alua_tg_pt_gp_implicit_trans_secs.attr, &target_core_alua_tg_pt_gp_preferred.attr, &target_core_alua_tg_pt_gp_tg_pt_gp_id.attr, &target_core_alua_tg_pt_gp_members.attr, @@ -2644,12 +2681,11 @@ static struct config_group *target_core_alua_create_tg_pt_gp( struct t10_alua *alua = container_of(group, struct t10_alua, alua_tg_pt_gps_group); struct t10_alua_tg_pt_gp *tg_pt_gp; - struct se_subsystem_dev *su_dev = alua->t10_sub_dev; struct config_group *alua_tg_pt_gp_cg = NULL; struct config_item *alua_tg_pt_gp_ci = NULL; - tg_pt_gp = core_alua_allocate_tg_pt_gp(su_dev, name, 0); - if (!(tg_pt_gp)) + tg_pt_gp = core_alua_allocate_tg_pt_gp(alua->t10_dev, name, 0); + if (!tg_pt_gp) return NULL; alua_tg_pt_gp_cg = &tg_pt_gp->tg_pt_gp_group; @@ -2658,7 +2694,7 @@ static struct config_group *target_core_alua_create_tg_pt_gp( config_group_init_type_name(alua_tg_pt_gp_cg, name, &target_core_alua_tg_pt_gp_cit); - printk(KERN_INFO "Target_Core_ConfigFS: Allocated ALUA Target Port" + pr_debug("Target_Core_ConfigFS: Allocated ALUA Target Port" " Group: alua/tg_pt_gps/%s\n", config_item_name(alua_tg_pt_gp_ci)); @@ -2672,7 +2708,7 @@ static void target_core_alua_drop_tg_pt_gp( struct t10_alua_tg_pt_gp *tg_pt_gp = container_of(to_config_group(item), struct t10_alua_tg_pt_gp, tg_pt_gp_group); - printk(KERN_INFO "Target_Core_ConfigFS: Releasing ALUA Target Port" + pr_debug("Target_Core_ConfigFS: Releasing ALUA Target Port" " Group: alua/tg_pt_gps/%s, ID: %hu\n", config_item_name(item), tg_pt_gp->tg_pt_gp_id); /* @@ -2745,10 +2781,10 @@ static struct config_group *target_core_make_subdev( const char *name) { struct t10_alua_tg_pt_gp *tg_pt_gp; - struct se_subsystem_dev *se_dev; struct se_subsystem_api *t; struct config_item *hba_ci = &group->cg_item; struct se_hba *hba = item_to_hba(hba_ci); + struct se_device *dev; struct config_group *dev_cg = NULL, *tg_pt_gp_cg = NULL; struct config_group *dev_stat_grp = NULL; int errno = -ENOMEM, ret; @@ -2761,124 +2797,80 @@ static struct config_group *target_core_make_subdev( */ t = hba->transport; - se_dev = kzalloc(sizeof(struct se_subsystem_dev), GFP_KERNEL); - if (!se_dev) { - printk(KERN_ERR "Unable to allocate memory for" - " struct se_subsystem_dev\n"); - goto unlock; - } - INIT_LIST_HEAD(&se_dev->g_se_dev_list); - INIT_LIST_HEAD(&se_dev->t10_wwn.t10_vpd_list); - spin_lock_init(&se_dev->t10_wwn.t10_vpd_lock); - INIT_LIST_HEAD(&se_dev->t10_reservation.registration_list); - INIT_LIST_HEAD(&se_dev->t10_reservation.aptpl_reg_list); - spin_lock_init(&se_dev->t10_reservation.registration_lock); - spin_lock_init(&se_dev->t10_reservation.aptpl_reg_lock); - INIT_LIST_HEAD(&se_dev->t10_alua.tg_pt_gps_list); - spin_lock_init(&se_dev->t10_alua.tg_pt_gps_lock); - spin_lock_init(&se_dev->se_dev_lock); - se_dev->t10_reservation.pr_aptpl_buf_len = PR_APTPL_BUF_LEN; - se_dev->t10_wwn.t10_sub_dev = se_dev; - se_dev->t10_alua.t10_sub_dev = se_dev; - se_dev->se_dev_attrib.da_sub_dev = se_dev; - - se_dev->se_dev_hba = hba; - dev_cg = &se_dev->se_dev_group; - - dev_cg->default_groups = kzalloc(sizeof(struct config_group) * 7, + dev = target_alloc_device(hba, name); + if (!dev) + goto out_unlock; + + dev_cg = &dev->dev_group; + + dev_cg->default_groups = kmalloc(sizeof(struct config_group *) * 6, GFP_KERNEL); - if (!(dev_cg->default_groups)) - goto out; - /* - * Set se_dev_su_ptr from struct se_subsystem_api returned void ptr - * for ->allocate_virtdevice() - * - * se_dev->se_dev_ptr will be set after ->create_virtdev() - * has been called successfully in the next level up in the - * configfs tree for device object's struct config_group. - */ - se_dev->se_dev_su_ptr = t->allocate_virtdevice(hba, name); - if (!(se_dev->se_dev_su_ptr)) { - printk(KERN_ERR "Unable to locate subsystem dependent pointer" - " from allocate_virtdevice()\n"); - goto out; - } - spin_lock(&se_global->g_device_lock); - list_add_tail(&se_dev->g_se_dev_list, &se_global->g_se_dev_list); - spin_unlock(&se_global->g_device_lock); + if (!dev_cg->default_groups) + goto out_free_device; - config_group_init_type_name(&se_dev->se_dev_group, name, - &target_core_dev_cit); - config_group_init_type_name(&se_dev->se_dev_attrib.da_group, "attrib", + config_group_init_type_name(dev_cg, name, &target_core_dev_cit); + config_group_init_type_name(&dev->dev_attrib.da_group, "attrib", &target_core_dev_attrib_cit); - config_group_init_type_name(&se_dev->se_dev_pr_group, "pr", + config_group_init_type_name(&dev->dev_pr_group, "pr", &target_core_dev_pr_cit); - config_group_init_type_name(&se_dev->t10_wwn.t10_wwn_group, "wwn", + config_group_init_type_name(&dev->t10_wwn.t10_wwn_group, "wwn", &target_core_dev_wwn_cit); - config_group_init_type_name(&se_dev->t10_alua.alua_tg_pt_gps_group, + config_group_init_type_name(&dev->t10_alua.alua_tg_pt_gps_group, "alua", &target_core_alua_tg_pt_gps_cit); - config_group_init_type_name(&se_dev->dev_stat_grps.stat_group, + config_group_init_type_name(&dev->dev_stat_grps.stat_group, "statistics", &target_core_stat_cit); - dev_cg->default_groups[0] = &se_dev->se_dev_attrib.da_group; - dev_cg->default_groups[1] = &se_dev->se_dev_pr_group; - dev_cg->default_groups[2] = &se_dev->t10_wwn.t10_wwn_group; - dev_cg->default_groups[3] = &se_dev->t10_alua.alua_tg_pt_gps_group; - dev_cg->default_groups[4] = &se_dev->dev_stat_grps.stat_group; + dev_cg->default_groups[0] = &dev->dev_attrib.da_group; + dev_cg->default_groups[1] = &dev->dev_pr_group; + dev_cg->default_groups[2] = &dev->t10_wwn.t10_wwn_group; + dev_cg->default_groups[3] = &dev->t10_alua.alua_tg_pt_gps_group; + dev_cg->default_groups[4] = &dev->dev_stat_grps.stat_group; dev_cg->default_groups[5] = NULL; /* * Add core/$HBA/$DEV/alua/default_tg_pt_gp */ - tg_pt_gp = core_alua_allocate_tg_pt_gp(se_dev, "default_tg_pt_gp", 1); - if (!(tg_pt_gp)) - goto out; + tg_pt_gp = core_alua_allocate_tg_pt_gp(dev, "default_tg_pt_gp", 1); + if (!tg_pt_gp) + goto out_free_dev_cg_default_groups; + dev->t10_alua.default_tg_pt_gp = tg_pt_gp; - tg_pt_gp_cg = &T10_ALUA(se_dev)->alua_tg_pt_gps_group; - tg_pt_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, + tg_pt_gp_cg = &dev->t10_alua.alua_tg_pt_gps_group; + tg_pt_gp_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); - if (!(tg_pt_gp_cg->default_groups)) { - printk(KERN_ERR "Unable to allocate tg_pt_gp_cg->" + if (!tg_pt_gp_cg->default_groups) { + pr_err("Unable to allocate tg_pt_gp_cg->" "default_groups\n"); - goto out; + goto out_free_tg_pt_gp; } config_group_init_type_name(&tg_pt_gp->tg_pt_gp_group, "default_tg_pt_gp", &target_core_alua_tg_pt_gp_cit); tg_pt_gp_cg->default_groups[0] = &tg_pt_gp->tg_pt_gp_group; tg_pt_gp_cg->default_groups[1] = NULL; - T10_ALUA(se_dev)->default_tg_pt_gp = tg_pt_gp; /* * Add core/$HBA/$DEV/statistics/ default groups */ - dev_stat_grp = &DEV_STAT_GRP(se_dev)->stat_group; - dev_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 4, + dev_stat_grp = &dev->dev_stat_grps.stat_group; + dev_stat_grp->default_groups = kmalloc(sizeof(struct config_group *) * 4, GFP_KERNEL); if (!dev_stat_grp->default_groups) { - printk(KERN_ERR "Unable to allocate dev_stat_grp->default_groups\n"); - goto out; + pr_err("Unable to allocate dev_stat_grp->default_groups\n"); + goto out_free_tg_pt_gp_cg_default_groups; } - target_stat_setup_dev_default_groups(se_dev); - - printk(KERN_INFO "Target_Core_ConfigFS: Allocated struct se_subsystem_dev:" - " %p se_dev_su_ptr: %p\n", se_dev, se_dev->se_dev_su_ptr); + target_stat_setup_dev_default_groups(dev); mutex_unlock(&hba->hba_access_mutex); - return &se_dev->se_dev_group; -out: - if (T10_ALUA(se_dev)->default_tg_pt_gp) { - core_alua_free_tg_pt_gp(T10_ALUA(se_dev)->default_tg_pt_gp); - T10_ALUA(se_dev)->default_tg_pt_gp = NULL; - } - if (dev_stat_grp) - kfree(dev_stat_grp->default_groups); - if (tg_pt_gp_cg) - kfree(tg_pt_gp_cg->default_groups); - if (dev_cg) - kfree(dev_cg->default_groups); - if (se_dev->se_dev_su_ptr) - t->free_device(se_dev->se_dev_su_ptr); - kfree(se_dev); -unlock: + return dev_cg; + +out_free_tg_pt_gp_cg_default_groups: + kfree(tg_pt_gp_cg->default_groups); +out_free_tg_pt_gp: + core_alua_free_tg_pt_gp(tg_pt_gp); +out_free_dev_cg_default_groups: + kfree(dev_cg->default_groups); +out_free_device: + target_free_device(dev); +out_unlock: mutex_unlock(&hba->hba_access_mutex); return ERR_PTR(errno); } @@ -2887,24 +2879,19 @@ static void target_core_drop_subdev( struct config_group *group, struct config_item *item) { - struct se_subsystem_dev *se_dev = container_of(to_config_group(item), - struct se_subsystem_dev, se_dev_group); + struct config_group *dev_cg = to_config_group(item); + struct se_device *dev = + container_of(dev_cg, struct se_device, dev_group); struct se_hba *hba; - struct se_subsystem_api *t; struct config_item *df_item; - struct config_group *dev_cg, *tg_pt_gp_cg, *dev_stat_grp; + struct config_group *tg_pt_gp_cg, *dev_stat_grp; int i; - hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item); + hba = item_to_hba(&dev->se_hba->hba_group.cg_item); mutex_lock(&hba->hba_access_mutex); - t = hba->transport; - - spin_lock(&se_global->g_device_lock); - list_del(&se_dev->g_se_dev_list); - spin_unlock(&se_global->g_device_lock); - dev_stat_grp = &DEV_STAT_GRP(se_dev)->stat_group; + dev_stat_grp = &dev->dev_stat_grps.stat_group; for (i = 0; dev_stat_grp->default_groups[i]; i++) { df_item = &dev_stat_grp->default_groups[i]->cg_item; dev_stat_grp->default_groups[i] = NULL; @@ -2912,7 +2899,7 @@ static void target_core_drop_subdev( } kfree(dev_stat_grp->default_groups); - tg_pt_gp_cg = &T10_ALUA(se_dev)->alua_tg_pt_gps_group; + tg_pt_gp_cg = &dev->t10_alua.alua_tg_pt_gps_group; for (i = 0; tg_pt_gp_cg->default_groups[i]; i++) { df_item = &tg_pt_gp_cg->default_groups[i]->cg_item; tg_pt_gp_cg->default_groups[i] = NULL; @@ -2923,17 +2910,15 @@ static void target_core_drop_subdev( * core_alua_free_tg_pt_gp() is called from ->default_tg_pt_gp * directly from target_core_alua_tg_pt_gp_release(). */ - T10_ALUA(se_dev)->default_tg_pt_gp = NULL; + dev->t10_alua.default_tg_pt_gp = NULL; - dev_cg = &se_dev->se_dev_group; for (i = 0; dev_cg->default_groups[i]; i++) { df_item = &dev_cg->default_groups[i]->cg_item; dev_cg->default_groups[i] = NULL; config_item_put(df_item); } /* - * The releasing of se_dev and associated se_dev->se_dev_ptr is done - * from target_core_dev_item_ops->release() ->target_core_dev_release(). + * se_dev is released from target_core_dev_item_ops->release() */ config_item_put(item); mutex_unlock(&hba->hba_access_mutex); @@ -2990,19 +2975,16 @@ static ssize_t target_core_hba_store_attr_hba_mode(struct se_hba *hba, if (transport->pmode_enable_hba == NULL) return -EINVAL; - ret = strict_strtoul(page, 0, &mode_flag); + ret = kstrtoul(page, 0, &mode_flag); if (ret < 0) { - printk(KERN_ERR "Unable to extract hba mode flag: %d\n", ret); - return -EINVAL; + pr_err("Unable to extract hba mode flag: %d\n", ret); + return ret; } - spin_lock(&hba->device_lock); - if (!(list_empty(&hba->hba_dev_list))) { - printk(KERN_ERR "Unable to set hba_mode with active devices\n"); - spin_unlock(&hba->device_lock); + if (hba->dev_count) { + pr_err("Unable to set hba_mode with active devices\n"); return -EINVAL; } - spin_unlock(&hba->device_lock); ret = transport->pmode_enable_hba(hba, mode_flag); if (ret < 0) @@ -3056,8 +3038,8 @@ static struct config_group *target_core_call_addhbatotarget( int ret; memset(buf, 0, TARGET_CORE_NAME_MAX_LEN); - if (strlen(name) > TARGET_CORE_NAME_MAX_LEN) { - printk(KERN_ERR "Passed *name strlen(): %d exceeds" + if (strlen(name) >= TARGET_CORE_NAME_MAX_LEN) { + pr_err("Passed *name strlen(): %d exceeds" " TARGET_CORE_NAME_MAX_LEN: %d\n", (int)strlen(name), TARGET_CORE_NAME_MAX_LEN); return ERR_PTR(-ENAMETOOLONG); @@ -3065,8 +3047,8 @@ static struct config_group *target_core_call_addhbatotarget( snprintf(buf, TARGET_CORE_NAME_MAX_LEN, "%s", name); str = strstr(buf, "_"); - if (!(str)) { - printk(KERN_ERR "Unable to locate \"_\" for $SUBSYSTEM_PLUGIN_$HOST_ID\n"); + if (!str) { + pr_err("Unable to locate \"_\" for $SUBSYSTEM_PLUGIN_$HOST_ID\n"); return ERR_PTR(-EINVAL); } se_plugin_str = buf; @@ -3075,7 +3057,7 @@ static struct config_group *target_core_call_addhbatotarget( * Namely rd_direct and rd_mcp.. */ str2 = strstr(str+1, "_"); - if ((str2)) { + if (str2) { *str2 = '\0'; /* Terminate for *se_plugin_str */ str2++; /* Skip to start of plugin dependent ID */ str = str2; @@ -3084,17 +3066,16 @@ static struct config_group *target_core_call_addhbatotarget( str++; /* Skip to start of plugin dependent ID */ } - ret = strict_strtoul(str, 0, &plugin_dep_id); + ret = kstrtoul(str, 0, &plugin_dep_id); if (ret < 0) { - printk(KERN_ERR "strict_strtoul() returned %d for" + pr_err("kstrtoul() returned %d for" " plugin_dep_id\n", ret); - return ERR_PTR(-EINVAL); + return ERR_PTR(ret); } /* * Load up TCM subsystem plugins if they have not already been loaded. */ - if (transport_subsystem_check_init() < 0) - return ERR_PTR(-EINVAL); + transport_subsystem_check_init(); hba = core_alloc_hba(se_plugin_str, plugin_dep_id, 0); if (IS_ERR(hba)) @@ -3139,7 +3120,7 @@ static int __init target_core_init_configfs(void) struct t10_alua_lu_gp *lu_gp; int ret; - printk(KERN_INFO "TARGET_CORE[0]: Loading Generic Kernel Storage" + pr_debug("TARGET_CORE[0]: Loading Generic Kernel Storage" " Engine: %s on %s/%s on "UTS_RELEASE"\n", TARGET_CORE_VERSION, utsname()->sysname, utsname()->machine); @@ -3147,70 +3128,73 @@ static int __init target_core_init_configfs(void) config_group_init(&subsys->su_group); mutex_init(&subsys->su_mutex); - INIT_LIST_HEAD(&g_tf_list); - mutex_init(&g_tf_lock); - init_scsi_index_table(); - ret = init_se_global(); + ret = init_se_kmem_caches(); if (ret < 0) - return -1; + return ret; /* * Create $CONFIGFS/target/core default group for HBA <-> Storage Object * and ALUA Logical Unit Group and Target Port Group infrastructure. */ target_cg = &subsys->su_group; - target_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, + target_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); - if (!(target_cg->default_groups)) { - printk(KERN_ERR "Unable to allocate target_cg->default_groups\n"); + if (!target_cg->default_groups) { + pr_err("Unable to allocate target_cg->default_groups\n"); + ret = -ENOMEM; goto out_global; } - config_group_init_type_name(&se_global->target_core_hbagroup, + config_group_init_type_name(&target_core_hbagroup, "core", &target_core_cit); - target_cg->default_groups[0] = &se_global->target_core_hbagroup; + target_cg->default_groups[0] = &target_core_hbagroup; target_cg->default_groups[1] = NULL; /* * Create ALUA infrastructure under /sys/kernel/config/target/core/alua/ */ - hba_cg = &se_global->target_core_hbagroup; - hba_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, + hba_cg = &target_core_hbagroup; + hba_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); - if (!(hba_cg->default_groups)) { - printk(KERN_ERR "Unable to allocate hba_cg->default_groups\n"); + if (!hba_cg->default_groups) { + pr_err("Unable to allocate hba_cg->default_groups\n"); + ret = -ENOMEM; goto out_global; } - config_group_init_type_name(&se_global->alua_group, + config_group_init_type_name(&alua_group, "alua", &target_core_alua_cit); - hba_cg->default_groups[0] = &se_global->alua_group; + hba_cg->default_groups[0] = &alua_group; hba_cg->default_groups[1] = NULL; /* * Add ALUA Logical Unit Group and Target Port Group ConfigFS * groups under /sys/kernel/config/target/core/alua/ */ - alua_cg = &se_global->alua_group; - alua_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, + alua_cg = &alua_group; + alua_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); - if (!(alua_cg->default_groups)) { - printk(KERN_ERR "Unable to allocate alua_cg->default_groups\n"); + if (!alua_cg->default_groups) { + pr_err("Unable to allocate alua_cg->default_groups\n"); + ret = -ENOMEM; goto out_global; } - config_group_init_type_name(&se_global->alua_lu_gps_group, + config_group_init_type_name(&alua_lu_gps_group, "lu_gps", &target_core_alua_lu_gps_cit); - alua_cg->default_groups[0] = &se_global->alua_lu_gps_group; + alua_cg->default_groups[0] = &alua_lu_gps_group; alua_cg->default_groups[1] = NULL; /* * Add core/alua/lu_gps/default_lu_gp */ lu_gp = core_alua_allocate_lu_gp("default_lu_gp", 1); - if (IS_ERR(lu_gp)) + if (IS_ERR(lu_gp)) { + ret = -ENOMEM; goto out_global; + } - lu_gp_cg = &se_global->alua_lu_gps_group; - lu_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, + lu_gp_cg = &alua_lu_gps_group; + lu_gp_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2, GFP_KERNEL); - if (!(lu_gp_cg->default_groups)) { - printk(KERN_ERR "Unable to allocate lu_gp_cg->default_groups\n"); + if (!lu_gp_cg->default_groups) { + pr_err("Unable to allocate lu_gp_cg->default_groups\n"); + ret = -ENOMEM; goto out_global; } @@ -3218,17 +3202,17 @@ static int __init target_core_init_configfs(void) &target_core_alua_lu_gp_cit); lu_gp_cg->default_groups[0] = &lu_gp->lu_gp_group; lu_gp_cg->default_groups[1] = NULL; - se_global->default_lu_gp = lu_gp; + default_lu_gp = lu_gp; /* * Register the target_core_mod subsystem with configfs. */ ret = configfs_register_subsystem(subsys); if (ret < 0) { - printk(KERN_ERR "Error %d while registering subsystem %s\n", + pr_err("Error %d while registering subsystem %s\n", ret, subsys->su_group.cg_item.ci_namebuf); goto out_global; } - printk(KERN_INFO "TARGET_CORE[0]: Initialized ConfigFS Fabric" + pr_debug("TARGET_CORE[0]: Initialized ConfigFS Fabric" " Infrastructure: "TARGET_CORE_CONFIGFS_VERSION" on %s/%s" " on "UTS_RELEASE"\n", utsname()->sysname, utsname()->machine); /* @@ -3238,7 +3222,12 @@ static int __init target_core_init_configfs(void) if (ret < 0) goto out; - if (core_dev_setup_virtual_lun0() < 0) + ret = core_dev_setup_virtual_lun0(); + if (ret < 0) + goto out; + + ret = target_xcopy_setup_pt(); + if (ret < 0) goto out; return 0; @@ -3248,9 +3237,9 @@ out: core_dev_release_virtual_lun0(); rd_module_exit(); out_global: - if (se_global->default_lu_gp) { - core_alua_free_lu_gp(se_global->default_lu_gp); - se_global->default_lu_gp = NULL; + if (default_lu_gp) { + core_alua_free_lu_gp(default_lu_gp); + default_lu_gp = NULL; } if (lu_gp_cg) kfree(lu_gp_cg->default_groups); @@ -3259,8 +3248,8 @@ out_global: if (hba_cg) kfree(hba_cg->default_groups); kfree(target_cg->default_groups); - release_se_global(); - return -1; + release_se_kmem_caches(); + return ret; } static void __exit target_core_exit_configfs(void) @@ -3270,10 +3259,9 @@ static void __exit target_core_exit_configfs(void) struct config_item *item; int i; - se_global->in_shutdown = 1; subsys = target_core_subsystem[0]; - lu_gp_cg = &se_global->alua_lu_gps_group; + lu_gp_cg = &alua_lu_gps_group; for (i = 0; lu_gp_cg->default_groups[i]; i++) { item = &lu_gp_cg->default_groups[i]->cg_item; lu_gp_cg->default_groups[i] = NULL; @@ -3282,7 +3270,7 @@ static void __exit target_core_exit_configfs(void) kfree(lu_gp_cg->default_groups); lu_gp_cg->default_groups = NULL; - alua_cg = &se_global->alua_group; + alua_cg = &alua_group; for (i = 0; alua_cg->default_groups[i]; i++) { item = &alua_cg->default_groups[i]->cg_item; alua_cg->default_groups[i] = NULL; @@ -3291,7 +3279,7 @@ static void __exit target_core_exit_configfs(void) kfree(alua_cg->default_groups); alua_cg->default_groups = NULL; - hba_cg = &se_global->target_core_hbagroup; + hba_cg = &target_core_hbagroup; for (i = 0; hba_cg->default_groups[i]; i++) { item = &hba_cg->default_groups[i]->cg_item; hba_cg->default_groups[i] = NULL; @@ -3306,17 +3294,16 @@ static void __exit target_core_exit_configfs(void) configfs_unregister_subsystem(subsys); kfree(subsys->su_group.default_groups); - core_alua_free_lu_gp(se_global->default_lu_gp); - se_global->default_lu_gp = NULL; + core_alua_free_lu_gp(default_lu_gp); + default_lu_gp = NULL; - printk(KERN_INFO "TARGET_CORE[0]: Released ConfigFS Fabric" + pr_debug("TARGET_CORE[0]: Released ConfigFS Fabric" " Infrastructure\n"); core_dev_release_virtual_lun0(); rd_module_exit(); - release_se_global(); - - return; + target_xcopy_release_pt(); + release_se_kmem_caches(); } MODULE_DESCRIPTION("Target_Core_Mod/ConfigFS"); |
