1c66ac9dbSNicholas Bellinger /******************************************************************************* 2c66ac9dbSNicholas Bellinger * Filename: target_core_configfs.c 3c66ac9dbSNicholas Bellinger * 4c66ac9dbSNicholas Bellinger * This file contains ConfigFS logic for the Generic Target Engine project. 5c66ac9dbSNicholas Bellinger * 612d23384SNicholas Bellinger * Copyright (c) 2008-2011 Rising Tide Systems 712d23384SNicholas Bellinger * Copyright (c) 2008-2011 Linux-iSCSI.org 8c66ac9dbSNicholas Bellinger * 9c66ac9dbSNicholas Bellinger * Nicholas A. Bellinger <nab@kernel.org> 10c66ac9dbSNicholas Bellinger * 11c66ac9dbSNicholas Bellinger * based on configfs Copyright (C) 2005 Oracle. All rights reserved. 12c66ac9dbSNicholas Bellinger * 13c66ac9dbSNicholas Bellinger * This program is free software; you can redistribute it and/or modify 14c66ac9dbSNicholas Bellinger * it under the terms of the GNU General Public License as published by 15c66ac9dbSNicholas Bellinger * the Free Software Foundation; either version 2 of the License, or 16c66ac9dbSNicholas Bellinger * (at your option) any later version. 17c66ac9dbSNicholas Bellinger * 18c66ac9dbSNicholas Bellinger * This program is distributed in the hope that it will be useful, 19c66ac9dbSNicholas Bellinger * but WITHOUT ANY WARRANTY; without even the implied warranty of 20c66ac9dbSNicholas Bellinger * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21c66ac9dbSNicholas Bellinger * GNU General Public License for more details. 22c66ac9dbSNicholas Bellinger ****************************************************************************/ 23c66ac9dbSNicholas Bellinger 24c66ac9dbSNicholas Bellinger #include <linux/module.h> 25c66ac9dbSNicholas Bellinger #include <linux/moduleparam.h> 26c66ac9dbSNicholas Bellinger #include <linux/version.h> 27c66ac9dbSNicholas Bellinger #include <generated/utsrelease.h> 28c66ac9dbSNicholas Bellinger #include <linux/utsname.h> 29c66ac9dbSNicholas Bellinger #include <linux/init.h> 30c66ac9dbSNicholas Bellinger #include <linux/fs.h> 31c66ac9dbSNicholas Bellinger #include <linux/namei.h> 32c66ac9dbSNicholas Bellinger #include <linux/slab.h> 33c66ac9dbSNicholas Bellinger #include <linux/types.h> 34c66ac9dbSNicholas Bellinger #include <linux/delay.h> 35c66ac9dbSNicholas Bellinger #include <linux/unistd.h> 36c66ac9dbSNicholas Bellinger #include <linux/string.h> 37c66ac9dbSNicholas Bellinger #include <linux/parser.h> 38c66ac9dbSNicholas Bellinger #include <linux/syscalls.h> 39c66ac9dbSNicholas Bellinger #include <linux/configfs.h> 40e3d6f909SAndy Grover #include <linux/spinlock.h> 41c66ac9dbSNicholas Bellinger 42c66ac9dbSNicholas Bellinger #include <target/target_core_base.h> 43c66ac9dbSNicholas Bellinger #include <target/target_core_device.h> 44c66ac9dbSNicholas Bellinger #include <target/target_core_transport.h> 45c66ac9dbSNicholas Bellinger #include <target/target_core_fabric_ops.h> 46c66ac9dbSNicholas Bellinger #include <target/target_core_fabric_configfs.h> 47c66ac9dbSNicholas Bellinger #include <target/target_core_configfs.h> 48c66ac9dbSNicholas Bellinger #include <target/configfs_macros.h> 49c66ac9dbSNicholas Bellinger 50c66ac9dbSNicholas Bellinger #include "target_core_alua.h" 51c66ac9dbSNicholas Bellinger #include "target_core_hba.h" 52c66ac9dbSNicholas Bellinger #include "target_core_pr.h" 53c66ac9dbSNicholas Bellinger #include "target_core_rd.h" 5412d23384SNicholas Bellinger #include "target_core_stat.h" 55c66ac9dbSNicholas Bellinger 56e3d6f909SAndy Grover extern struct t10_alua_lu_gp *default_lu_gp; 57e3d6f909SAndy Grover 58c66ac9dbSNicholas Bellinger static struct list_head g_tf_list; 59c66ac9dbSNicholas Bellinger static struct mutex g_tf_lock; 60c66ac9dbSNicholas Bellinger 61c66ac9dbSNicholas Bellinger struct target_core_configfs_attribute { 62c66ac9dbSNicholas Bellinger struct configfs_attribute attr; 63c66ac9dbSNicholas Bellinger ssize_t (*show)(void *, char *); 64c66ac9dbSNicholas Bellinger ssize_t (*store)(void *, const char *, size_t); 65c66ac9dbSNicholas Bellinger }; 66c66ac9dbSNicholas Bellinger 67e3d6f909SAndy Grover static struct config_group target_core_hbagroup; 68e3d6f909SAndy Grover static struct config_group alua_group; 69e3d6f909SAndy Grover static struct config_group alua_lu_gps_group; 70e3d6f909SAndy Grover 71e3d6f909SAndy Grover static DEFINE_SPINLOCK(se_device_lock); 72e3d6f909SAndy Grover static LIST_HEAD(se_dev_list); 73e3d6f909SAndy Grover 74c66ac9dbSNicholas Bellinger static inline struct se_hba * 75c66ac9dbSNicholas Bellinger item_to_hba(struct config_item *item) 76c66ac9dbSNicholas Bellinger { 77c66ac9dbSNicholas Bellinger return container_of(to_config_group(item), struct se_hba, hba_group); 78c66ac9dbSNicholas Bellinger } 79c66ac9dbSNicholas Bellinger 80c66ac9dbSNicholas Bellinger /* 81c66ac9dbSNicholas Bellinger * Attributes for /sys/kernel/config/target/ 82c66ac9dbSNicholas Bellinger */ 83c66ac9dbSNicholas Bellinger static ssize_t target_core_attr_show(struct config_item *item, 84c66ac9dbSNicholas Bellinger struct configfs_attribute *attr, 85c66ac9dbSNicholas Bellinger char *page) 86c66ac9dbSNicholas Bellinger { 87c66ac9dbSNicholas Bellinger return sprintf(page, "Target Engine Core ConfigFS Infrastructure %s" 88c66ac9dbSNicholas Bellinger " on %s/%s on "UTS_RELEASE"\n", TARGET_CORE_CONFIGFS_VERSION, 89c66ac9dbSNicholas Bellinger utsname()->sysname, utsname()->machine); 90c66ac9dbSNicholas Bellinger } 91c66ac9dbSNicholas Bellinger 92c66ac9dbSNicholas Bellinger static struct configfs_item_operations target_core_fabric_item_ops = { 93c66ac9dbSNicholas Bellinger .show_attribute = target_core_attr_show, 94c66ac9dbSNicholas Bellinger }; 95c66ac9dbSNicholas Bellinger 96c66ac9dbSNicholas Bellinger static struct configfs_attribute target_core_item_attr_version = { 97c66ac9dbSNicholas Bellinger .ca_owner = THIS_MODULE, 98c66ac9dbSNicholas Bellinger .ca_name = "version", 99c66ac9dbSNicholas Bellinger .ca_mode = S_IRUGO, 100c66ac9dbSNicholas Bellinger }; 101c66ac9dbSNicholas Bellinger 102c66ac9dbSNicholas Bellinger static struct target_fabric_configfs *target_core_get_fabric( 103c66ac9dbSNicholas Bellinger const char *name) 104c66ac9dbSNicholas Bellinger { 105c66ac9dbSNicholas Bellinger struct target_fabric_configfs *tf; 106c66ac9dbSNicholas Bellinger 107c66ac9dbSNicholas Bellinger if (!(name)) 108c66ac9dbSNicholas Bellinger return NULL; 109c66ac9dbSNicholas Bellinger 110c66ac9dbSNicholas Bellinger mutex_lock(&g_tf_lock); 111c66ac9dbSNicholas Bellinger list_for_each_entry(tf, &g_tf_list, tf_list) { 112c66ac9dbSNicholas Bellinger if (!(strcmp(tf->tf_name, name))) { 113c66ac9dbSNicholas Bellinger atomic_inc(&tf->tf_access_cnt); 114c66ac9dbSNicholas Bellinger mutex_unlock(&g_tf_lock); 115c66ac9dbSNicholas Bellinger return tf; 116c66ac9dbSNicholas Bellinger } 117c66ac9dbSNicholas Bellinger } 118c66ac9dbSNicholas Bellinger mutex_unlock(&g_tf_lock); 119c66ac9dbSNicholas Bellinger 120c66ac9dbSNicholas Bellinger return NULL; 121c66ac9dbSNicholas Bellinger } 122c66ac9dbSNicholas Bellinger 123c66ac9dbSNicholas Bellinger /* 124c66ac9dbSNicholas Bellinger * Called from struct target_core_group_ops->make_group() 125c66ac9dbSNicholas Bellinger */ 126c66ac9dbSNicholas Bellinger static struct config_group *target_core_register_fabric( 127c66ac9dbSNicholas Bellinger struct config_group *group, 128c66ac9dbSNicholas Bellinger const char *name) 129c66ac9dbSNicholas Bellinger { 130c66ac9dbSNicholas Bellinger struct target_fabric_configfs *tf; 131c66ac9dbSNicholas Bellinger int ret; 132c66ac9dbSNicholas Bellinger 133c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: REGISTER -> group: %p name:" 134c66ac9dbSNicholas Bellinger " %s\n", group, name); 135c66ac9dbSNicholas Bellinger /* 136c66ac9dbSNicholas Bellinger * Ensure that TCM subsystem plugins are loaded at this point for 137c66ac9dbSNicholas Bellinger * using the RAMDISK_DR virtual LUN 0 and all other struct se_port 138c66ac9dbSNicholas Bellinger * LUN symlinks. 139c66ac9dbSNicholas Bellinger */ 140c66ac9dbSNicholas Bellinger if (transport_subsystem_check_init() < 0) 141c66ac9dbSNicholas Bellinger return ERR_PTR(-EINVAL); 142c66ac9dbSNicholas Bellinger 143c66ac9dbSNicholas Bellinger /* 144c66ac9dbSNicholas Bellinger * Below are some hardcoded request_module() calls to automatically 145c66ac9dbSNicholas Bellinger * local fabric modules when the following is called: 146c66ac9dbSNicholas Bellinger * 147c66ac9dbSNicholas Bellinger * mkdir -p /sys/kernel/config/target/$MODULE_NAME 148c66ac9dbSNicholas Bellinger * 149c66ac9dbSNicholas Bellinger * Note that this does not limit which TCM fabric module can be 150c66ac9dbSNicholas Bellinger * registered, but simply provids auto loading logic for modules with 151c66ac9dbSNicholas Bellinger * mkdir(2) system calls with known TCM fabric modules. 152c66ac9dbSNicholas Bellinger */ 153c66ac9dbSNicholas Bellinger if (!(strncmp(name, "iscsi", 5))) { 154c66ac9dbSNicholas Bellinger /* 155c66ac9dbSNicholas Bellinger * Automatically load the LIO Target fabric module when the 156c66ac9dbSNicholas Bellinger * following is called: 157c66ac9dbSNicholas Bellinger * 158c66ac9dbSNicholas Bellinger * mkdir -p $CONFIGFS/target/iscsi 159c66ac9dbSNicholas Bellinger */ 160c66ac9dbSNicholas Bellinger ret = request_module("iscsi_target_mod"); 161c66ac9dbSNicholas Bellinger if (ret < 0) { 162c66ac9dbSNicholas Bellinger printk(KERN_ERR "request_module() failed for" 163c66ac9dbSNicholas Bellinger " iscsi_target_mod.ko: %d\n", ret); 164c66ac9dbSNicholas Bellinger return ERR_PTR(-EINVAL); 165c66ac9dbSNicholas Bellinger } 166c66ac9dbSNicholas Bellinger } else if (!(strncmp(name, "loopback", 8))) { 167c66ac9dbSNicholas Bellinger /* 168c66ac9dbSNicholas Bellinger * Automatically load the tcm_loop fabric module when the 169c66ac9dbSNicholas Bellinger * following is called: 170c66ac9dbSNicholas Bellinger * 171c66ac9dbSNicholas Bellinger * mkdir -p $CONFIGFS/target/loopback 172c66ac9dbSNicholas Bellinger */ 173c66ac9dbSNicholas Bellinger ret = request_module("tcm_loop"); 174c66ac9dbSNicholas Bellinger if (ret < 0) { 175c66ac9dbSNicholas Bellinger printk(KERN_ERR "request_module() failed for" 176c66ac9dbSNicholas Bellinger " tcm_loop.ko: %d\n", ret); 177c66ac9dbSNicholas Bellinger return ERR_PTR(-EINVAL); 178c66ac9dbSNicholas Bellinger } 179c66ac9dbSNicholas Bellinger } 180c66ac9dbSNicholas Bellinger 181c66ac9dbSNicholas Bellinger tf = target_core_get_fabric(name); 182c66ac9dbSNicholas Bellinger if (!(tf)) { 183c66ac9dbSNicholas Bellinger printk(KERN_ERR "target_core_get_fabric() failed for %s\n", 184c66ac9dbSNicholas Bellinger name); 185c66ac9dbSNicholas Bellinger return ERR_PTR(-EINVAL); 186c66ac9dbSNicholas Bellinger } 187c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: REGISTER -> Located fabric:" 188c66ac9dbSNicholas Bellinger " %s\n", tf->tf_name); 189c66ac9dbSNicholas Bellinger /* 190c66ac9dbSNicholas Bellinger * On a successful target_core_get_fabric() look, the returned 191c66ac9dbSNicholas Bellinger * struct target_fabric_configfs *tf will contain a usage reference. 192c66ac9dbSNicholas Bellinger */ 193c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: REGISTER tfc_wwn_cit -> %p\n", 194c66ac9dbSNicholas Bellinger &TF_CIT_TMPL(tf)->tfc_wwn_cit); 195c66ac9dbSNicholas Bellinger 196c66ac9dbSNicholas Bellinger tf->tf_group.default_groups = tf->tf_default_groups; 197c66ac9dbSNicholas Bellinger tf->tf_group.default_groups[0] = &tf->tf_disc_group; 198c66ac9dbSNicholas Bellinger tf->tf_group.default_groups[1] = NULL; 199c66ac9dbSNicholas Bellinger 200c66ac9dbSNicholas Bellinger config_group_init_type_name(&tf->tf_group, name, 201c66ac9dbSNicholas Bellinger &TF_CIT_TMPL(tf)->tfc_wwn_cit); 202c66ac9dbSNicholas Bellinger config_group_init_type_name(&tf->tf_disc_group, "discovery_auth", 203c66ac9dbSNicholas Bellinger &TF_CIT_TMPL(tf)->tfc_discovery_cit); 204c66ac9dbSNicholas Bellinger 205c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: REGISTER -> Allocated Fabric:" 206c66ac9dbSNicholas Bellinger " %s\n", tf->tf_group.cg_item.ci_name); 207c66ac9dbSNicholas Bellinger /* 208c66ac9dbSNicholas Bellinger * Setup tf_ops.tf_subsys pointer for usage with configfs_depend_item() 209c66ac9dbSNicholas Bellinger */ 210c66ac9dbSNicholas Bellinger tf->tf_ops.tf_subsys = tf->tf_subsys; 211c66ac9dbSNicholas Bellinger tf->tf_fabric = &tf->tf_group.cg_item; 212c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: REGISTER -> Set tf->tf_fabric" 213c66ac9dbSNicholas Bellinger " for %s\n", name); 214c66ac9dbSNicholas Bellinger 215c66ac9dbSNicholas Bellinger return &tf->tf_group; 216c66ac9dbSNicholas Bellinger } 217c66ac9dbSNicholas Bellinger 218c66ac9dbSNicholas Bellinger /* 219c66ac9dbSNicholas Bellinger * Called from struct target_core_group_ops->drop_item() 220c66ac9dbSNicholas Bellinger */ 221c66ac9dbSNicholas Bellinger static void target_core_deregister_fabric( 222c66ac9dbSNicholas Bellinger struct config_group *group, 223c66ac9dbSNicholas Bellinger struct config_item *item) 224c66ac9dbSNicholas Bellinger { 225c66ac9dbSNicholas Bellinger struct target_fabric_configfs *tf = container_of( 226c66ac9dbSNicholas Bellinger to_config_group(item), struct target_fabric_configfs, tf_group); 227c66ac9dbSNicholas Bellinger struct config_group *tf_group; 228c66ac9dbSNicholas Bellinger struct config_item *df_item; 229c66ac9dbSNicholas Bellinger int i; 230c66ac9dbSNicholas Bellinger 231c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: DEREGISTER -> Looking up %s in" 232c66ac9dbSNicholas Bellinger " tf list\n", config_item_name(item)); 233c66ac9dbSNicholas Bellinger 234c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: DEREGISTER -> located fabric:" 235c66ac9dbSNicholas Bellinger " %s\n", tf->tf_name); 236c66ac9dbSNicholas Bellinger atomic_dec(&tf->tf_access_cnt); 237c66ac9dbSNicholas Bellinger 238c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: DEREGISTER -> Releasing" 239c66ac9dbSNicholas Bellinger " tf->tf_fabric for %s\n", tf->tf_name); 240c66ac9dbSNicholas Bellinger tf->tf_fabric = NULL; 241c66ac9dbSNicholas Bellinger 242c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: DEREGISTER -> Releasing ci" 243c66ac9dbSNicholas Bellinger " %s\n", config_item_name(item)); 244c66ac9dbSNicholas Bellinger 245c66ac9dbSNicholas Bellinger tf_group = &tf->tf_group; 246c66ac9dbSNicholas Bellinger for (i = 0; tf_group->default_groups[i]; i++) { 247c66ac9dbSNicholas Bellinger df_item = &tf_group->default_groups[i]->cg_item; 248c66ac9dbSNicholas Bellinger tf_group->default_groups[i] = NULL; 249c66ac9dbSNicholas Bellinger config_item_put(df_item); 250c66ac9dbSNicholas Bellinger } 251c66ac9dbSNicholas Bellinger config_item_put(item); 252c66ac9dbSNicholas Bellinger } 253c66ac9dbSNicholas Bellinger 254c66ac9dbSNicholas Bellinger static struct configfs_group_operations target_core_fabric_group_ops = { 255c66ac9dbSNicholas Bellinger .make_group = &target_core_register_fabric, 256c66ac9dbSNicholas Bellinger .drop_item = &target_core_deregister_fabric, 257c66ac9dbSNicholas Bellinger }; 258c66ac9dbSNicholas Bellinger 259c66ac9dbSNicholas Bellinger /* 260c66ac9dbSNicholas Bellinger * All item attributes appearing in /sys/kernel/target/ appear here. 261c66ac9dbSNicholas Bellinger */ 262c66ac9dbSNicholas Bellinger static struct configfs_attribute *target_core_fabric_item_attrs[] = { 263c66ac9dbSNicholas Bellinger &target_core_item_attr_version, 264c66ac9dbSNicholas Bellinger NULL, 265c66ac9dbSNicholas Bellinger }; 266c66ac9dbSNicholas Bellinger 267c66ac9dbSNicholas Bellinger /* 268c66ac9dbSNicholas Bellinger * Provides Fabrics Groups and Item Attributes for /sys/kernel/config/target/ 269c66ac9dbSNicholas Bellinger */ 270c66ac9dbSNicholas Bellinger static struct config_item_type target_core_fabrics_item = { 271c66ac9dbSNicholas Bellinger .ct_item_ops = &target_core_fabric_item_ops, 272c66ac9dbSNicholas Bellinger .ct_group_ops = &target_core_fabric_group_ops, 273c66ac9dbSNicholas Bellinger .ct_attrs = target_core_fabric_item_attrs, 274c66ac9dbSNicholas Bellinger .ct_owner = THIS_MODULE, 275c66ac9dbSNicholas Bellinger }; 276c66ac9dbSNicholas Bellinger 277c66ac9dbSNicholas Bellinger static struct configfs_subsystem target_core_fabrics = { 278c66ac9dbSNicholas Bellinger .su_group = { 279c66ac9dbSNicholas Bellinger .cg_item = { 280c66ac9dbSNicholas Bellinger .ci_namebuf = "target", 281c66ac9dbSNicholas Bellinger .ci_type = &target_core_fabrics_item, 282c66ac9dbSNicholas Bellinger }, 283c66ac9dbSNicholas Bellinger }, 284c66ac9dbSNicholas Bellinger }; 285c66ac9dbSNicholas Bellinger 286c66ac9dbSNicholas Bellinger static struct configfs_subsystem *target_core_subsystem[] = { 287c66ac9dbSNicholas Bellinger &target_core_fabrics, 288c66ac9dbSNicholas Bellinger NULL, 289c66ac9dbSNicholas Bellinger }; 290c66ac9dbSNicholas Bellinger 291c66ac9dbSNicholas Bellinger /*############################################################################## 292c66ac9dbSNicholas Bellinger // Start functions called by external Target Fabrics Modules 293c66ac9dbSNicholas Bellinger //############################################################################*/ 294c66ac9dbSNicholas Bellinger 295c66ac9dbSNicholas Bellinger /* 296c66ac9dbSNicholas Bellinger * First function called by fabric modules to: 297c66ac9dbSNicholas Bellinger * 298c66ac9dbSNicholas Bellinger * 1) Allocate a struct target_fabric_configfs and save the *fabric_cit pointer. 299c66ac9dbSNicholas Bellinger * 2) Add struct target_fabric_configfs to g_tf_list 300c66ac9dbSNicholas Bellinger * 3) Return struct target_fabric_configfs to fabric module to be passed 301c66ac9dbSNicholas Bellinger * into target_fabric_configfs_register(). 302c66ac9dbSNicholas Bellinger */ 303c66ac9dbSNicholas Bellinger struct target_fabric_configfs *target_fabric_configfs_init( 304c66ac9dbSNicholas Bellinger struct module *fabric_mod, 305c66ac9dbSNicholas Bellinger const char *name) 306c66ac9dbSNicholas Bellinger { 307c66ac9dbSNicholas Bellinger struct target_fabric_configfs *tf; 308c66ac9dbSNicholas Bellinger 309c66ac9dbSNicholas Bellinger if (!(fabric_mod)) { 310c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing struct module *fabric_mod pointer\n"); 311e3d6f909SAndy Grover return ERR_PTR(-EINVAL); 312c66ac9dbSNicholas Bellinger } 313c66ac9dbSNicholas Bellinger if (!(name)) { 314c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to locate passed fabric name\n"); 315e3d6f909SAndy Grover return ERR_PTR(-EINVAL); 316c66ac9dbSNicholas Bellinger } 31760d645a4SDan Carpenter if (strlen(name) >= TARGET_FABRIC_NAME_SIZE) { 318c66ac9dbSNicholas Bellinger printk(KERN_ERR "Passed name: %s exceeds TARGET_FABRIC" 319c66ac9dbSNicholas Bellinger "_NAME_SIZE\n", name); 320e3d6f909SAndy Grover return ERR_PTR(-EINVAL); 321c66ac9dbSNicholas Bellinger } 322c66ac9dbSNicholas Bellinger 323c66ac9dbSNicholas Bellinger tf = kzalloc(sizeof(struct target_fabric_configfs), GFP_KERNEL); 324c66ac9dbSNicholas Bellinger if (!(tf)) 325e3d6f909SAndy Grover return ERR_PTR(-ENOMEM); 326c66ac9dbSNicholas Bellinger 327c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&tf->tf_list); 328c66ac9dbSNicholas Bellinger atomic_set(&tf->tf_access_cnt, 0); 329c66ac9dbSNicholas Bellinger /* 330c66ac9dbSNicholas Bellinger * Setup the default generic struct config_item_type's (cits) in 331c66ac9dbSNicholas Bellinger * struct target_fabric_configfs->tf_cit_tmpl 332c66ac9dbSNicholas Bellinger */ 333c66ac9dbSNicholas Bellinger tf->tf_module = fabric_mod; 334c66ac9dbSNicholas Bellinger target_fabric_setup_cits(tf); 335c66ac9dbSNicholas Bellinger 336c66ac9dbSNicholas Bellinger tf->tf_subsys = target_core_subsystem[0]; 337c66ac9dbSNicholas Bellinger snprintf(tf->tf_name, TARGET_FABRIC_NAME_SIZE, "%s", name); 338c66ac9dbSNicholas Bellinger 339c66ac9dbSNicholas Bellinger mutex_lock(&g_tf_lock); 340c66ac9dbSNicholas Bellinger list_add_tail(&tf->tf_list, &g_tf_list); 341c66ac9dbSNicholas Bellinger mutex_unlock(&g_tf_lock); 342c66ac9dbSNicholas Bellinger 343c66ac9dbSNicholas Bellinger printk(KERN_INFO "<<<<<<<<<<<<<<<<<<<<<< BEGIN FABRIC API >>>>>>>>" 344c66ac9dbSNicholas Bellinger ">>>>>>>>>>>>>>\n"); 345c66ac9dbSNicholas Bellinger printk(KERN_INFO "Initialized struct target_fabric_configfs: %p for" 346c66ac9dbSNicholas Bellinger " %s\n", tf, tf->tf_name); 347c66ac9dbSNicholas Bellinger return tf; 348c66ac9dbSNicholas Bellinger } 349c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(target_fabric_configfs_init); 350c66ac9dbSNicholas Bellinger 351c66ac9dbSNicholas Bellinger /* 352c66ac9dbSNicholas Bellinger * Called by fabric plugins after FAILED target_fabric_configfs_register() call. 353c66ac9dbSNicholas Bellinger */ 354c66ac9dbSNicholas Bellinger void target_fabric_configfs_free( 355c66ac9dbSNicholas Bellinger struct target_fabric_configfs *tf) 356c66ac9dbSNicholas Bellinger { 357c66ac9dbSNicholas Bellinger mutex_lock(&g_tf_lock); 358c66ac9dbSNicholas Bellinger list_del(&tf->tf_list); 359c66ac9dbSNicholas Bellinger mutex_unlock(&g_tf_lock); 360c66ac9dbSNicholas Bellinger 361c66ac9dbSNicholas Bellinger kfree(tf); 362c66ac9dbSNicholas Bellinger } 363c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(target_fabric_configfs_free); 364c66ac9dbSNicholas Bellinger 365c66ac9dbSNicholas Bellinger /* 366c66ac9dbSNicholas Bellinger * Perform a sanity check of the passed tf->tf_ops before completing 367c66ac9dbSNicholas Bellinger * TCM fabric module registration. 368c66ac9dbSNicholas Bellinger */ 369c66ac9dbSNicholas Bellinger static int target_fabric_tf_ops_check( 370c66ac9dbSNicholas Bellinger struct target_fabric_configfs *tf) 371c66ac9dbSNicholas Bellinger { 372c66ac9dbSNicholas Bellinger struct target_core_fabric_ops *tfo = &tf->tf_ops; 373c66ac9dbSNicholas Bellinger 374c66ac9dbSNicholas Bellinger if (!(tfo->get_fabric_name)) { 375c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->get_fabric_name()\n"); 376c66ac9dbSNicholas Bellinger return -EINVAL; 377c66ac9dbSNicholas Bellinger } 378c66ac9dbSNicholas Bellinger if (!(tfo->get_fabric_proto_ident)) { 379c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->get_fabric_proto_ident()\n"); 380c66ac9dbSNicholas Bellinger return -EINVAL; 381c66ac9dbSNicholas Bellinger } 382c66ac9dbSNicholas Bellinger if (!(tfo->tpg_get_wwn)) { 383c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->tpg_get_wwn()\n"); 384c66ac9dbSNicholas Bellinger return -EINVAL; 385c66ac9dbSNicholas Bellinger } 386c66ac9dbSNicholas Bellinger if (!(tfo->tpg_get_tag)) { 387c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->tpg_get_tag()\n"); 388c66ac9dbSNicholas Bellinger return -EINVAL; 389c66ac9dbSNicholas Bellinger } 390c66ac9dbSNicholas Bellinger if (!(tfo->tpg_get_default_depth)) { 391c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->tpg_get_default_depth()\n"); 392c66ac9dbSNicholas Bellinger return -EINVAL; 393c66ac9dbSNicholas Bellinger } 394c66ac9dbSNicholas Bellinger if (!(tfo->tpg_get_pr_transport_id)) { 395c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->tpg_get_pr_transport_id()\n"); 396c66ac9dbSNicholas Bellinger return -EINVAL; 397c66ac9dbSNicholas Bellinger } 398c66ac9dbSNicholas Bellinger if (!(tfo->tpg_get_pr_transport_id_len)) { 399c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->tpg_get_pr_transport_id_len()\n"); 400c66ac9dbSNicholas Bellinger return -EINVAL; 401c66ac9dbSNicholas Bellinger } 402c66ac9dbSNicholas Bellinger if (!(tfo->tpg_check_demo_mode)) { 403c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->tpg_check_demo_mode()\n"); 404c66ac9dbSNicholas Bellinger return -EINVAL; 405c66ac9dbSNicholas Bellinger } 406c66ac9dbSNicholas Bellinger if (!(tfo->tpg_check_demo_mode_cache)) { 407c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->tpg_check_demo_mode_cache()\n"); 408c66ac9dbSNicholas Bellinger return -EINVAL; 409c66ac9dbSNicholas Bellinger } 410c66ac9dbSNicholas Bellinger if (!(tfo->tpg_check_demo_mode_write_protect)) { 411c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->tpg_check_demo_mode_write_protect()\n"); 412c66ac9dbSNicholas Bellinger return -EINVAL; 413c66ac9dbSNicholas Bellinger } 414c66ac9dbSNicholas Bellinger if (!(tfo->tpg_check_prod_mode_write_protect)) { 415c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->tpg_check_prod_mode_write_protect()\n"); 416c66ac9dbSNicholas Bellinger return -EINVAL; 417c66ac9dbSNicholas Bellinger } 418c66ac9dbSNicholas Bellinger if (!(tfo->tpg_alloc_fabric_acl)) { 419c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->tpg_alloc_fabric_acl()\n"); 420c66ac9dbSNicholas Bellinger return -EINVAL; 421c66ac9dbSNicholas Bellinger } 422c66ac9dbSNicholas Bellinger if (!(tfo->tpg_release_fabric_acl)) { 423c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->tpg_release_fabric_acl()\n"); 424c66ac9dbSNicholas Bellinger return -EINVAL; 425c66ac9dbSNicholas Bellinger } 426c66ac9dbSNicholas Bellinger if (!(tfo->tpg_get_inst_index)) { 427c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->tpg_get_inst_index()\n"); 428c66ac9dbSNicholas Bellinger return -EINVAL; 429c66ac9dbSNicholas Bellinger } 43035462975SChristoph Hellwig if (!tfo->release_cmd) { 43135462975SChristoph Hellwig printk(KERN_ERR "Missing tfo->release_cmd()\n"); 432c66ac9dbSNicholas Bellinger return -EINVAL; 433c66ac9dbSNicholas Bellinger } 434c66ac9dbSNicholas Bellinger if (!(tfo->shutdown_session)) { 435c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->shutdown_session()\n"); 436c66ac9dbSNicholas Bellinger return -EINVAL; 437c66ac9dbSNicholas Bellinger } 438c66ac9dbSNicholas Bellinger if (!(tfo->close_session)) { 439c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->close_session()\n"); 440c66ac9dbSNicholas Bellinger return -EINVAL; 441c66ac9dbSNicholas Bellinger } 442c66ac9dbSNicholas Bellinger if (!(tfo->stop_session)) { 443c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->stop_session()\n"); 444c66ac9dbSNicholas Bellinger return -EINVAL; 445c66ac9dbSNicholas Bellinger } 446c66ac9dbSNicholas Bellinger if (!(tfo->fall_back_to_erl0)) { 447c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->fall_back_to_erl0()\n"); 448c66ac9dbSNicholas Bellinger return -EINVAL; 449c66ac9dbSNicholas Bellinger } 450c66ac9dbSNicholas Bellinger if (!(tfo->sess_logged_in)) { 451c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->sess_logged_in()\n"); 452c66ac9dbSNicholas Bellinger return -EINVAL; 453c66ac9dbSNicholas Bellinger } 454c66ac9dbSNicholas Bellinger if (!(tfo->sess_get_index)) { 455c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->sess_get_index()\n"); 456c66ac9dbSNicholas Bellinger return -EINVAL; 457c66ac9dbSNicholas Bellinger } 458c66ac9dbSNicholas Bellinger if (!(tfo->write_pending)) { 459c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->write_pending()\n"); 460c66ac9dbSNicholas Bellinger return -EINVAL; 461c66ac9dbSNicholas Bellinger } 462c66ac9dbSNicholas Bellinger if (!(tfo->write_pending_status)) { 463c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->write_pending_status()\n"); 464c66ac9dbSNicholas Bellinger return -EINVAL; 465c66ac9dbSNicholas Bellinger } 466c66ac9dbSNicholas Bellinger if (!(tfo->set_default_node_attributes)) { 467c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->set_default_node_attributes()\n"); 468c66ac9dbSNicholas Bellinger return -EINVAL; 469c66ac9dbSNicholas Bellinger } 470c66ac9dbSNicholas Bellinger if (!(tfo->get_task_tag)) { 471c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->get_task_tag()\n"); 472c66ac9dbSNicholas Bellinger return -EINVAL; 473c66ac9dbSNicholas Bellinger } 474c66ac9dbSNicholas Bellinger if (!(tfo->get_cmd_state)) { 475c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->get_cmd_state()\n"); 476c66ac9dbSNicholas Bellinger return -EINVAL; 477c66ac9dbSNicholas Bellinger } 478c66ac9dbSNicholas Bellinger if (!(tfo->queue_data_in)) { 479c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->queue_data_in()\n"); 480c66ac9dbSNicholas Bellinger return -EINVAL; 481c66ac9dbSNicholas Bellinger } 482c66ac9dbSNicholas Bellinger if (!(tfo->queue_status)) { 483c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->queue_status()\n"); 484c66ac9dbSNicholas Bellinger return -EINVAL; 485c66ac9dbSNicholas Bellinger } 486c66ac9dbSNicholas Bellinger if (!(tfo->queue_tm_rsp)) { 487c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->queue_tm_rsp()\n"); 488c66ac9dbSNicholas Bellinger return -EINVAL; 489c66ac9dbSNicholas Bellinger } 490c66ac9dbSNicholas Bellinger if (!(tfo->set_fabric_sense_len)) { 491c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->set_fabric_sense_len()\n"); 492c66ac9dbSNicholas Bellinger return -EINVAL; 493c66ac9dbSNicholas Bellinger } 494c66ac9dbSNicholas Bellinger if (!(tfo->get_fabric_sense_len)) { 495c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->get_fabric_sense_len()\n"); 496c66ac9dbSNicholas Bellinger return -EINVAL; 497c66ac9dbSNicholas Bellinger } 498c66ac9dbSNicholas Bellinger if (!(tfo->is_state_remove)) { 499c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->is_state_remove()\n"); 500c66ac9dbSNicholas Bellinger return -EINVAL; 501c66ac9dbSNicholas Bellinger } 502c66ac9dbSNicholas Bellinger /* 503c66ac9dbSNicholas Bellinger * We at least require tfo->fabric_make_wwn(), tfo->fabric_drop_wwn() 504c66ac9dbSNicholas Bellinger * tfo->fabric_make_tpg() and tfo->fabric_drop_tpg() in 505c66ac9dbSNicholas Bellinger * target_core_fabric_configfs.c WWN+TPG group context code. 506c66ac9dbSNicholas Bellinger */ 507c66ac9dbSNicholas Bellinger if (!(tfo->fabric_make_wwn)) { 508c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->fabric_make_wwn()\n"); 509c66ac9dbSNicholas Bellinger return -EINVAL; 510c66ac9dbSNicholas Bellinger } 511c66ac9dbSNicholas Bellinger if (!(tfo->fabric_drop_wwn)) { 512c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->fabric_drop_wwn()\n"); 513c66ac9dbSNicholas Bellinger return -EINVAL; 514c66ac9dbSNicholas Bellinger } 515c66ac9dbSNicholas Bellinger if (!(tfo->fabric_make_tpg)) { 516c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->fabric_make_tpg()\n"); 517c66ac9dbSNicholas Bellinger return -EINVAL; 518c66ac9dbSNicholas Bellinger } 519c66ac9dbSNicholas Bellinger if (!(tfo->fabric_drop_tpg)) { 520c66ac9dbSNicholas Bellinger printk(KERN_ERR "Missing tfo->fabric_drop_tpg()\n"); 521c66ac9dbSNicholas Bellinger return -EINVAL; 522c66ac9dbSNicholas Bellinger } 523c66ac9dbSNicholas Bellinger 524c66ac9dbSNicholas Bellinger return 0; 525c66ac9dbSNicholas Bellinger } 526c66ac9dbSNicholas Bellinger 527c66ac9dbSNicholas Bellinger /* 528c66ac9dbSNicholas Bellinger * Called 2nd from fabric module with returned parameter of 529c66ac9dbSNicholas Bellinger * struct target_fabric_configfs * from target_fabric_configfs_init(). 530c66ac9dbSNicholas Bellinger * 531c66ac9dbSNicholas Bellinger * Upon a successful registration, the new fabric's struct config_item is 532c66ac9dbSNicholas Bellinger * return. Also, a pointer to this struct is set in the passed 533c66ac9dbSNicholas Bellinger * struct target_fabric_configfs. 534c66ac9dbSNicholas Bellinger */ 535c66ac9dbSNicholas Bellinger int target_fabric_configfs_register( 536c66ac9dbSNicholas Bellinger struct target_fabric_configfs *tf) 537c66ac9dbSNicholas Bellinger { 538c66ac9dbSNicholas Bellinger int ret; 539c66ac9dbSNicholas Bellinger 540c66ac9dbSNicholas Bellinger if (!(tf)) { 541c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to locate target_fabric_configfs" 542c66ac9dbSNicholas Bellinger " pointer\n"); 543c66ac9dbSNicholas Bellinger return -EINVAL; 544c66ac9dbSNicholas Bellinger } 545c66ac9dbSNicholas Bellinger if (!(tf->tf_subsys)) { 546c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to target struct config_subsystem" 547c66ac9dbSNicholas Bellinger " pointer\n"); 548c66ac9dbSNicholas Bellinger return -EINVAL; 549c66ac9dbSNicholas Bellinger } 550c66ac9dbSNicholas Bellinger ret = target_fabric_tf_ops_check(tf); 551c66ac9dbSNicholas Bellinger if (ret < 0) 552c66ac9dbSNicholas Bellinger return ret; 553c66ac9dbSNicholas Bellinger 554c66ac9dbSNicholas Bellinger printk(KERN_INFO "<<<<<<<<<<<<<<<<<<<<<< END FABRIC API >>>>>>>>>>>>" 555c66ac9dbSNicholas Bellinger ">>>>>>>>>>\n"); 556c66ac9dbSNicholas Bellinger return 0; 557c66ac9dbSNicholas Bellinger } 558c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(target_fabric_configfs_register); 559c66ac9dbSNicholas Bellinger 560c66ac9dbSNicholas Bellinger void target_fabric_configfs_deregister( 561c66ac9dbSNicholas Bellinger struct target_fabric_configfs *tf) 562c66ac9dbSNicholas Bellinger { 563c66ac9dbSNicholas Bellinger struct configfs_subsystem *su; 564c66ac9dbSNicholas Bellinger 565c66ac9dbSNicholas Bellinger if (!(tf)) { 566c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to locate passed target_fabric_" 567c66ac9dbSNicholas Bellinger "configfs\n"); 568c66ac9dbSNicholas Bellinger return; 569c66ac9dbSNicholas Bellinger } 570c66ac9dbSNicholas Bellinger su = tf->tf_subsys; 571c66ac9dbSNicholas Bellinger if (!(su)) { 572c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to locate passed tf->tf_subsys" 573c66ac9dbSNicholas Bellinger " pointer\n"); 574c66ac9dbSNicholas Bellinger return; 575c66ac9dbSNicholas Bellinger } 576c66ac9dbSNicholas Bellinger printk(KERN_INFO "<<<<<<<<<<<<<<<<<<<<<< BEGIN FABRIC API >>>>>>>>>>" 577c66ac9dbSNicholas Bellinger ">>>>>>>>>>>>\n"); 578c66ac9dbSNicholas Bellinger mutex_lock(&g_tf_lock); 579c66ac9dbSNicholas Bellinger if (atomic_read(&tf->tf_access_cnt)) { 580c66ac9dbSNicholas Bellinger mutex_unlock(&g_tf_lock); 581c66ac9dbSNicholas Bellinger printk(KERN_ERR "Non zero tf->tf_access_cnt for fabric %s\n", 582c66ac9dbSNicholas Bellinger tf->tf_name); 583c66ac9dbSNicholas Bellinger BUG(); 584c66ac9dbSNicholas Bellinger } 585c66ac9dbSNicholas Bellinger list_del(&tf->tf_list); 586c66ac9dbSNicholas Bellinger mutex_unlock(&g_tf_lock); 587c66ac9dbSNicholas Bellinger 588c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: DEREGISTER -> Releasing tf:" 589c66ac9dbSNicholas Bellinger " %s\n", tf->tf_name); 590c66ac9dbSNicholas Bellinger tf->tf_module = NULL; 591c66ac9dbSNicholas Bellinger tf->tf_subsys = NULL; 592c66ac9dbSNicholas Bellinger kfree(tf); 593c66ac9dbSNicholas Bellinger 594c66ac9dbSNicholas Bellinger printk("<<<<<<<<<<<<<<<<<<<<<< END FABRIC API >>>>>>>>>>>>>>>>>" 595c66ac9dbSNicholas Bellinger ">>>>>\n"); 596c66ac9dbSNicholas Bellinger } 597c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(target_fabric_configfs_deregister); 598c66ac9dbSNicholas Bellinger 599c66ac9dbSNicholas Bellinger /*############################################################################## 600c66ac9dbSNicholas Bellinger // Stop functions called by external Target Fabrics Modules 601c66ac9dbSNicholas Bellinger //############################################################################*/ 602c66ac9dbSNicholas Bellinger 603c66ac9dbSNicholas Bellinger /* Start functions for struct config_item_type target_core_dev_attrib_cit */ 604c66ac9dbSNicholas Bellinger 605c66ac9dbSNicholas Bellinger #define DEF_DEV_ATTRIB_SHOW(_name) \ 606c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_show_attr_##_name( \ 607c66ac9dbSNicholas Bellinger struct se_dev_attrib *da, \ 608c66ac9dbSNicholas Bellinger char *page) \ 609c66ac9dbSNicholas Bellinger { \ 610c66ac9dbSNicholas Bellinger struct se_device *dev; \ 611c66ac9dbSNicholas Bellinger struct se_subsystem_dev *se_dev = da->da_sub_dev; \ 612c66ac9dbSNicholas Bellinger ssize_t rb; \ 613c66ac9dbSNicholas Bellinger \ 614c66ac9dbSNicholas Bellinger spin_lock(&se_dev->se_dev_lock); \ 615c66ac9dbSNicholas Bellinger dev = se_dev->se_dev_ptr; \ 616c66ac9dbSNicholas Bellinger if (!(dev)) { \ 617c66ac9dbSNicholas Bellinger spin_unlock(&se_dev->se_dev_lock); \ 618c66ac9dbSNicholas Bellinger return -ENODEV; \ 619c66ac9dbSNicholas Bellinger } \ 620e3d6f909SAndy Grover rb = snprintf(page, PAGE_SIZE, "%u\n", \ 621e3d6f909SAndy Grover (u32)dev->se_sub_dev->se_dev_attrib._name); \ 622c66ac9dbSNicholas Bellinger spin_unlock(&se_dev->se_dev_lock); \ 623c66ac9dbSNicholas Bellinger \ 624c66ac9dbSNicholas Bellinger return rb; \ 625c66ac9dbSNicholas Bellinger } 626c66ac9dbSNicholas Bellinger 627c66ac9dbSNicholas Bellinger #define DEF_DEV_ATTRIB_STORE(_name) \ 628c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_store_attr_##_name( \ 629c66ac9dbSNicholas Bellinger struct se_dev_attrib *da, \ 630c66ac9dbSNicholas Bellinger const char *page, \ 631c66ac9dbSNicholas Bellinger size_t count) \ 632c66ac9dbSNicholas Bellinger { \ 633c66ac9dbSNicholas Bellinger struct se_device *dev; \ 634c66ac9dbSNicholas Bellinger struct se_subsystem_dev *se_dev = da->da_sub_dev; \ 635c66ac9dbSNicholas Bellinger unsigned long val; \ 636c66ac9dbSNicholas Bellinger int ret; \ 637c66ac9dbSNicholas Bellinger \ 638c66ac9dbSNicholas Bellinger spin_lock(&se_dev->se_dev_lock); \ 639c66ac9dbSNicholas Bellinger dev = se_dev->se_dev_ptr; \ 640c66ac9dbSNicholas Bellinger if (!(dev)) { \ 641c66ac9dbSNicholas Bellinger spin_unlock(&se_dev->se_dev_lock); \ 642c66ac9dbSNicholas Bellinger return -ENODEV; \ 643c66ac9dbSNicholas Bellinger } \ 644c66ac9dbSNicholas Bellinger ret = strict_strtoul(page, 0, &val); \ 645c66ac9dbSNicholas Bellinger if (ret < 0) { \ 646c66ac9dbSNicholas Bellinger spin_unlock(&se_dev->se_dev_lock); \ 647c66ac9dbSNicholas Bellinger printk(KERN_ERR "strict_strtoul() failed with" \ 648c66ac9dbSNicholas Bellinger " ret: %d\n", ret); \ 649c66ac9dbSNicholas Bellinger return -EINVAL; \ 650c66ac9dbSNicholas Bellinger } \ 651c66ac9dbSNicholas Bellinger ret = se_dev_set_##_name(dev, (u32)val); \ 652c66ac9dbSNicholas Bellinger spin_unlock(&se_dev->se_dev_lock); \ 653c66ac9dbSNicholas Bellinger \ 654c66ac9dbSNicholas Bellinger return (!ret) ? count : -EINVAL; \ 655c66ac9dbSNicholas Bellinger } 656c66ac9dbSNicholas Bellinger 657c66ac9dbSNicholas Bellinger #define DEF_DEV_ATTRIB(_name) \ 658c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB_SHOW(_name); \ 659c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB_STORE(_name); 660c66ac9dbSNicholas Bellinger 661c66ac9dbSNicholas Bellinger #define DEF_DEV_ATTRIB_RO(_name) \ 662c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB_SHOW(_name); 663c66ac9dbSNicholas Bellinger 664c66ac9dbSNicholas Bellinger CONFIGFS_EATTR_STRUCT(target_core_dev_attrib, se_dev_attrib); 665c66ac9dbSNicholas Bellinger #define SE_DEV_ATTR(_name, _mode) \ 666c66ac9dbSNicholas Bellinger static struct target_core_dev_attrib_attribute \ 667c66ac9dbSNicholas Bellinger target_core_dev_attrib_##_name = \ 668c66ac9dbSNicholas Bellinger __CONFIGFS_EATTR(_name, _mode, \ 669c66ac9dbSNicholas Bellinger target_core_dev_show_attr_##_name, \ 670c66ac9dbSNicholas Bellinger target_core_dev_store_attr_##_name); 671c66ac9dbSNicholas Bellinger 672c66ac9dbSNicholas Bellinger #define SE_DEV_ATTR_RO(_name); \ 673c66ac9dbSNicholas Bellinger static struct target_core_dev_attrib_attribute \ 674c66ac9dbSNicholas Bellinger target_core_dev_attrib_##_name = \ 675c66ac9dbSNicholas Bellinger __CONFIGFS_EATTR_RO(_name, \ 676c66ac9dbSNicholas Bellinger target_core_dev_show_attr_##_name); 677c66ac9dbSNicholas Bellinger 678c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(emulate_dpo); 679c66ac9dbSNicholas Bellinger SE_DEV_ATTR(emulate_dpo, S_IRUGO | S_IWUSR); 680c66ac9dbSNicholas Bellinger 681c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(emulate_fua_write); 682c66ac9dbSNicholas Bellinger SE_DEV_ATTR(emulate_fua_write, S_IRUGO | S_IWUSR); 683c66ac9dbSNicholas Bellinger 684c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(emulate_fua_read); 685c66ac9dbSNicholas Bellinger SE_DEV_ATTR(emulate_fua_read, S_IRUGO | S_IWUSR); 686c66ac9dbSNicholas Bellinger 687c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(emulate_write_cache); 688c66ac9dbSNicholas Bellinger SE_DEV_ATTR(emulate_write_cache, S_IRUGO | S_IWUSR); 689c66ac9dbSNicholas Bellinger 690c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(emulate_ua_intlck_ctrl); 691c66ac9dbSNicholas Bellinger SE_DEV_ATTR(emulate_ua_intlck_ctrl, S_IRUGO | S_IWUSR); 692c66ac9dbSNicholas Bellinger 693c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(emulate_tas); 694c66ac9dbSNicholas Bellinger SE_DEV_ATTR(emulate_tas, S_IRUGO | S_IWUSR); 695c66ac9dbSNicholas Bellinger 696c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(emulate_tpu); 697c66ac9dbSNicholas Bellinger SE_DEV_ATTR(emulate_tpu, S_IRUGO | S_IWUSR); 698c66ac9dbSNicholas Bellinger 699c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(emulate_tpws); 700c66ac9dbSNicholas Bellinger SE_DEV_ATTR(emulate_tpws, S_IRUGO | S_IWUSR); 701c66ac9dbSNicholas Bellinger 702c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(enforce_pr_isids); 703c66ac9dbSNicholas Bellinger SE_DEV_ATTR(enforce_pr_isids, S_IRUGO | S_IWUSR); 704c66ac9dbSNicholas Bellinger 705c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB_RO(hw_block_size); 706c66ac9dbSNicholas Bellinger SE_DEV_ATTR_RO(hw_block_size); 707c66ac9dbSNicholas Bellinger 708c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(block_size); 709c66ac9dbSNicholas Bellinger SE_DEV_ATTR(block_size, S_IRUGO | S_IWUSR); 710c66ac9dbSNicholas Bellinger 711c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB_RO(hw_max_sectors); 712c66ac9dbSNicholas Bellinger SE_DEV_ATTR_RO(hw_max_sectors); 713c66ac9dbSNicholas Bellinger 714c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(max_sectors); 715c66ac9dbSNicholas Bellinger SE_DEV_ATTR(max_sectors, S_IRUGO | S_IWUSR); 716c66ac9dbSNicholas Bellinger 717c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(optimal_sectors); 718c66ac9dbSNicholas Bellinger SE_DEV_ATTR(optimal_sectors, S_IRUGO | S_IWUSR); 719c66ac9dbSNicholas Bellinger 720c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB_RO(hw_queue_depth); 721c66ac9dbSNicholas Bellinger SE_DEV_ATTR_RO(hw_queue_depth); 722c66ac9dbSNicholas Bellinger 723c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(queue_depth); 724c66ac9dbSNicholas Bellinger SE_DEV_ATTR(queue_depth, S_IRUGO | S_IWUSR); 725c66ac9dbSNicholas Bellinger 726c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(task_timeout); 727c66ac9dbSNicholas Bellinger SE_DEV_ATTR(task_timeout, S_IRUGO | S_IWUSR); 728c66ac9dbSNicholas Bellinger 729c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(max_unmap_lba_count); 730c66ac9dbSNicholas Bellinger SE_DEV_ATTR(max_unmap_lba_count, S_IRUGO | S_IWUSR); 731c66ac9dbSNicholas Bellinger 732c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(max_unmap_block_desc_count); 733c66ac9dbSNicholas Bellinger SE_DEV_ATTR(max_unmap_block_desc_count, S_IRUGO | S_IWUSR); 734c66ac9dbSNicholas Bellinger 735c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(unmap_granularity); 736c66ac9dbSNicholas Bellinger SE_DEV_ATTR(unmap_granularity, S_IRUGO | S_IWUSR); 737c66ac9dbSNicholas Bellinger 738c66ac9dbSNicholas Bellinger DEF_DEV_ATTRIB(unmap_granularity_alignment); 739c66ac9dbSNicholas Bellinger SE_DEV_ATTR(unmap_granularity_alignment, S_IRUGO | S_IWUSR); 740c66ac9dbSNicholas Bellinger 741c66ac9dbSNicholas Bellinger CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group); 742c66ac9dbSNicholas Bellinger 743c66ac9dbSNicholas Bellinger static struct configfs_attribute *target_core_dev_attrib_attrs[] = { 744c66ac9dbSNicholas Bellinger &target_core_dev_attrib_emulate_dpo.attr, 745c66ac9dbSNicholas Bellinger &target_core_dev_attrib_emulate_fua_write.attr, 746c66ac9dbSNicholas Bellinger &target_core_dev_attrib_emulate_fua_read.attr, 747c66ac9dbSNicholas Bellinger &target_core_dev_attrib_emulate_write_cache.attr, 748c66ac9dbSNicholas Bellinger &target_core_dev_attrib_emulate_ua_intlck_ctrl.attr, 749c66ac9dbSNicholas Bellinger &target_core_dev_attrib_emulate_tas.attr, 750c66ac9dbSNicholas Bellinger &target_core_dev_attrib_emulate_tpu.attr, 751c66ac9dbSNicholas Bellinger &target_core_dev_attrib_emulate_tpws.attr, 752c66ac9dbSNicholas Bellinger &target_core_dev_attrib_enforce_pr_isids.attr, 753c66ac9dbSNicholas Bellinger &target_core_dev_attrib_hw_block_size.attr, 754c66ac9dbSNicholas Bellinger &target_core_dev_attrib_block_size.attr, 755c66ac9dbSNicholas Bellinger &target_core_dev_attrib_hw_max_sectors.attr, 756c66ac9dbSNicholas Bellinger &target_core_dev_attrib_max_sectors.attr, 757c66ac9dbSNicholas Bellinger &target_core_dev_attrib_optimal_sectors.attr, 758c66ac9dbSNicholas Bellinger &target_core_dev_attrib_hw_queue_depth.attr, 759c66ac9dbSNicholas Bellinger &target_core_dev_attrib_queue_depth.attr, 760c66ac9dbSNicholas Bellinger &target_core_dev_attrib_task_timeout.attr, 761c66ac9dbSNicholas Bellinger &target_core_dev_attrib_max_unmap_lba_count.attr, 762c66ac9dbSNicholas Bellinger &target_core_dev_attrib_max_unmap_block_desc_count.attr, 763c66ac9dbSNicholas Bellinger &target_core_dev_attrib_unmap_granularity.attr, 764c66ac9dbSNicholas Bellinger &target_core_dev_attrib_unmap_granularity_alignment.attr, 765c66ac9dbSNicholas Bellinger NULL, 766c66ac9dbSNicholas Bellinger }; 767c66ac9dbSNicholas Bellinger 768c66ac9dbSNicholas Bellinger static struct configfs_item_operations target_core_dev_attrib_ops = { 769c66ac9dbSNicholas Bellinger .show_attribute = target_core_dev_attrib_attr_show, 770c66ac9dbSNicholas Bellinger .store_attribute = target_core_dev_attrib_attr_store, 771c66ac9dbSNicholas Bellinger }; 772c66ac9dbSNicholas Bellinger 773c66ac9dbSNicholas Bellinger static struct config_item_type target_core_dev_attrib_cit = { 774c66ac9dbSNicholas Bellinger .ct_item_ops = &target_core_dev_attrib_ops, 775c66ac9dbSNicholas Bellinger .ct_attrs = target_core_dev_attrib_attrs, 776c66ac9dbSNicholas Bellinger .ct_owner = THIS_MODULE, 777c66ac9dbSNicholas Bellinger }; 778c66ac9dbSNicholas Bellinger 779c66ac9dbSNicholas Bellinger /* End functions for struct config_item_type target_core_dev_attrib_cit */ 780c66ac9dbSNicholas Bellinger 781c66ac9dbSNicholas Bellinger /* Start functions for struct config_item_type target_core_dev_wwn_cit */ 782c66ac9dbSNicholas Bellinger 783c66ac9dbSNicholas Bellinger CONFIGFS_EATTR_STRUCT(target_core_dev_wwn, t10_wwn); 784c66ac9dbSNicholas Bellinger #define SE_DEV_WWN_ATTR(_name, _mode) \ 785c66ac9dbSNicholas Bellinger static struct target_core_dev_wwn_attribute target_core_dev_wwn_##_name = \ 786c66ac9dbSNicholas Bellinger __CONFIGFS_EATTR(_name, _mode, \ 787c66ac9dbSNicholas Bellinger target_core_dev_wwn_show_attr_##_name, \ 788c66ac9dbSNicholas Bellinger target_core_dev_wwn_store_attr_##_name); 789c66ac9dbSNicholas Bellinger 790c66ac9dbSNicholas Bellinger #define SE_DEV_WWN_ATTR_RO(_name); \ 791c66ac9dbSNicholas Bellinger do { \ 792c66ac9dbSNicholas Bellinger static struct target_core_dev_wwn_attribute \ 793c66ac9dbSNicholas Bellinger target_core_dev_wwn_##_name = \ 794c66ac9dbSNicholas Bellinger __CONFIGFS_EATTR_RO(_name, \ 795c66ac9dbSNicholas Bellinger target_core_dev_wwn_show_attr_##_name); \ 796c66ac9dbSNicholas Bellinger } while (0); 797c66ac9dbSNicholas Bellinger 798c66ac9dbSNicholas Bellinger /* 799c66ac9dbSNicholas Bellinger * VPD page 0x80 Unit serial 800c66ac9dbSNicholas Bellinger */ 801c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_wwn_show_attr_vpd_unit_serial( 802c66ac9dbSNicholas Bellinger struct t10_wwn *t10_wwn, 803c66ac9dbSNicholas Bellinger char *page) 804c66ac9dbSNicholas Bellinger { 805c66ac9dbSNicholas Bellinger struct se_subsystem_dev *se_dev = t10_wwn->t10_sub_dev; 806c66ac9dbSNicholas Bellinger struct se_device *dev; 807c66ac9dbSNicholas Bellinger 808c66ac9dbSNicholas Bellinger dev = se_dev->se_dev_ptr; 809c66ac9dbSNicholas Bellinger if (!(dev)) 810c66ac9dbSNicholas Bellinger return -ENODEV; 811c66ac9dbSNicholas Bellinger 812c66ac9dbSNicholas Bellinger return sprintf(page, "T10 VPD Unit Serial Number: %s\n", 813c66ac9dbSNicholas Bellinger &t10_wwn->unit_serial[0]); 814c66ac9dbSNicholas Bellinger } 815c66ac9dbSNicholas Bellinger 816c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial( 817c66ac9dbSNicholas Bellinger struct t10_wwn *t10_wwn, 818c66ac9dbSNicholas Bellinger const char *page, 819c66ac9dbSNicholas Bellinger size_t count) 820c66ac9dbSNicholas Bellinger { 821c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev = t10_wwn->t10_sub_dev; 822c66ac9dbSNicholas Bellinger struct se_device *dev; 823c66ac9dbSNicholas Bellinger unsigned char buf[INQUIRY_VPD_SERIAL_LEN]; 824c66ac9dbSNicholas Bellinger 825c66ac9dbSNicholas Bellinger /* 826c66ac9dbSNicholas Bellinger * If Linux/SCSI subsystem_api_t plugin got a VPD Unit Serial 827c66ac9dbSNicholas Bellinger * from the struct scsi_device level firmware, do not allow 828c66ac9dbSNicholas Bellinger * VPD Unit Serial to be emulated. 829c66ac9dbSNicholas Bellinger * 830c66ac9dbSNicholas Bellinger * Note this struct scsi_device could also be emulating VPD 831c66ac9dbSNicholas Bellinger * information from its drivers/scsi LLD. But for now we assume 832c66ac9dbSNicholas Bellinger * it is doing 'the right thing' wrt a world wide unique 833c66ac9dbSNicholas Bellinger * VPD Unit Serial Number that OS dependent multipath can depend on. 834c66ac9dbSNicholas Bellinger */ 835c66ac9dbSNicholas Bellinger if (su_dev->su_dev_flags & SDF_FIRMWARE_VPD_UNIT_SERIAL) { 836c66ac9dbSNicholas Bellinger printk(KERN_ERR "Underlying SCSI device firmware provided VPD" 837c66ac9dbSNicholas Bellinger " Unit Serial, ignoring request\n"); 838c66ac9dbSNicholas Bellinger return -EOPNOTSUPP; 839c66ac9dbSNicholas Bellinger } 840c66ac9dbSNicholas Bellinger 84160d645a4SDan Carpenter if (strlen(page) >= INQUIRY_VPD_SERIAL_LEN) { 842c66ac9dbSNicholas Bellinger printk(KERN_ERR "Emulated VPD Unit Serial exceeds" 843c66ac9dbSNicholas Bellinger " INQUIRY_VPD_SERIAL_LEN: %d\n", INQUIRY_VPD_SERIAL_LEN); 844c66ac9dbSNicholas Bellinger return -EOVERFLOW; 845c66ac9dbSNicholas Bellinger } 846c66ac9dbSNicholas Bellinger /* 847c66ac9dbSNicholas Bellinger * Check to see if any active $FABRIC_MOD exports exist. If they 848c66ac9dbSNicholas Bellinger * do exist, fail here as changing this information on the fly 849c66ac9dbSNicholas Bellinger * (underneath the initiator side OS dependent multipath code) 850c66ac9dbSNicholas Bellinger * could cause negative effects. 851c66ac9dbSNicholas Bellinger */ 852c66ac9dbSNicholas Bellinger dev = su_dev->se_dev_ptr; 853c66ac9dbSNicholas Bellinger if ((dev)) { 854c66ac9dbSNicholas Bellinger if (atomic_read(&dev->dev_export_obj.obj_access_count)) { 855c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to set VPD Unit Serial while" 856c66ac9dbSNicholas Bellinger " active %d $FABRIC_MOD exports exist\n", 857c66ac9dbSNicholas Bellinger atomic_read(&dev->dev_export_obj.obj_access_count)); 858c66ac9dbSNicholas Bellinger return -EINVAL; 859c66ac9dbSNicholas Bellinger } 860c66ac9dbSNicholas Bellinger } 861c66ac9dbSNicholas Bellinger /* 862c66ac9dbSNicholas Bellinger * This currently assumes ASCII encoding for emulated VPD Unit Serial. 863c66ac9dbSNicholas Bellinger * 864c66ac9dbSNicholas Bellinger * Also, strip any newline added from the userspace 865c66ac9dbSNicholas Bellinger * echo $UUID > $TARGET/$HBA/$STORAGE_OBJECT/wwn/vpd_unit_serial 866c66ac9dbSNicholas Bellinger */ 867c66ac9dbSNicholas Bellinger memset(buf, 0, INQUIRY_VPD_SERIAL_LEN); 868c66ac9dbSNicholas Bellinger snprintf(buf, INQUIRY_VPD_SERIAL_LEN, "%s", page); 869c66ac9dbSNicholas Bellinger snprintf(su_dev->t10_wwn.unit_serial, INQUIRY_VPD_SERIAL_LEN, 870c66ac9dbSNicholas Bellinger "%s", strstrip(buf)); 871c66ac9dbSNicholas Bellinger su_dev->su_dev_flags |= SDF_EMULATED_VPD_UNIT_SERIAL; 872c66ac9dbSNicholas Bellinger 873c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: Set emulated VPD Unit Serial:" 874c66ac9dbSNicholas Bellinger " %s\n", su_dev->t10_wwn.unit_serial); 875c66ac9dbSNicholas Bellinger 876c66ac9dbSNicholas Bellinger return count; 877c66ac9dbSNicholas Bellinger } 878c66ac9dbSNicholas Bellinger 879c66ac9dbSNicholas Bellinger SE_DEV_WWN_ATTR(vpd_unit_serial, S_IRUGO | S_IWUSR); 880c66ac9dbSNicholas Bellinger 881c66ac9dbSNicholas Bellinger /* 882c66ac9dbSNicholas Bellinger * VPD page 0x83 Protocol Identifier 883c66ac9dbSNicholas Bellinger */ 884c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_wwn_show_attr_vpd_protocol_identifier( 885c66ac9dbSNicholas Bellinger struct t10_wwn *t10_wwn, 886c66ac9dbSNicholas Bellinger char *page) 887c66ac9dbSNicholas Bellinger { 888c66ac9dbSNicholas Bellinger struct se_subsystem_dev *se_dev = t10_wwn->t10_sub_dev; 889c66ac9dbSNicholas Bellinger struct se_device *dev; 890c66ac9dbSNicholas Bellinger struct t10_vpd *vpd; 891c66ac9dbSNicholas Bellinger unsigned char buf[VPD_TMP_BUF_SIZE]; 892c66ac9dbSNicholas Bellinger ssize_t len = 0; 893c66ac9dbSNicholas Bellinger 894c66ac9dbSNicholas Bellinger dev = se_dev->se_dev_ptr; 895c66ac9dbSNicholas Bellinger if (!(dev)) 896c66ac9dbSNicholas Bellinger return -ENODEV; 897c66ac9dbSNicholas Bellinger 898c66ac9dbSNicholas Bellinger memset(buf, 0, VPD_TMP_BUF_SIZE); 899c66ac9dbSNicholas Bellinger 900c66ac9dbSNicholas Bellinger spin_lock(&t10_wwn->t10_vpd_lock); 901c66ac9dbSNicholas Bellinger list_for_each_entry(vpd, &t10_wwn->t10_vpd_list, vpd_list) { 902c66ac9dbSNicholas Bellinger if (!(vpd->protocol_identifier_set)) 903c66ac9dbSNicholas Bellinger continue; 904c66ac9dbSNicholas Bellinger 905c66ac9dbSNicholas Bellinger transport_dump_vpd_proto_id(vpd, buf, VPD_TMP_BUF_SIZE); 906c66ac9dbSNicholas Bellinger 90760d645a4SDan Carpenter if ((len + strlen(buf) >= PAGE_SIZE)) 908c66ac9dbSNicholas Bellinger break; 909c66ac9dbSNicholas Bellinger 910c66ac9dbSNicholas Bellinger len += sprintf(page+len, "%s", buf); 911c66ac9dbSNicholas Bellinger } 912c66ac9dbSNicholas Bellinger spin_unlock(&t10_wwn->t10_vpd_lock); 913c66ac9dbSNicholas Bellinger 914c66ac9dbSNicholas Bellinger return len; 915c66ac9dbSNicholas Bellinger } 916c66ac9dbSNicholas Bellinger 917c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_wwn_store_attr_vpd_protocol_identifier( 918c66ac9dbSNicholas Bellinger struct t10_wwn *t10_wwn, 919c66ac9dbSNicholas Bellinger const char *page, 920c66ac9dbSNicholas Bellinger size_t count) 921c66ac9dbSNicholas Bellinger { 922c66ac9dbSNicholas Bellinger return -ENOSYS; 923c66ac9dbSNicholas Bellinger } 924c66ac9dbSNicholas Bellinger 925c66ac9dbSNicholas Bellinger SE_DEV_WWN_ATTR(vpd_protocol_identifier, S_IRUGO | S_IWUSR); 926c66ac9dbSNicholas Bellinger 927c66ac9dbSNicholas Bellinger /* 928c66ac9dbSNicholas Bellinger * Generic wrapper for dumping VPD identifiers by association. 929c66ac9dbSNicholas Bellinger */ 930c66ac9dbSNicholas Bellinger #define DEF_DEV_WWN_ASSOC_SHOW(_name, _assoc) \ 931c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_wwn_show_attr_##_name( \ 932c66ac9dbSNicholas Bellinger struct t10_wwn *t10_wwn, \ 933c66ac9dbSNicholas Bellinger char *page) \ 934c66ac9dbSNicholas Bellinger { \ 935c66ac9dbSNicholas Bellinger struct se_subsystem_dev *se_dev = t10_wwn->t10_sub_dev; \ 936c66ac9dbSNicholas Bellinger struct se_device *dev; \ 937c66ac9dbSNicholas Bellinger struct t10_vpd *vpd; \ 938c66ac9dbSNicholas Bellinger unsigned char buf[VPD_TMP_BUF_SIZE]; \ 939c66ac9dbSNicholas Bellinger ssize_t len = 0; \ 940c66ac9dbSNicholas Bellinger \ 941c66ac9dbSNicholas Bellinger dev = se_dev->se_dev_ptr; \ 942c66ac9dbSNicholas Bellinger if (!(dev)) \ 943c66ac9dbSNicholas Bellinger return -ENODEV; \ 944c66ac9dbSNicholas Bellinger \ 945c66ac9dbSNicholas Bellinger spin_lock(&t10_wwn->t10_vpd_lock); \ 946c66ac9dbSNicholas Bellinger list_for_each_entry(vpd, &t10_wwn->t10_vpd_list, vpd_list) { \ 947c66ac9dbSNicholas Bellinger if (vpd->association != _assoc) \ 948c66ac9dbSNicholas Bellinger continue; \ 949c66ac9dbSNicholas Bellinger \ 950c66ac9dbSNicholas Bellinger memset(buf, 0, VPD_TMP_BUF_SIZE); \ 951c66ac9dbSNicholas Bellinger transport_dump_vpd_assoc(vpd, buf, VPD_TMP_BUF_SIZE); \ 95260d645a4SDan Carpenter if ((len + strlen(buf) >= PAGE_SIZE)) \ 953c66ac9dbSNicholas Bellinger break; \ 954c66ac9dbSNicholas Bellinger len += sprintf(page+len, "%s", buf); \ 955c66ac9dbSNicholas Bellinger \ 956c66ac9dbSNicholas Bellinger memset(buf, 0, VPD_TMP_BUF_SIZE); \ 957c66ac9dbSNicholas Bellinger transport_dump_vpd_ident_type(vpd, buf, VPD_TMP_BUF_SIZE); \ 95860d645a4SDan Carpenter if ((len + strlen(buf) >= PAGE_SIZE)) \ 959c66ac9dbSNicholas Bellinger break; \ 960c66ac9dbSNicholas Bellinger len += sprintf(page+len, "%s", buf); \ 961c66ac9dbSNicholas Bellinger \ 962c66ac9dbSNicholas Bellinger memset(buf, 0, VPD_TMP_BUF_SIZE); \ 963c66ac9dbSNicholas Bellinger transport_dump_vpd_ident(vpd, buf, VPD_TMP_BUF_SIZE); \ 96460d645a4SDan Carpenter if ((len + strlen(buf) >= PAGE_SIZE)) \ 965c66ac9dbSNicholas Bellinger break; \ 966c66ac9dbSNicholas Bellinger len += sprintf(page+len, "%s", buf); \ 967c66ac9dbSNicholas Bellinger } \ 968c66ac9dbSNicholas Bellinger spin_unlock(&t10_wwn->t10_vpd_lock); \ 969c66ac9dbSNicholas Bellinger \ 970c66ac9dbSNicholas Bellinger return len; \ 971c66ac9dbSNicholas Bellinger } 972c66ac9dbSNicholas Bellinger 973c66ac9dbSNicholas Bellinger /* 974c66ac9dbSNicholas Bellinger * VPD page 0x83 Assoication: Logical Unit 975c66ac9dbSNicholas Bellinger */ 976c66ac9dbSNicholas Bellinger DEF_DEV_WWN_ASSOC_SHOW(vpd_assoc_logical_unit, 0x00); 977c66ac9dbSNicholas Bellinger 978c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_wwn_store_attr_vpd_assoc_logical_unit( 979c66ac9dbSNicholas Bellinger struct t10_wwn *t10_wwn, 980c66ac9dbSNicholas Bellinger const char *page, 981c66ac9dbSNicholas Bellinger size_t count) 982c66ac9dbSNicholas Bellinger { 983c66ac9dbSNicholas Bellinger return -ENOSYS; 984c66ac9dbSNicholas Bellinger } 985c66ac9dbSNicholas Bellinger 986c66ac9dbSNicholas Bellinger SE_DEV_WWN_ATTR(vpd_assoc_logical_unit, S_IRUGO | S_IWUSR); 987c66ac9dbSNicholas Bellinger 988c66ac9dbSNicholas Bellinger /* 989c66ac9dbSNicholas Bellinger * VPD page 0x83 Association: Target Port 990c66ac9dbSNicholas Bellinger */ 991c66ac9dbSNicholas Bellinger DEF_DEV_WWN_ASSOC_SHOW(vpd_assoc_target_port, 0x10); 992c66ac9dbSNicholas Bellinger 993c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_wwn_store_attr_vpd_assoc_target_port( 994c66ac9dbSNicholas Bellinger struct t10_wwn *t10_wwn, 995c66ac9dbSNicholas Bellinger const char *page, 996c66ac9dbSNicholas Bellinger size_t count) 997c66ac9dbSNicholas Bellinger { 998c66ac9dbSNicholas Bellinger return -ENOSYS; 999c66ac9dbSNicholas Bellinger } 1000c66ac9dbSNicholas Bellinger 1001c66ac9dbSNicholas Bellinger SE_DEV_WWN_ATTR(vpd_assoc_target_port, S_IRUGO | S_IWUSR); 1002c66ac9dbSNicholas Bellinger 1003c66ac9dbSNicholas Bellinger /* 1004c66ac9dbSNicholas Bellinger * VPD page 0x83 Association: SCSI Target Device 1005c66ac9dbSNicholas Bellinger */ 1006c66ac9dbSNicholas Bellinger DEF_DEV_WWN_ASSOC_SHOW(vpd_assoc_scsi_target_device, 0x20); 1007c66ac9dbSNicholas Bellinger 1008c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_wwn_store_attr_vpd_assoc_scsi_target_device( 1009c66ac9dbSNicholas Bellinger struct t10_wwn *t10_wwn, 1010c66ac9dbSNicholas Bellinger const char *page, 1011c66ac9dbSNicholas Bellinger size_t count) 1012c66ac9dbSNicholas Bellinger { 1013c66ac9dbSNicholas Bellinger return -ENOSYS; 1014c66ac9dbSNicholas Bellinger } 1015c66ac9dbSNicholas Bellinger 1016c66ac9dbSNicholas Bellinger SE_DEV_WWN_ATTR(vpd_assoc_scsi_target_device, S_IRUGO | S_IWUSR); 1017c66ac9dbSNicholas Bellinger 1018c66ac9dbSNicholas Bellinger CONFIGFS_EATTR_OPS(target_core_dev_wwn, t10_wwn, t10_wwn_group); 1019c66ac9dbSNicholas Bellinger 1020c66ac9dbSNicholas Bellinger static struct configfs_attribute *target_core_dev_wwn_attrs[] = { 1021c66ac9dbSNicholas Bellinger &target_core_dev_wwn_vpd_unit_serial.attr, 1022c66ac9dbSNicholas Bellinger &target_core_dev_wwn_vpd_protocol_identifier.attr, 1023c66ac9dbSNicholas Bellinger &target_core_dev_wwn_vpd_assoc_logical_unit.attr, 1024c66ac9dbSNicholas Bellinger &target_core_dev_wwn_vpd_assoc_target_port.attr, 1025c66ac9dbSNicholas Bellinger &target_core_dev_wwn_vpd_assoc_scsi_target_device.attr, 1026c66ac9dbSNicholas Bellinger NULL, 1027c66ac9dbSNicholas Bellinger }; 1028c66ac9dbSNicholas Bellinger 1029c66ac9dbSNicholas Bellinger static struct configfs_item_operations target_core_dev_wwn_ops = { 1030c66ac9dbSNicholas Bellinger .show_attribute = target_core_dev_wwn_attr_show, 1031c66ac9dbSNicholas Bellinger .store_attribute = target_core_dev_wwn_attr_store, 1032c66ac9dbSNicholas Bellinger }; 1033c66ac9dbSNicholas Bellinger 1034c66ac9dbSNicholas Bellinger static struct config_item_type target_core_dev_wwn_cit = { 1035c66ac9dbSNicholas Bellinger .ct_item_ops = &target_core_dev_wwn_ops, 1036c66ac9dbSNicholas Bellinger .ct_attrs = target_core_dev_wwn_attrs, 1037c66ac9dbSNicholas Bellinger .ct_owner = THIS_MODULE, 1038c66ac9dbSNicholas Bellinger }; 1039c66ac9dbSNicholas Bellinger 1040c66ac9dbSNicholas Bellinger /* End functions for struct config_item_type target_core_dev_wwn_cit */ 1041c66ac9dbSNicholas Bellinger 1042c66ac9dbSNicholas Bellinger /* Start functions for struct config_item_type target_core_dev_pr_cit */ 1043c66ac9dbSNicholas Bellinger 1044c66ac9dbSNicholas Bellinger CONFIGFS_EATTR_STRUCT(target_core_dev_pr, se_subsystem_dev); 1045c66ac9dbSNicholas Bellinger #define SE_DEV_PR_ATTR(_name, _mode) \ 1046c66ac9dbSNicholas Bellinger static struct target_core_dev_pr_attribute target_core_dev_pr_##_name = \ 1047c66ac9dbSNicholas Bellinger __CONFIGFS_EATTR(_name, _mode, \ 1048c66ac9dbSNicholas Bellinger target_core_dev_pr_show_attr_##_name, \ 1049c66ac9dbSNicholas Bellinger target_core_dev_pr_store_attr_##_name); 1050c66ac9dbSNicholas Bellinger 1051c66ac9dbSNicholas Bellinger #define SE_DEV_PR_ATTR_RO(_name); \ 1052c66ac9dbSNicholas Bellinger static struct target_core_dev_pr_attribute target_core_dev_pr_##_name = \ 1053c66ac9dbSNicholas Bellinger __CONFIGFS_EATTR_RO(_name, \ 1054c66ac9dbSNicholas Bellinger target_core_dev_pr_show_attr_##_name); 1055c66ac9dbSNicholas Bellinger 1056c66ac9dbSNicholas Bellinger /* 1057c66ac9dbSNicholas Bellinger * res_holder 1058c66ac9dbSNicholas Bellinger */ 1059c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_pr_show_spc3_res( 1060c66ac9dbSNicholas Bellinger struct se_device *dev, 1061c66ac9dbSNicholas Bellinger char *page, 1062c66ac9dbSNicholas Bellinger ssize_t *len) 1063c66ac9dbSNicholas Bellinger { 1064c66ac9dbSNicholas Bellinger struct se_node_acl *se_nacl; 1065c66ac9dbSNicholas Bellinger struct t10_pr_registration *pr_reg; 1066c66ac9dbSNicholas Bellinger char i_buf[PR_REG_ISID_ID_LEN]; 1067c66ac9dbSNicholas Bellinger int prf_isid; 1068c66ac9dbSNicholas Bellinger 1069c66ac9dbSNicholas Bellinger memset(i_buf, 0, PR_REG_ISID_ID_LEN); 1070c66ac9dbSNicholas Bellinger 1071c66ac9dbSNicholas Bellinger spin_lock(&dev->dev_reservation_lock); 1072c66ac9dbSNicholas Bellinger pr_reg = dev->dev_pr_res_holder; 1073c66ac9dbSNicholas Bellinger if (!(pr_reg)) { 1074c66ac9dbSNicholas Bellinger *len += sprintf(page + *len, "No SPC-3 Reservation holder\n"); 1075c66ac9dbSNicholas Bellinger spin_unlock(&dev->dev_reservation_lock); 1076c66ac9dbSNicholas Bellinger return *len; 1077c66ac9dbSNicholas Bellinger } 1078c66ac9dbSNicholas Bellinger se_nacl = pr_reg->pr_reg_nacl; 1079c66ac9dbSNicholas Bellinger prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], 1080c66ac9dbSNicholas Bellinger PR_REG_ISID_ID_LEN); 1081c66ac9dbSNicholas Bellinger 1082c66ac9dbSNicholas Bellinger *len += sprintf(page + *len, "SPC-3 Reservation: %s Initiator: %s%s\n", 1083e3d6f909SAndy Grover se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(), 1084c66ac9dbSNicholas Bellinger se_nacl->initiatorname, (prf_isid) ? &i_buf[0] : ""); 1085c66ac9dbSNicholas Bellinger spin_unlock(&dev->dev_reservation_lock); 1086c66ac9dbSNicholas Bellinger 1087c66ac9dbSNicholas Bellinger return *len; 1088c66ac9dbSNicholas Bellinger } 1089c66ac9dbSNicholas Bellinger 1090c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_pr_show_spc2_res( 1091c66ac9dbSNicholas Bellinger struct se_device *dev, 1092c66ac9dbSNicholas Bellinger char *page, 1093c66ac9dbSNicholas Bellinger ssize_t *len) 1094c66ac9dbSNicholas Bellinger { 1095c66ac9dbSNicholas Bellinger struct se_node_acl *se_nacl; 1096c66ac9dbSNicholas Bellinger 1097c66ac9dbSNicholas Bellinger spin_lock(&dev->dev_reservation_lock); 1098c66ac9dbSNicholas Bellinger se_nacl = dev->dev_reserved_node_acl; 1099c66ac9dbSNicholas Bellinger if (!(se_nacl)) { 1100c66ac9dbSNicholas Bellinger *len += sprintf(page + *len, "No SPC-2 Reservation holder\n"); 1101c66ac9dbSNicholas Bellinger spin_unlock(&dev->dev_reservation_lock); 1102c66ac9dbSNicholas Bellinger return *len; 1103c66ac9dbSNicholas Bellinger } 1104c66ac9dbSNicholas Bellinger *len += sprintf(page + *len, "SPC-2 Reservation: %s Initiator: %s\n", 1105e3d6f909SAndy Grover se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(), 1106c66ac9dbSNicholas Bellinger se_nacl->initiatorname); 1107c66ac9dbSNicholas Bellinger spin_unlock(&dev->dev_reservation_lock); 1108c66ac9dbSNicholas Bellinger 1109c66ac9dbSNicholas Bellinger return *len; 1110c66ac9dbSNicholas Bellinger } 1111c66ac9dbSNicholas Bellinger 1112c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_pr_show_attr_res_holder( 1113c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev, 1114c66ac9dbSNicholas Bellinger char *page) 1115c66ac9dbSNicholas Bellinger { 1116c66ac9dbSNicholas Bellinger ssize_t len = 0; 1117c66ac9dbSNicholas Bellinger 1118c66ac9dbSNicholas Bellinger if (!(su_dev->se_dev_ptr)) 1119c66ac9dbSNicholas Bellinger return -ENODEV; 1120c66ac9dbSNicholas Bellinger 1121e3d6f909SAndy Grover switch (su_dev->t10_pr.res_type) { 1122c66ac9dbSNicholas Bellinger case SPC3_PERSISTENT_RESERVATIONS: 1123c66ac9dbSNicholas Bellinger target_core_dev_pr_show_spc3_res(su_dev->se_dev_ptr, 1124c66ac9dbSNicholas Bellinger page, &len); 1125c66ac9dbSNicholas Bellinger break; 1126c66ac9dbSNicholas Bellinger case SPC2_RESERVATIONS: 1127c66ac9dbSNicholas Bellinger target_core_dev_pr_show_spc2_res(su_dev->se_dev_ptr, 1128c66ac9dbSNicholas Bellinger page, &len); 1129c66ac9dbSNicholas Bellinger break; 1130c66ac9dbSNicholas Bellinger case SPC_PASSTHROUGH: 1131c66ac9dbSNicholas Bellinger len += sprintf(page+len, "Passthrough\n"); 1132c66ac9dbSNicholas Bellinger break; 1133c66ac9dbSNicholas Bellinger default: 1134c66ac9dbSNicholas Bellinger len += sprintf(page+len, "Unknown\n"); 1135c66ac9dbSNicholas Bellinger break; 1136c66ac9dbSNicholas Bellinger } 1137c66ac9dbSNicholas Bellinger 1138c66ac9dbSNicholas Bellinger return len; 1139c66ac9dbSNicholas Bellinger } 1140c66ac9dbSNicholas Bellinger 1141c66ac9dbSNicholas Bellinger SE_DEV_PR_ATTR_RO(res_holder); 1142c66ac9dbSNicholas Bellinger 1143c66ac9dbSNicholas Bellinger /* 1144c66ac9dbSNicholas Bellinger * res_pr_all_tgt_pts 1145c66ac9dbSNicholas Bellinger */ 1146c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_pr_show_attr_res_pr_all_tgt_pts( 1147c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev, 1148c66ac9dbSNicholas Bellinger char *page) 1149c66ac9dbSNicholas Bellinger { 1150c66ac9dbSNicholas Bellinger struct se_device *dev; 1151c66ac9dbSNicholas Bellinger struct t10_pr_registration *pr_reg; 1152c66ac9dbSNicholas Bellinger ssize_t len = 0; 1153c66ac9dbSNicholas Bellinger 1154c66ac9dbSNicholas Bellinger dev = su_dev->se_dev_ptr; 1155c66ac9dbSNicholas Bellinger if (!(dev)) 1156c66ac9dbSNicholas Bellinger return -ENODEV; 1157c66ac9dbSNicholas Bellinger 1158e3d6f909SAndy Grover if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) 1159c66ac9dbSNicholas Bellinger return len; 1160c66ac9dbSNicholas Bellinger 1161c66ac9dbSNicholas Bellinger spin_lock(&dev->dev_reservation_lock); 1162c66ac9dbSNicholas Bellinger pr_reg = dev->dev_pr_res_holder; 1163c66ac9dbSNicholas Bellinger if (!(pr_reg)) { 1164c66ac9dbSNicholas Bellinger len = sprintf(page, "No SPC-3 Reservation holder\n"); 1165c66ac9dbSNicholas Bellinger spin_unlock(&dev->dev_reservation_lock); 1166c66ac9dbSNicholas Bellinger return len; 1167c66ac9dbSNicholas Bellinger } 1168c66ac9dbSNicholas Bellinger /* 1169c66ac9dbSNicholas Bellinger * See All Target Ports (ALL_TG_PT) bit in spcr17, section 6.14.3 1170c66ac9dbSNicholas Bellinger * Basic PERSISTENT RESERVER OUT parameter list, page 290 1171c66ac9dbSNicholas Bellinger */ 1172c66ac9dbSNicholas Bellinger if (pr_reg->pr_reg_all_tg_pt) 1173c66ac9dbSNicholas Bellinger len = sprintf(page, "SPC-3 Reservation: All Target" 1174c66ac9dbSNicholas Bellinger " Ports registration\n"); 1175c66ac9dbSNicholas Bellinger else 1176c66ac9dbSNicholas Bellinger len = sprintf(page, "SPC-3 Reservation: Single" 1177c66ac9dbSNicholas Bellinger " Target Port registration\n"); 1178c66ac9dbSNicholas Bellinger spin_unlock(&dev->dev_reservation_lock); 1179c66ac9dbSNicholas Bellinger 1180c66ac9dbSNicholas Bellinger return len; 1181c66ac9dbSNicholas Bellinger } 1182c66ac9dbSNicholas Bellinger 1183c66ac9dbSNicholas Bellinger SE_DEV_PR_ATTR_RO(res_pr_all_tgt_pts); 1184c66ac9dbSNicholas Bellinger 1185c66ac9dbSNicholas Bellinger /* 1186c66ac9dbSNicholas Bellinger * res_pr_generation 1187c66ac9dbSNicholas Bellinger */ 1188c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_pr_show_attr_res_pr_generation( 1189c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev, 1190c66ac9dbSNicholas Bellinger char *page) 1191c66ac9dbSNicholas Bellinger { 1192c66ac9dbSNicholas Bellinger if (!(su_dev->se_dev_ptr)) 1193c66ac9dbSNicholas Bellinger return -ENODEV; 1194c66ac9dbSNicholas Bellinger 1195e3d6f909SAndy Grover if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) 1196c66ac9dbSNicholas Bellinger return 0; 1197c66ac9dbSNicholas Bellinger 1198e3d6f909SAndy Grover return sprintf(page, "0x%08x\n", su_dev->t10_pr.pr_generation); 1199c66ac9dbSNicholas Bellinger } 1200c66ac9dbSNicholas Bellinger 1201c66ac9dbSNicholas Bellinger SE_DEV_PR_ATTR_RO(res_pr_generation); 1202c66ac9dbSNicholas Bellinger 1203c66ac9dbSNicholas Bellinger /* 1204c66ac9dbSNicholas Bellinger * res_pr_holder_tg_port 1205c66ac9dbSNicholas Bellinger */ 1206c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port( 1207c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev, 1208c66ac9dbSNicholas Bellinger char *page) 1209c66ac9dbSNicholas Bellinger { 1210c66ac9dbSNicholas Bellinger struct se_device *dev; 1211c66ac9dbSNicholas Bellinger struct se_node_acl *se_nacl; 1212c66ac9dbSNicholas Bellinger struct se_lun *lun; 1213c66ac9dbSNicholas Bellinger struct se_portal_group *se_tpg; 1214c66ac9dbSNicholas Bellinger struct t10_pr_registration *pr_reg; 1215c66ac9dbSNicholas Bellinger struct target_core_fabric_ops *tfo; 1216c66ac9dbSNicholas Bellinger ssize_t len = 0; 1217c66ac9dbSNicholas Bellinger 1218c66ac9dbSNicholas Bellinger dev = su_dev->se_dev_ptr; 1219c66ac9dbSNicholas Bellinger if (!(dev)) 1220c66ac9dbSNicholas Bellinger return -ENODEV; 1221c66ac9dbSNicholas Bellinger 1222e3d6f909SAndy Grover if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) 1223c66ac9dbSNicholas Bellinger return len; 1224c66ac9dbSNicholas Bellinger 1225c66ac9dbSNicholas Bellinger spin_lock(&dev->dev_reservation_lock); 1226c66ac9dbSNicholas Bellinger pr_reg = dev->dev_pr_res_holder; 1227c66ac9dbSNicholas Bellinger if (!(pr_reg)) { 1228c66ac9dbSNicholas Bellinger len = sprintf(page, "No SPC-3 Reservation holder\n"); 1229c66ac9dbSNicholas Bellinger spin_unlock(&dev->dev_reservation_lock); 1230c66ac9dbSNicholas Bellinger return len; 1231c66ac9dbSNicholas Bellinger } 1232c66ac9dbSNicholas Bellinger se_nacl = pr_reg->pr_reg_nacl; 1233c66ac9dbSNicholas Bellinger se_tpg = se_nacl->se_tpg; 1234c66ac9dbSNicholas Bellinger lun = pr_reg->pr_reg_tg_pt_lun; 1235e3d6f909SAndy Grover tfo = se_tpg->se_tpg_tfo; 1236c66ac9dbSNicholas Bellinger 1237c66ac9dbSNicholas Bellinger len += sprintf(page+len, "SPC-3 Reservation: %s" 1238c66ac9dbSNicholas Bellinger " Target Node Endpoint: %s\n", tfo->get_fabric_name(), 1239c66ac9dbSNicholas Bellinger tfo->tpg_get_wwn(se_tpg)); 1240c66ac9dbSNicholas Bellinger len += sprintf(page+len, "SPC-3 Reservation: Relative Port" 1241c66ac9dbSNicholas Bellinger " Identifer Tag: %hu %s Portal Group Tag: %hu" 1242c66ac9dbSNicholas Bellinger " %s Logical Unit: %u\n", lun->lun_sep->sep_rtpi, 1243c66ac9dbSNicholas Bellinger tfo->get_fabric_name(), tfo->tpg_get_tag(se_tpg), 1244c66ac9dbSNicholas Bellinger tfo->get_fabric_name(), lun->unpacked_lun); 1245c66ac9dbSNicholas Bellinger spin_unlock(&dev->dev_reservation_lock); 1246c66ac9dbSNicholas Bellinger 1247c66ac9dbSNicholas Bellinger return len; 1248c66ac9dbSNicholas Bellinger } 1249c66ac9dbSNicholas Bellinger 1250c66ac9dbSNicholas Bellinger SE_DEV_PR_ATTR_RO(res_pr_holder_tg_port); 1251c66ac9dbSNicholas Bellinger 1252c66ac9dbSNicholas Bellinger /* 1253c66ac9dbSNicholas Bellinger * res_pr_registered_i_pts 1254c66ac9dbSNicholas Bellinger */ 1255c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts( 1256c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev, 1257c66ac9dbSNicholas Bellinger char *page) 1258c66ac9dbSNicholas Bellinger { 1259c66ac9dbSNicholas Bellinger struct target_core_fabric_ops *tfo; 1260c66ac9dbSNicholas Bellinger struct t10_pr_registration *pr_reg; 1261c66ac9dbSNicholas Bellinger unsigned char buf[384]; 1262c66ac9dbSNicholas Bellinger char i_buf[PR_REG_ISID_ID_LEN]; 1263c66ac9dbSNicholas Bellinger ssize_t len = 0; 1264c66ac9dbSNicholas Bellinger int reg_count = 0, prf_isid; 1265c66ac9dbSNicholas Bellinger 1266c66ac9dbSNicholas Bellinger if (!(su_dev->se_dev_ptr)) 1267c66ac9dbSNicholas Bellinger return -ENODEV; 1268c66ac9dbSNicholas Bellinger 1269e3d6f909SAndy Grover if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) 1270c66ac9dbSNicholas Bellinger return len; 1271c66ac9dbSNicholas Bellinger 1272c66ac9dbSNicholas Bellinger len += sprintf(page+len, "SPC-3 PR Registrations:\n"); 1273c66ac9dbSNicholas Bellinger 1274e3d6f909SAndy Grover spin_lock(&su_dev->t10_pr.registration_lock); 1275e3d6f909SAndy Grover list_for_each_entry(pr_reg, &su_dev->t10_pr.registration_list, 1276c66ac9dbSNicholas Bellinger pr_reg_list) { 1277c66ac9dbSNicholas Bellinger 1278c66ac9dbSNicholas Bellinger memset(buf, 0, 384); 1279c66ac9dbSNicholas Bellinger memset(i_buf, 0, PR_REG_ISID_ID_LEN); 1280c66ac9dbSNicholas Bellinger tfo = pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo; 1281c66ac9dbSNicholas Bellinger prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], 1282c66ac9dbSNicholas Bellinger PR_REG_ISID_ID_LEN); 1283c66ac9dbSNicholas Bellinger sprintf(buf, "%s Node: %s%s Key: 0x%016Lx PRgen: 0x%08x\n", 1284c66ac9dbSNicholas Bellinger tfo->get_fabric_name(), 1285c66ac9dbSNicholas Bellinger pr_reg->pr_reg_nacl->initiatorname, (prf_isid) ? 1286c66ac9dbSNicholas Bellinger &i_buf[0] : "", pr_reg->pr_res_key, 1287c66ac9dbSNicholas Bellinger pr_reg->pr_res_generation); 1288c66ac9dbSNicholas Bellinger 128960d645a4SDan Carpenter if ((len + strlen(buf) >= PAGE_SIZE)) 1290c66ac9dbSNicholas Bellinger break; 1291c66ac9dbSNicholas Bellinger 1292c66ac9dbSNicholas Bellinger len += sprintf(page+len, "%s", buf); 1293c66ac9dbSNicholas Bellinger reg_count++; 1294c66ac9dbSNicholas Bellinger } 1295e3d6f909SAndy Grover spin_unlock(&su_dev->t10_pr.registration_lock); 1296c66ac9dbSNicholas Bellinger 1297c66ac9dbSNicholas Bellinger if (!(reg_count)) 1298c66ac9dbSNicholas Bellinger len += sprintf(page+len, "None\n"); 1299c66ac9dbSNicholas Bellinger 1300c66ac9dbSNicholas Bellinger return len; 1301c66ac9dbSNicholas Bellinger } 1302c66ac9dbSNicholas Bellinger 1303c66ac9dbSNicholas Bellinger SE_DEV_PR_ATTR_RO(res_pr_registered_i_pts); 1304c66ac9dbSNicholas Bellinger 1305c66ac9dbSNicholas Bellinger /* 1306c66ac9dbSNicholas Bellinger * res_pr_type 1307c66ac9dbSNicholas Bellinger */ 1308c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_pr_show_attr_res_pr_type( 1309c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev, 1310c66ac9dbSNicholas Bellinger char *page) 1311c66ac9dbSNicholas Bellinger { 1312c66ac9dbSNicholas Bellinger struct se_device *dev; 1313c66ac9dbSNicholas Bellinger struct t10_pr_registration *pr_reg; 1314c66ac9dbSNicholas Bellinger ssize_t len = 0; 1315c66ac9dbSNicholas Bellinger 1316c66ac9dbSNicholas Bellinger dev = su_dev->se_dev_ptr; 1317c66ac9dbSNicholas Bellinger if (!(dev)) 1318c66ac9dbSNicholas Bellinger return -ENODEV; 1319c66ac9dbSNicholas Bellinger 1320e3d6f909SAndy Grover if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) 1321c66ac9dbSNicholas Bellinger return len; 1322c66ac9dbSNicholas Bellinger 1323c66ac9dbSNicholas Bellinger spin_lock(&dev->dev_reservation_lock); 1324c66ac9dbSNicholas Bellinger pr_reg = dev->dev_pr_res_holder; 1325c66ac9dbSNicholas Bellinger if (!(pr_reg)) { 1326c66ac9dbSNicholas Bellinger len = sprintf(page, "No SPC-3 Reservation holder\n"); 1327c66ac9dbSNicholas Bellinger spin_unlock(&dev->dev_reservation_lock); 1328c66ac9dbSNicholas Bellinger return len; 1329c66ac9dbSNicholas Bellinger } 1330c66ac9dbSNicholas Bellinger len = sprintf(page, "SPC-3 Reservation Type: %s\n", 1331c66ac9dbSNicholas Bellinger core_scsi3_pr_dump_type(pr_reg->pr_res_type)); 1332c66ac9dbSNicholas Bellinger spin_unlock(&dev->dev_reservation_lock); 1333c66ac9dbSNicholas Bellinger 1334c66ac9dbSNicholas Bellinger return len; 1335c66ac9dbSNicholas Bellinger } 1336c66ac9dbSNicholas Bellinger 1337c66ac9dbSNicholas Bellinger SE_DEV_PR_ATTR_RO(res_pr_type); 1338c66ac9dbSNicholas Bellinger 1339c66ac9dbSNicholas Bellinger /* 1340c66ac9dbSNicholas Bellinger * res_type 1341c66ac9dbSNicholas Bellinger */ 1342c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_pr_show_attr_res_type( 1343c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev, 1344c66ac9dbSNicholas Bellinger char *page) 1345c66ac9dbSNicholas Bellinger { 1346c66ac9dbSNicholas Bellinger ssize_t len = 0; 1347c66ac9dbSNicholas Bellinger 1348c66ac9dbSNicholas Bellinger if (!(su_dev->se_dev_ptr)) 1349c66ac9dbSNicholas Bellinger return -ENODEV; 1350c66ac9dbSNicholas Bellinger 1351e3d6f909SAndy Grover switch (su_dev->t10_pr.res_type) { 1352c66ac9dbSNicholas Bellinger case SPC3_PERSISTENT_RESERVATIONS: 1353c66ac9dbSNicholas Bellinger len = sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n"); 1354c66ac9dbSNicholas Bellinger break; 1355c66ac9dbSNicholas Bellinger case SPC2_RESERVATIONS: 1356c66ac9dbSNicholas Bellinger len = sprintf(page, "SPC2_RESERVATIONS\n"); 1357c66ac9dbSNicholas Bellinger break; 1358c66ac9dbSNicholas Bellinger case SPC_PASSTHROUGH: 1359c66ac9dbSNicholas Bellinger len = sprintf(page, "SPC_PASSTHROUGH\n"); 1360c66ac9dbSNicholas Bellinger break; 1361c66ac9dbSNicholas Bellinger default: 1362c66ac9dbSNicholas Bellinger len = sprintf(page, "UNKNOWN\n"); 1363c66ac9dbSNicholas Bellinger break; 1364c66ac9dbSNicholas Bellinger } 1365c66ac9dbSNicholas Bellinger 1366c66ac9dbSNicholas Bellinger return len; 1367c66ac9dbSNicholas Bellinger } 1368c66ac9dbSNicholas Bellinger 1369c66ac9dbSNicholas Bellinger SE_DEV_PR_ATTR_RO(res_type); 1370c66ac9dbSNicholas Bellinger 1371c66ac9dbSNicholas Bellinger /* 1372c66ac9dbSNicholas Bellinger * res_aptpl_active 1373c66ac9dbSNicholas Bellinger */ 1374c66ac9dbSNicholas Bellinger 1375c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_pr_show_attr_res_aptpl_active( 1376c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev, 1377c66ac9dbSNicholas Bellinger char *page) 1378c66ac9dbSNicholas Bellinger { 1379c66ac9dbSNicholas Bellinger if (!(su_dev->se_dev_ptr)) 1380c66ac9dbSNicholas Bellinger return -ENODEV; 1381c66ac9dbSNicholas Bellinger 1382e3d6f909SAndy Grover if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) 1383c66ac9dbSNicholas Bellinger return 0; 1384c66ac9dbSNicholas Bellinger 1385c66ac9dbSNicholas Bellinger return sprintf(page, "APTPL Bit Status: %s\n", 1386e3d6f909SAndy Grover (su_dev->t10_pr.pr_aptpl_active) ? "Activated" : "Disabled"); 1387c66ac9dbSNicholas Bellinger } 1388c66ac9dbSNicholas Bellinger 1389c66ac9dbSNicholas Bellinger SE_DEV_PR_ATTR_RO(res_aptpl_active); 1390c66ac9dbSNicholas Bellinger 1391c66ac9dbSNicholas Bellinger /* 1392c66ac9dbSNicholas Bellinger * res_aptpl_metadata 1393c66ac9dbSNicholas Bellinger */ 1394c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_pr_show_attr_res_aptpl_metadata( 1395c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev, 1396c66ac9dbSNicholas Bellinger char *page) 1397c66ac9dbSNicholas Bellinger { 1398c66ac9dbSNicholas Bellinger if (!(su_dev->se_dev_ptr)) 1399c66ac9dbSNicholas Bellinger return -ENODEV; 1400c66ac9dbSNicholas Bellinger 1401e3d6f909SAndy Grover if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) 1402c66ac9dbSNicholas Bellinger return 0; 1403c66ac9dbSNicholas Bellinger 1404c66ac9dbSNicholas Bellinger return sprintf(page, "Ready to process PR APTPL metadata..\n"); 1405c66ac9dbSNicholas Bellinger } 1406c66ac9dbSNicholas Bellinger 1407c66ac9dbSNicholas Bellinger enum { 1408c66ac9dbSNicholas Bellinger Opt_initiator_fabric, Opt_initiator_node, Opt_initiator_sid, 1409c66ac9dbSNicholas Bellinger Opt_sa_res_key, Opt_res_holder, Opt_res_type, Opt_res_scope, 1410c66ac9dbSNicholas Bellinger Opt_res_all_tg_pt, Opt_mapped_lun, Opt_target_fabric, 1411c66ac9dbSNicholas Bellinger Opt_target_node, Opt_tpgt, Opt_port_rtpi, Opt_target_lun, Opt_err 1412c66ac9dbSNicholas Bellinger }; 1413c66ac9dbSNicholas Bellinger 1414c66ac9dbSNicholas Bellinger static match_table_t tokens = { 1415c66ac9dbSNicholas Bellinger {Opt_initiator_fabric, "initiator_fabric=%s"}, 1416c66ac9dbSNicholas Bellinger {Opt_initiator_node, "initiator_node=%s"}, 1417c66ac9dbSNicholas Bellinger {Opt_initiator_sid, "initiator_sid=%s"}, 1418c66ac9dbSNicholas Bellinger {Opt_sa_res_key, "sa_res_key=%s"}, 1419c66ac9dbSNicholas Bellinger {Opt_res_holder, "res_holder=%d"}, 1420c66ac9dbSNicholas Bellinger {Opt_res_type, "res_type=%d"}, 1421c66ac9dbSNicholas Bellinger {Opt_res_scope, "res_scope=%d"}, 1422c66ac9dbSNicholas Bellinger {Opt_res_all_tg_pt, "res_all_tg_pt=%d"}, 1423c66ac9dbSNicholas Bellinger {Opt_mapped_lun, "mapped_lun=%d"}, 1424c66ac9dbSNicholas Bellinger {Opt_target_fabric, "target_fabric=%s"}, 1425c66ac9dbSNicholas Bellinger {Opt_target_node, "target_node=%s"}, 1426c66ac9dbSNicholas Bellinger {Opt_tpgt, "tpgt=%d"}, 1427c66ac9dbSNicholas Bellinger {Opt_port_rtpi, "port_rtpi=%d"}, 1428c66ac9dbSNicholas Bellinger {Opt_target_lun, "target_lun=%d"}, 1429c66ac9dbSNicholas Bellinger {Opt_err, NULL} 1430c66ac9dbSNicholas Bellinger }; 1431c66ac9dbSNicholas Bellinger 1432c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( 1433c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev, 1434c66ac9dbSNicholas Bellinger const char *page, 1435c66ac9dbSNicholas Bellinger size_t count) 1436c66ac9dbSNicholas Bellinger { 1437c66ac9dbSNicholas Bellinger struct se_device *dev; 14386d180253SJesper Juhl unsigned char *i_fabric = NULL, *i_port = NULL, *isid = NULL; 14396d180253SJesper Juhl unsigned char *t_fabric = NULL, *t_port = NULL; 1440c66ac9dbSNicholas Bellinger char *orig, *ptr, *arg_p, *opts; 1441c66ac9dbSNicholas Bellinger substring_t args[MAX_OPT_ARGS]; 1442c66ac9dbSNicholas Bellinger unsigned long long tmp_ll; 1443c66ac9dbSNicholas Bellinger u64 sa_res_key = 0; 1444c66ac9dbSNicholas Bellinger u32 mapped_lun = 0, target_lun = 0; 1445c66ac9dbSNicholas Bellinger int ret = -1, res_holder = 0, all_tg_pt = 0, arg, token; 1446c66ac9dbSNicholas Bellinger u16 port_rpti = 0, tpgt = 0; 1447c66ac9dbSNicholas Bellinger u8 type = 0, scope; 1448c66ac9dbSNicholas Bellinger 1449c66ac9dbSNicholas Bellinger dev = su_dev->se_dev_ptr; 1450c66ac9dbSNicholas Bellinger if (!(dev)) 1451c66ac9dbSNicholas Bellinger return -ENODEV; 1452c66ac9dbSNicholas Bellinger 1453e3d6f909SAndy Grover if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS) 1454c66ac9dbSNicholas Bellinger return 0; 1455c66ac9dbSNicholas Bellinger 1456c66ac9dbSNicholas Bellinger if (atomic_read(&dev->dev_export_obj.obj_access_count)) { 1457c66ac9dbSNicholas Bellinger printk(KERN_INFO "Unable to process APTPL metadata while" 1458c66ac9dbSNicholas Bellinger " active fabric exports exist\n"); 1459c66ac9dbSNicholas Bellinger return -EINVAL; 1460c66ac9dbSNicholas Bellinger } 1461c66ac9dbSNicholas Bellinger 1462c66ac9dbSNicholas Bellinger opts = kstrdup(page, GFP_KERNEL); 1463c66ac9dbSNicholas Bellinger if (!opts) 1464c66ac9dbSNicholas Bellinger return -ENOMEM; 1465c66ac9dbSNicholas Bellinger 1466c66ac9dbSNicholas Bellinger orig = opts; 1467c66ac9dbSNicholas Bellinger while ((ptr = strsep(&opts, ",")) != NULL) { 1468c66ac9dbSNicholas Bellinger if (!*ptr) 1469c66ac9dbSNicholas Bellinger continue; 1470c66ac9dbSNicholas Bellinger 1471c66ac9dbSNicholas Bellinger token = match_token(ptr, tokens, args); 1472c66ac9dbSNicholas Bellinger switch (token) { 1473c66ac9dbSNicholas Bellinger case Opt_initiator_fabric: 1474c66ac9dbSNicholas Bellinger i_fabric = match_strdup(&args[0]); 14756d180253SJesper Juhl if (!i_fabric) { 14766d180253SJesper Juhl ret = -ENOMEM; 14776d180253SJesper Juhl goto out; 14786d180253SJesper Juhl } 1479c66ac9dbSNicholas Bellinger break; 1480c66ac9dbSNicholas Bellinger case Opt_initiator_node: 1481c66ac9dbSNicholas Bellinger i_port = match_strdup(&args[0]); 14826d180253SJesper Juhl if (!i_port) { 14836d180253SJesper Juhl ret = -ENOMEM; 14846d180253SJesper Juhl goto out; 14856d180253SJesper Juhl } 148660d645a4SDan Carpenter if (strlen(i_port) >= PR_APTPL_MAX_IPORT_LEN) { 1487c66ac9dbSNicholas Bellinger printk(KERN_ERR "APTPL metadata initiator_node=" 1488c66ac9dbSNicholas Bellinger " exceeds PR_APTPL_MAX_IPORT_LEN: %d\n", 1489c66ac9dbSNicholas Bellinger PR_APTPL_MAX_IPORT_LEN); 1490c66ac9dbSNicholas Bellinger ret = -EINVAL; 1491c66ac9dbSNicholas Bellinger break; 1492c66ac9dbSNicholas Bellinger } 1493c66ac9dbSNicholas Bellinger break; 1494c66ac9dbSNicholas Bellinger case Opt_initiator_sid: 1495c66ac9dbSNicholas Bellinger isid = match_strdup(&args[0]); 14966d180253SJesper Juhl if (!isid) { 14976d180253SJesper Juhl ret = -ENOMEM; 14986d180253SJesper Juhl goto out; 14996d180253SJesper Juhl } 150060d645a4SDan Carpenter if (strlen(isid) >= PR_REG_ISID_LEN) { 1501c66ac9dbSNicholas Bellinger printk(KERN_ERR "APTPL metadata initiator_isid" 1502c66ac9dbSNicholas Bellinger "= exceeds PR_REG_ISID_LEN: %d\n", 1503c66ac9dbSNicholas Bellinger PR_REG_ISID_LEN); 1504c66ac9dbSNicholas Bellinger ret = -EINVAL; 1505c66ac9dbSNicholas Bellinger break; 1506c66ac9dbSNicholas Bellinger } 1507c66ac9dbSNicholas Bellinger break; 1508c66ac9dbSNicholas Bellinger case Opt_sa_res_key: 1509c66ac9dbSNicholas Bellinger arg_p = match_strdup(&args[0]); 15106d180253SJesper Juhl if (!arg_p) { 15116d180253SJesper Juhl ret = -ENOMEM; 15126d180253SJesper Juhl goto out; 15136d180253SJesper Juhl } 1514c66ac9dbSNicholas Bellinger ret = strict_strtoull(arg_p, 0, &tmp_ll); 1515c66ac9dbSNicholas Bellinger if (ret < 0) { 1516c66ac9dbSNicholas Bellinger printk(KERN_ERR "strict_strtoull() failed for" 1517c66ac9dbSNicholas Bellinger " sa_res_key=\n"); 1518c66ac9dbSNicholas Bellinger goto out; 1519c66ac9dbSNicholas Bellinger } 1520c66ac9dbSNicholas Bellinger sa_res_key = (u64)tmp_ll; 1521c66ac9dbSNicholas Bellinger break; 1522c66ac9dbSNicholas Bellinger /* 1523c66ac9dbSNicholas Bellinger * PR APTPL Metadata for Reservation 1524c66ac9dbSNicholas Bellinger */ 1525c66ac9dbSNicholas Bellinger case Opt_res_holder: 1526c66ac9dbSNicholas Bellinger match_int(args, &arg); 1527c66ac9dbSNicholas Bellinger res_holder = arg; 1528c66ac9dbSNicholas Bellinger break; 1529c66ac9dbSNicholas Bellinger case Opt_res_type: 1530c66ac9dbSNicholas Bellinger match_int(args, &arg); 1531c66ac9dbSNicholas Bellinger type = (u8)arg; 1532c66ac9dbSNicholas Bellinger break; 1533c66ac9dbSNicholas Bellinger case Opt_res_scope: 1534c66ac9dbSNicholas Bellinger match_int(args, &arg); 1535c66ac9dbSNicholas Bellinger scope = (u8)arg; 1536c66ac9dbSNicholas Bellinger break; 1537c66ac9dbSNicholas Bellinger case Opt_res_all_tg_pt: 1538c66ac9dbSNicholas Bellinger match_int(args, &arg); 1539c66ac9dbSNicholas Bellinger all_tg_pt = (int)arg; 1540c66ac9dbSNicholas Bellinger break; 1541c66ac9dbSNicholas Bellinger case Opt_mapped_lun: 1542c66ac9dbSNicholas Bellinger match_int(args, &arg); 1543c66ac9dbSNicholas Bellinger mapped_lun = (u32)arg; 1544c66ac9dbSNicholas Bellinger break; 1545c66ac9dbSNicholas Bellinger /* 1546c66ac9dbSNicholas Bellinger * PR APTPL Metadata for Target Port 1547c66ac9dbSNicholas Bellinger */ 1548c66ac9dbSNicholas Bellinger case Opt_target_fabric: 1549c66ac9dbSNicholas Bellinger t_fabric = match_strdup(&args[0]); 15506d180253SJesper Juhl if (!t_fabric) { 15516d180253SJesper Juhl ret = -ENOMEM; 15526d180253SJesper Juhl goto out; 15536d180253SJesper Juhl } 1554c66ac9dbSNicholas Bellinger break; 1555c66ac9dbSNicholas Bellinger case Opt_target_node: 1556c66ac9dbSNicholas Bellinger t_port = match_strdup(&args[0]); 15576d180253SJesper Juhl if (!t_port) { 15586d180253SJesper Juhl ret = -ENOMEM; 15596d180253SJesper Juhl goto out; 15606d180253SJesper Juhl } 156160d645a4SDan Carpenter if (strlen(t_port) >= PR_APTPL_MAX_TPORT_LEN) { 1562c66ac9dbSNicholas Bellinger printk(KERN_ERR "APTPL metadata target_node=" 1563c66ac9dbSNicholas Bellinger " exceeds PR_APTPL_MAX_TPORT_LEN: %d\n", 1564c66ac9dbSNicholas Bellinger PR_APTPL_MAX_TPORT_LEN); 1565c66ac9dbSNicholas Bellinger ret = -EINVAL; 1566c66ac9dbSNicholas Bellinger break; 1567c66ac9dbSNicholas Bellinger } 1568c66ac9dbSNicholas Bellinger break; 1569c66ac9dbSNicholas Bellinger case Opt_tpgt: 1570c66ac9dbSNicholas Bellinger match_int(args, &arg); 1571c66ac9dbSNicholas Bellinger tpgt = (u16)arg; 1572c66ac9dbSNicholas Bellinger break; 1573c66ac9dbSNicholas Bellinger case Opt_port_rtpi: 1574c66ac9dbSNicholas Bellinger match_int(args, &arg); 1575c66ac9dbSNicholas Bellinger port_rpti = (u16)arg; 1576c66ac9dbSNicholas Bellinger break; 1577c66ac9dbSNicholas Bellinger case Opt_target_lun: 1578c66ac9dbSNicholas Bellinger match_int(args, &arg); 1579c66ac9dbSNicholas Bellinger target_lun = (u32)arg; 1580c66ac9dbSNicholas Bellinger break; 1581c66ac9dbSNicholas Bellinger default: 1582c66ac9dbSNicholas Bellinger break; 1583c66ac9dbSNicholas Bellinger } 1584c66ac9dbSNicholas Bellinger } 1585c66ac9dbSNicholas Bellinger 1586c66ac9dbSNicholas Bellinger if (!(i_port) || !(t_port) || !(sa_res_key)) { 1587c66ac9dbSNicholas Bellinger printk(KERN_ERR "Illegal parameters for APTPL registration\n"); 1588c66ac9dbSNicholas Bellinger ret = -EINVAL; 1589c66ac9dbSNicholas Bellinger goto out; 1590c66ac9dbSNicholas Bellinger } 1591c66ac9dbSNicholas Bellinger 1592c66ac9dbSNicholas Bellinger if (res_holder && !(type)) { 1593c66ac9dbSNicholas Bellinger printk(KERN_ERR "Illegal PR type: 0x%02x for reservation" 1594c66ac9dbSNicholas Bellinger " holder\n", type); 1595c66ac9dbSNicholas Bellinger ret = -EINVAL; 1596c66ac9dbSNicholas Bellinger goto out; 1597c66ac9dbSNicholas Bellinger } 1598c66ac9dbSNicholas Bellinger 1599e3d6f909SAndy Grover ret = core_scsi3_alloc_aptpl_registration(&su_dev->t10_pr, sa_res_key, 1600c66ac9dbSNicholas Bellinger i_port, isid, mapped_lun, t_port, tpgt, target_lun, 1601c66ac9dbSNicholas Bellinger res_holder, all_tg_pt, type); 1602c66ac9dbSNicholas Bellinger out: 16036d180253SJesper Juhl kfree(i_fabric); 16046d180253SJesper Juhl kfree(i_port); 16056d180253SJesper Juhl kfree(isid); 16066d180253SJesper Juhl kfree(t_fabric); 16076d180253SJesper Juhl kfree(t_port); 1608c66ac9dbSNicholas Bellinger kfree(orig); 1609c66ac9dbSNicholas Bellinger return (ret == 0) ? count : ret; 1610c66ac9dbSNicholas Bellinger } 1611c66ac9dbSNicholas Bellinger 1612c66ac9dbSNicholas Bellinger SE_DEV_PR_ATTR(res_aptpl_metadata, S_IRUGO | S_IWUSR); 1613c66ac9dbSNicholas Bellinger 1614c66ac9dbSNicholas Bellinger CONFIGFS_EATTR_OPS(target_core_dev_pr, se_subsystem_dev, se_dev_pr_group); 1615c66ac9dbSNicholas Bellinger 1616c66ac9dbSNicholas Bellinger static struct configfs_attribute *target_core_dev_pr_attrs[] = { 1617c66ac9dbSNicholas Bellinger &target_core_dev_pr_res_holder.attr, 1618c66ac9dbSNicholas Bellinger &target_core_dev_pr_res_pr_all_tgt_pts.attr, 1619c66ac9dbSNicholas Bellinger &target_core_dev_pr_res_pr_generation.attr, 1620c66ac9dbSNicholas Bellinger &target_core_dev_pr_res_pr_holder_tg_port.attr, 1621c66ac9dbSNicholas Bellinger &target_core_dev_pr_res_pr_registered_i_pts.attr, 1622c66ac9dbSNicholas Bellinger &target_core_dev_pr_res_pr_type.attr, 1623c66ac9dbSNicholas Bellinger &target_core_dev_pr_res_type.attr, 1624c66ac9dbSNicholas Bellinger &target_core_dev_pr_res_aptpl_active.attr, 1625c66ac9dbSNicholas Bellinger &target_core_dev_pr_res_aptpl_metadata.attr, 1626c66ac9dbSNicholas Bellinger NULL, 1627c66ac9dbSNicholas Bellinger }; 1628c66ac9dbSNicholas Bellinger 1629c66ac9dbSNicholas Bellinger static struct configfs_item_operations target_core_dev_pr_ops = { 1630c66ac9dbSNicholas Bellinger .show_attribute = target_core_dev_pr_attr_show, 1631c66ac9dbSNicholas Bellinger .store_attribute = target_core_dev_pr_attr_store, 1632c66ac9dbSNicholas Bellinger }; 1633c66ac9dbSNicholas Bellinger 1634c66ac9dbSNicholas Bellinger static struct config_item_type target_core_dev_pr_cit = { 1635c66ac9dbSNicholas Bellinger .ct_item_ops = &target_core_dev_pr_ops, 1636c66ac9dbSNicholas Bellinger .ct_attrs = target_core_dev_pr_attrs, 1637c66ac9dbSNicholas Bellinger .ct_owner = THIS_MODULE, 1638c66ac9dbSNicholas Bellinger }; 1639c66ac9dbSNicholas Bellinger 1640c66ac9dbSNicholas Bellinger /* End functions for struct config_item_type target_core_dev_pr_cit */ 1641c66ac9dbSNicholas Bellinger 1642c66ac9dbSNicholas Bellinger /* Start functions for struct config_item_type target_core_dev_cit */ 1643c66ac9dbSNicholas Bellinger 1644c66ac9dbSNicholas Bellinger static ssize_t target_core_show_dev_info(void *p, char *page) 1645c66ac9dbSNicholas Bellinger { 1646c66ac9dbSNicholas Bellinger struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p; 1647c66ac9dbSNicholas Bellinger struct se_hba *hba = se_dev->se_dev_hba; 1648c66ac9dbSNicholas Bellinger struct se_subsystem_api *t = hba->transport; 1649c66ac9dbSNicholas Bellinger int bl = 0; 1650c66ac9dbSNicholas Bellinger ssize_t read_bytes = 0; 1651c66ac9dbSNicholas Bellinger 1652c66ac9dbSNicholas Bellinger if (!(se_dev->se_dev_ptr)) 1653c66ac9dbSNicholas Bellinger return -ENODEV; 1654c66ac9dbSNicholas Bellinger 1655c66ac9dbSNicholas Bellinger transport_dump_dev_state(se_dev->se_dev_ptr, page, &bl); 1656c66ac9dbSNicholas Bellinger read_bytes += bl; 1657c66ac9dbSNicholas Bellinger read_bytes += t->show_configfs_dev_params(hba, se_dev, page+read_bytes); 1658c66ac9dbSNicholas Bellinger return read_bytes; 1659c66ac9dbSNicholas Bellinger } 1660c66ac9dbSNicholas Bellinger 1661c66ac9dbSNicholas Bellinger static struct target_core_configfs_attribute target_core_attr_dev_info = { 1662c66ac9dbSNicholas Bellinger .attr = { .ca_owner = THIS_MODULE, 1663c66ac9dbSNicholas Bellinger .ca_name = "info", 1664c66ac9dbSNicholas Bellinger .ca_mode = S_IRUGO }, 1665c66ac9dbSNicholas Bellinger .show = target_core_show_dev_info, 1666c66ac9dbSNicholas Bellinger .store = NULL, 1667c66ac9dbSNicholas Bellinger }; 1668c66ac9dbSNicholas Bellinger 1669c66ac9dbSNicholas Bellinger static ssize_t target_core_store_dev_control( 1670c66ac9dbSNicholas Bellinger void *p, 1671c66ac9dbSNicholas Bellinger const char *page, 1672c66ac9dbSNicholas Bellinger size_t count) 1673c66ac9dbSNicholas Bellinger { 1674c66ac9dbSNicholas Bellinger struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p; 1675c66ac9dbSNicholas Bellinger struct se_hba *hba = se_dev->se_dev_hba; 1676c66ac9dbSNicholas Bellinger struct se_subsystem_api *t = hba->transport; 1677c66ac9dbSNicholas Bellinger 1678c66ac9dbSNicholas Bellinger if (!(se_dev->se_dev_su_ptr)) { 1679c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to locate struct se_subsystem_dev>se" 1680c66ac9dbSNicholas Bellinger "_dev_su_ptr\n"); 1681c66ac9dbSNicholas Bellinger return -EINVAL; 1682c66ac9dbSNicholas Bellinger } 1683c66ac9dbSNicholas Bellinger 1684c66ac9dbSNicholas Bellinger return t->set_configfs_dev_params(hba, se_dev, page, count); 1685c66ac9dbSNicholas Bellinger } 1686c66ac9dbSNicholas Bellinger 1687c66ac9dbSNicholas Bellinger static struct target_core_configfs_attribute target_core_attr_dev_control = { 1688c66ac9dbSNicholas Bellinger .attr = { .ca_owner = THIS_MODULE, 1689c66ac9dbSNicholas Bellinger .ca_name = "control", 1690c66ac9dbSNicholas Bellinger .ca_mode = S_IWUSR }, 1691c66ac9dbSNicholas Bellinger .show = NULL, 1692c66ac9dbSNicholas Bellinger .store = target_core_store_dev_control, 1693c66ac9dbSNicholas Bellinger }; 1694c66ac9dbSNicholas Bellinger 1695c66ac9dbSNicholas Bellinger static ssize_t target_core_show_dev_alias(void *p, char *page) 1696c66ac9dbSNicholas Bellinger { 1697c66ac9dbSNicholas Bellinger struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p; 1698c66ac9dbSNicholas Bellinger 1699c66ac9dbSNicholas Bellinger if (!(se_dev->su_dev_flags & SDF_USING_ALIAS)) 1700c66ac9dbSNicholas Bellinger return 0; 1701c66ac9dbSNicholas Bellinger 1702c66ac9dbSNicholas Bellinger return snprintf(page, PAGE_SIZE, "%s\n", se_dev->se_dev_alias); 1703c66ac9dbSNicholas Bellinger } 1704c66ac9dbSNicholas Bellinger 1705c66ac9dbSNicholas Bellinger static ssize_t target_core_store_dev_alias( 1706c66ac9dbSNicholas Bellinger void *p, 1707c66ac9dbSNicholas Bellinger const char *page, 1708c66ac9dbSNicholas Bellinger size_t count) 1709c66ac9dbSNicholas Bellinger { 1710c66ac9dbSNicholas Bellinger struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p; 1711c66ac9dbSNicholas Bellinger struct se_hba *hba = se_dev->se_dev_hba; 1712c66ac9dbSNicholas Bellinger ssize_t read_bytes; 1713c66ac9dbSNicholas Bellinger 1714c66ac9dbSNicholas Bellinger if (count > (SE_DEV_ALIAS_LEN-1)) { 1715c66ac9dbSNicholas Bellinger printk(KERN_ERR "alias count: %d exceeds" 1716c66ac9dbSNicholas Bellinger " SE_DEV_ALIAS_LEN-1: %u\n", (int)count, 1717c66ac9dbSNicholas Bellinger SE_DEV_ALIAS_LEN-1); 1718c66ac9dbSNicholas Bellinger return -EINVAL; 1719c66ac9dbSNicholas Bellinger } 1720c66ac9dbSNicholas Bellinger 1721c66ac9dbSNicholas Bellinger se_dev->su_dev_flags |= SDF_USING_ALIAS; 1722c66ac9dbSNicholas Bellinger read_bytes = snprintf(&se_dev->se_dev_alias[0], SE_DEV_ALIAS_LEN, 1723c66ac9dbSNicholas Bellinger "%s", page); 1724c66ac9dbSNicholas Bellinger 1725c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: %s/%s set alias: %s\n", 1726c66ac9dbSNicholas Bellinger config_item_name(&hba->hba_group.cg_item), 1727c66ac9dbSNicholas Bellinger config_item_name(&se_dev->se_dev_group.cg_item), 1728c66ac9dbSNicholas Bellinger se_dev->se_dev_alias); 1729c66ac9dbSNicholas Bellinger 1730c66ac9dbSNicholas Bellinger return read_bytes; 1731c66ac9dbSNicholas Bellinger } 1732c66ac9dbSNicholas Bellinger 1733c66ac9dbSNicholas Bellinger static struct target_core_configfs_attribute target_core_attr_dev_alias = { 1734c66ac9dbSNicholas Bellinger .attr = { .ca_owner = THIS_MODULE, 1735c66ac9dbSNicholas Bellinger .ca_name = "alias", 1736c66ac9dbSNicholas Bellinger .ca_mode = S_IRUGO | S_IWUSR }, 1737c66ac9dbSNicholas Bellinger .show = target_core_show_dev_alias, 1738c66ac9dbSNicholas Bellinger .store = target_core_store_dev_alias, 1739c66ac9dbSNicholas Bellinger }; 1740c66ac9dbSNicholas Bellinger 1741c66ac9dbSNicholas Bellinger static ssize_t target_core_show_dev_udev_path(void *p, char *page) 1742c66ac9dbSNicholas Bellinger { 1743c66ac9dbSNicholas Bellinger struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p; 1744c66ac9dbSNicholas Bellinger 1745c66ac9dbSNicholas Bellinger if (!(se_dev->su_dev_flags & SDF_USING_UDEV_PATH)) 1746c66ac9dbSNicholas Bellinger return 0; 1747c66ac9dbSNicholas Bellinger 1748c66ac9dbSNicholas Bellinger return snprintf(page, PAGE_SIZE, "%s\n", se_dev->se_dev_udev_path); 1749c66ac9dbSNicholas Bellinger } 1750c66ac9dbSNicholas Bellinger 1751c66ac9dbSNicholas Bellinger static ssize_t target_core_store_dev_udev_path( 1752c66ac9dbSNicholas Bellinger void *p, 1753c66ac9dbSNicholas Bellinger const char *page, 1754c66ac9dbSNicholas Bellinger size_t count) 1755c66ac9dbSNicholas Bellinger { 1756c66ac9dbSNicholas Bellinger struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p; 1757c66ac9dbSNicholas Bellinger struct se_hba *hba = se_dev->se_dev_hba; 1758c66ac9dbSNicholas Bellinger ssize_t read_bytes; 1759c66ac9dbSNicholas Bellinger 1760c66ac9dbSNicholas Bellinger if (count > (SE_UDEV_PATH_LEN-1)) { 1761c66ac9dbSNicholas Bellinger printk(KERN_ERR "udev_path count: %d exceeds" 1762c66ac9dbSNicholas Bellinger " SE_UDEV_PATH_LEN-1: %u\n", (int)count, 1763c66ac9dbSNicholas Bellinger SE_UDEV_PATH_LEN-1); 1764c66ac9dbSNicholas Bellinger return -EINVAL; 1765c66ac9dbSNicholas Bellinger } 1766c66ac9dbSNicholas Bellinger 1767c66ac9dbSNicholas Bellinger se_dev->su_dev_flags |= SDF_USING_UDEV_PATH; 1768c66ac9dbSNicholas Bellinger read_bytes = snprintf(&se_dev->se_dev_udev_path[0], SE_UDEV_PATH_LEN, 1769c66ac9dbSNicholas Bellinger "%s", page); 1770c66ac9dbSNicholas Bellinger 1771c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: %s/%s set udev_path: %s\n", 1772c66ac9dbSNicholas Bellinger config_item_name(&hba->hba_group.cg_item), 1773c66ac9dbSNicholas Bellinger config_item_name(&se_dev->se_dev_group.cg_item), 1774c66ac9dbSNicholas Bellinger se_dev->se_dev_udev_path); 1775c66ac9dbSNicholas Bellinger 1776c66ac9dbSNicholas Bellinger return read_bytes; 1777c66ac9dbSNicholas Bellinger } 1778c66ac9dbSNicholas Bellinger 1779c66ac9dbSNicholas Bellinger static struct target_core_configfs_attribute target_core_attr_dev_udev_path = { 1780c66ac9dbSNicholas Bellinger .attr = { .ca_owner = THIS_MODULE, 1781c66ac9dbSNicholas Bellinger .ca_name = "udev_path", 1782c66ac9dbSNicholas Bellinger .ca_mode = S_IRUGO | S_IWUSR }, 1783c66ac9dbSNicholas Bellinger .show = target_core_show_dev_udev_path, 1784c66ac9dbSNicholas Bellinger .store = target_core_store_dev_udev_path, 1785c66ac9dbSNicholas Bellinger }; 1786c66ac9dbSNicholas Bellinger 1787c66ac9dbSNicholas Bellinger static ssize_t target_core_store_dev_enable( 1788c66ac9dbSNicholas Bellinger void *p, 1789c66ac9dbSNicholas Bellinger const char *page, 1790c66ac9dbSNicholas Bellinger size_t count) 1791c66ac9dbSNicholas Bellinger { 1792c66ac9dbSNicholas Bellinger struct se_subsystem_dev *se_dev = (struct se_subsystem_dev *)p; 1793c66ac9dbSNicholas Bellinger struct se_device *dev; 1794c66ac9dbSNicholas Bellinger struct se_hba *hba = se_dev->se_dev_hba; 1795c66ac9dbSNicholas Bellinger struct se_subsystem_api *t = hba->transport; 1796c66ac9dbSNicholas Bellinger char *ptr; 1797c66ac9dbSNicholas Bellinger 1798c66ac9dbSNicholas Bellinger ptr = strstr(page, "1"); 1799c66ac9dbSNicholas Bellinger if (!(ptr)) { 1800c66ac9dbSNicholas Bellinger printk(KERN_ERR "For dev_enable ops, only valid value" 1801c66ac9dbSNicholas Bellinger " is \"1\"\n"); 1802c66ac9dbSNicholas Bellinger return -EINVAL; 1803c66ac9dbSNicholas Bellinger } 1804c66ac9dbSNicholas Bellinger if ((se_dev->se_dev_ptr)) { 1805c66ac9dbSNicholas Bellinger printk(KERN_ERR "se_dev->se_dev_ptr already set for storage" 1806c66ac9dbSNicholas Bellinger " object\n"); 1807c66ac9dbSNicholas Bellinger return -EEXIST; 1808c66ac9dbSNicholas Bellinger } 1809c66ac9dbSNicholas Bellinger 1810c66ac9dbSNicholas Bellinger if (t->check_configfs_dev_params(hba, se_dev) < 0) 1811c66ac9dbSNicholas Bellinger return -EINVAL; 1812c66ac9dbSNicholas Bellinger 1813c66ac9dbSNicholas Bellinger dev = t->create_virtdevice(hba, se_dev, se_dev->se_dev_su_ptr); 1814613640e4SNicholas Bellinger if (IS_ERR(dev)) 1815613640e4SNicholas Bellinger return PTR_ERR(dev); 1816613640e4SNicholas Bellinger else if (!dev) 1817c66ac9dbSNicholas Bellinger return -EINVAL; 1818c66ac9dbSNicholas Bellinger 1819c66ac9dbSNicholas Bellinger se_dev->se_dev_ptr = dev; 1820c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: Registered se_dev->se_dev_ptr:" 1821c66ac9dbSNicholas Bellinger " %p\n", se_dev->se_dev_ptr); 1822c66ac9dbSNicholas Bellinger 1823c66ac9dbSNicholas Bellinger return count; 1824c66ac9dbSNicholas Bellinger } 1825c66ac9dbSNicholas Bellinger 1826c66ac9dbSNicholas Bellinger static struct target_core_configfs_attribute target_core_attr_dev_enable = { 1827c66ac9dbSNicholas Bellinger .attr = { .ca_owner = THIS_MODULE, 1828c66ac9dbSNicholas Bellinger .ca_name = "enable", 1829c66ac9dbSNicholas Bellinger .ca_mode = S_IWUSR }, 1830c66ac9dbSNicholas Bellinger .show = NULL, 1831c66ac9dbSNicholas Bellinger .store = target_core_store_dev_enable, 1832c66ac9dbSNicholas Bellinger }; 1833c66ac9dbSNicholas Bellinger 1834c66ac9dbSNicholas Bellinger static ssize_t target_core_show_alua_lu_gp(void *p, char *page) 1835c66ac9dbSNicholas Bellinger { 1836c66ac9dbSNicholas Bellinger struct se_device *dev; 1837c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev = (struct se_subsystem_dev *)p; 1838c66ac9dbSNicholas Bellinger struct config_item *lu_ci; 1839c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp; 1840c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem; 1841c66ac9dbSNicholas Bellinger ssize_t len = 0; 1842c66ac9dbSNicholas Bellinger 1843c66ac9dbSNicholas Bellinger dev = su_dev->se_dev_ptr; 1844c66ac9dbSNicholas Bellinger if (!(dev)) 1845c66ac9dbSNicholas Bellinger return -ENODEV; 1846c66ac9dbSNicholas Bellinger 1847e3d6f909SAndy Grover if (su_dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) 1848c66ac9dbSNicholas Bellinger return len; 1849c66ac9dbSNicholas Bellinger 1850c66ac9dbSNicholas Bellinger lu_gp_mem = dev->dev_alua_lu_gp_mem; 1851c66ac9dbSNicholas Bellinger if (!(lu_gp_mem)) { 1852c66ac9dbSNicholas Bellinger printk(KERN_ERR "NULL struct se_device->dev_alua_lu_gp_mem" 1853c66ac9dbSNicholas Bellinger " pointer\n"); 1854c66ac9dbSNicholas Bellinger return -EINVAL; 1855c66ac9dbSNicholas Bellinger } 1856c66ac9dbSNicholas Bellinger 1857c66ac9dbSNicholas Bellinger spin_lock(&lu_gp_mem->lu_gp_mem_lock); 1858c66ac9dbSNicholas Bellinger lu_gp = lu_gp_mem->lu_gp; 1859c66ac9dbSNicholas Bellinger if ((lu_gp)) { 1860c66ac9dbSNicholas Bellinger lu_ci = &lu_gp->lu_gp_group.cg_item; 1861c66ac9dbSNicholas Bellinger len += sprintf(page, "LU Group Alias: %s\nLU Group ID: %hu\n", 1862c66ac9dbSNicholas Bellinger config_item_name(lu_ci), lu_gp->lu_gp_id); 1863c66ac9dbSNicholas Bellinger } 1864c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp_mem->lu_gp_mem_lock); 1865c66ac9dbSNicholas Bellinger 1866c66ac9dbSNicholas Bellinger return len; 1867c66ac9dbSNicholas Bellinger } 1868c66ac9dbSNicholas Bellinger 1869c66ac9dbSNicholas Bellinger static ssize_t target_core_store_alua_lu_gp( 1870c66ac9dbSNicholas Bellinger void *p, 1871c66ac9dbSNicholas Bellinger const char *page, 1872c66ac9dbSNicholas Bellinger size_t count) 1873c66ac9dbSNicholas Bellinger { 1874c66ac9dbSNicholas Bellinger struct se_device *dev; 1875c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev = (struct se_subsystem_dev *)p; 1876c66ac9dbSNicholas Bellinger struct se_hba *hba = su_dev->se_dev_hba; 1877c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp = NULL, *lu_gp_new = NULL; 1878c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem; 1879c66ac9dbSNicholas Bellinger unsigned char buf[LU_GROUP_NAME_BUF]; 1880c66ac9dbSNicholas Bellinger int move = 0; 1881c66ac9dbSNicholas Bellinger 1882c66ac9dbSNicholas Bellinger dev = su_dev->se_dev_ptr; 1883c66ac9dbSNicholas Bellinger if (!(dev)) 1884c66ac9dbSNicholas Bellinger return -ENODEV; 1885c66ac9dbSNicholas Bellinger 1886e3d6f909SAndy Grover if (su_dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) { 1887c66ac9dbSNicholas Bellinger printk(KERN_WARNING "SPC3_ALUA_EMULATED not enabled for %s/%s\n", 1888c66ac9dbSNicholas Bellinger config_item_name(&hba->hba_group.cg_item), 1889c66ac9dbSNicholas Bellinger config_item_name(&su_dev->se_dev_group.cg_item)); 1890c66ac9dbSNicholas Bellinger return -EINVAL; 1891c66ac9dbSNicholas Bellinger } 1892c66ac9dbSNicholas Bellinger if (count > LU_GROUP_NAME_BUF) { 1893c66ac9dbSNicholas Bellinger printk(KERN_ERR "ALUA LU Group Alias too large!\n"); 1894c66ac9dbSNicholas Bellinger return -EINVAL; 1895c66ac9dbSNicholas Bellinger } 1896c66ac9dbSNicholas Bellinger memset(buf, 0, LU_GROUP_NAME_BUF); 1897c66ac9dbSNicholas Bellinger memcpy(buf, page, count); 1898c66ac9dbSNicholas Bellinger /* 1899c66ac9dbSNicholas Bellinger * Any ALUA logical unit alias besides "NULL" means we will be 1900c66ac9dbSNicholas Bellinger * making a new group association. 1901c66ac9dbSNicholas Bellinger */ 1902c66ac9dbSNicholas Bellinger if (strcmp(strstrip(buf), "NULL")) { 1903c66ac9dbSNicholas Bellinger /* 1904c66ac9dbSNicholas Bellinger * core_alua_get_lu_gp_by_name() will increment reference to 1905c66ac9dbSNicholas Bellinger * struct t10_alua_lu_gp. This reference is released with 1906c66ac9dbSNicholas Bellinger * core_alua_get_lu_gp_by_name below(). 1907c66ac9dbSNicholas Bellinger */ 1908c66ac9dbSNicholas Bellinger lu_gp_new = core_alua_get_lu_gp_by_name(strstrip(buf)); 1909c66ac9dbSNicholas Bellinger if (!(lu_gp_new)) 1910c66ac9dbSNicholas Bellinger return -ENODEV; 1911c66ac9dbSNicholas Bellinger } 1912c66ac9dbSNicholas Bellinger lu_gp_mem = dev->dev_alua_lu_gp_mem; 1913c66ac9dbSNicholas Bellinger if (!(lu_gp_mem)) { 1914c66ac9dbSNicholas Bellinger if (lu_gp_new) 1915c66ac9dbSNicholas Bellinger core_alua_put_lu_gp_from_name(lu_gp_new); 1916c66ac9dbSNicholas Bellinger printk(KERN_ERR "NULL struct se_device->dev_alua_lu_gp_mem" 1917c66ac9dbSNicholas Bellinger " pointer\n"); 1918c66ac9dbSNicholas Bellinger return -EINVAL; 1919c66ac9dbSNicholas Bellinger } 1920c66ac9dbSNicholas Bellinger 1921c66ac9dbSNicholas Bellinger spin_lock(&lu_gp_mem->lu_gp_mem_lock); 1922c66ac9dbSNicholas Bellinger lu_gp = lu_gp_mem->lu_gp; 1923c66ac9dbSNicholas Bellinger if ((lu_gp)) { 1924c66ac9dbSNicholas Bellinger /* 1925c66ac9dbSNicholas Bellinger * Clearing an existing lu_gp association, and replacing 1926c66ac9dbSNicholas Bellinger * with NULL 1927c66ac9dbSNicholas Bellinger */ 1928c66ac9dbSNicholas Bellinger if (!(lu_gp_new)) { 1929c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: Releasing %s/%s" 1930c66ac9dbSNicholas Bellinger " from ALUA LU Group: core/alua/lu_gps/%s, ID:" 1931c66ac9dbSNicholas Bellinger " %hu\n", 1932c66ac9dbSNicholas Bellinger config_item_name(&hba->hba_group.cg_item), 1933c66ac9dbSNicholas Bellinger config_item_name(&su_dev->se_dev_group.cg_item), 1934c66ac9dbSNicholas Bellinger config_item_name(&lu_gp->lu_gp_group.cg_item), 1935c66ac9dbSNicholas Bellinger lu_gp->lu_gp_id); 1936c66ac9dbSNicholas Bellinger 1937c66ac9dbSNicholas Bellinger __core_alua_drop_lu_gp_mem(lu_gp_mem, lu_gp); 1938c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp_mem->lu_gp_mem_lock); 1939c66ac9dbSNicholas Bellinger 1940c66ac9dbSNicholas Bellinger return count; 1941c66ac9dbSNicholas Bellinger } 1942c66ac9dbSNicholas Bellinger /* 1943c66ac9dbSNicholas Bellinger * Removing existing association of lu_gp_mem with lu_gp 1944c66ac9dbSNicholas Bellinger */ 1945c66ac9dbSNicholas Bellinger __core_alua_drop_lu_gp_mem(lu_gp_mem, lu_gp); 1946c66ac9dbSNicholas Bellinger move = 1; 1947c66ac9dbSNicholas Bellinger } 1948c66ac9dbSNicholas Bellinger /* 1949c66ac9dbSNicholas Bellinger * Associate lu_gp_mem with lu_gp_new. 1950c66ac9dbSNicholas Bellinger */ 1951c66ac9dbSNicholas Bellinger __core_alua_attach_lu_gp_mem(lu_gp_mem, lu_gp_new); 1952c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp_mem->lu_gp_mem_lock); 1953c66ac9dbSNicholas Bellinger 1954c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: %s %s/%s to ALUA LU Group:" 1955c66ac9dbSNicholas Bellinger " core/alua/lu_gps/%s, ID: %hu\n", 1956c66ac9dbSNicholas Bellinger (move) ? "Moving" : "Adding", 1957c66ac9dbSNicholas Bellinger config_item_name(&hba->hba_group.cg_item), 1958c66ac9dbSNicholas Bellinger config_item_name(&su_dev->se_dev_group.cg_item), 1959c66ac9dbSNicholas Bellinger config_item_name(&lu_gp_new->lu_gp_group.cg_item), 1960c66ac9dbSNicholas Bellinger lu_gp_new->lu_gp_id); 1961c66ac9dbSNicholas Bellinger 1962c66ac9dbSNicholas Bellinger core_alua_put_lu_gp_from_name(lu_gp_new); 1963c66ac9dbSNicholas Bellinger return count; 1964c66ac9dbSNicholas Bellinger } 1965c66ac9dbSNicholas Bellinger 1966c66ac9dbSNicholas Bellinger static struct target_core_configfs_attribute target_core_attr_dev_alua_lu_gp = { 1967c66ac9dbSNicholas Bellinger .attr = { .ca_owner = THIS_MODULE, 1968c66ac9dbSNicholas Bellinger .ca_name = "alua_lu_gp", 1969c66ac9dbSNicholas Bellinger .ca_mode = S_IRUGO | S_IWUSR }, 1970c66ac9dbSNicholas Bellinger .show = target_core_show_alua_lu_gp, 1971c66ac9dbSNicholas Bellinger .store = target_core_store_alua_lu_gp, 1972c66ac9dbSNicholas Bellinger }; 1973c66ac9dbSNicholas Bellinger 1974c66ac9dbSNicholas Bellinger static struct configfs_attribute *lio_core_dev_attrs[] = { 1975c66ac9dbSNicholas Bellinger &target_core_attr_dev_info.attr, 1976c66ac9dbSNicholas Bellinger &target_core_attr_dev_control.attr, 1977c66ac9dbSNicholas Bellinger &target_core_attr_dev_alias.attr, 1978c66ac9dbSNicholas Bellinger &target_core_attr_dev_udev_path.attr, 1979c66ac9dbSNicholas Bellinger &target_core_attr_dev_enable.attr, 1980c66ac9dbSNicholas Bellinger &target_core_attr_dev_alua_lu_gp.attr, 1981c66ac9dbSNicholas Bellinger NULL, 1982c66ac9dbSNicholas Bellinger }; 1983c66ac9dbSNicholas Bellinger 1984c66ac9dbSNicholas Bellinger static void target_core_dev_release(struct config_item *item) 1985c66ac9dbSNicholas Bellinger { 1986c66ac9dbSNicholas Bellinger struct se_subsystem_dev *se_dev = container_of(to_config_group(item), 1987c66ac9dbSNicholas Bellinger struct se_subsystem_dev, se_dev_group); 19881f6fe7cbSNicholas Bellinger struct se_hba *hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item); 19891f6fe7cbSNicholas Bellinger struct se_subsystem_api *t = hba->transport; 19901f6fe7cbSNicholas Bellinger struct config_group *dev_cg = &se_dev->se_dev_group; 1991c66ac9dbSNicholas Bellinger 1992c66ac9dbSNicholas Bellinger kfree(dev_cg->default_groups); 19931f6fe7cbSNicholas Bellinger /* 19941f6fe7cbSNicholas Bellinger * This pointer will set when the storage is enabled with: 19951f6fe7cbSNicholas Bellinger *`echo 1 > $CONFIGFS/core/$HBA/$DEV/dev_enable` 19961f6fe7cbSNicholas Bellinger */ 19971f6fe7cbSNicholas Bellinger if (se_dev->se_dev_ptr) { 19981f6fe7cbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: Calling se_free_" 19991f6fe7cbSNicholas Bellinger "virtual_device() for se_dev_ptr: %p\n", 20001f6fe7cbSNicholas Bellinger se_dev->se_dev_ptr); 20011f6fe7cbSNicholas Bellinger 20021f6fe7cbSNicholas Bellinger se_free_virtual_device(se_dev->se_dev_ptr, hba); 20031f6fe7cbSNicholas Bellinger } else { 20041f6fe7cbSNicholas Bellinger /* 20051f6fe7cbSNicholas Bellinger * Release struct se_subsystem_dev->se_dev_su_ptr.. 20061f6fe7cbSNicholas Bellinger */ 20071f6fe7cbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: Calling t->free_" 20081f6fe7cbSNicholas Bellinger "device() for se_dev_su_ptr: %p\n", 20091f6fe7cbSNicholas Bellinger se_dev->se_dev_su_ptr); 20101f6fe7cbSNicholas Bellinger 20111f6fe7cbSNicholas Bellinger t->free_device(se_dev->se_dev_su_ptr); 20121f6fe7cbSNicholas Bellinger } 20131f6fe7cbSNicholas Bellinger 20141f6fe7cbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: Deallocating se_subsystem" 20151f6fe7cbSNicholas Bellinger "_dev_t: %p\n", se_dev); 20161f6fe7cbSNicholas Bellinger kfree(se_dev); 2017c66ac9dbSNicholas Bellinger } 2018c66ac9dbSNicholas Bellinger 2019c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_show(struct config_item *item, 2020c66ac9dbSNicholas Bellinger struct configfs_attribute *attr, 2021c66ac9dbSNicholas Bellinger char *page) 2022c66ac9dbSNicholas Bellinger { 2023c66ac9dbSNicholas Bellinger struct se_subsystem_dev *se_dev = container_of( 2024c66ac9dbSNicholas Bellinger to_config_group(item), struct se_subsystem_dev, 2025c66ac9dbSNicholas Bellinger se_dev_group); 2026c66ac9dbSNicholas Bellinger struct target_core_configfs_attribute *tc_attr = container_of( 2027c66ac9dbSNicholas Bellinger attr, struct target_core_configfs_attribute, attr); 2028c66ac9dbSNicholas Bellinger 2029c66ac9dbSNicholas Bellinger if (!(tc_attr->show)) 2030c66ac9dbSNicholas Bellinger return -EINVAL; 2031c66ac9dbSNicholas Bellinger 20325951146dSAndy Grover return tc_attr->show(se_dev, page); 2033c66ac9dbSNicholas Bellinger } 2034c66ac9dbSNicholas Bellinger 2035c66ac9dbSNicholas Bellinger static ssize_t target_core_dev_store(struct config_item *item, 2036c66ac9dbSNicholas Bellinger struct configfs_attribute *attr, 2037c66ac9dbSNicholas Bellinger const char *page, size_t count) 2038c66ac9dbSNicholas Bellinger { 2039c66ac9dbSNicholas Bellinger struct se_subsystem_dev *se_dev = container_of( 2040c66ac9dbSNicholas Bellinger to_config_group(item), struct se_subsystem_dev, 2041c66ac9dbSNicholas Bellinger se_dev_group); 2042c66ac9dbSNicholas Bellinger struct target_core_configfs_attribute *tc_attr = container_of( 2043c66ac9dbSNicholas Bellinger attr, struct target_core_configfs_attribute, attr); 2044c66ac9dbSNicholas Bellinger 2045c66ac9dbSNicholas Bellinger if (!(tc_attr->store)) 2046c66ac9dbSNicholas Bellinger return -EINVAL; 2047c66ac9dbSNicholas Bellinger 20485951146dSAndy Grover return tc_attr->store(se_dev, page, count); 2049c66ac9dbSNicholas Bellinger } 2050c66ac9dbSNicholas Bellinger 2051c66ac9dbSNicholas Bellinger static struct configfs_item_operations target_core_dev_item_ops = { 2052c66ac9dbSNicholas Bellinger .release = target_core_dev_release, 2053c66ac9dbSNicholas Bellinger .show_attribute = target_core_dev_show, 2054c66ac9dbSNicholas Bellinger .store_attribute = target_core_dev_store, 2055c66ac9dbSNicholas Bellinger }; 2056c66ac9dbSNicholas Bellinger 2057c66ac9dbSNicholas Bellinger static struct config_item_type target_core_dev_cit = { 2058c66ac9dbSNicholas Bellinger .ct_item_ops = &target_core_dev_item_ops, 2059c66ac9dbSNicholas Bellinger .ct_attrs = lio_core_dev_attrs, 2060c66ac9dbSNicholas Bellinger .ct_owner = THIS_MODULE, 2061c66ac9dbSNicholas Bellinger }; 2062c66ac9dbSNicholas Bellinger 2063c66ac9dbSNicholas Bellinger /* End functions for struct config_item_type target_core_dev_cit */ 2064c66ac9dbSNicholas Bellinger 2065c66ac9dbSNicholas Bellinger /* Start functions for struct config_item_type target_core_alua_lu_gp_cit */ 2066c66ac9dbSNicholas Bellinger 2067c66ac9dbSNicholas Bellinger CONFIGFS_EATTR_STRUCT(target_core_alua_lu_gp, t10_alua_lu_gp); 2068c66ac9dbSNicholas Bellinger #define SE_DEV_ALUA_LU_ATTR(_name, _mode) \ 2069c66ac9dbSNicholas Bellinger static struct target_core_alua_lu_gp_attribute \ 2070c66ac9dbSNicholas Bellinger target_core_alua_lu_gp_##_name = \ 2071c66ac9dbSNicholas Bellinger __CONFIGFS_EATTR(_name, _mode, \ 2072c66ac9dbSNicholas Bellinger target_core_alua_lu_gp_show_attr_##_name, \ 2073c66ac9dbSNicholas Bellinger target_core_alua_lu_gp_store_attr_##_name); 2074c66ac9dbSNicholas Bellinger 2075c66ac9dbSNicholas Bellinger #define SE_DEV_ALUA_LU_ATTR_RO(_name) \ 2076c66ac9dbSNicholas Bellinger static struct target_core_alua_lu_gp_attribute \ 2077c66ac9dbSNicholas Bellinger target_core_alua_lu_gp_##_name = \ 2078c66ac9dbSNicholas Bellinger __CONFIGFS_EATTR_RO(_name, \ 2079c66ac9dbSNicholas Bellinger target_core_alua_lu_gp_show_attr_##_name); 2080c66ac9dbSNicholas Bellinger 2081c66ac9dbSNicholas Bellinger /* 2082c66ac9dbSNicholas Bellinger * lu_gp_id 2083c66ac9dbSNicholas Bellinger */ 2084c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_lu_gp_show_attr_lu_gp_id( 2085c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp, 2086c66ac9dbSNicholas Bellinger char *page) 2087c66ac9dbSNicholas Bellinger { 2088c66ac9dbSNicholas Bellinger if (!(lu_gp->lu_gp_valid_id)) 2089c66ac9dbSNicholas Bellinger return 0; 2090c66ac9dbSNicholas Bellinger 2091c66ac9dbSNicholas Bellinger return sprintf(page, "%hu\n", lu_gp->lu_gp_id); 2092c66ac9dbSNicholas Bellinger } 2093c66ac9dbSNicholas Bellinger 2094c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_lu_gp_store_attr_lu_gp_id( 2095c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp, 2096c66ac9dbSNicholas Bellinger const char *page, 2097c66ac9dbSNicholas Bellinger size_t count) 2098c66ac9dbSNicholas Bellinger { 2099c66ac9dbSNicholas Bellinger struct config_group *alua_lu_gp_cg = &lu_gp->lu_gp_group; 2100c66ac9dbSNicholas Bellinger unsigned long lu_gp_id; 2101c66ac9dbSNicholas Bellinger int ret; 2102c66ac9dbSNicholas Bellinger 2103c66ac9dbSNicholas Bellinger ret = strict_strtoul(page, 0, &lu_gp_id); 2104c66ac9dbSNicholas Bellinger if (ret < 0) { 2105c66ac9dbSNicholas Bellinger printk(KERN_ERR "strict_strtoul() returned %d for" 2106c66ac9dbSNicholas Bellinger " lu_gp_id\n", ret); 2107c66ac9dbSNicholas Bellinger return -EINVAL; 2108c66ac9dbSNicholas Bellinger } 2109c66ac9dbSNicholas Bellinger if (lu_gp_id > 0x0000ffff) { 2110c66ac9dbSNicholas Bellinger printk(KERN_ERR "ALUA lu_gp_id: %lu exceeds maximum:" 2111c66ac9dbSNicholas Bellinger " 0x0000ffff\n", lu_gp_id); 2112c66ac9dbSNicholas Bellinger return -EINVAL; 2113c66ac9dbSNicholas Bellinger } 2114c66ac9dbSNicholas Bellinger 2115c66ac9dbSNicholas Bellinger ret = core_alua_set_lu_gp_id(lu_gp, (u16)lu_gp_id); 2116c66ac9dbSNicholas Bellinger if (ret < 0) 2117c66ac9dbSNicholas Bellinger return -EINVAL; 2118c66ac9dbSNicholas Bellinger 2119c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: Set ALUA Logical Unit" 2120c66ac9dbSNicholas Bellinger " Group: core/alua/lu_gps/%s to ID: %hu\n", 2121c66ac9dbSNicholas Bellinger config_item_name(&alua_lu_gp_cg->cg_item), 2122c66ac9dbSNicholas Bellinger lu_gp->lu_gp_id); 2123c66ac9dbSNicholas Bellinger 2124c66ac9dbSNicholas Bellinger return count; 2125c66ac9dbSNicholas Bellinger } 2126c66ac9dbSNicholas Bellinger 2127c66ac9dbSNicholas Bellinger SE_DEV_ALUA_LU_ATTR(lu_gp_id, S_IRUGO | S_IWUSR); 2128c66ac9dbSNicholas Bellinger 2129c66ac9dbSNicholas Bellinger /* 2130c66ac9dbSNicholas Bellinger * members 2131c66ac9dbSNicholas Bellinger */ 2132c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_lu_gp_show_attr_members( 2133c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp, 2134c66ac9dbSNicholas Bellinger char *page) 2135c66ac9dbSNicholas Bellinger { 2136c66ac9dbSNicholas Bellinger struct se_device *dev; 2137c66ac9dbSNicholas Bellinger struct se_hba *hba; 2138c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev; 2139c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem; 2140c66ac9dbSNicholas Bellinger ssize_t len = 0, cur_len; 2141c66ac9dbSNicholas Bellinger unsigned char buf[LU_GROUP_NAME_BUF]; 2142c66ac9dbSNicholas Bellinger 2143c66ac9dbSNicholas Bellinger memset(buf, 0, LU_GROUP_NAME_BUF); 2144c66ac9dbSNicholas Bellinger 2145c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 2146c66ac9dbSNicholas Bellinger list_for_each_entry(lu_gp_mem, &lu_gp->lu_gp_mem_list, lu_gp_mem_list) { 2147c66ac9dbSNicholas Bellinger dev = lu_gp_mem->lu_gp_mem_dev; 2148c66ac9dbSNicholas Bellinger su_dev = dev->se_sub_dev; 2149c66ac9dbSNicholas Bellinger hba = su_dev->se_dev_hba; 2150c66ac9dbSNicholas Bellinger 2151c66ac9dbSNicholas Bellinger cur_len = snprintf(buf, LU_GROUP_NAME_BUF, "%s/%s\n", 2152c66ac9dbSNicholas Bellinger config_item_name(&hba->hba_group.cg_item), 2153c66ac9dbSNicholas Bellinger config_item_name(&su_dev->se_dev_group.cg_item)); 2154c66ac9dbSNicholas Bellinger cur_len++; /* Extra byte for NULL terminator */ 2155c66ac9dbSNicholas Bellinger 2156c66ac9dbSNicholas Bellinger if ((cur_len + len) > PAGE_SIZE) { 2157c66ac9dbSNicholas Bellinger printk(KERN_WARNING "Ran out of lu_gp_show_attr" 2158c66ac9dbSNicholas Bellinger "_members buffer\n"); 2159c66ac9dbSNicholas Bellinger break; 2160c66ac9dbSNicholas Bellinger } 2161c66ac9dbSNicholas Bellinger memcpy(page+len, buf, cur_len); 2162c66ac9dbSNicholas Bellinger len += cur_len; 2163c66ac9dbSNicholas Bellinger } 2164c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 2165c66ac9dbSNicholas Bellinger 2166c66ac9dbSNicholas Bellinger return len; 2167c66ac9dbSNicholas Bellinger } 2168c66ac9dbSNicholas Bellinger 2169c66ac9dbSNicholas Bellinger SE_DEV_ALUA_LU_ATTR_RO(members); 2170c66ac9dbSNicholas Bellinger 2171c66ac9dbSNicholas Bellinger CONFIGFS_EATTR_OPS(target_core_alua_lu_gp, t10_alua_lu_gp, lu_gp_group); 2172c66ac9dbSNicholas Bellinger 2173c66ac9dbSNicholas Bellinger static struct configfs_attribute *target_core_alua_lu_gp_attrs[] = { 2174c66ac9dbSNicholas Bellinger &target_core_alua_lu_gp_lu_gp_id.attr, 2175c66ac9dbSNicholas Bellinger &target_core_alua_lu_gp_members.attr, 2176c66ac9dbSNicholas Bellinger NULL, 2177c66ac9dbSNicholas Bellinger }; 2178c66ac9dbSNicholas Bellinger 21791f6fe7cbSNicholas Bellinger static void target_core_alua_lu_gp_release(struct config_item *item) 21801f6fe7cbSNicholas Bellinger { 21811f6fe7cbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp = container_of(to_config_group(item), 21821f6fe7cbSNicholas Bellinger struct t10_alua_lu_gp, lu_gp_group); 21831f6fe7cbSNicholas Bellinger 21841f6fe7cbSNicholas Bellinger core_alua_free_lu_gp(lu_gp); 21851f6fe7cbSNicholas Bellinger } 21861f6fe7cbSNicholas Bellinger 2187c66ac9dbSNicholas Bellinger static struct configfs_item_operations target_core_alua_lu_gp_ops = { 21881f6fe7cbSNicholas Bellinger .release = target_core_alua_lu_gp_release, 2189c66ac9dbSNicholas Bellinger .show_attribute = target_core_alua_lu_gp_attr_show, 2190c66ac9dbSNicholas Bellinger .store_attribute = target_core_alua_lu_gp_attr_store, 2191c66ac9dbSNicholas Bellinger }; 2192c66ac9dbSNicholas Bellinger 2193c66ac9dbSNicholas Bellinger static struct config_item_type target_core_alua_lu_gp_cit = { 2194c66ac9dbSNicholas Bellinger .ct_item_ops = &target_core_alua_lu_gp_ops, 2195c66ac9dbSNicholas Bellinger .ct_attrs = target_core_alua_lu_gp_attrs, 2196c66ac9dbSNicholas Bellinger .ct_owner = THIS_MODULE, 2197c66ac9dbSNicholas Bellinger }; 2198c66ac9dbSNicholas Bellinger 2199c66ac9dbSNicholas Bellinger /* End functions for struct config_item_type target_core_alua_lu_gp_cit */ 2200c66ac9dbSNicholas Bellinger 2201c66ac9dbSNicholas Bellinger /* Start functions for struct config_item_type target_core_alua_lu_gps_cit */ 2202c66ac9dbSNicholas Bellinger 2203c66ac9dbSNicholas Bellinger static struct config_group *target_core_alua_create_lu_gp( 2204c66ac9dbSNicholas Bellinger struct config_group *group, 2205c66ac9dbSNicholas Bellinger const char *name) 2206c66ac9dbSNicholas Bellinger { 2207c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp; 2208c66ac9dbSNicholas Bellinger struct config_group *alua_lu_gp_cg = NULL; 2209c66ac9dbSNicholas Bellinger struct config_item *alua_lu_gp_ci = NULL; 2210c66ac9dbSNicholas Bellinger 2211c66ac9dbSNicholas Bellinger lu_gp = core_alua_allocate_lu_gp(name, 0); 2212c66ac9dbSNicholas Bellinger if (IS_ERR(lu_gp)) 2213c66ac9dbSNicholas Bellinger return NULL; 2214c66ac9dbSNicholas Bellinger 2215c66ac9dbSNicholas Bellinger alua_lu_gp_cg = &lu_gp->lu_gp_group; 2216c66ac9dbSNicholas Bellinger alua_lu_gp_ci = &alua_lu_gp_cg->cg_item; 2217c66ac9dbSNicholas Bellinger 2218c66ac9dbSNicholas Bellinger config_group_init_type_name(alua_lu_gp_cg, name, 2219c66ac9dbSNicholas Bellinger &target_core_alua_lu_gp_cit); 2220c66ac9dbSNicholas Bellinger 2221c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: Allocated ALUA Logical Unit" 2222c66ac9dbSNicholas Bellinger " Group: core/alua/lu_gps/%s\n", 2223c66ac9dbSNicholas Bellinger config_item_name(alua_lu_gp_ci)); 2224c66ac9dbSNicholas Bellinger 2225c66ac9dbSNicholas Bellinger return alua_lu_gp_cg; 2226c66ac9dbSNicholas Bellinger 2227c66ac9dbSNicholas Bellinger } 2228c66ac9dbSNicholas Bellinger 2229c66ac9dbSNicholas Bellinger static void target_core_alua_drop_lu_gp( 2230c66ac9dbSNicholas Bellinger struct config_group *group, 2231c66ac9dbSNicholas Bellinger struct config_item *item) 2232c66ac9dbSNicholas Bellinger { 2233c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp = container_of(to_config_group(item), 2234c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp, lu_gp_group); 2235c66ac9dbSNicholas Bellinger 2236c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: Releasing ALUA Logical Unit" 2237c66ac9dbSNicholas Bellinger " Group: core/alua/lu_gps/%s, ID: %hu\n", 2238c66ac9dbSNicholas Bellinger config_item_name(item), lu_gp->lu_gp_id); 22391f6fe7cbSNicholas Bellinger /* 22401f6fe7cbSNicholas Bellinger * core_alua_free_lu_gp() is called from target_core_alua_lu_gp_ops->release() 22411f6fe7cbSNicholas Bellinger * -> target_core_alua_lu_gp_release() 22421f6fe7cbSNicholas Bellinger */ 2243c66ac9dbSNicholas Bellinger config_item_put(item); 2244c66ac9dbSNicholas Bellinger } 2245c66ac9dbSNicholas Bellinger 2246c66ac9dbSNicholas Bellinger static struct configfs_group_operations target_core_alua_lu_gps_group_ops = { 2247c66ac9dbSNicholas Bellinger .make_group = &target_core_alua_create_lu_gp, 2248c66ac9dbSNicholas Bellinger .drop_item = &target_core_alua_drop_lu_gp, 2249c66ac9dbSNicholas Bellinger }; 2250c66ac9dbSNicholas Bellinger 2251c66ac9dbSNicholas Bellinger static struct config_item_type target_core_alua_lu_gps_cit = { 2252c66ac9dbSNicholas Bellinger .ct_item_ops = NULL, 2253c66ac9dbSNicholas Bellinger .ct_group_ops = &target_core_alua_lu_gps_group_ops, 2254c66ac9dbSNicholas Bellinger .ct_owner = THIS_MODULE, 2255c66ac9dbSNicholas Bellinger }; 2256c66ac9dbSNicholas Bellinger 2257c66ac9dbSNicholas Bellinger /* End functions for struct config_item_type target_core_alua_lu_gps_cit */ 2258c66ac9dbSNicholas Bellinger 2259c66ac9dbSNicholas Bellinger /* Start functions for struct config_item_type target_core_alua_tg_pt_gp_cit */ 2260c66ac9dbSNicholas Bellinger 2261c66ac9dbSNicholas Bellinger CONFIGFS_EATTR_STRUCT(target_core_alua_tg_pt_gp, t10_alua_tg_pt_gp); 2262c66ac9dbSNicholas Bellinger #define SE_DEV_ALUA_TG_PT_ATTR(_name, _mode) \ 2263c66ac9dbSNicholas Bellinger static struct target_core_alua_tg_pt_gp_attribute \ 2264c66ac9dbSNicholas Bellinger target_core_alua_tg_pt_gp_##_name = \ 2265c66ac9dbSNicholas Bellinger __CONFIGFS_EATTR(_name, _mode, \ 2266c66ac9dbSNicholas Bellinger target_core_alua_tg_pt_gp_show_attr_##_name, \ 2267c66ac9dbSNicholas Bellinger target_core_alua_tg_pt_gp_store_attr_##_name); 2268c66ac9dbSNicholas Bellinger 2269c66ac9dbSNicholas Bellinger #define SE_DEV_ALUA_TG_PT_ATTR_RO(_name) \ 2270c66ac9dbSNicholas Bellinger static struct target_core_alua_tg_pt_gp_attribute \ 2271c66ac9dbSNicholas Bellinger target_core_alua_tg_pt_gp_##_name = \ 2272c66ac9dbSNicholas Bellinger __CONFIGFS_EATTR_RO(_name, \ 2273c66ac9dbSNicholas Bellinger target_core_alua_tg_pt_gp_show_attr_##_name); 2274c66ac9dbSNicholas Bellinger 2275c66ac9dbSNicholas Bellinger /* 2276c66ac9dbSNicholas Bellinger * alua_access_state 2277c66ac9dbSNicholas Bellinger */ 2278c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_access_state( 2279c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2280c66ac9dbSNicholas Bellinger char *page) 2281c66ac9dbSNicholas Bellinger { 2282c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", 2283c66ac9dbSNicholas Bellinger atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state)); 2284c66ac9dbSNicholas Bellinger } 2285c66ac9dbSNicholas Bellinger 2286c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_state( 2287c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2288c66ac9dbSNicholas Bellinger const char *page, 2289c66ac9dbSNicholas Bellinger size_t count) 2290c66ac9dbSNicholas Bellinger { 2291c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev; 2292c66ac9dbSNicholas Bellinger unsigned long tmp; 2293c66ac9dbSNicholas Bellinger int new_state, ret; 2294c66ac9dbSNicholas Bellinger 2295c66ac9dbSNicholas Bellinger if (!(tg_pt_gp->tg_pt_gp_valid_id)) { 2296c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to do implict ALUA on non valid" 2297c66ac9dbSNicholas Bellinger " tg_pt_gp ID: %hu\n", tg_pt_gp->tg_pt_gp_valid_id); 2298c66ac9dbSNicholas Bellinger return -EINVAL; 2299c66ac9dbSNicholas Bellinger } 2300c66ac9dbSNicholas Bellinger 2301c66ac9dbSNicholas Bellinger ret = strict_strtoul(page, 0, &tmp); 2302c66ac9dbSNicholas Bellinger if (ret < 0) { 2303c66ac9dbSNicholas Bellinger printk("Unable to extract new ALUA access state from" 2304c66ac9dbSNicholas Bellinger " %s\n", page); 2305c66ac9dbSNicholas Bellinger return -EINVAL; 2306c66ac9dbSNicholas Bellinger } 2307c66ac9dbSNicholas Bellinger new_state = (int)tmp; 2308c66ac9dbSNicholas Bellinger 2309c66ac9dbSNicholas Bellinger if (!(tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICT_ALUA)) { 2310c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to process implict configfs ALUA" 2311c66ac9dbSNicholas Bellinger " transition while TPGS_IMPLICT_ALUA is diabled\n"); 2312c66ac9dbSNicholas Bellinger return -EINVAL; 2313c66ac9dbSNicholas Bellinger } 2314c66ac9dbSNicholas Bellinger 2315c66ac9dbSNicholas Bellinger ret = core_alua_do_port_transition(tg_pt_gp, su_dev->se_dev_ptr, 2316c66ac9dbSNicholas Bellinger NULL, NULL, new_state, 0); 2317c66ac9dbSNicholas Bellinger return (!ret) ? count : -EINVAL; 2318c66ac9dbSNicholas Bellinger } 2319c66ac9dbSNicholas Bellinger 2320c66ac9dbSNicholas Bellinger SE_DEV_ALUA_TG_PT_ATTR(alua_access_state, S_IRUGO | S_IWUSR); 2321c66ac9dbSNicholas Bellinger 2322c66ac9dbSNicholas Bellinger /* 2323c66ac9dbSNicholas Bellinger * alua_access_status 2324c66ac9dbSNicholas Bellinger */ 2325c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_access_status( 2326c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2327c66ac9dbSNicholas Bellinger char *page) 2328c66ac9dbSNicholas Bellinger { 2329c66ac9dbSNicholas Bellinger return sprintf(page, "%s\n", 2330c66ac9dbSNicholas Bellinger core_alua_dump_status(tg_pt_gp->tg_pt_gp_alua_access_status)); 2331c66ac9dbSNicholas Bellinger } 2332c66ac9dbSNicholas Bellinger 2333c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_status( 2334c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2335c66ac9dbSNicholas Bellinger const char *page, 2336c66ac9dbSNicholas Bellinger size_t count) 2337c66ac9dbSNicholas Bellinger { 2338c66ac9dbSNicholas Bellinger unsigned long tmp; 2339c66ac9dbSNicholas Bellinger int new_status, ret; 2340c66ac9dbSNicholas Bellinger 2341c66ac9dbSNicholas Bellinger if (!(tg_pt_gp->tg_pt_gp_valid_id)) { 2342c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to do set ALUA access status on non" 2343c66ac9dbSNicholas Bellinger " valid tg_pt_gp ID: %hu\n", 2344c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_valid_id); 2345c66ac9dbSNicholas Bellinger return -EINVAL; 2346c66ac9dbSNicholas Bellinger } 2347c66ac9dbSNicholas Bellinger 2348c66ac9dbSNicholas Bellinger ret = strict_strtoul(page, 0, &tmp); 2349c66ac9dbSNicholas Bellinger if (ret < 0) { 2350c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to extract new ALUA access status" 2351c66ac9dbSNicholas Bellinger " from %s\n", page); 2352c66ac9dbSNicholas Bellinger return -EINVAL; 2353c66ac9dbSNicholas Bellinger } 2354c66ac9dbSNicholas Bellinger new_status = (int)tmp; 2355c66ac9dbSNicholas Bellinger 2356c66ac9dbSNicholas Bellinger if ((new_status != ALUA_STATUS_NONE) && 2357c66ac9dbSNicholas Bellinger (new_status != ALUA_STATUS_ALTERED_BY_EXPLICT_STPG) && 2358c66ac9dbSNicholas Bellinger (new_status != ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA)) { 2359c66ac9dbSNicholas Bellinger printk(KERN_ERR "Illegal ALUA access status: 0x%02x\n", 2360c66ac9dbSNicholas Bellinger new_status); 2361c66ac9dbSNicholas Bellinger return -EINVAL; 2362c66ac9dbSNicholas Bellinger } 2363c66ac9dbSNicholas Bellinger 2364c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_status = new_status; 2365c66ac9dbSNicholas Bellinger return count; 2366c66ac9dbSNicholas Bellinger } 2367c66ac9dbSNicholas Bellinger 2368c66ac9dbSNicholas Bellinger SE_DEV_ALUA_TG_PT_ATTR(alua_access_status, S_IRUGO | S_IWUSR); 2369c66ac9dbSNicholas Bellinger 2370c66ac9dbSNicholas Bellinger /* 2371c66ac9dbSNicholas Bellinger * alua_access_type 2372c66ac9dbSNicholas Bellinger */ 2373c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_access_type( 2374c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2375c66ac9dbSNicholas Bellinger char *page) 2376c66ac9dbSNicholas Bellinger { 2377c66ac9dbSNicholas Bellinger return core_alua_show_access_type(tg_pt_gp, page); 2378c66ac9dbSNicholas Bellinger } 2379c66ac9dbSNicholas Bellinger 2380c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_access_type( 2381c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2382c66ac9dbSNicholas Bellinger const char *page, 2383c66ac9dbSNicholas Bellinger size_t count) 2384c66ac9dbSNicholas Bellinger { 2385c66ac9dbSNicholas Bellinger return core_alua_store_access_type(tg_pt_gp, page, count); 2386c66ac9dbSNicholas Bellinger } 2387c66ac9dbSNicholas Bellinger 2388c66ac9dbSNicholas Bellinger SE_DEV_ALUA_TG_PT_ATTR(alua_access_type, S_IRUGO | S_IWUSR); 2389c66ac9dbSNicholas Bellinger 2390c66ac9dbSNicholas Bellinger /* 2391c66ac9dbSNicholas Bellinger * alua_write_metadata 2392c66ac9dbSNicholas Bellinger */ 2393c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_tg_pt_gp_show_attr_alua_write_metadata( 2394c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2395c66ac9dbSNicholas Bellinger char *page) 2396c66ac9dbSNicholas Bellinger { 2397c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_write_metadata); 2398c66ac9dbSNicholas Bellinger } 2399c66ac9dbSNicholas Bellinger 2400c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_tg_pt_gp_store_attr_alua_write_metadata( 2401c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2402c66ac9dbSNicholas Bellinger const char *page, 2403c66ac9dbSNicholas Bellinger size_t count) 2404c66ac9dbSNicholas Bellinger { 2405c66ac9dbSNicholas Bellinger unsigned long tmp; 2406c66ac9dbSNicholas Bellinger int ret; 2407c66ac9dbSNicholas Bellinger 2408c66ac9dbSNicholas Bellinger ret = strict_strtoul(page, 0, &tmp); 2409c66ac9dbSNicholas Bellinger if (ret < 0) { 2410c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to extract alua_write_metadata\n"); 2411c66ac9dbSNicholas Bellinger return -EINVAL; 2412c66ac9dbSNicholas Bellinger } 2413c66ac9dbSNicholas Bellinger 2414c66ac9dbSNicholas Bellinger if ((tmp != 0) && (tmp != 1)) { 2415c66ac9dbSNicholas Bellinger printk(KERN_ERR "Illegal value for alua_write_metadata:" 2416c66ac9dbSNicholas Bellinger " %lu\n", tmp); 2417c66ac9dbSNicholas Bellinger return -EINVAL; 2418c66ac9dbSNicholas Bellinger } 2419c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_write_metadata = (int)tmp; 2420c66ac9dbSNicholas Bellinger 2421c66ac9dbSNicholas Bellinger return count; 2422c66ac9dbSNicholas Bellinger } 2423c66ac9dbSNicholas Bellinger 2424c66ac9dbSNicholas Bellinger SE_DEV_ALUA_TG_PT_ATTR(alua_write_metadata, S_IRUGO | S_IWUSR); 2425c66ac9dbSNicholas Bellinger 2426c66ac9dbSNicholas Bellinger 2427c66ac9dbSNicholas Bellinger 2428c66ac9dbSNicholas Bellinger /* 2429c66ac9dbSNicholas Bellinger * nonop_delay_msecs 2430c66ac9dbSNicholas Bellinger */ 2431c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_tg_pt_gp_show_attr_nonop_delay_msecs( 2432c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2433c66ac9dbSNicholas Bellinger char *page) 2434c66ac9dbSNicholas Bellinger { 2435c66ac9dbSNicholas Bellinger return core_alua_show_nonop_delay_msecs(tg_pt_gp, page); 2436c66ac9dbSNicholas Bellinger 2437c66ac9dbSNicholas Bellinger } 2438c66ac9dbSNicholas Bellinger 2439c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_tg_pt_gp_store_attr_nonop_delay_msecs( 2440c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2441c66ac9dbSNicholas Bellinger const char *page, 2442c66ac9dbSNicholas Bellinger size_t count) 2443c66ac9dbSNicholas Bellinger { 2444c66ac9dbSNicholas Bellinger return core_alua_store_nonop_delay_msecs(tg_pt_gp, page, count); 2445c66ac9dbSNicholas Bellinger } 2446c66ac9dbSNicholas Bellinger 2447c66ac9dbSNicholas Bellinger SE_DEV_ALUA_TG_PT_ATTR(nonop_delay_msecs, S_IRUGO | S_IWUSR); 2448c66ac9dbSNicholas Bellinger 2449c66ac9dbSNicholas Bellinger /* 2450c66ac9dbSNicholas Bellinger * trans_delay_msecs 2451c66ac9dbSNicholas Bellinger */ 2452c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_tg_pt_gp_show_attr_trans_delay_msecs( 2453c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2454c66ac9dbSNicholas Bellinger char *page) 2455c66ac9dbSNicholas Bellinger { 2456c66ac9dbSNicholas Bellinger return core_alua_show_trans_delay_msecs(tg_pt_gp, page); 2457c66ac9dbSNicholas Bellinger } 2458c66ac9dbSNicholas Bellinger 2459c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_tg_pt_gp_store_attr_trans_delay_msecs( 2460c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2461c66ac9dbSNicholas Bellinger const char *page, 2462c66ac9dbSNicholas Bellinger size_t count) 2463c66ac9dbSNicholas Bellinger { 2464c66ac9dbSNicholas Bellinger return core_alua_store_trans_delay_msecs(tg_pt_gp, page, count); 2465c66ac9dbSNicholas Bellinger } 2466c66ac9dbSNicholas Bellinger 2467c66ac9dbSNicholas Bellinger SE_DEV_ALUA_TG_PT_ATTR(trans_delay_msecs, S_IRUGO | S_IWUSR); 2468c66ac9dbSNicholas Bellinger 2469c66ac9dbSNicholas Bellinger /* 2470c66ac9dbSNicholas Bellinger * preferred 2471c66ac9dbSNicholas Bellinger */ 2472c66ac9dbSNicholas Bellinger 2473c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_tg_pt_gp_show_attr_preferred( 2474c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2475c66ac9dbSNicholas Bellinger char *page) 2476c66ac9dbSNicholas Bellinger { 2477c66ac9dbSNicholas Bellinger return core_alua_show_preferred_bit(tg_pt_gp, page); 2478c66ac9dbSNicholas Bellinger } 2479c66ac9dbSNicholas Bellinger 2480c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_tg_pt_gp_store_attr_preferred( 2481c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2482c66ac9dbSNicholas Bellinger const char *page, 2483c66ac9dbSNicholas Bellinger size_t count) 2484c66ac9dbSNicholas Bellinger { 2485c66ac9dbSNicholas Bellinger return core_alua_store_preferred_bit(tg_pt_gp, page, count); 2486c66ac9dbSNicholas Bellinger } 2487c66ac9dbSNicholas Bellinger 2488c66ac9dbSNicholas Bellinger SE_DEV_ALUA_TG_PT_ATTR(preferred, S_IRUGO | S_IWUSR); 2489c66ac9dbSNicholas Bellinger 2490c66ac9dbSNicholas Bellinger /* 2491c66ac9dbSNicholas Bellinger * tg_pt_gp_id 2492c66ac9dbSNicholas Bellinger */ 2493c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_tg_pt_gp_show_attr_tg_pt_gp_id( 2494c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2495c66ac9dbSNicholas Bellinger char *page) 2496c66ac9dbSNicholas Bellinger { 2497c66ac9dbSNicholas Bellinger if (!(tg_pt_gp->tg_pt_gp_valid_id)) 2498c66ac9dbSNicholas Bellinger return 0; 2499c66ac9dbSNicholas Bellinger 2500c66ac9dbSNicholas Bellinger return sprintf(page, "%hu\n", tg_pt_gp->tg_pt_gp_id); 2501c66ac9dbSNicholas Bellinger } 2502c66ac9dbSNicholas Bellinger 2503c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_tg_pt_gp_store_attr_tg_pt_gp_id( 2504c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2505c66ac9dbSNicholas Bellinger const char *page, 2506c66ac9dbSNicholas Bellinger size_t count) 2507c66ac9dbSNicholas Bellinger { 2508c66ac9dbSNicholas Bellinger struct config_group *alua_tg_pt_gp_cg = &tg_pt_gp->tg_pt_gp_group; 2509c66ac9dbSNicholas Bellinger unsigned long tg_pt_gp_id; 2510c66ac9dbSNicholas Bellinger int ret; 2511c66ac9dbSNicholas Bellinger 2512c66ac9dbSNicholas Bellinger ret = strict_strtoul(page, 0, &tg_pt_gp_id); 2513c66ac9dbSNicholas Bellinger if (ret < 0) { 2514c66ac9dbSNicholas Bellinger printk(KERN_ERR "strict_strtoul() returned %d for" 2515c66ac9dbSNicholas Bellinger " tg_pt_gp_id\n", ret); 2516c66ac9dbSNicholas Bellinger return -EINVAL; 2517c66ac9dbSNicholas Bellinger } 2518c66ac9dbSNicholas Bellinger if (tg_pt_gp_id > 0x0000ffff) { 2519c66ac9dbSNicholas Bellinger printk(KERN_ERR "ALUA tg_pt_gp_id: %lu exceeds maximum:" 2520c66ac9dbSNicholas Bellinger " 0x0000ffff\n", tg_pt_gp_id); 2521c66ac9dbSNicholas Bellinger return -EINVAL; 2522c66ac9dbSNicholas Bellinger } 2523c66ac9dbSNicholas Bellinger 2524c66ac9dbSNicholas Bellinger ret = core_alua_set_tg_pt_gp_id(tg_pt_gp, (u16)tg_pt_gp_id); 2525c66ac9dbSNicholas Bellinger if (ret < 0) 2526c66ac9dbSNicholas Bellinger return -EINVAL; 2527c66ac9dbSNicholas Bellinger 2528c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: Set ALUA Target Port Group: " 2529c66ac9dbSNicholas Bellinger "core/alua/tg_pt_gps/%s to ID: %hu\n", 2530c66ac9dbSNicholas Bellinger config_item_name(&alua_tg_pt_gp_cg->cg_item), 2531c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_id); 2532c66ac9dbSNicholas Bellinger 2533c66ac9dbSNicholas Bellinger return count; 2534c66ac9dbSNicholas Bellinger } 2535c66ac9dbSNicholas Bellinger 2536c66ac9dbSNicholas Bellinger SE_DEV_ALUA_TG_PT_ATTR(tg_pt_gp_id, S_IRUGO | S_IWUSR); 2537c66ac9dbSNicholas Bellinger 2538c66ac9dbSNicholas Bellinger /* 2539c66ac9dbSNicholas Bellinger * members 2540c66ac9dbSNicholas Bellinger */ 2541c66ac9dbSNicholas Bellinger static ssize_t target_core_alua_tg_pt_gp_show_attr_members( 2542c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2543c66ac9dbSNicholas Bellinger char *page) 2544c66ac9dbSNicholas Bellinger { 2545c66ac9dbSNicholas Bellinger struct se_port *port; 2546c66ac9dbSNicholas Bellinger struct se_portal_group *tpg; 2547c66ac9dbSNicholas Bellinger struct se_lun *lun; 2548c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 2549c66ac9dbSNicholas Bellinger ssize_t len = 0, cur_len; 2550c66ac9dbSNicholas Bellinger unsigned char buf[TG_PT_GROUP_NAME_BUF]; 2551c66ac9dbSNicholas Bellinger 2552c66ac9dbSNicholas Bellinger memset(buf, 0, TG_PT_GROUP_NAME_BUF); 2553c66ac9dbSNicholas Bellinger 2554c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 2555c66ac9dbSNicholas Bellinger list_for_each_entry(tg_pt_gp_mem, &tg_pt_gp->tg_pt_gp_mem_list, 2556c66ac9dbSNicholas Bellinger tg_pt_gp_mem_list) { 2557c66ac9dbSNicholas Bellinger port = tg_pt_gp_mem->tg_pt; 2558c66ac9dbSNicholas Bellinger tpg = port->sep_tpg; 2559c66ac9dbSNicholas Bellinger lun = port->sep_lun; 2560c66ac9dbSNicholas Bellinger 2561c66ac9dbSNicholas Bellinger cur_len = snprintf(buf, TG_PT_GROUP_NAME_BUF, "%s/%s/tpgt_%hu" 2562e3d6f909SAndy Grover "/%s\n", tpg->se_tpg_tfo->get_fabric_name(), 2563e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_wwn(tpg), 2564e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), 2565c66ac9dbSNicholas Bellinger config_item_name(&lun->lun_group.cg_item)); 2566c66ac9dbSNicholas Bellinger cur_len++; /* Extra byte for NULL terminator */ 2567c66ac9dbSNicholas Bellinger 2568c66ac9dbSNicholas Bellinger if ((cur_len + len) > PAGE_SIZE) { 2569c66ac9dbSNicholas Bellinger printk(KERN_WARNING "Ran out of lu_gp_show_attr" 2570c66ac9dbSNicholas Bellinger "_members buffer\n"); 2571c66ac9dbSNicholas Bellinger break; 2572c66ac9dbSNicholas Bellinger } 2573c66ac9dbSNicholas Bellinger memcpy(page+len, buf, cur_len); 2574c66ac9dbSNicholas Bellinger len += cur_len; 2575c66ac9dbSNicholas Bellinger } 2576c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 2577c66ac9dbSNicholas Bellinger 2578c66ac9dbSNicholas Bellinger return len; 2579c66ac9dbSNicholas Bellinger } 2580c66ac9dbSNicholas Bellinger 2581c66ac9dbSNicholas Bellinger SE_DEV_ALUA_TG_PT_ATTR_RO(members); 2582c66ac9dbSNicholas Bellinger 2583c66ac9dbSNicholas Bellinger CONFIGFS_EATTR_OPS(target_core_alua_tg_pt_gp, t10_alua_tg_pt_gp, 2584c66ac9dbSNicholas Bellinger tg_pt_gp_group); 2585c66ac9dbSNicholas Bellinger 2586c66ac9dbSNicholas Bellinger static struct configfs_attribute *target_core_alua_tg_pt_gp_attrs[] = { 2587c66ac9dbSNicholas Bellinger &target_core_alua_tg_pt_gp_alua_access_state.attr, 2588c66ac9dbSNicholas Bellinger &target_core_alua_tg_pt_gp_alua_access_status.attr, 2589c66ac9dbSNicholas Bellinger &target_core_alua_tg_pt_gp_alua_access_type.attr, 2590c66ac9dbSNicholas Bellinger &target_core_alua_tg_pt_gp_alua_write_metadata.attr, 2591c66ac9dbSNicholas Bellinger &target_core_alua_tg_pt_gp_nonop_delay_msecs.attr, 2592c66ac9dbSNicholas Bellinger &target_core_alua_tg_pt_gp_trans_delay_msecs.attr, 2593c66ac9dbSNicholas Bellinger &target_core_alua_tg_pt_gp_preferred.attr, 2594c66ac9dbSNicholas Bellinger &target_core_alua_tg_pt_gp_tg_pt_gp_id.attr, 2595c66ac9dbSNicholas Bellinger &target_core_alua_tg_pt_gp_members.attr, 2596c66ac9dbSNicholas Bellinger NULL, 2597c66ac9dbSNicholas Bellinger }; 2598c66ac9dbSNicholas Bellinger 25991f6fe7cbSNicholas Bellinger static void target_core_alua_tg_pt_gp_release(struct config_item *item) 26001f6fe7cbSNicholas Bellinger { 26011f6fe7cbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp = container_of(to_config_group(item), 26021f6fe7cbSNicholas Bellinger struct t10_alua_tg_pt_gp, tg_pt_gp_group); 26031f6fe7cbSNicholas Bellinger 26041f6fe7cbSNicholas Bellinger core_alua_free_tg_pt_gp(tg_pt_gp); 26051f6fe7cbSNicholas Bellinger } 26061f6fe7cbSNicholas Bellinger 2607c66ac9dbSNicholas Bellinger static struct configfs_item_operations target_core_alua_tg_pt_gp_ops = { 26081f6fe7cbSNicholas Bellinger .release = target_core_alua_tg_pt_gp_release, 2609c66ac9dbSNicholas Bellinger .show_attribute = target_core_alua_tg_pt_gp_attr_show, 2610c66ac9dbSNicholas Bellinger .store_attribute = target_core_alua_tg_pt_gp_attr_store, 2611c66ac9dbSNicholas Bellinger }; 2612c66ac9dbSNicholas Bellinger 2613c66ac9dbSNicholas Bellinger static struct config_item_type target_core_alua_tg_pt_gp_cit = { 2614c66ac9dbSNicholas Bellinger .ct_item_ops = &target_core_alua_tg_pt_gp_ops, 2615c66ac9dbSNicholas Bellinger .ct_attrs = target_core_alua_tg_pt_gp_attrs, 2616c66ac9dbSNicholas Bellinger .ct_owner = THIS_MODULE, 2617c66ac9dbSNicholas Bellinger }; 2618c66ac9dbSNicholas Bellinger 2619c66ac9dbSNicholas Bellinger /* End functions for struct config_item_type target_core_alua_tg_pt_gp_cit */ 2620c66ac9dbSNicholas Bellinger 2621c66ac9dbSNicholas Bellinger /* Start functions for struct config_item_type target_core_alua_tg_pt_gps_cit */ 2622c66ac9dbSNicholas Bellinger 2623c66ac9dbSNicholas Bellinger static struct config_group *target_core_alua_create_tg_pt_gp( 2624c66ac9dbSNicholas Bellinger struct config_group *group, 2625c66ac9dbSNicholas Bellinger const char *name) 2626c66ac9dbSNicholas Bellinger { 2627c66ac9dbSNicholas Bellinger struct t10_alua *alua = container_of(group, struct t10_alua, 2628c66ac9dbSNicholas Bellinger alua_tg_pt_gps_group); 2629c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 2630c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev = alua->t10_sub_dev; 2631c66ac9dbSNicholas Bellinger struct config_group *alua_tg_pt_gp_cg = NULL; 2632c66ac9dbSNicholas Bellinger struct config_item *alua_tg_pt_gp_ci = NULL; 2633c66ac9dbSNicholas Bellinger 2634c66ac9dbSNicholas Bellinger tg_pt_gp = core_alua_allocate_tg_pt_gp(su_dev, name, 0); 2635c66ac9dbSNicholas Bellinger if (!(tg_pt_gp)) 2636c66ac9dbSNicholas Bellinger return NULL; 2637c66ac9dbSNicholas Bellinger 2638c66ac9dbSNicholas Bellinger alua_tg_pt_gp_cg = &tg_pt_gp->tg_pt_gp_group; 2639c66ac9dbSNicholas Bellinger alua_tg_pt_gp_ci = &alua_tg_pt_gp_cg->cg_item; 2640c66ac9dbSNicholas Bellinger 2641c66ac9dbSNicholas Bellinger config_group_init_type_name(alua_tg_pt_gp_cg, name, 2642c66ac9dbSNicholas Bellinger &target_core_alua_tg_pt_gp_cit); 2643c66ac9dbSNicholas Bellinger 2644c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: Allocated ALUA Target Port" 2645c66ac9dbSNicholas Bellinger " Group: alua/tg_pt_gps/%s\n", 2646c66ac9dbSNicholas Bellinger config_item_name(alua_tg_pt_gp_ci)); 2647c66ac9dbSNicholas Bellinger 2648c66ac9dbSNicholas Bellinger return alua_tg_pt_gp_cg; 2649c66ac9dbSNicholas Bellinger } 2650c66ac9dbSNicholas Bellinger 2651c66ac9dbSNicholas Bellinger static void target_core_alua_drop_tg_pt_gp( 2652c66ac9dbSNicholas Bellinger struct config_group *group, 2653c66ac9dbSNicholas Bellinger struct config_item *item) 2654c66ac9dbSNicholas Bellinger { 2655c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp = container_of(to_config_group(item), 2656c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp, tg_pt_gp_group); 2657c66ac9dbSNicholas Bellinger 2658c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: Releasing ALUA Target Port" 2659c66ac9dbSNicholas Bellinger " Group: alua/tg_pt_gps/%s, ID: %hu\n", 2660c66ac9dbSNicholas Bellinger config_item_name(item), tg_pt_gp->tg_pt_gp_id); 26611f6fe7cbSNicholas Bellinger /* 26621f6fe7cbSNicholas Bellinger * core_alua_free_tg_pt_gp() is called from target_core_alua_tg_pt_gp_ops->release() 26631f6fe7cbSNicholas Bellinger * -> target_core_alua_tg_pt_gp_release(). 26641f6fe7cbSNicholas Bellinger */ 2665c66ac9dbSNicholas Bellinger config_item_put(item); 2666c66ac9dbSNicholas Bellinger } 2667c66ac9dbSNicholas Bellinger 2668c66ac9dbSNicholas Bellinger static struct configfs_group_operations target_core_alua_tg_pt_gps_group_ops = { 2669c66ac9dbSNicholas Bellinger .make_group = &target_core_alua_create_tg_pt_gp, 2670c66ac9dbSNicholas Bellinger .drop_item = &target_core_alua_drop_tg_pt_gp, 2671c66ac9dbSNicholas Bellinger }; 2672c66ac9dbSNicholas Bellinger 2673c66ac9dbSNicholas Bellinger static struct config_item_type target_core_alua_tg_pt_gps_cit = { 2674c66ac9dbSNicholas Bellinger .ct_group_ops = &target_core_alua_tg_pt_gps_group_ops, 2675c66ac9dbSNicholas Bellinger .ct_owner = THIS_MODULE, 2676c66ac9dbSNicholas Bellinger }; 2677c66ac9dbSNicholas Bellinger 2678c66ac9dbSNicholas Bellinger /* End functions for struct config_item_type target_core_alua_tg_pt_gps_cit */ 2679c66ac9dbSNicholas Bellinger 2680c66ac9dbSNicholas Bellinger /* Start functions for struct config_item_type target_core_alua_cit */ 2681c66ac9dbSNicholas Bellinger 2682c66ac9dbSNicholas Bellinger /* 2683c66ac9dbSNicholas Bellinger * target_core_alua_cit is a ConfigFS group that lives under 2684c66ac9dbSNicholas Bellinger * /sys/kernel/config/target/core/alua. There are default groups 2685c66ac9dbSNicholas Bellinger * core/alua/lu_gps and core/alua/tg_pt_gps that are attached to 2686c66ac9dbSNicholas Bellinger * target_core_alua_cit in target_core_init_configfs() below. 2687c66ac9dbSNicholas Bellinger */ 2688c66ac9dbSNicholas Bellinger static struct config_item_type target_core_alua_cit = { 2689c66ac9dbSNicholas Bellinger .ct_item_ops = NULL, 2690c66ac9dbSNicholas Bellinger .ct_attrs = NULL, 2691c66ac9dbSNicholas Bellinger .ct_owner = THIS_MODULE, 2692c66ac9dbSNicholas Bellinger }; 2693c66ac9dbSNicholas Bellinger 2694c66ac9dbSNicholas Bellinger /* End functions for struct config_item_type target_core_alua_cit */ 2695c66ac9dbSNicholas Bellinger 269612d23384SNicholas Bellinger /* Start functions for struct config_item_type target_core_stat_cit */ 269712d23384SNicholas Bellinger 269812d23384SNicholas Bellinger static struct config_group *target_core_stat_mkdir( 269912d23384SNicholas Bellinger struct config_group *group, 270012d23384SNicholas Bellinger const char *name) 270112d23384SNicholas Bellinger { 270212d23384SNicholas Bellinger return ERR_PTR(-ENOSYS); 270312d23384SNicholas Bellinger } 270412d23384SNicholas Bellinger 270512d23384SNicholas Bellinger static void target_core_stat_rmdir( 270612d23384SNicholas Bellinger struct config_group *group, 270712d23384SNicholas Bellinger struct config_item *item) 270812d23384SNicholas Bellinger { 270912d23384SNicholas Bellinger return; 271012d23384SNicholas Bellinger } 271112d23384SNicholas Bellinger 271212d23384SNicholas Bellinger static struct configfs_group_operations target_core_stat_group_ops = { 271312d23384SNicholas Bellinger .make_group = &target_core_stat_mkdir, 271412d23384SNicholas Bellinger .drop_item = &target_core_stat_rmdir, 271512d23384SNicholas Bellinger }; 271612d23384SNicholas Bellinger 271712d23384SNicholas Bellinger static struct config_item_type target_core_stat_cit = { 271812d23384SNicholas Bellinger .ct_group_ops = &target_core_stat_group_ops, 271912d23384SNicholas Bellinger .ct_owner = THIS_MODULE, 272012d23384SNicholas Bellinger }; 272112d23384SNicholas Bellinger 272212d23384SNicholas Bellinger /* End functions for struct config_item_type target_core_stat_cit */ 272312d23384SNicholas Bellinger 2724c66ac9dbSNicholas Bellinger /* Start functions for struct config_item_type target_core_hba_cit */ 2725c66ac9dbSNicholas Bellinger 2726c66ac9dbSNicholas Bellinger static struct config_group *target_core_make_subdev( 2727c66ac9dbSNicholas Bellinger struct config_group *group, 2728c66ac9dbSNicholas Bellinger const char *name) 2729c66ac9dbSNicholas Bellinger { 2730c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 2731c66ac9dbSNicholas Bellinger struct se_subsystem_dev *se_dev; 2732c66ac9dbSNicholas Bellinger struct se_subsystem_api *t; 2733c66ac9dbSNicholas Bellinger struct config_item *hba_ci = &group->cg_item; 2734c66ac9dbSNicholas Bellinger struct se_hba *hba = item_to_hba(hba_ci); 2735c66ac9dbSNicholas Bellinger struct config_group *dev_cg = NULL, *tg_pt_gp_cg = NULL; 273612d23384SNicholas Bellinger struct config_group *dev_stat_grp = NULL; 273712d23384SNicholas Bellinger int errno = -ENOMEM, ret; 2738c66ac9dbSNicholas Bellinger 273912d23384SNicholas Bellinger ret = mutex_lock_interruptible(&hba->hba_access_mutex); 274012d23384SNicholas Bellinger if (ret) 274112d23384SNicholas Bellinger return ERR_PTR(ret); 2742c66ac9dbSNicholas Bellinger /* 2743c66ac9dbSNicholas Bellinger * Locate the struct se_subsystem_api from parent's struct se_hba. 2744c66ac9dbSNicholas Bellinger */ 2745c66ac9dbSNicholas Bellinger t = hba->transport; 2746c66ac9dbSNicholas Bellinger 2747c66ac9dbSNicholas Bellinger se_dev = kzalloc(sizeof(struct se_subsystem_dev), GFP_KERNEL); 2748c66ac9dbSNicholas Bellinger if (!se_dev) { 2749c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to allocate memory for" 2750c66ac9dbSNicholas Bellinger " struct se_subsystem_dev\n"); 2751c66ac9dbSNicholas Bellinger goto unlock; 2752c66ac9dbSNicholas Bellinger } 2753e3d6f909SAndy Grover INIT_LIST_HEAD(&se_dev->se_dev_node); 2754c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&se_dev->t10_wwn.t10_vpd_list); 2755c66ac9dbSNicholas Bellinger spin_lock_init(&se_dev->t10_wwn.t10_vpd_lock); 2756e3d6f909SAndy Grover INIT_LIST_HEAD(&se_dev->t10_pr.registration_list); 2757e3d6f909SAndy Grover INIT_LIST_HEAD(&se_dev->t10_pr.aptpl_reg_list); 2758e3d6f909SAndy Grover spin_lock_init(&se_dev->t10_pr.registration_lock); 2759e3d6f909SAndy Grover spin_lock_init(&se_dev->t10_pr.aptpl_reg_lock); 2760c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&se_dev->t10_alua.tg_pt_gps_list); 2761c66ac9dbSNicholas Bellinger spin_lock_init(&se_dev->t10_alua.tg_pt_gps_lock); 2762c66ac9dbSNicholas Bellinger spin_lock_init(&se_dev->se_dev_lock); 2763e3d6f909SAndy Grover se_dev->t10_pr.pr_aptpl_buf_len = PR_APTPL_BUF_LEN; 2764c66ac9dbSNicholas Bellinger se_dev->t10_wwn.t10_sub_dev = se_dev; 2765c66ac9dbSNicholas Bellinger se_dev->t10_alua.t10_sub_dev = se_dev; 2766c66ac9dbSNicholas Bellinger se_dev->se_dev_attrib.da_sub_dev = se_dev; 2767c66ac9dbSNicholas Bellinger 2768c66ac9dbSNicholas Bellinger se_dev->se_dev_hba = hba; 2769c66ac9dbSNicholas Bellinger dev_cg = &se_dev->se_dev_group; 2770c66ac9dbSNicholas Bellinger 277112d23384SNicholas Bellinger dev_cg->default_groups = kzalloc(sizeof(struct config_group) * 7, 2772c66ac9dbSNicholas Bellinger GFP_KERNEL); 2773c66ac9dbSNicholas Bellinger if (!(dev_cg->default_groups)) 2774c66ac9dbSNicholas Bellinger goto out; 2775c66ac9dbSNicholas Bellinger /* 2776c66ac9dbSNicholas Bellinger * Set se_dev_su_ptr from struct se_subsystem_api returned void ptr 2777c66ac9dbSNicholas Bellinger * for ->allocate_virtdevice() 2778c66ac9dbSNicholas Bellinger * 2779c66ac9dbSNicholas Bellinger * se_dev->se_dev_ptr will be set after ->create_virtdev() 2780c66ac9dbSNicholas Bellinger * has been called successfully in the next level up in the 2781c66ac9dbSNicholas Bellinger * configfs tree for device object's struct config_group. 2782c66ac9dbSNicholas Bellinger */ 2783c66ac9dbSNicholas Bellinger se_dev->se_dev_su_ptr = t->allocate_virtdevice(hba, name); 2784c66ac9dbSNicholas Bellinger if (!(se_dev->se_dev_su_ptr)) { 2785c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to locate subsystem dependent pointer" 2786c66ac9dbSNicholas Bellinger " from allocate_virtdevice()\n"); 2787c66ac9dbSNicholas Bellinger goto out; 2788c66ac9dbSNicholas Bellinger } 2789e3d6f909SAndy Grover spin_lock(&se_device_lock); 2790e3d6f909SAndy Grover list_add_tail(&se_dev->se_dev_node, &se_dev_list); 2791e3d6f909SAndy Grover spin_unlock(&se_device_lock); 2792c66ac9dbSNicholas Bellinger 2793c66ac9dbSNicholas Bellinger config_group_init_type_name(&se_dev->se_dev_group, name, 2794c66ac9dbSNicholas Bellinger &target_core_dev_cit); 2795c66ac9dbSNicholas Bellinger config_group_init_type_name(&se_dev->se_dev_attrib.da_group, "attrib", 2796c66ac9dbSNicholas Bellinger &target_core_dev_attrib_cit); 2797c66ac9dbSNicholas Bellinger config_group_init_type_name(&se_dev->se_dev_pr_group, "pr", 2798c66ac9dbSNicholas Bellinger &target_core_dev_pr_cit); 2799c66ac9dbSNicholas Bellinger config_group_init_type_name(&se_dev->t10_wwn.t10_wwn_group, "wwn", 2800c66ac9dbSNicholas Bellinger &target_core_dev_wwn_cit); 2801c66ac9dbSNicholas Bellinger config_group_init_type_name(&se_dev->t10_alua.alua_tg_pt_gps_group, 2802c66ac9dbSNicholas Bellinger "alua", &target_core_alua_tg_pt_gps_cit); 280312d23384SNicholas Bellinger config_group_init_type_name(&se_dev->dev_stat_grps.stat_group, 280412d23384SNicholas Bellinger "statistics", &target_core_stat_cit); 280512d23384SNicholas Bellinger 2806c66ac9dbSNicholas Bellinger dev_cg->default_groups[0] = &se_dev->se_dev_attrib.da_group; 2807c66ac9dbSNicholas Bellinger dev_cg->default_groups[1] = &se_dev->se_dev_pr_group; 2808c66ac9dbSNicholas Bellinger dev_cg->default_groups[2] = &se_dev->t10_wwn.t10_wwn_group; 2809c66ac9dbSNicholas Bellinger dev_cg->default_groups[3] = &se_dev->t10_alua.alua_tg_pt_gps_group; 281012d23384SNicholas Bellinger dev_cg->default_groups[4] = &se_dev->dev_stat_grps.stat_group; 281112d23384SNicholas Bellinger dev_cg->default_groups[5] = NULL; 2812c66ac9dbSNicholas Bellinger /* 281312d23384SNicholas Bellinger * Add core/$HBA/$DEV/alua/default_tg_pt_gp 2814c66ac9dbSNicholas Bellinger */ 2815c66ac9dbSNicholas Bellinger tg_pt_gp = core_alua_allocate_tg_pt_gp(se_dev, "default_tg_pt_gp", 1); 2816c66ac9dbSNicholas Bellinger if (!(tg_pt_gp)) 2817c66ac9dbSNicholas Bellinger goto out; 2818c66ac9dbSNicholas Bellinger 2819e3d6f909SAndy Grover tg_pt_gp_cg = &se_dev->t10_alua.alua_tg_pt_gps_group; 2820c66ac9dbSNicholas Bellinger tg_pt_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, 2821c66ac9dbSNicholas Bellinger GFP_KERNEL); 2822c66ac9dbSNicholas Bellinger if (!(tg_pt_gp_cg->default_groups)) { 2823c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to allocate tg_pt_gp_cg->" 2824c66ac9dbSNicholas Bellinger "default_groups\n"); 2825c66ac9dbSNicholas Bellinger goto out; 2826c66ac9dbSNicholas Bellinger } 2827c66ac9dbSNicholas Bellinger 2828c66ac9dbSNicholas Bellinger config_group_init_type_name(&tg_pt_gp->tg_pt_gp_group, 2829c66ac9dbSNicholas Bellinger "default_tg_pt_gp", &target_core_alua_tg_pt_gp_cit); 2830c66ac9dbSNicholas Bellinger tg_pt_gp_cg->default_groups[0] = &tg_pt_gp->tg_pt_gp_group; 2831c66ac9dbSNicholas Bellinger tg_pt_gp_cg->default_groups[1] = NULL; 2832e3d6f909SAndy Grover se_dev->t10_alua.default_tg_pt_gp = tg_pt_gp; 283312d23384SNicholas Bellinger /* 283412d23384SNicholas Bellinger * Add core/$HBA/$DEV/statistics/ default groups 283512d23384SNicholas Bellinger */ 2836e3d6f909SAndy Grover dev_stat_grp = &se_dev->dev_stat_grps.stat_group; 283712d23384SNicholas Bellinger dev_stat_grp->default_groups = kzalloc(sizeof(struct config_group) * 4, 283812d23384SNicholas Bellinger GFP_KERNEL); 283912d23384SNicholas Bellinger if (!dev_stat_grp->default_groups) { 284012d23384SNicholas Bellinger printk(KERN_ERR "Unable to allocate dev_stat_grp->default_groups\n"); 284112d23384SNicholas Bellinger goto out; 284212d23384SNicholas Bellinger } 284312d23384SNicholas Bellinger target_stat_setup_dev_default_groups(se_dev); 2844c66ac9dbSNicholas Bellinger 2845c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: Allocated struct se_subsystem_dev:" 2846c66ac9dbSNicholas Bellinger " %p se_dev_su_ptr: %p\n", se_dev, se_dev->se_dev_su_ptr); 2847c66ac9dbSNicholas Bellinger 2848c66ac9dbSNicholas Bellinger mutex_unlock(&hba->hba_access_mutex); 2849c66ac9dbSNicholas Bellinger return &se_dev->se_dev_group; 2850c66ac9dbSNicholas Bellinger out: 2851e3d6f909SAndy Grover if (se_dev->t10_alua.default_tg_pt_gp) { 2852e3d6f909SAndy Grover core_alua_free_tg_pt_gp(se_dev->t10_alua.default_tg_pt_gp); 2853e3d6f909SAndy Grover se_dev->t10_alua.default_tg_pt_gp = NULL; 2854c66ac9dbSNicholas Bellinger } 285512d23384SNicholas Bellinger if (dev_stat_grp) 285612d23384SNicholas Bellinger kfree(dev_stat_grp->default_groups); 2857c66ac9dbSNicholas Bellinger if (tg_pt_gp_cg) 2858c66ac9dbSNicholas Bellinger kfree(tg_pt_gp_cg->default_groups); 2859c66ac9dbSNicholas Bellinger if (dev_cg) 2860c66ac9dbSNicholas Bellinger kfree(dev_cg->default_groups); 2861c66ac9dbSNicholas Bellinger if (se_dev->se_dev_su_ptr) 2862c66ac9dbSNicholas Bellinger t->free_device(se_dev->se_dev_su_ptr); 2863c66ac9dbSNicholas Bellinger kfree(se_dev); 2864c66ac9dbSNicholas Bellinger unlock: 2865c66ac9dbSNicholas Bellinger mutex_unlock(&hba->hba_access_mutex); 286612d23384SNicholas Bellinger return ERR_PTR(errno); 2867c66ac9dbSNicholas Bellinger } 2868c66ac9dbSNicholas Bellinger 2869c66ac9dbSNicholas Bellinger static void target_core_drop_subdev( 2870c66ac9dbSNicholas Bellinger struct config_group *group, 2871c66ac9dbSNicholas Bellinger struct config_item *item) 2872c66ac9dbSNicholas Bellinger { 2873c66ac9dbSNicholas Bellinger struct se_subsystem_dev *se_dev = container_of(to_config_group(item), 2874c66ac9dbSNicholas Bellinger struct se_subsystem_dev, se_dev_group); 2875c66ac9dbSNicholas Bellinger struct se_hba *hba; 2876c66ac9dbSNicholas Bellinger struct se_subsystem_api *t; 2877c66ac9dbSNicholas Bellinger struct config_item *df_item; 287812d23384SNicholas Bellinger struct config_group *dev_cg, *tg_pt_gp_cg, *dev_stat_grp; 28791f6fe7cbSNicholas Bellinger int i; 2880c66ac9dbSNicholas Bellinger 2881c66ac9dbSNicholas Bellinger hba = item_to_hba(&se_dev->se_dev_hba->hba_group.cg_item); 2882c66ac9dbSNicholas Bellinger 28831f6fe7cbSNicholas Bellinger mutex_lock(&hba->hba_access_mutex); 2884c66ac9dbSNicholas Bellinger t = hba->transport; 2885c66ac9dbSNicholas Bellinger 2886e3d6f909SAndy Grover spin_lock(&se_device_lock); 2887e3d6f909SAndy Grover list_del(&se_dev->se_dev_node); 2888e3d6f909SAndy Grover spin_unlock(&se_device_lock); 2889c66ac9dbSNicholas Bellinger 2890e3d6f909SAndy Grover dev_stat_grp = &se_dev->dev_stat_grps.stat_group; 289112d23384SNicholas Bellinger for (i = 0; dev_stat_grp->default_groups[i]; i++) { 289212d23384SNicholas Bellinger df_item = &dev_stat_grp->default_groups[i]->cg_item; 289312d23384SNicholas Bellinger dev_stat_grp->default_groups[i] = NULL; 289412d23384SNicholas Bellinger config_item_put(df_item); 289512d23384SNicholas Bellinger } 289612d23384SNicholas Bellinger kfree(dev_stat_grp->default_groups); 289712d23384SNicholas Bellinger 2898e3d6f909SAndy Grover tg_pt_gp_cg = &se_dev->t10_alua.alua_tg_pt_gps_group; 2899c66ac9dbSNicholas Bellinger for (i = 0; tg_pt_gp_cg->default_groups[i]; i++) { 2900c66ac9dbSNicholas Bellinger df_item = &tg_pt_gp_cg->default_groups[i]->cg_item; 2901c66ac9dbSNicholas Bellinger tg_pt_gp_cg->default_groups[i] = NULL; 2902c66ac9dbSNicholas Bellinger config_item_put(df_item); 2903c66ac9dbSNicholas Bellinger } 2904c66ac9dbSNicholas Bellinger kfree(tg_pt_gp_cg->default_groups); 29051f6fe7cbSNicholas Bellinger /* 29061f6fe7cbSNicholas Bellinger * core_alua_free_tg_pt_gp() is called from ->default_tg_pt_gp 29071f6fe7cbSNicholas Bellinger * directly from target_core_alua_tg_pt_gp_release(). 29081f6fe7cbSNicholas Bellinger */ 2909e3d6f909SAndy Grover se_dev->t10_alua.default_tg_pt_gp = NULL; 2910c66ac9dbSNicholas Bellinger 2911c66ac9dbSNicholas Bellinger dev_cg = &se_dev->se_dev_group; 2912c66ac9dbSNicholas Bellinger for (i = 0; dev_cg->default_groups[i]; i++) { 2913c66ac9dbSNicholas Bellinger df_item = &dev_cg->default_groups[i]->cg_item; 2914c66ac9dbSNicholas Bellinger dev_cg->default_groups[i] = NULL; 2915c66ac9dbSNicholas Bellinger config_item_put(df_item); 2916c66ac9dbSNicholas Bellinger } 29171f6fe7cbSNicholas Bellinger /* 29181f6fe7cbSNicholas Bellinger * The releasing of se_dev and associated se_dev->se_dev_ptr is done 29191f6fe7cbSNicholas Bellinger * from target_core_dev_item_ops->release() ->target_core_dev_release(). 29201f6fe7cbSNicholas Bellinger */ 2921c66ac9dbSNicholas Bellinger config_item_put(item); 2922c66ac9dbSNicholas Bellinger mutex_unlock(&hba->hba_access_mutex); 2923c66ac9dbSNicholas Bellinger } 2924c66ac9dbSNicholas Bellinger 2925c66ac9dbSNicholas Bellinger static struct configfs_group_operations target_core_hba_group_ops = { 2926c66ac9dbSNicholas Bellinger .make_group = target_core_make_subdev, 2927c66ac9dbSNicholas Bellinger .drop_item = target_core_drop_subdev, 2928c66ac9dbSNicholas Bellinger }; 2929c66ac9dbSNicholas Bellinger 2930c66ac9dbSNicholas Bellinger CONFIGFS_EATTR_STRUCT(target_core_hba, se_hba); 2931c66ac9dbSNicholas Bellinger #define SE_HBA_ATTR(_name, _mode) \ 2932c66ac9dbSNicholas Bellinger static struct target_core_hba_attribute \ 2933c66ac9dbSNicholas Bellinger target_core_hba_##_name = \ 2934c66ac9dbSNicholas Bellinger __CONFIGFS_EATTR(_name, _mode, \ 2935c66ac9dbSNicholas Bellinger target_core_hba_show_attr_##_name, \ 2936c66ac9dbSNicholas Bellinger target_core_hba_store_attr_##_name); 2937c66ac9dbSNicholas Bellinger 2938c66ac9dbSNicholas Bellinger #define SE_HBA_ATTR_RO(_name) \ 2939c66ac9dbSNicholas Bellinger static struct target_core_hba_attribute \ 2940c66ac9dbSNicholas Bellinger target_core_hba_##_name = \ 2941c66ac9dbSNicholas Bellinger __CONFIGFS_EATTR_RO(_name, \ 2942c66ac9dbSNicholas Bellinger target_core_hba_show_attr_##_name); 2943c66ac9dbSNicholas Bellinger 2944c66ac9dbSNicholas Bellinger static ssize_t target_core_hba_show_attr_hba_info( 2945c66ac9dbSNicholas Bellinger struct se_hba *hba, 2946c66ac9dbSNicholas Bellinger char *page) 2947c66ac9dbSNicholas Bellinger { 2948c66ac9dbSNicholas Bellinger return sprintf(page, "HBA Index: %d plugin: %s version: %s\n", 2949c66ac9dbSNicholas Bellinger hba->hba_id, hba->transport->name, 2950c66ac9dbSNicholas Bellinger TARGET_CORE_CONFIGFS_VERSION); 2951c66ac9dbSNicholas Bellinger } 2952c66ac9dbSNicholas Bellinger 2953c66ac9dbSNicholas Bellinger SE_HBA_ATTR_RO(hba_info); 2954c66ac9dbSNicholas Bellinger 2955c66ac9dbSNicholas Bellinger static ssize_t target_core_hba_show_attr_hba_mode(struct se_hba *hba, 2956c66ac9dbSNicholas Bellinger char *page) 2957c66ac9dbSNicholas Bellinger { 2958c66ac9dbSNicholas Bellinger int hba_mode = 0; 2959c66ac9dbSNicholas Bellinger 2960c66ac9dbSNicholas Bellinger if (hba->hba_flags & HBA_FLAGS_PSCSI_MODE) 2961c66ac9dbSNicholas Bellinger hba_mode = 1; 2962c66ac9dbSNicholas Bellinger 2963c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", hba_mode); 2964c66ac9dbSNicholas Bellinger } 2965c66ac9dbSNicholas Bellinger 2966c66ac9dbSNicholas Bellinger static ssize_t target_core_hba_store_attr_hba_mode(struct se_hba *hba, 2967c66ac9dbSNicholas Bellinger const char *page, size_t count) 2968c66ac9dbSNicholas Bellinger { 2969c66ac9dbSNicholas Bellinger struct se_subsystem_api *transport = hba->transport; 2970c66ac9dbSNicholas Bellinger unsigned long mode_flag; 2971c66ac9dbSNicholas Bellinger int ret; 2972c66ac9dbSNicholas Bellinger 2973c66ac9dbSNicholas Bellinger if (transport->pmode_enable_hba == NULL) 2974c66ac9dbSNicholas Bellinger return -EINVAL; 2975c66ac9dbSNicholas Bellinger 2976c66ac9dbSNicholas Bellinger ret = strict_strtoul(page, 0, &mode_flag); 2977c66ac9dbSNicholas Bellinger if (ret < 0) { 2978c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to extract hba mode flag: %d\n", ret); 2979c66ac9dbSNicholas Bellinger return -EINVAL; 2980c66ac9dbSNicholas Bellinger } 2981c66ac9dbSNicholas Bellinger 2982c66ac9dbSNicholas Bellinger spin_lock(&hba->device_lock); 2983c66ac9dbSNicholas Bellinger if (!(list_empty(&hba->hba_dev_list))) { 2984c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to set hba_mode with active devices\n"); 2985c66ac9dbSNicholas Bellinger spin_unlock(&hba->device_lock); 2986c66ac9dbSNicholas Bellinger return -EINVAL; 2987c66ac9dbSNicholas Bellinger } 2988c66ac9dbSNicholas Bellinger spin_unlock(&hba->device_lock); 2989c66ac9dbSNicholas Bellinger 2990c66ac9dbSNicholas Bellinger ret = transport->pmode_enable_hba(hba, mode_flag); 2991c66ac9dbSNicholas Bellinger if (ret < 0) 2992c66ac9dbSNicholas Bellinger return -EINVAL; 2993c66ac9dbSNicholas Bellinger if (ret > 0) 2994c66ac9dbSNicholas Bellinger hba->hba_flags |= HBA_FLAGS_PSCSI_MODE; 2995c66ac9dbSNicholas Bellinger else if (ret == 0) 2996c66ac9dbSNicholas Bellinger hba->hba_flags &= ~HBA_FLAGS_PSCSI_MODE; 2997c66ac9dbSNicholas Bellinger 2998c66ac9dbSNicholas Bellinger return count; 2999c66ac9dbSNicholas Bellinger } 3000c66ac9dbSNicholas Bellinger 3001c66ac9dbSNicholas Bellinger SE_HBA_ATTR(hba_mode, S_IRUGO | S_IWUSR); 3002c66ac9dbSNicholas Bellinger 3003c66ac9dbSNicholas Bellinger CONFIGFS_EATTR_OPS(target_core_hba, se_hba, hba_group); 3004c66ac9dbSNicholas Bellinger 30051f6fe7cbSNicholas Bellinger static void target_core_hba_release(struct config_item *item) 30061f6fe7cbSNicholas Bellinger { 30071f6fe7cbSNicholas Bellinger struct se_hba *hba = container_of(to_config_group(item), 30081f6fe7cbSNicholas Bellinger struct se_hba, hba_group); 30091f6fe7cbSNicholas Bellinger core_delete_hba(hba); 30101f6fe7cbSNicholas Bellinger } 30111f6fe7cbSNicholas Bellinger 3012c66ac9dbSNicholas Bellinger static struct configfs_attribute *target_core_hba_attrs[] = { 3013c66ac9dbSNicholas Bellinger &target_core_hba_hba_info.attr, 3014c66ac9dbSNicholas Bellinger &target_core_hba_hba_mode.attr, 3015c66ac9dbSNicholas Bellinger NULL, 3016c66ac9dbSNicholas Bellinger }; 3017c66ac9dbSNicholas Bellinger 3018c66ac9dbSNicholas Bellinger static struct configfs_item_operations target_core_hba_item_ops = { 30191f6fe7cbSNicholas Bellinger .release = target_core_hba_release, 3020c66ac9dbSNicholas Bellinger .show_attribute = target_core_hba_attr_show, 3021c66ac9dbSNicholas Bellinger .store_attribute = target_core_hba_attr_store, 3022c66ac9dbSNicholas Bellinger }; 3023c66ac9dbSNicholas Bellinger 3024c66ac9dbSNicholas Bellinger static struct config_item_type target_core_hba_cit = { 3025c66ac9dbSNicholas Bellinger .ct_item_ops = &target_core_hba_item_ops, 3026c66ac9dbSNicholas Bellinger .ct_group_ops = &target_core_hba_group_ops, 3027c66ac9dbSNicholas Bellinger .ct_attrs = target_core_hba_attrs, 3028c66ac9dbSNicholas Bellinger .ct_owner = THIS_MODULE, 3029c66ac9dbSNicholas Bellinger }; 3030c66ac9dbSNicholas Bellinger 3031c66ac9dbSNicholas Bellinger static struct config_group *target_core_call_addhbatotarget( 3032c66ac9dbSNicholas Bellinger struct config_group *group, 3033c66ac9dbSNicholas Bellinger const char *name) 3034c66ac9dbSNicholas Bellinger { 3035c66ac9dbSNicholas Bellinger char *se_plugin_str, *str, *str2; 3036c66ac9dbSNicholas Bellinger struct se_hba *hba; 3037c66ac9dbSNicholas Bellinger char buf[TARGET_CORE_NAME_MAX_LEN]; 3038c66ac9dbSNicholas Bellinger unsigned long plugin_dep_id = 0; 3039c66ac9dbSNicholas Bellinger int ret; 3040c66ac9dbSNicholas Bellinger 3041c66ac9dbSNicholas Bellinger memset(buf, 0, TARGET_CORE_NAME_MAX_LEN); 304260d645a4SDan Carpenter if (strlen(name) >= TARGET_CORE_NAME_MAX_LEN) { 3043c66ac9dbSNicholas Bellinger printk(KERN_ERR "Passed *name strlen(): %d exceeds" 3044c66ac9dbSNicholas Bellinger " TARGET_CORE_NAME_MAX_LEN: %d\n", (int)strlen(name), 3045c66ac9dbSNicholas Bellinger TARGET_CORE_NAME_MAX_LEN); 3046c66ac9dbSNicholas Bellinger return ERR_PTR(-ENAMETOOLONG); 3047c66ac9dbSNicholas Bellinger } 3048c66ac9dbSNicholas Bellinger snprintf(buf, TARGET_CORE_NAME_MAX_LEN, "%s", name); 3049c66ac9dbSNicholas Bellinger 3050c66ac9dbSNicholas Bellinger str = strstr(buf, "_"); 3051c66ac9dbSNicholas Bellinger if (!(str)) { 3052c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to locate \"_\" for $SUBSYSTEM_PLUGIN_$HOST_ID\n"); 3053c66ac9dbSNicholas Bellinger return ERR_PTR(-EINVAL); 3054c66ac9dbSNicholas Bellinger } 3055c66ac9dbSNicholas Bellinger se_plugin_str = buf; 3056c66ac9dbSNicholas Bellinger /* 3057c66ac9dbSNicholas Bellinger * Special case for subsystem plugins that have "_" in their names. 3058c66ac9dbSNicholas Bellinger * Namely rd_direct and rd_mcp.. 3059c66ac9dbSNicholas Bellinger */ 3060c66ac9dbSNicholas Bellinger str2 = strstr(str+1, "_"); 3061c66ac9dbSNicholas Bellinger if ((str2)) { 3062c66ac9dbSNicholas Bellinger *str2 = '\0'; /* Terminate for *se_plugin_str */ 3063c66ac9dbSNicholas Bellinger str2++; /* Skip to start of plugin dependent ID */ 3064c66ac9dbSNicholas Bellinger str = str2; 3065c66ac9dbSNicholas Bellinger } else { 3066c66ac9dbSNicholas Bellinger *str = '\0'; /* Terminate for *se_plugin_str */ 3067c66ac9dbSNicholas Bellinger str++; /* Skip to start of plugin dependent ID */ 3068c66ac9dbSNicholas Bellinger } 3069c66ac9dbSNicholas Bellinger 3070c66ac9dbSNicholas Bellinger ret = strict_strtoul(str, 0, &plugin_dep_id); 3071c66ac9dbSNicholas Bellinger if (ret < 0) { 3072c66ac9dbSNicholas Bellinger printk(KERN_ERR "strict_strtoul() returned %d for" 3073c66ac9dbSNicholas Bellinger " plugin_dep_id\n", ret); 3074c66ac9dbSNicholas Bellinger return ERR_PTR(-EINVAL); 3075c66ac9dbSNicholas Bellinger } 3076c66ac9dbSNicholas Bellinger /* 3077c66ac9dbSNicholas Bellinger * Load up TCM subsystem plugins if they have not already been loaded. 3078c66ac9dbSNicholas Bellinger */ 3079c66ac9dbSNicholas Bellinger if (transport_subsystem_check_init() < 0) 3080c66ac9dbSNicholas Bellinger return ERR_PTR(-EINVAL); 3081c66ac9dbSNicholas Bellinger 3082c66ac9dbSNicholas Bellinger hba = core_alloc_hba(se_plugin_str, plugin_dep_id, 0); 3083c66ac9dbSNicholas Bellinger if (IS_ERR(hba)) 3084c66ac9dbSNicholas Bellinger return ERR_CAST(hba); 3085c66ac9dbSNicholas Bellinger 3086c66ac9dbSNicholas Bellinger config_group_init_type_name(&hba->hba_group, name, 3087c66ac9dbSNicholas Bellinger &target_core_hba_cit); 3088c66ac9dbSNicholas Bellinger 3089c66ac9dbSNicholas Bellinger return &hba->hba_group; 3090c66ac9dbSNicholas Bellinger } 3091c66ac9dbSNicholas Bellinger 3092c66ac9dbSNicholas Bellinger static void target_core_call_delhbafromtarget( 3093c66ac9dbSNicholas Bellinger struct config_group *group, 3094c66ac9dbSNicholas Bellinger struct config_item *item) 3095c66ac9dbSNicholas Bellinger { 30961f6fe7cbSNicholas Bellinger /* 30971f6fe7cbSNicholas Bellinger * core_delete_hba() is called from target_core_hba_item_ops->release() 30981f6fe7cbSNicholas Bellinger * -> target_core_hba_release() 30991f6fe7cbSNicholas Bellinger */ 3100c66ac9dbSNicholas Bellinger config_item_put(item); 3101c66ac9dbSNicholas Bellinger } 3102c66ac9dbSNicholas Bellinger 3103c66ac9dbSNicholas Bellinger static struct configfs_group_operations target_core_group_ops = { 3104c66ac9dbSNicholas Bellinger .make_group = target_core_call_addhbatotarget, 3105c66ac9dbSNicholas Bellinger .drop_item = target_core_call_delhbafromtarget, 3106c66ac9dbSNicholas Bellinger }; 3107c66ac9dbSNicholas Bellinger 3108c66ac9dbSNicholas Bellinger static struct config_item_type target_core_cit = { 3109c66ac9dbSNicholas Bellinger .ct_item_ops = NULL, 3110c66ac9dbSNicholas Bellinger .ct_group_ops = &target_core_group_ops, 3111c66ac9dbSNicholas Bellinger .ct_attrs = NULL, 3112c66ac9dbSNicholas Bellinger .ct_owner = THIS_MODULE, 3113c66ac9dbSNicholas Bellinger }; 3114c66ac9dbSNicholas Bellinger 3115c66ac9dbSNicholas Bellinger /* Stop functions for struct config_item_type target_core_hba_cit */ 3116c66ac9dbSNicholas Bellinger 311754550fabSAxel Lin static int __init target_core_init_configfs(void) 3118c66ac9dbSNicholas Bellinger { 3119c66ac9dbSNicholas Bellinger struct config_group *target_cg, *hba_cg = NULL, *alua_cg = NULL; 3120c66ac9dbSNicholas Bellinger struct config_group *lu_gp_cg = NULL; 3121c66ac9dbSNicholas Bellinger struct configfs_subsystem *subsys; 3122c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp; 3123c66ac9dbSNicholas Bellinger int ret; 3124c66ac9dbSNicholas Bellinger 3125c66ac9dbSNicholas Bellinger printk(KERN_INFO "TARGET_CORE[0]: Loading Generic Kernel Storage" 3126c66ac9dbSNicholas Bellinger " Engine: %s on %s/%s on "UTS_RELEASE"\n", 3127c66ac9dbSNicholas Bellinger TARGET_CORE_VERSION, utsname()->sysname, utsname()->machine); 3128c66ac9dbSNicholas Bellinger 3129c66ac9dbSNicholas Bellinger subsys = target_core_subsystem[0]; 3130c66ac9dbSNicholas Bellinger config_group_init(&subsys->su_group); 3131c66ac9dbSNicholas Bellinger mutex_init(&subsys->su_mutex); 3132c66ac9dbSNicholas Bellinger 3133c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&g_tf_list); 3134c66ac9dbSNicholas Bellinger mutex_init(&g_tf_lock); 3135e3d6f909SAndy Grover ret = init_se_kmem_caches(); 3136c66ac9dbSNicholas Bellinger if (ret < 0) 3137e3d6f909SAndy Grover return ret; 3138c66ac9dbSNicholas Bellinger /* 3139c66ac9dbSNicholas Bellinger * Create $CONFIGFS/target/core default group for HBA <-> Storage Object 3140c66ac9dbSNicholas Bellinger * and ALUA Logical Unit Group and Target Port Group infrastructure. 3141c66ac9dbSNicholas Bellinger */ 3142c66ac9dbSNicholas Bellinger target_cg = &subsys->su_group; 3143c66ac9dbSNicholas Bellinger target_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, 3144c66ac9dbSNicholas Bellinger GFP_KERNEL); 3145c66ac9dbSNicholas Bellinger if (!(target_cg->default_groups)) { 3146c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to allocate target_cg->default_groups\n"); 3147c66ac9dbSNicholas Bellinger goto out_global; 3148c66ac9dbSNicholas Bellinger } 3149c66ac9dbSNicholas Bellinger 3150e3d6f909SAndy Grover config_group_init_type_name(&target_core_hbagroup, 3151c66ac9dbSNicholas Bellinger "core", &target_core_cit); 3152e3d6f909SAndy Grover target_cg->default_groups[0] = &target_core_hbagroup; 3153c66ac9dbSNicholas Bellinger target_cg->default_groups[1] = NULL; 3154c66ac9dbSNicholas Bellinger /* 3155c66ac9dbSNicholas Bellinger * Create ALUA infrastructure under /sys/kernel/config/target/core/alua/ 3156c66ac9dbSNicholas Bellinger */ 3157e3d6f909SAndy Grover hba_cg = &target_core_hbagroup; 3158c66ac9dbSNicholas Bellinger hba_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, 3159c66ac9dbSNicholas Bellinger GFP_KERNEL); 3160c66ac9dbSNicholas Bellinger if (!(hba_cg->default_groups)) { 3161c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to allocate hba_cg->default_groups\n"); 3162c66ac9dbSNicholas Bellinger goto out_global; 3163c66ac9dbSNicholas Bellinger } 3164e3d6f909SAndy Grover config_group_init_type_name(&alua_group, 3165c66ac9dbSNicholas Bellinger "alua", &target_core_alua_cit); 3166e3d6f909SAndy Grover hba_cg->default_groups[0] = &alua_group; 3167c66ac9dbSNicholas Bellinger hba_cg->default_groups[1] = NULL; 3168c66ac9dbSNicholas Bellinger /* 3169c66ac9dbSNicholas Bellinger * Add ALUA Logical Unit Group and Target Port Group ConfigFS 3170c66ac9dbSNicholas Bellinger * groups under /sys/kernel/config/target/core/alua/ 3171c66ac9dbSNicholas Bellinger */ 3172e3d6f909SAndy Grover alua_cg = &alua_group; 3173c66ac9dbSNicholas Bellinger alua_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, 3174c66ac9dbSNicholas Bellinger GFP_KERNEL); 3175c66ac9dbSNicholas Bellinger if (!(alua_cg->default_groups)) { 3176c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to allocate alua_cg->default_groups\n"); 3177c66ac9dbSNicholas Bellinger goto out_global; 3178c66ac9dbSNicholas Bellinger } 3179c66ac9dbSNicholas Bellinger 3180e3d6f909SAndy Grover config_group_init_type_name(&alua_lu_gps_group, 3181c66ac9dbSNicholas Bellinger "lu_gps", &target_core_alua_lu_gps_cit); 3182e3d6f909SAndy Grover alua_cg->default_groups[0] = &alua_lu_gps_group; 3183c66ac9dbSNicholas Bellinger alua_cg->default_groups[1] = NULL; 3184c66ac9dbSNicholas Bellinger /* 3185c66ac9dbSNicholas Bellinger * Add core/alua/lu_gps/default_lu_gp 3186c66ac9dbSNicholas Bellinger */ 3187c66ac9dbSNicholas Bellinger lu_gp = core_alua_allocate_lu_gp("default_lu_gp", 1); 3188c66ac9dbSNicholas Bellinger if (IS_ERR(lu_gp)) 3189c66ac9dbSNicholas Bellinger goto out_global; 3190c66ac9dbSNicholas Bellinger 3191e3d6f909SAndy Grover lu_gp_cg = &alua_lu_gps_group; 3192c66ac9dbSNicholas Bellinger lu_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, 3193c66ac9dbSNicholas Bellinger GFP_KERNEL); 3194c66ac9dbSNicholas Bellinger if (!(lu_gp_cg->default_groups)) { 3195c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to allocate lu_gp_cg->default_groups\n"); 3196c66ac9dbSNicholas Bellinger goto out_global; 3197c66ac9dbSNicholas Bellinger } 3198c66ac9dbSNicholas Bellinger 3199c66ac9dbSNicholas Bellinger config_group_init_type_name(&lu_gp->lu_gp_group, "default_lu_gp", 3200c66ac9dbSNicholas Bellinger &target_core_alua_lu_gp_cit); 3201c66ac9dbSNicholas Bellinger lu_gp_cg->default_groups[0] = &lu_gp->lu_gp_group; 3202c66ac9dbSNicholas Bellinger lu_gp_cg->default_groups[1] = NULL; 3203e3d6f909SAndy Grover default_lu_gp = lu_gp; 3204c66ac9dbSNicholas Bellinger /* 3205c66ac9dbSNicholas Bellinger * Register the target_core_mod subsystem with configfs. 3206c66ac9dbSNicholas Bellinger */ 3207c66ac9dbSNicholas Bellinger ret = configfs_register_subsystem(subsys); 3208c66ac9dbSNicholas Bellinger if (ret < 0) { 3209c66ac9dbSNicholas Bellinger printk(KERN_ERR "Error %d while registering subsystem %s\n", 3210c66ac9dbSNicholas Bellinger ret, subsys->su_group.cg_item.ci_namebuf); 3211c66ac9dbSNicholas Bellinger goto out_global; 3212c66ac9dbSNicholas Bellinger } 3213c66ac9dbSNicholas Bellinger printk(KERN_INFO "TARGET_CORE[0]: Initialized ConfigFS Fabric" 3214c66ac9dbSNicholas Bellinger " Infrastructure: "TARGET_CORE_CONFIGFS_VERSION" on %s/%s" 3215c66ac9dbSNicholas Bellinger " on "UTS_RELEASE"\n", utsname()->sysname, utsname()->machine); 3216c66ac9dbSNicholas Bellinger /* 3217c66ac9dbSNicholas Bellinger * Register built-in RAMDISK subsystem logic for virtual LUN 0 3218c66ac9dbSNicholas Bellinger */ 3219c66ac9dbSNicholas Bellinger ret = rd_module_init(); 3220c66ac9dbSNicholas Bellinger if (ret < 0) 3221c66ac9dbSNicholas Bellinger goto out; 3222c66ac9dbSNicholas Bellinger 3223c66ac9dbSNicholas Bellinger if (core_dev_setup_virtual_lun0() < 0) 3224c66ac9dbSNicholas Bellinger goto out; 3225c66ac9dbSNicholas Bellinger 3226c66ac9dbSNicholas Bellinger return 0; 3227c66ac9dbSNicholas Bellinger 3228c66ac9dbSNicholas Bellinger out: 3229c66ac9dbSNicholas Bellinger configfs_unregister_subsystem(subsys); 3230c66ac9dbSNicholas Bellinger core_dev_release_virtual_lun0(); 3231c66ac9dbSNicholas Bellinger rd_module_exit(); 3232c66ac9dbSNicholas Bellinger out_global: 3233e3d6f909SAndy Grover if (default_lu_gp) { 3234e3d6f909SAndy Grover core_alua_free_lu_gp(default_lu_gp); 3235e3d6f909SAndy Grover default_lu_gp = NULL; 3236c66ac9dbSNicholas Bellinger } 3237c66ac9dbSNicholas Bellinger if (lu_gp_cg) 3238c66ac9dbSNicholas Bellinger kfree(lu_gp_cg->default_groups); 3239c66ac9dbSNicholas Bellinger if (alua_cg) 3240c66ac9dbSNicholas Bellinger kfree(alua_cg->default_groups); 3241c66ac9dbSNicholas Bellinger if (hba_cg) 3242c66ac9dbSNicholas Bellinger kfree(hba_cg->default_groups); 3243c66ac9dbSNicholas Bellinger kfree(target_cg->default_groups); 3244e3d6f909SAndy Grover release_se_kmem_caches(); 3245e3d6f909SAndy Grover return ret; 3246c66ac9dbSNicholas Bellinger } 3247c66ac9dbSNicholas Bellinger 324854550fabSAxel Lin static void __exit target_core_exit_configfs(void) 3249c66ac9dbSNicholas Bellinger { 3250c66ac9dbSNicholas Bellinger struct configfs_subsystem *subsys; 3251c66ac9dbSNicholas Bellinger struct config_group *hba_cg, *alua_cg, *lu_gp_cg; 3252c66ac9dbSNicholas Bellinger struct config_item *item; 3253c66ac9dbSNicholas Bellinger int i; 3254c66ac9dbSNicholas Bellinger 3255c66ac9dbSNicholas Bellinger subsys = target_core_subsystem[0]; 3256c66ac9dbSNicholas Bellinger 3257e3d6f909SAndy Grover lu_gp_cg = &alua_lu_gps_group; 3258c66ac9dbSNicholas Bellinger for (i = 0; lu_gp_cg->default_groups[i]; i++) { 3259c66ac9dbSNicholas Bellinger item = &lu_gp_cg->default_groups[i]->cg_item; 3260c66ac9dbSNicholas Bellinger lu_gp_cg->default_groups[i] = NULL; 3261c66ac9dbSNicholas Bellinger config_item_put(item); 3262c66ac9dbSNicholas Bellinger } 3263c66ac9dbSNicholas Bellinger kfree(lu_gp_cg->default_groups); 32647c2bf6e9SNicholas Bellinger lu_gp_cg->default_groups = NULL; 3265c66ac9dbSNicholas Bellinger 3266e3d6f909SAndy Grover alua_cg = &alua_group; 3267c66ac9dbSNicholas Bellinger for (i = 0; alua_cg->default_groups[i]; i++) { 3268c66ac9dbSNicholas Bellinger item = &alua_cg->default_groups[i]->cg_item; 3269c66ac9dbSNicholas Bellinger alua_cg->default_groups[i] = NULL; 3270c66ac9dbSNicholas Bellinger config_item_put(item); 3271c66ac9dbSNicholas Bellinger } 3272c66ac9dbSNicholas Bellinger kfree(alua_cg->default_groups); 32737c2bf6e9SNicholas Bellinger alua_cg->default_groups = NULL; 3274c66ac9dbSNicholas Bellinger 3275e3d6f909SAndy Grover hba_cg = &target_core_hbagroup; 3276c66ac9dbSNicholas Bellinger for (i = 0; hba_cg->default_groups[i]; i++) { 3277c66ac9dbSNicholas Bellinger item = &hba_cg->default_groups[i]->cg_item; 3278c66ac9dbSNicholas Bellinger hba_cg->default_groups[i] = NULL; 3279c66ac9dbSNicholas Bellinger config_item_put(item); 3280c66ac9dbSNicholas Bellinger } 3281c66ac9dbSNicholas Bellinger kfree(hba_cg->default_groups); 32827c2bf6e9SNicholas Bellinger hba_cg->default_groups = NULL; 32837c2bf6e9SNicholas Bellinger /* 32847c2bf6e9SNicholas Bellinger * We expect subsys->su_group.default_groups to be released 32857c2bf6e9SNicholas Bellinger * by configfs subsystem provider logic.. 32867c2bf6e9SNicholas Bellinger */ 32877c2bf6e9SNicholas Bellinger configfs_unregister_subsystem(subsys); 3288c66ac9dbSNicholas Bellinger kfree(subsys->su_group.default_groups); 3289c66ac9dbSNicholas Bellinger 3290e3d6f909SAndy Grover core_alua_free_lu_gp(default_lu_gp); 3291e3d6f909SAndy Grover default_lu_gp = NULL; 32927c2bf6e9SNicholas Bellinger 3293c66ac9dbSNicholas Bellinger printk(KERN_INFO "TARGET_CORE[0]: Released ConfigFS Fabric" 3294c66ac9dbSNicholas Bellinger " Infrastructure\n"); 3295c66ac9dbSNicholas Bellinger 3296c66ac9dbSNicholas Bellinger core_dev_release_virtual_lun0(); 3297c66ac9dbSNicholas Bellinger rd_module_exit(); 3298e3d6f909SAndy Grover release_se_kmem_caches(); 3299c66ac9dbSNicholas Bellinger } 3300c66ac9dbSNicholas Bellinger 3301c66ac9dbSNicholas Bellinger MODULE_DESCRIPTION("Target_Core_Mod/ConfigFS"); 3302c66ac9dbSNicholas Bellinger MODULE_AUTHOR("nab@Linux-iSCSI.org"); 3303c66ac9dbSNicholas Bellinger MODULE_LICENSE("GPL"); 3304c66ac9dbSNicholas Bellinger 3305c66ac9dbSNicholas Bellinger module_init(target_core_init_configfs); 3306c66ac9dbSNicholas Bellinger module_exit(target_core_exit_configfs); 3307