[<prev] [next>] [day] [month] [year] [list]
Message-Id: <1249924211.31984.1.camel@haakon2.linux-iscsi.org>
Date: Mon, 10 Aug 2009 10:10:11 -0700
From: "Nicholas A. Bellinger" <nab@...ux-iscsi.org>
To: LKML <linux-kernel@...r.kernel.org>,
linux-scsi <linux-scsi@...r.kernel.org>
Cc: Douglas Gilbert <dgilbert@...erlog.com>,
Hannes Reinecke <hare@...e.de>,
FUJITA Tomonori <fujita.tomonori@....ntt.co.jp>,
Mike Christie <michaelc@...wisc.edu>,
James Bottomley <James.Bottomley@...senPartnership.com>,
Andrew Morton <akpm@...ux-foundation.org>,
Joel Becker <joel.becker@...cle.com>,
James Smart <James.Smart@...lex.Com>,
Philipp Reisner <philipp.reisner@...bit.com>,
Florian Haas <florian.haas@...bit.com>
Subject: [PATCH 2/2] [Target_Core_Mod/ConfigFS]: Add PR APTPL device
attributes
Hello,
This patch adds two configfs attributes in /sys/kernel/config/target/core/$HBA/$DEV/pr.
First a read only attr called res_aptpl_active that shows read-only APTPL_A status,
and then res_aptpl_metadata which accepts key=value pairs for core_scsi3_alloc_aptpl_registration()
to perform PR registrations from APTPL provided metadata through the target_core_mod
configfs interface. The key=value pairs currently defined in target_core_dev_pr_store_attr_res_aptpl_metadata()
and which are written to /sys/kernel/config/target/core/$HBA/$DEV/res_aptpl_metadata
in key0=value0,key1=value1,etc format are:
*) initiator_fabric
*) initiator_node
*) sa_res_key
*) res_holder
*) res_type
*) res_scope
*) res_all_tg_pt
*) mapped_lun
*) target_fabric
*) target_node
*) tpgt
*) port_rtpi
*) target_lun
Note that initiator_fabric, target_fabric, and port_rtpi keys are saved in struct file
PR APTPL metadta and are currently being extracted, but not being passed in
core_scsi3_alloc_aptpl_registration() which saves the incoming metadata into a PR registration.
This will probably change in the near future as this code moves to use SCSI Transport IDs
parsing provide by struct target_core_fabric_ops
Also note that /sys/kernel/config/target/core/$HBA/$DEV/pr/res_aptpl_metadata can also
used to create PR registration from APTPL metadata when no active fabric module
(eg: iSCSI ports) exist, which prevents things from changing while SCSI Initiator ports
are actively using PR logic for the TCM storage object.
Signed-off-by: Nicholas A. Bellinger <nab@...ux-iscsi.org>
---
drivers/target/target_core_configfs.c | 266 ++++++++++++++++++++++++++++++++-
1 files changed, 265 insertions(+), 1 deletions(-)
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 4561ee2..847995a 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -1125,6 +1125,266 @@ static ssize_t target_core_dev_pr_show_attr_res_type(
SE_DEV_PR_ATTR_RO(res_type);
+/*
+ * res_aptpl_active
+ */
+
+static ssize_t target_core_dev_pr_show_attr_res_aptpl_active(
+ struct se_subsystem_dev_s *su_dev,
+ char *page)
+{
+ if (!(su_dev->se_dev_ptr))
+ return -ENODEV;
+
+ if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS)
+ return 0;
+
+ return sprintf(page, "APTPL Bit Status: %s\n",
+ (T10_RES(su_dev)->pr_aptpl_active) ? "Activated" : "Disabled");
+}
+
+SE_DEV_PR_ATTR_RO(res_aptpl_active);
+
+/*
+ * res_aptpl_metadata
+ */
+static ssize_t target_core_dev_pr_show_attr_res_aptpl_metadata(
+ struct se_subsystem_dev_s *su_dev,
+ char *page)
+{
+ if (!(su_dev->se_dev_ptr))
+ return -ENODEV;
+
+ if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS)
+ return 0;
+
+ return sprintf(page, "Ready to process PR APTPL metadata..\n");
+}
+
+static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
+ struct se_subsystem_dev_s *su_dev,
+ const char *page,
+ size_t count)
+{
+ se_device_t *dev;
+ unsigned char *i_fabric, *t_fabric, *i_port = NULL, *t_port = NULL;
+ char *ptr, *ptr2, *cur, *buf;
+ unsigned long long tmp_ll;
+ unsigned long tmp_l;
+ u64 sa_res_key = 0;
+ u32 mapped_lun = 0, target_lun = 0;
+ int ret = -1, res_holder = 0, all_tg_pt = 0;
+ u16 port_rpti = 0, tpgt = 0;
+ u8 type = 0, scope;
+
+ dev = su_dev->se_dev_ptr;
+ if (!(dev))
+ return -ENODEV;
+
+ if (T10_RES(su_dev)->res_type != SPC3_PERSISTENT_RESERVATIONS)
+ return 0;
+
+ if (DEV_OBJ_API(dev)->check_count(&dev->dev_export_obj)) {
+ printk(KERN_INFO "Unable to process APTPL metadata while"
+ " active fabric exports exist\n");
+ return -EINVAL;
+ }
+ /*
+ * Allocate and copy input to our own buffer so that we can setup
+ * NULL terminators later for incoming PR APTPL metadata..
+ */
+ buf = kzalloc(count, GFP_KERNEL);
+ memcpy(buf, page, count);
+ cur = &buf[0];
+
+ while (cur) {
+ ptr = strstr(cur, "=");
+ if (!(ptr))
+ goto out;
+
+ *ptr = '\0';
+ ptr++;
+ /*
+ * PR APTPL Metadata for Initiator Port
+ */
+ ptr2 = strstr(cur, "initiator_fabric");
+ if (ptr2) {
+ transport_check_dev_params_delim(ptr, &cur);
+ i_fabric = ptr;
+ continue;
+ }
+ ptr2 = strstr(cur, "initiator_node");
+ if (ptr2) {
+ transport_check_dev_params_delim(ptr, &cur);
+ if (strlen(ptr) > PR_APTPL_MAX_IPORT_LEN) {
+ printk(KERN_ERR "APTPL metadata initiator_node="
+ " exceeds PR_APTPL_MAX_IPORT_LEN: %d\n",
+ PR_APTPL_MAX_IPORT_LEN);
+ ret = -1;
+ break;
+ }
+ i_port = ptr;
+ continue;
+ }
+ ptr2 = strstr(cur, "sa_res_key");
+ if (ptr2) {
+ transport_check_dev_params_delim(ptr, &cur);
+ ret = strict_strtoull(ptr, 0, &tmp_ll);
+ if (ret < 0) {
+ printk(KERN_ERR "strict_strtoull() failed for"
+ " sa_res_key=\n");
+ break;
+ }
+ sa_res_key = (u64)tmp_ll;
+ continue;
+ }
+ /*
+ * PR APTPL Metadata for Reservation
+ */
+ ptr2 = strstr(cur, "res_holder");
+ if (ptr2) {
+ transport_check_dev_params_delim(ptr, &cur);
+ ret = strict_strtoul(ptr, 0, &tmp_l);
+ if (ret < 0) {
+ printk(KERN_ERR "strict_strtoul() failed for"
+ " res_holder=\n");
+ break;
+ }
+ res_holder = (int)tmp_l;
+ continue;
+ }
+ ptr2 = strstr(cur, "res_type");
+ if (ptr2) {
+ transport_check_dev_params_delim(ptr, &cur);
+ ret = strict_strtoul(ptr, 0, &tmp_l);
+ if (ret < 0) {
+ printk(KERN_ERR "strict_strtoul() failed for"
+ " res_type=\n");
+ break;
+ }
+ type = (u8)tmp_l;
+ continue;
+ }
+ ptr2 = strstr(cur, "res_scope");
+ if (ptr2) {
+ transport_check_dev_params_delim(ptr, &cur);
+ ret = strict_strtoul(ptr, 0, &tmp_l);
+ if (ret < 0) {
+ printk(KERN_ERR "strict_strtoul() failed for"
+ " res_scope=\n");
+ break;
+ }
+ scope = (u8)tmp_l;
+ continue;
+ }
+ ptr2 = strstr(cur, "res_all_tg_pt");
+ if (ptr2) {
+ transport_check_dev_params_delim(ptr, &cur);
+ ret = strict_strtoul(ptr, 0, &tmp_l);
+ if (ret < 0) {
+ printk(KERN_ERR "strict_strtoul() failed for"
+ " res_all_tg_pt=\n");
+ break;
+ }
+ all_tg_pt = (int)tmp_l;
+ continue;
+ }
+ ptr2 = strstr(cur, "mapped_lun");
+ if (ptr2) {
+ transport_check_dev_params_delim(ptr, &cur);
+ ret = strict_strtoul(ptr, 0, &tmp_l);
+ if (ret < 0) {
+ printk(KERN_ERR "strict_strtoul() failed for"
+ " mapped_lun=\n");
+ break;
+ }
+ mapped_lun = (u32)tmp_l;
+ continue;
+ }
+ /*
+ * PR APTPL Metadata for Target Port
+ */
+ ptr2 = strstr(cur, "target_fabric");
+ if (ptr2) {
+ transport_check_dev_params_delim(ptr, &cur);
+ t_fabric = ptr;
+ continue;
+ }
+ ptr2 = strstr(cur, "target_node");
+ if (ptr2) {
+ transport_check_dev_params_delim(ptr, &cur);
+ if (strlen(ptr) > PR_APTPL_MAX_TPORT_LEN) {
+ printk(KERN_ERR "APTPL metadata target_node="
+ " exceeds PR_APTPL_MAX_TPORT_LEN: %d\n",
+ PR_APTPL_MAX_TPORT_LEN);
+ ret = -1;
+ break;
+ }
+ t_port = ptr;
+ continue;
+ }
+ ptr2 = strstr(cur, "tpgt");
+ if (ptr2) {
+ transport_check_dev_params_delim(ptr, &cur);
+ ret = strict_strtoul(ptr, 0, &tmp_l);
+ if (ret < 0) {
+ printk(KERN_ERR "strict_strtoul() failed for"
+ " tpgt=\n");
+ break;
+ }
+ tpgt = (u16)tmp_l;
+ continue;
+ }
+ ptr2 = strstr(cur, "port_rtpi");
+ if (ptr2) {
+ transport_check_dev_params_delim(ptr, &cur);
+ ret = strict_strtoul(ptr, 0, &tmp_l);
+ if (ret < 0) {
+ printk(KERN_ERR "strict_strtoul() failed for"
+ " port_rtpi=\n");
+ break;
+ }
+ port_rpti = (u16)tmp_l;
+ continue;
+ }
+ ptr2 = strstr(cur, "target_lun");
+ if (ptr2) {
+ transport_check_dev_params_delim(ptr, &cur);
+ ret = strict_strtoul(ptr, 0, &tmp_l);
+ if (ret < 0) {
+ printk(KERN_ERR "strict_strtoul() failed for"
+ " target_lun=\n");
+ break;
+ }
+ target_lun = (u32)tmp_l;
+ continue;
+ } else
+ cur = NULL;
+ }
+
+ if (!(i_port) || !(t_port) || !(sa_res_key)) {
+ printk(KERN_ERR "Illegal parameters for APTPL registration\n");
+ ret = -1;
+ goto out;
+ }
+
+ if (res_holder && !(type)) {
+ printk(KERN_ERR "Illegal PR type: 0x%02x for reservation"
+ " holder\n", type);
+ ret = -1;
+ goto out;
+ }
+
+ ret = core_scsi3_alloc_aptpl_registration(T10_RES(su_dev), sa_res_key,
+ i_port, mapped_lun, t_port, tpgt, target_lun, res_holder,
+ all_tg_pt, type);
+out:
+ kfree(buf);
+ return (ret == 0) ? count : -EINVAL;
+}
+
+SE_DEV_PR_ATTR(res_aptpl_metadata, S_IRUGO | S_IWUSR);
+
CONFIGFS_EATTR_OPS(target_core_dev_pr, se_subsystem_dev_s, se_dev_pr_group);
static struct configfs_attribute *target_core_dev_pr_attrs[] = {
@@ -1135,6 +1395,8 @@ static struct configfs_attribute *target_core_dev_pr_attrs[] = {
&target_core_dev_pr_res_pr_registered_i_pts.attr,
&target_core_dev_pr_res_pr_type.attr,
&target_core_dev_pr_res_type.attr,
+ &target_core_dev_pr_res_aptpl_active.attr,
+ &target_core_dev_pr_res_aptpl_metadata.attr,
NULL,
};
@@ -2158,9 +2420,11 @@ static struct config_group *target_core_call_createdev(
INIT_LIST_HEAD(&se_dev->t10_wwn.t10_vpd_list);
spin_lock_init(&se_dev->t10_wwn.t10_vpd_lock);
INIT_LIST_HEAD(&se_dev->t10_reservation.registration_list);
+ INIT_LIST_HEAD(&se_dev->t10_reservation.aptpl_reg_list);
spin_lock_init(&se_dev->t10_reservation.registration_lock);
+ spin_lock_init(&se_dev->t10_reservation.aptpl_reg_lock);
spin_lock_init(&se_dev->se_dev_lock);
-
+ se_dev->t10_reservation.pr_aptpl_buf_len = PR_APTPL_BUF_LEN;
se_dev->t10_wwn.t10_sub_dev = se_dev;
se_dev->se_dev_attrib.da_sub_dev = se_dev;
--
1.5.4.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists