[PATCH 1/1] ISCSI: Add support for show/add/remove portals

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Tomo, list

Please find attached a patch to show/add/remove iscsi portals at runtime.
Please comment or consider for inclusion.


Manpage is also updated to show examples on how to show/add/remove portals.
(in the future, as policy, perhaps patches that add new functionality
should be rejected if they do not update manpage?)


Portals added/removed apply globally to the entire tgtd process.
At a later stage I think we should decide on how to implement
binding/filtering portals per initiators and setting up ACLs,
but that is for a separate patch later.


regards
ronnie sahlberg

Attachment: 0001-Add-support-to-tgtd-and-tgtadm-to-show-add-remove-is.patch.gz
Description: GNU Zip compressed data

From 1f524b94f6c70b6cf70142f2f1804659dfe8ba44 Mon Sep 17 00:00:00 2001
From: Ronnie Sahlberg <ronniesahlberg@xxxxxxxxx>
Date: Wed, 20 Apr 2011 17:42:41 +1000
Subject: [PATCH] Add support to tgtd and tgtadm to show/add/remove iscsi portals at runtime

This patch adds a new mode : PORTAL
and two new device methods : add portal / remove portal

This allows to add/remove portals at runtime without having to restart
tgtd.

Manpage is updated to show examples of show/add/remove portal
with tgtadm utility.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@xxxxxxxxx>
---
 doc/htmlpages/tgtadm.8.html |   46 +++++++++++++------
 doc/manpages/tgtadm.8       |   51 ++++++++++++++++++++-
 doc/tgtadm.8.xml            |   35 ++++++++++++++
 usr/driver.h                |    3 +
 usr/iscsi/iscsi_tcp.c       |   56 ++++++++++++++++++++++-
 usr/iscsi/iscsid.c          |  106 ++++++++++++++++++++++++++++---------------
 usr/iscsi/iscsid.h          |    4 +-
 usr/iscsi/target.c          |   31 ++++++++++++-
 usr/mgmt.c                  |   38 +++++++++++++++
 usr/target.c                |   50 ++++++++++++++++++++
 usr/tgtadm.c                |   59 +++++++++++++++++++++++-
 usr/tgtadm.h                |    1 +
 usr/tgtd.h                  |    3 +
 13 files changed, 422 insertions(+), 61 deletions(-)

diff --git a/doc/htmlpages/tgtadm.8.html b/doc/htmlpages/tgtadm.8.html
index b8dcce2..689ce75 100644
--- a/doc/htmlpages/tgtadm.8.html
+++ b/doc/htmlpages/tgtadm.8.html
@@ -1,7 +1,7 @@
-<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>tgtadm</title><meta name="generator" content="DocBook XSL Stylesheets V1.75.2"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" title="tgtadm"><a name="tgtadm.8"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>tgtadm &#8212; Linux SCSI Target Administration Utility</p></div><div class="refsynopsisdiv" title="Synopsis"><h2>Synopsis</h2><div class="cmdsynopsis"><p><code class="command">tgtadm [OPTIONS]...</code>  [-C --control-port &lt;port&gt;] [-L --lld &lt;driver&gt;] [-o --op &lt;operation&gt;] [-m --mode &lt;mode&gt;] [-t --tid &lt;id&gt;] [-T --targetname &lt;targetname&gt;] [-Y --device-type &lt;type&gt;] [-l --lun &lt;lun&gt;] [-b --backing-store &lt;path&gt;] [-E --bstype &lt;type&gt;] [-I --initiator-address &lt;address&gt;] [-n --name &lt;parameter&gt;] [-v --value &lt;value&gt;] [-P --params &lt;param=value[,param=value...]&gt;] [-h --help]</p></div></div><div class="refsect1" title="DESCRIPTION"><a name="id355729"></a><h2>DESCRIPTION</h2><p>
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>tgtadm</title><meta name="generator" content="DocBook XSL Stylesheets V1.75.2"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" title="tgtadm"><a name="tgtadm.8"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>tgtadm &#8212; Linux SCSI Target Administration Utility</p></div><div class="refsynopsisdiv" title="Synopsis"><h2>Synopsis</h2><div class="cmdsynopsis"><p><code class="command">tgtadm [OPTIONS]...</code>  [-C --control-port &lt;port&gt;] [-L --lld &lt;driver&gt;] [-o --op &lt;operation&gt;] [-m --mode &lt;mode&gt;] [-t --tid &lt;id&gt;] [-T --targetname &lt;targetname&gt;] [-Y --device-type &lt;type&gt;] [-l --lun &lt;lun&gt;] [-b --backing-store &lt;path&gt;] [-E --bstype &lt;type&gt;] [-I --initiator-address &lt;address&gt;] [-n --name &lt;parameter&gt;] [-v --value &lt;value&gt;] [-P --params &lt;param=value[,param=value...]&gt;] [-h --help]</p></div></div><div class="refsect1" title="DESCRIPTION"><a name="id319787"></a><h2>DESCRIPTION</h2><p>
       tgtadm is used to monitor and modify everything about Linux SCSI target
       software: targets, volumes, etc.
-    </p></div><div class="refsect1" title="OPTIONS"><a name="id355740"></a><h2>OPTIONS</h2><div class="variablelist"><pre class="screen">
+    </p></div><div class="refsect1" title="OPTIONS"><a name="id319798"></a><h2>OPTIONS</h2><div class="variablelist"><pre class="screen">
 Possible device-types are:
     disk    : emulate a disk device
     tape    : emulate a tape reader
@@ -54,7 +54,7 @@ Possible backend types are:
 	    Sets/changes the value of one or more parameters.
           </p></dd><dt><span class="term"><code class="option">--help</code></span></dt><dd><p>
 	    Display a list of available options and exits.
-          </p></dd></dl></div></div><div class="refsect1" title="LUN PARAMETERS"><a name="id355985"></a><h2>LUN PARAMETERS</h2><p>
+          </p></dd></dl></div></div><div class="refsect1" title="LUN PARAMETERS"><a name="id320042"></a><h2>LUN PARAMETERS</h2><p>
       These parameters are only applicable for "--mode logicalunit".
     </p><div class="variablelist"><pre class="screen">
 Example:
@@ -128,7 +128,7 @@ tgtadm --lld iscsi --mode logicalunit --op update --tid 1 --lun 1 \
 	    refuse any attempts to write data to it.
           </p><p>
 	    This parameter only applies to DISK devices.
-          </p></dd></dl></div></div><div class="refsect1" title="SMC SPECIFIC LUN PARAMETERS"><a name="id356158"></a><h2>SMC SPECIFIC LUN PARAMETERS</h2><p>
+          </p></dd></dl></div></div><div class="refsect1" title="SMC SPECIFIC LUN PARAMETERS"><a name="id320216"></a><h2>SMC SPECIFIC LUN PARAMETERS</h2><p>
       These parameters are only applicable for luns that are of type "changer"
       i.e. the media changer device for a DVD Jukebox or a Virtual Tape Library.
     </p><div class="variablelist"><pre class="screen">
@@ -213,7 +213,7 @@ Slot types:
 	    To assign a media image file to a storage element slot,
 	    you assign "barcode" to be the name of the image file in
 	    the "media_home" directory.
-          </p></dd></dl></div></div><div class="refsect1" title="Passthrough devices"><a name="id356318"></a><h2>Passthrough devices</h2><p>
+          </p></dd></dl></div></div><div class="refsect1" title="Passthrough devices"><a name="id320376"></a><h2>Passthrough devices</h2><p>
       In addition to device emulation TGTD also supports utilizing existing SG devices on the host and exporting these through a special passthrough device type.
     </p><dt><span class="term"><code class="option">--bstype=sg</code></span></dt><dd><p>
 	  This specifies that an SG devices is used.
@@ -226,13 +226,13 @@ Example:
 Make /dev/sg4 available to initiators connecting to TGTD.
 
 tgtadm --lld iscsi --op new --mode logicalunit --tid 1 --lun 1 --bstype=sg --device-type=pt --backing-store=/dev/sg4
-    </pre></div><div class="refsect1" title="Header Digest and Data Digest"><a name="id356377"></a><h2>Header Digest and Data Digest</h2><p>
+    </pre></div><div class="refsect1" title="Header Digest and Data Digest"><a name="id320434"></a><h2>Header Digest and Data Digest</h2><p>
       Header and data digests can be set on a per target parameter.
       TGTD supports two modes, None and CRC32C.
       When the digest is set to None, TDTD will negotiate that digests
       will not be used, and when CRC32C is set, TGTD will force the
       connection to use digest.
-    </p><div class="refsect2" title="Viewing the current settings"><a name="id356387"></a><h3>Viewing the current settings</h3><p>
+    </p><div class="refsect2" title="Viewing the current settings"><a name="id320445"></a><h3>Viewing the current settings</h3><p>
 	This command is used to view the current settings for header/data
 	digest.
       </p><pre class="screen">
@@ -241,13 +241,13 @@ tgtadm --op show --mode target --tid 1
   HeaderDigest=None
   DataDigest=None
   ...
-      </pre></div><div class="refsect2" title="Setting digest"><a name="id356403"></a><h3>Setting digest</h3><pre class="screen">
+      </pre></div><div class="refsect2" title="Setting digest"><a name="id320461"></a><h3>Setting digest</h3><pre class="screen">
 Set header digest to CRC32C:
 tgtadm --op update --mode target --tid 1 -n HeaderDigest -v CRC32C
 
 Set data digest to None:
 tgtadm --op update --mode target --tid 1 -n DataDigest -v None
-      </pre></div></div><div class="refsect1" title="CHAP Authentication"><a name="id356417"></a><h2>CHAP Authentication</h2><p>
+      </pre></div></div><div class="refsect1" title="CHAP Authentication"><a name="id320475"></a><h2>CHAP Authentication</h2><p>
       CHAP authentication is supported to require authentication before
       an initiator is allowed to log in and access devices.
       TGTD supports setting CHAP for normal log in sessions only, not
@@ -258,18 +258,18 @@ tgtadm --op update --mode target --tid 1 -n DataDigest -v None
       To set up CHAP authentication we first need to create an account
       and its associated password, then we bind the account to one or more
       targets.
-    </p><div class="refsect2" title="Setting CHAP on a target"><a name="id356433"></a><h3>Setting CHAP on a target</h3><p>
+    </p><div class="refsect2" title="Setting CHAP on a target"><a name="id320490"></a><h3>Setting CHAP on a target</h3><p>
 	These two commands create a user account and binds it to target 1.
       </p><pre class="screen">
 tgtadm --lld iscsi --op new --mode account --user ronnie --password password
 tgtadm --lld iscsi --op bind --mode account --tid 1 --user ronnie
-      </pre></div><div class="refsect2" title="List all accounts"><a name="id356449"></a><h3>List all accounts</h3><p>
+      </pre></div><div class="refsect2" title="List all accounts"><a name="id320507"></a><h3>List all accounts</h3><p>
 	This command is used to list all accounts that have been created.
       </p><pre class="screen">
 tgtadm --lld iscsi --op show --mode account
 Account list:
     ronnie
-      </pre></div><div class="refsect2" title="Show if a target requires authentication"><a name="id356465"></a><h3>Show if a target requires authentication</h3><p>
+      </pre></div><div class="refsect2" title="Show if a target requires authentication"><a name="id320523"></a><h3>Show if a target requires authentication</h3><p>
 	When listing the targets, each target that has authantication enabled
 	will contain a listing of all accoutns bound to that target.
       </p><pre class="screen">
@@ -279,7 +279,23 @@ Target 1: iqn.ronnie.test
 Account information:
     ronnie
 ...
-      </pre></div></div><div class="refsect1" title="iSNS PARAMETERS"><a name="id356483"></a><h2>iSNS PARAMETERS</h2><p>
+      </pre></div></div><div class="refsect1" title="iSCSI PORTALS"><a name="id320541"></a><h2>iSCSI PORTALS</h2><p>
+      iSCSI portals can be viewed, added and removed at runtime.
+    </p><div class="refsect2" title="List portals"><a name="id320549"></a><h3>List portals</h3><p>
+      This command is used to list the current iSCSI portals defined on the target:
+      </p><pre class="screen">
+tgtadm --lld iscsi --op show --mode portal
+Portal: 10.1.1.101:3260,1
+Portal: 127.0.0.1:3260,1
+      </pre></div><div class="refsect2" title="Add portal"><a name="id320565"></a><h3>Add portal</h3><p>
+      This command is used to add a portal to the target :
+      </p><pre class="screen">
+tgtadm --lld iscsi --op new --mode portal --param portal=10.1.1.101:3260
+      </pre></div><div class="refsect2" title="Remove portal"><a name="id320581"></a><h3>Remove portal</h3><p>
+      This command is used to remove a portal from the target :
+      </p><pre class="screen">
+tgtadm --lld iscsi --op delete --mode portal --param portal=10.1.1.101:3260
+      </pre></div></div><div class="refsect1" title="iSNS PARAMETERS"><a name="id320598"></a><h2>iSNS PARAMETERS</h2><p>
       iSNS configuration for a target is by using the tgtadm command.
     </p><div class="variablelist"><pre class="screen">
 Example:
@@ -306,9 +322,9 @@ tgtadm --op update --mode sys --name iSNSAccessControl --value Off
 	    This setting specifies the port to use for iSNS.
           </p></dd><dt><span class="term"><code class="option">iSNSAccessControl</code></span></dt><dd><p>
 	    Enable/disable access control for iSNS.
-          </p></dd></dl></div></div><div class="refsect1" title="SEE ALSO"><a name="id356576"></a><h2>SEE ALSO</h2><p>
+          </p></dd></dl></div></div><div class="refsect1" title="SEE ALSO"><a name="id320691"></a><h2>SEE ALSO</h2><p>
       tgtd(8), tgt-admin(8), tgtimg(8), tgt-setup-lun(8).
       <a class="ulink" href="http://stgt.sourceforge.net/"; target="_top">http://stgt.sourceforge.net/</a>
-    </p></div><div class="refsect1" title="REPORTING BUGS"><a name="id356590"></a><h2>REPORTING BUGS</h2><p>
+    </p></div><div class="refsect1" title="REPORTING BUGS"><a name="id320705"></a><h2>REPORTING BUGS</h2><p>
       Report bugs to &lt;stgt@xxxxxxxxxxxxxxx&gt;
     </p></div></div></body></html>
diff --git a/doc/manpages/tgtadm.8 b/doc/manpages/tgtadm.8
index 080ca66..c530ec3 100644
--- a/doc/manpages/tgtadm.8
+++ b/doc/manpages/tgtadm.8
@@ -2,12 +2,12 @@
 .\"     Title: tgtadm
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: 02/19/2011
+.\"      Date: 04/20/2011
 .\"    Manual: [FIXME: manual]
 .\"    Source: [FIXME: source]
 .\"  Language: English
 .\"
-.TH "TGTADM" "8" "02/19/2011" "[FIXME: source]" "[FIXME: manual]"
+.TH "TGTADM" "8" "04/20/2011" "[FIXME: source]" "[FIXME: manual]"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -497,6 +497,53 @@ Account information:
 .if n \{\
 .RE
 .\}
+.SH "ISCSI PORTALS"
+.PP
+iSCSI portals can be viewed, added and removed at runtime\&.
+.SS "List portals"
+.PP
+This command is used to list the current iSCSI portals defined on the target:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+tgtadm \-\-lld iscsi \-\-op show \-\-mode portal
+Portal: 10\&.1\&.1\&.101:3260,1
+Portal: 127\&.0\&.0\&.1:3260,1
+      
+.fi
+.if n \{\
+.RE
+.\}
+.SS "Add portal"
+.PP
+This command is used to add a portal to the target :
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+tgtadm \-\-lld iscsi \-\-op new \-\-mode portal \-\-param portal=10\&.1\&.1\&.101:3260
+      
+.fi
+.if n \{\
+.RE
+.\}
+.SS "Remove portal"
+.PP
+This command is used to remove a portal from the target :
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+tgtadm \-\-lld iscsi \-\-op delete \-\-mode portal \-\-param portal=10\&.1\&.1\&.101:3260
+      
+.fi
+.if n \{\
+.RE
+.\}
 .SH "ISNS PARAMETERS"
 .PP
 iSNS configuration for a target is by using the tgtadm command\&.
diff --git a/doc/tgtadm.8.xml b/doc/tgtadm.8.xml
index 421f638..dd53d78 100644
--- a/doc/tgtadm.8.xml
+++ b/doc/tgtadm.8.xml
@@ -188,6 +188,7 @@ Possible backend types are:
     </variablelist>
   </refsect1>
 
+
   <refsect1><title>LUN PARAMETERS</title>
     <para>
       These parameters are only applicable for "--mode logicalunit".
@@ -584,6 +585,40 @@ Account information:
   </refsect1>
 
 
+  <refsect1><title>iSCSI PORTALS</title>
+    <para>
+      iSCSI portals can be viewed, added and removed at runtime.
+    </para>
+    <refsect2><title>List portals</title>
+      <para>
+      This command is used to list the current iSCSI portals defined on the target:
+      </para>
+      <screen format="linespecific">
+tgtadm --lld iscsi --op show --mode portal
+Portal: 10.1.1.101:3260,1
+Portal: 127.0.0.1:3260,1
+      </screen>
+    </refsect2>
+    <refsect2><title>Add portal</title>
+      <para>
+      This command is used to add a portal to the target :
+      </para>
+      <screen format="linespecific">
+tgtadm --lld iscsi --op new --mode portal --param portal=10.1.1.101:3260
+      </screen>
+    </refsect2>
+    <refsect2><title>Remove portal</title>
+      <para>
+      This command is used to remove a portal from the target :
+      </para>
+      <screen format="linespecific">
+tgtadm --lld iscsi --op delete --mode portal --param portal=10.1.1.101:3260
+      </screen>
+    </refsect2>
+  </refsect1>
+
+
+
   <refsect1><title>iSNS PARAMETERS</title>
     <para>
       iSNS configuration for a target is by using the tgtadm command.
diff --git a/usr/driver.h b/usr/driver.h
index f53e012..173471c 100644
--- a/usr/driver.h
+++ b/usr/driver.h
@@ -11,6 +11,9 @@ struct tgt_driver {
 	int (*target_create)(struct target *);
 	void (*target_destroy)(int);
 
+	int (*portal_create)(char *);
+	int (*portal_destroy)(char *);
+
 	int (*lu_create)(struct scsi_lu *);
 
 	int (*update)(int, int, int ,uint64_t, uint64_t, uint32_t, char *);
diff --git a/usr/iscsi/iscsi_tcp.c b/usr/iscsi/iscsi_tcp.c
index 14c55bb..e87bbf1 100644
--- a/usr/iscsi/iscsi_tcp.c
+++ b/usr/iscsi/iscsi_tcp.c
@@ -246,6 +246,58 @@ static int iscsi_tcp_init_portal(struct iscsi_portal *portal)
 	return !nr_sock;
 }
 
+int iscsi_add_portal(char *addr, int port, int tpgt, int do_create)
+{
+	struct iscsi_portal *new_portal;
+
+	list_for_each_entry(new_portal, &iscsi_portals_list,
+			    iscsi_portal_siblings) {
+		if (!strcmp(addr, new_portal->addr)
+			&& port == new_portal->port) {
+			eprintf("add_portal failed. This portal already "
+				"exists %s:%d\n", addr, port);
+			return -1;
+		}
+	}
+
+	new_portal = zalloc(sizeof(struct iscsi_portal));
+	new_portal->addr = strdup(addr);
+	new_portal->port = port ? port : ISCSI_LISTEN_PORT;
+	new_portal->tpgt = tpgt;
+	new_portal->fd   = -1;
+
+	if (do_create && iscsi_tcp_init_portal(new_portal)) {
+		eprintf("failed to create/bind to portal %s:%d\n", addr, port);
+		free(new_portal->addr);
+		free(new_portal);
+		return -1;
+	}
+
+	list_add(&new_portal->iscsi_portal_siblings, &iscsi_portals_list);
+	return 0;
+};
+
+int iscsi_delete_portal(char *addr, int port)
+{
+	struct iscsi_portal *portal;
+
+	list_for_each_entry(portal, &iscsi_portals_list,
+			    iscsi_portal_siblings) {
+		if (!strcmp(addr, portal->addr) && port == portal->port) {
+			if (portal->fd != -1)
+				tgt_event_del(portal->fd);
+			close(portal->fd);
+			list_del(&portal->iscsi_portal_siblings);
+			free(portal->addr);
+			free(portal);
+			return 0;
+		}
+	}
+	eprintf("delete_portal failed. No such portal found %s:%d\n",
+			addr, port);
+	return -1;
+}
+
 static int iscsi_tcp_init(void)
 {
 	struct iscsi_portal *portal;
@@ -254,8 +306,8 @@ static int iscsi_tcp_init(void)
 	   for ipv4 and ipv6
 	*/
 	if (list_empty(&iscsi_portals_list)) {
-		iscsi_add_portal("0::0", 0);
-		iscsi_add_portal("0.0.0.0", 0);
+		iscsi_add_portal("0::0", 0, 1, 0);
+		iscsi_add_portal("0.0.0.0", 0, 1, 0);
 	}
 
 	list_for_each_entry(portal, &iscsi_portals_list,
diff --git a/usr/iscsi/iscsid.c b/usr/iscsi/iscsid.c
index b61bb28..7666381 100644
--- a/usr/iscsi/iscsid.c
+++ b/usr/iscsi/iscsid.c
@@ -73,18 +73,6 @@ enum {
 	IOSTATE_TX_END,
 };
 
-void iscsi_add_portal(char *addr, int port)
-{
-	struct iscsi_portal *new_portal;
-
-	new_portal = zalloc(sizeof(struct iscsi_portal));
-	new_portal->addr = strdup(addr);
-	new_portal->port = port ? port : ISCSI_LISTEN_PORT;
-	new_portal->fd   = -1;
-
-	list_add(&new_portal->iscsi_portal_siblings, &iscsi_portals_list);
-};
-
 void conn_read_pdu(struct iscsi_connection *conn)
 {
 	conn->rx_iostate = IOSTATE_RX_BHS;
@@ -2371,48 +2359,58 @@ int iscsi_transportid(int tid, uint64_t itn_id, char *buf, int size)
 	return len;
 }
 
-static struct tgt_driver iscsi = {
-	.name			= "iscsi",
-	.use_kernel		= 0,
-	.init			= iscsi_init,
-	.exit			= iscsi_exit,
-	.target_create		= iscsi_target_create,
-	.target_destroy		= iscsi_target_destroy,
-
-	.update			= iscsi_target_update,
-	.show			= iscsi_target_show,
-	.cmd_end_notify		= iscsi_scsi_cmd_done,
-	.mgmt_end_notify	= iscsi_tm_done,
-	.transportid		= iscsi_transportid,
-	.default_bst		= "rdwr",
-};
-
-static int iscsi_param_parser(char *p)
+static int iscsi_param_parse_portals(char *p, int do_add,
+			int do_create, int do_delete)
 {
 	while (*p) {
 		if (!strncmp(p, "portal", 6)) {
 			char *addr, *q;
-			int len, port = 0;
+			int len = 0, port = 0;
 
 			addr = p + 7;
 
-			q = strchr(addr, ':');
+			if (addr[0] == '[') {
+				addr++;
+				q = strchr(addr, ']');
+				if (!q) {
+					eprintf("malformed string when parsing "
+						"portal (%s). mismatched ipv6 "
+						"'[' ']'\n", p);
+					return -1;
+				}
+				q++;
+				len = q - addr -1;
+				if (*q != ':')
+					q = NULL;
+			} else
+				q = strchr(addr, ':');
+
 			if (q)
 				port = atoi(q + 1);
 			else
 				q = strchr(addr, ',');
 
-			if (q)
-				len = q - addr;
-			else
-				len = strlen(addr);
+			if (!len) {
+				if (q)
+					len = q - addr;
+				else
+					len = strlen(addr);
+			}
 
 			if (len) {
 				char *tmp;
 				tmp = zalloc(len + 1);
 				memcpy(tmp, addr, len);
-				iscsi_add_portal(tmp, port);
-				free(tmp);
+				if (do_add && iscsi_add_portal(tmp, port, 1,
+							do_create)) {
+					free(tmp);
+					return -1;
+				}
+				if (do_delete && iscsi_delete_portal(tmp,
+							port)) {
+					free(tmp);
+					return -1;
+				}
 			}
 		}
 
@@ -2424,6 +2422,40 @@ static int iscsi_param_parser(char *p)
 	return 0;
 }
 
+static int iscsi_param_parser(char *p)
+{
+	return iscsi_param_parse_portals(p, 1, 0, 0);
+}
+
+static int iscsi_portal_create(char *p)
+{
+	return iscsi_param_parse_portals(p, 1, 1, 0);
+}
+
+static int iscsi_portal_destroy(char *p)
+{
+	return iscsi_param_parse_portals(p, 0, 0, 1);
+}
+
+static struct tgt_driver iscsi = {
+	.name			= "iscsi",
+	.use_kernel		= 0,
+	.init			= iscsi_init,
+	.exit			= iscsi_exit,
+	.target_create		= iscsi_target_create,
+	.target_destroy		= iscsi_target_destroy,
+
+	.portal_create		= iscsi_portal_create,
+	.portal_destroy		= iscsi_portal_destroy,
+
+	.update			= iscsi_target_update,
+	.show			= iscsi_target_show,
+	.cmd_end_notify		= iscsi_scsi_cmd_done,
+	.mgmt_end_notify	= iscsi_tm_done,
+	.transportid		= iscsi_transportid,
+	.default_bst		= "rdwr",
+};
+
 __attribute__((constructor)) static void iscsi_driver_constructor(void)
 {
 	register_driver(&iscsi);
diff --git a/usr/iscsi/iscsid.h b/usr/iscsi/iscsid.h
index 76f6496..0a72261 100644
--- a/usr/iscsi/iscsid.h
+++ b/usr/iscsi/iscsid.h
@@ -270,6 +270,7 @@ struct iscsi_portal {
 	struct list_head iscsi_portal_siblings;
 	char *addr;
 	int port;
+	int tpgt;
 	int fd;
 };
 
@@ -308,7 +309,8 @@ extern int iscsi_tx_handler(struct iscsi_connection *conn);
 extern void iscsi_rx_handler(struct iscsi_connection *conn);
 extern int iscsi_scsi_cmd_execute(struct iscsi_task *task);
 extern int iscsi_transportid(int tid, uint64_t itn_id, char *buf, int size);
-extern void iscsi_add_portal(char *addr, int port);
+extern int iscsi_add_portal(char *addr, int port, int tpgt, int do_create);
+extern int iscsi_delete_portal(char *addr, int port);
 
 /* iscsid.c iscsi_task */
 extern void iscsi_free_task(struct iscsi_task *task);
diff --git a/usr/iscsi/target.c b/usr/iscsi/target.c
index fd3ed92..a125f0e 100644
--- a/usr/iscsi/target.c
+++ b/usr/iscsi/target.c
@@ -609,6 +609,31 @@ static int iscsi_target_show_stats(struct iscsi_target *target, uint64_t sid,
 
 }
 
+static int iscsi_target_show_portals(struct iscsi_target *target, uint64_t sid,
+				   char *buf, int rest)
+{
+	int len = 0, total = 0;
+	struct iscsi_portal *portal;
+
+	list_for_each_entry(portal, &iscsi_portals_list,
+			iscsi_portal_siblings) {
+		int is_ipv6;
+
+		is_ipv6 = strchr(portal->addr, ':') != NULL;
+		len = snprintf(buf, rest,
+			       "Portal: %s%s%s:%d,%d\n",
+			       is_ipv6 ? "[" : "",
+			       portal->addr,
+			       is_ipv6 ? "]" : "",
+			       portal->port ? portal->port : ISCSI_LISTEN_PORT,
+			       portal->tpgt);
+		__buffer_check(buf, total, len, rest);
+	}
+
+	return total;
+
+}
+
 static int show_redirect_info(struct iscsi_target* target, char *buf, int rest)
 {
 	int len, total = 0;
@@ -647,7 +672,7 @@ int iscsi_target_show(int mode, int tid, uint64_t sid, uint32_t cid, uint64_t lu
 	struct iscsi_target* target = NULL;
 	int len, total = 0;
 
-	if (mode != MODE_SYSTEM) {
+	if (mode != MODE_SYSTEM && mode != MODE_PORTAL) {
 	    target = target_find_by_id(tid);
 	    if (!target)
 		    return -TGTADM_NO_TARGET;
@@ -670,6 +695,10 @@ int iscsi_target_show(int mode, int tid, uint64_t sid, uint32_t cid, uint64_t lu
 		len = iscsi_target_show_session(target, sid, buf, rest);
 		total += len;
 		break;
+	case MODE_PORTAL:
+		len = iscsi_target_show_portals(target, sid, buf, rest);
+		total += len;
+		break;
 	case MODE_STATS:
 		len = iscsi_target_show_stats(target, sid, buf, rest);
 		total += len;
diff --git a/usr/mgmt.c b/usr/mgmt.c
index b1c118e..26a93c8 100644
--- a/usr/mgmt.c
+++ b/usr/mgmt.c
@@ -164,6 +164,41 @@ static int target_mgmt(int lld_no, struct mgmt_task *mtask)
 	return err;
 }
 
+static int portal_mgmt(int lld_no, struct mgmt_task *mtask,
+		       struct tgtadm_req *req,
+		       struct tgtadm_rsp *rsp)
+{
+	int err = TGTADM_INVALID_REQUEST;
+
+	switch (req->op) {
+	case OP_SHOW:
+		if (tgt_drivers[lld_no]->show) {
+			err = tgt_drivers[lld_no]->show(req->mode,
+							req->tid, req->sid,
+							req->cid, req->lun,
+							mtask->buf,
+							mtask->bsize);
+
+			set_show_results(rsp, &err);
+			return err;
+		}
+		break;
+	case OP_NEW:
+		err = tgt_portal_create(lld_no, mtask->buf);
+		break;
+	case OP_DELETE:
+		err = tgt_portal_destroy(lld_no, mtask->buf);
+		break;
+	default:
+		break;
+	}
+
+	rsp->err = err;
+	rsp->len = sizeof(*rsp);
+
+	return err;
+}
+
 static int device_mgmt(int lld_no, struct tgtadm_req *req, char *params,
 		       struct tgtadm_rsp *rsp, int *rlen)
 {
@@ -353,6 +388,9 @@ static int tgt_mgmt(struct mgmt_task *mtask)
 	case MODE_TARGET:
 		err = target_mgmt(lld_no, mtask);
 		break;
+	case MODE_PORTAL:
+		err = portal_mgmt(lld_no, mtask, req, rsp);
+		break;
 	case MODE_DEVICE:
 		err = device_mgmt(lld_no, req, mtask->buf, rsp, &len);
 		break;
diff --git a/usr/target.c b/usr/target.c
index b8b8715..32c7fd8 100644
--- a/usr/target.c
+++ b/usr/target.c
@@ -1964,6 +1964,56 @@ int tgt_target_destroy(int lld_no, int tid)
 	return 0;
 }
 
+int tgt_portal_create(int lld, char *args)
+{
+	char *portals = NULL;
+
+	portals = strstr(args, "portal=");
+	if (!portals) {
+		eprintf("invalid option when creating portals: %s\n", args);
+		return TGTADM_INVALID_REQUEST;
+	}
+
+	if (tgt_drivers[lld]->portal_create) {
+		if (tgt_drivers[lld]->portal_create(portals)) {
+			eprintf("failed to create portal %s\n", portals);
+			return TGTADM_INVALID_REQUEST;
+		}
+	} else {
+		eprintf("can not create portals for for this lld type\n");
+		return TGTADM_INVALID_REQUEST;
+	}
+
+	dprintf("succeed to create new portals %s\n", portals);
+
+	return 0;
+}
+
+int tgt_portal_destroy(int lld, char *args)
+{
+	char *portals = NULL;
+
+	portals = strstr(args, "portal=");
+	if (!portals) {
+		eprintf("invalid option when destroying portals: %s\n", args);
+		return TGTADM_INVALID_REQUEST;
+	}
+
+	if (tgt_drivers[lld]->portal_destroy) {
+		if (tgt_drivers[lld]->portal_destroy(portals)) {
+			eprintf("failed to destroy portal %s\n", portals);
+			return TGTADM_INVALID_REQUEST;
+		}
+	} else {
+		eprintf("can not destroy portals for for this lld type\n");
+		return TGTADM_INVALID_REQUEST;
+	}
+
+	dprintf("succeed to destroy portals %s\n", portals);
+
+	return 0;
+}
+
 int account_show(char *buf, int rest)
 {
 	int total = 0, max = rest;
diff --git a/usr/tgtadm.c b/usr/tgtadm.c
index 9821917..7653275 100644
--- a/usr/tgtadm.c
+++ b/usr/tgtadm.c
@@ -373,6 +373,8 @@ static int str_to_mode(char *str)
 		return MODE_TARGET;
 	else if (!strcmp("logicalunit", str) || !strcmp("lu", str))
 		return MODE_DEVICE;
+	else if (!strcmp("portal", str) || !strcmp("pt", str))
+		return MODE_PORTAL;
 	else if (!strcmp("session", str) || !strcmp("sess", str))
 		return MODE_SESSION;
 	else if (!strcmp("connection", str) || !strcmp("conn", str))
@@ -432,7 +434,7 @@ int main(int argc, char **argv)
 	uint32_t cid, hostno;
 	uint64_t sid, lun;
 	char *name, *value, *path, *targetname, *params, *address, *targetOps;
-	char *bstype;
+	char *portalOps, *bstype;
 	char *bsoflags;
 	char *user, *password;
 	char *buf;
@@ -447,7 +449,8 @@ int main(int argc, char **argv)
 	dev_type = TYPE_DISK;
 	ac_dir = ACCOUNT_TYPE_INCOMING;
 	rest = BUFSIZE;
-	name = value = path = targetname = address = targetOps = bstype = NULL;
+	name = value = path = targetname = address = NULL;
+	targetOps = portalOps = bstype = NULL;
 	bsoflags = user = password = NULL;
 
 	buf = valloc(bufsz);
@@ -490,7 +493,10 @@ int main(int argc, char **argv)
 			lun = strtoull(optarg, NULL, 10);
 			break;
 		case 'P':
-			targetOps = optarg;
+			if (mode == MODE_PORTAL)
+				portalOps = optarg;
+			else
+				targetOps = optarg;
 			break;
 		case 'n':
 			name = optarg;
@@ -762,6 +768,50 @@ int main(int argc, char **argv)
 		}
 	}
 
+	if (mode == MODE_PORTAL) {
+		switch (op) {
+		case OP_NEW:
+			rc = verify_mode_params(argc, argv, "LmoCP");
+			if (rc) {
+				eprintf("portal mode: option '-%c' is not "
+					  "allowed/supported\n", rc);
+				exit(EINVAL);
+			}
+			if (!portalOps) {
+				eprintf("you must specify --param "
+					  "portal=<portal>\n");
+				exit(EINVAL);
+			}
+			break;
+		case OP_DELETE:
+			rc = verify_mode_params(argc, argv, "LmoCP");
+			if (rc) {
+				eprintf("portal mode: option '-%c' is not "
+					  "allowed/supported\n", rc);
+				exit(EINVAL);
+			}
+			if (!portalOps) {
+				eprintf("you must specify --param "
+					  "portal=<portal>\n");
+				exit(EINVAL);
+			}
+			break;
+		case OP_SHOW:
+			rc = verify_mode_params(argc, argv, "LmoC");
+			if (rc) {
+				eprintf("option '-%c' not supported in "
+					"portal mode\n", rc);
+				exit(EINVAL);
+			}
+			break;
+		default:
+			eprintf("option %d not supported in "
+					"portal mode\n", op);
+			exit(EINVAL);
+			break;
+		}
+	}
+
 	req->op = op;
 	req->tid = tid;
 	req->sid = sid;
@@ -805,6 +855,9 @@ int main(int argc, char **argv)
 	if (targetOps)
 		shprintf(total, params, rest, "%stargetOps %s,",
 			 rest == BUFSIZE ? "" : ",", targetOps);
+	if (portalOps)
+		shprintf(total, params, rest, "%sportalOps %s,",
+			 rest == BUFSIZE ? "" : ",", portalOps);
 
 	req->len = sizeof(*req) + total;
 
diff --git a/usr/tgtadm.h b/usr/tgtadm.h
index f53baaa..0a92e94 100644
--- a/usr/tgtadm.h
+++ b/usr/tgtadm.h
@@ -21,6 +21,7 @@ enum tgtadm_mode {
 	MODE_SYSTEM,
 	MODE_TARGET,
 	MODE_DEVICE,
+	MODE_PORTAL,
 
 	MODE_SESSION,
 	MODE_CONNECTION,
diff --git a/usr/tgtd.h b/usr/tgtd.h
index 39fa364..3a7e724 100644
--- a/usr/tgtd.h
+++ b/usr/tgtd.h
@@ -247,6 +247,9 @@ int system_show(int mode, char *buf, int rest);
 int is_system_available(void);
 int is_system_inactive(void);
 
+extern int tgt_portal_create(int lld, char *args);
+extern int tgt_portal_destroy(int lld, char *args);
+
 extern int tgt_bind_host_to_target(int tid, int host_no);
 extern int tgt_unbind_host_to_target(int tid, int host_no);
 extern int tgt_bound_target_lookup(int host_no);
-- 
1.7.3.1


[Index of Archives]     [Linux SCSI]     [Linux RAID]     [Linux Clusters]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]

  Powered by Linux