Mercurial > illumos > illumos-gate
changeset 3126:4f4fb617fdd0
PSARC 2006/622 iSCSI/ZFS Integration
6484731 zfs import only mounts and shares the first layer of hierarchy
6493750 zfs and iSCSI do not work togetherly correctly
6494075 destroying a pool shouldn't touch the DSL
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/cmd/iscsi/common/iscsi_door.h Wed Nov 15 19:25:44 2006 -0800 @@ -0,0 +1,159 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _ISCSI_DOOR_H +#define _ISCSI_DOOR_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ISCSI_TARGET_MGMT_DOOR "/var/run/iscsi_tgt_door" +#define ISCSI_DOOR_REQ_SIGNATURE 0x53435349 +#define ISCSI_DOOR_REQ_VERSION_1 1 +#define ISCSI_DOOR_MAX_DATA_SIZE 8192 + + +#define ISCSI_DOOR_GETIPNODEBYNAME_REQ 0x0000 +#define ISCSI_DOOR_GETIPNODEBYNAME_CNF 0x4000 +#define ISCSI_DOOR_ERROR_IND 0x8000 + +#define ISCSI_DOOR_STATUS_SUCCESS 0x00000000 +#define ISCSI_DOOR_STATUS_REQ_LENGTH 0x00000001 +#define ISCSI_DOOR_STATUS_REQ_FORMAT 0x00000002 +#define ISCSI_DOOR_STATUS_REQ_INVALID 0x00000003 +#define ISCSI_DOOR_STATUS_REQ_VERSION 0x00000004 +#define ISCSI_DOOR_STATUS_MORE 0x00000005 + +typedef struct _iscsi_door_msg_hdr { + uint32_t signature; + uint32_t version; + uint32_t opcode; + uint32_t status; +} iscsi_door_msg_hdr_t; + +typedef struct _getipnodebyname_req { + iscsi_door_msg_hdr_t hdr; + uint32_t name_offset; + uint32_t name_length; + uint32_t af; + uint32_t flags; +} getipnodebyname_req_t; + +typedef struct _getipnodebyname_cnf { + iscsi_door_msg_hdr_t hdr; + uint32_t h_size_needed; + uint32_t h_addr_list_offset; + uint32_t h_addr_list_length; + uint32_t h_addrtype; + uint32_t h_addrlen; + uint32_t h_name_offset; + uint32_t h_name_len; + uint32_t h_alias_list_offset; + uint32_t h_alias_list_length; + int32_t error_num; +} getipnodebyname_cnf_t; + +typedef union _iscsi_door_req { + iscsi_door_msg_hdr_t hdr; + getipnodebyname_req_t ginbn_req; +} iscsi_door_req_t; + +typedef union _iscsi_door_cnf { + iscsi_door_msg_hdr_t hdr; + getipnodebyname_cnf_t ginbn_cnf; +} iscsi_door_cnf_t; + +typedef union _iscsi_door_ind { + iscsi_door_msg_hdr_t hdr; + iscsi_door_msg_hdr_t error_ind; +} iscsi_door_ind_t; + +typedef union _iscsi_door_msg { + iscsi_door_msg_hdr_t hdr; + iscsi_door_req_t req; + iscsi_door_cnf_t cnf; + iscsi_door_ind_t ind; +} iscsi_door_msg_t; + +#ifdef _KERNEL + +/* Defines copied from netdb.h */ +#define HOST_NOT_FOUND 1 /* Authoritive Answer Host not found */ +#define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */ +#define NO_RECOVERY 3 /* Non recoverable errors,FORMERR,REFUSED,NOTIMP */ +#define NO_DATA 4 /* Valid name, no data record of requested type */ +#define NO_ADDRESS NO_DATA /* no address, look for MX record */ + +#define AI_V4MAPPED 0x0001 /* IPv4 mapped addresses if no IPv6 */ +#define AI_ALL 0x0002 /* IPv6 and IPv4 mapped addresses */ +#define AI_ADDRCONFIG 0x0004 /* AAAA or A records only if IPv6/IPv4 cnfgd */ + +struct hostent { + char *h_name; /* official name of host */ + char **h_aliases; /* alias list */ + int h_addrtype; /* host address type */ + int h_length; /* length of address */ + char **h_addr_list; /* list of addresses from name server */ +}; + +boolean_t +iscsi_door_ini(void); + +boolean_t +iscsi_door_term(void); + +boolean_t +iscsi_door_bind( + int did +); + +void +kfreehostent( + struct hostent *hptr +); + +struct hostent * +kgetipnodebyname( + const char *name, + int af, + int flags, + int *error_num +); + +#else /* !_KERNEL */ + +#define kfreehostent freehostent +#define kgetipnodebyname getipnodebyname + +#endif /* _KERNEL */ + +#ifdef __cplusplus +} +#endif + +#endif /* _ISCSI_DOOR_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/cmd/iscsi/common/local_types.h Wed Nov 15 19:25:44 2006 -0800 @@ -0,0 +1,66 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _LOCAL_TYPES_H +#define _LOCAL_TYPES_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Block comment which describes the contents of this file. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MIN +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#endif +#ifndef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#endif + +/* + * Solaris typedefs boolean_t to be an enum with B_TRUE and B_FALSE. + * MacOS X typedefs boolean_t to be an int with #defines for TRUE & FALSE + * I like the use of enum's for return codes so that compilers can catch + * sloppy coding practices so I've defined a Boolean_t which is unique here. + */ +typedef enum { + False = 0, + True = 1 +} Boolean_t; + +#ifndef DTYPE_OSD +#define DTYPE_OSD 0x11 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _LOCAL_TYPES_H */
--- a/usr/src/Makefile.lint Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/Makefile.lint Wed Nov 15 19:25:44 2006 -0800 @@ -332,6 +332,7 @@ lib/libipmp \ lib/libipp \ lib/libipsecutil \ + lib/libiscsitgt \ lib/libkmf \ lib/libkstat \ lib/liblaadm \
--- a/usr/src/Targetdirs Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/Targetdirs Wed Nov 15 19:25:44 2006 -0800 @@ -857,6 +857,8 @@ $(ROOT)/usr/lib/libinetutil.so:= REALPATH=../../lib/libinetutil.so.1 $(ROOT)/usr/lib/libintl.so.1:= REALPATH=../../lib/libintl.so.1 $(ROOT)/usr/lib/libintl.so:= REALPATH=../../lib/libintl.so.1 +$(ROOT)/usr/lib/libiscsitgt.so.1:= REALPATH=../../lib/libiscsitgt.so.1 +$(ROOT)/usr/lib/libiscsitgt.so:= REALPATH=../../lib/libiscsitgt.so.1 $(ROOT)/usr/lib/libkstat.so.1:= REALPATH=../../lib/libkstat.so.1 $(ROOT)/usr/lib/libkstat.so:= REALPATH=../../lib/libkstat.so.1 $(ROOT)/usr/lib/liblddbg.so.4:= REALPATH=../../lib/liblddbg.so.4 @@ -1126,6 +1128,10 @@ REALPATH=../../../lib/$(MACH64)/libintl.so.1 $(ROOT)/usr/lib/$(MACH64)/libintl.so:= \ REALPATH=../../../lib/$(MACH64)/libintl.so.1 +$(ROOT)/usr/lib/$(MACH64)/libiscsitgt.so.1:= \ + REALPATH=../../../lib/$(MACH64)/libiscsitgt.so.1 +$(ROOT)/usr/lib/$(MACH64)/libiscsitgt.so:= \ + REALPATH=../../../lib/$(MACH64)/libiscsitgt.so.1 $(ROOT)/usr/lib/$(MACH64)/libkstat.so.1:= \ REALPATH=../../../lib/$(MACH64)/libkstat.so.1 $(ROOT)/usr/lib/$(MACH64)/libkstat.so:= \ @@ -1435,6 +1441,8 @@ /usr/lib/libinetutil.so.1 \ /usr/lib/libintl.so \ /usr/lib/libintl.so.1 \ + /usr/lib/libiscsitgt.so \ + /usr/lib/libiscsitgt.so.1 \ /usr/lib/libkstat.so \ /usr/lib/libkstat.so.1 \ /usr/lib/liblddbg.so.4 \ @@ -1669,6 +1677,8 @@ /usr/lib/$(MACH64)/libinetutil.so.1 \ /usr/lib/$(MACH64)/libintl.so \ /usr/lib/$(MACH64)/libintl.so.1 \ + /usr/lib/$(MACH64)/libiscsitgt.so \ + /usr/lib/$(MACH64)/libiscsitgt.so.1 \ /usr/lib/$(MACH64)/libkstat.so \ /usr/lib/$(MACH64)/libkstat.so.1 \ /usr/lib/$(MACH64)/liblddbg.so.4 \
--- a/usr/src/cmd/dfs.cmds/sharemgr/sharemgr.h Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/dfs.cmds/sharemgr/sharemgr.h Wed Nov 15 19:25:44 2006 -0800 @@ -81,7 +81,7 @@ #define SVC_SET 0x01 /* need value permissions */ #define SVC_ACTION 0x02 /* need action permissions */ -#define ZFS_SHAREALL "/usr/sbin/zfs share -a" +#define ZFS_SHAREALL "/usr/sbin/zfs share -a nfs" /* * functions/values for manipulating options
--- a/usr/src/cmd/iscsi/Makefile.iscsi Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/Makefile.iscsi Wed Nov 15 19:25:44 2006 -0800 @@ -29,6 +29,3 @@ ISCSISRC = $(SRC)/cmd/iscsi ISCSICOMMONDIR = $(ISCSISRC)/common - -COMMON_OBJS = xml.o -COMMON_SRCS = $(COMMON_OBJS:%.o=$(ISCSICOMMONDIR)/%.c)
--- a/usr/src/cmd/iscsi/common/iscsi_door.h Wed Nov 15 19:19:07 2006 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,159 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _ISCSI_DOOR_H -#define _ISCSI_DOOR_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ISCSI_TARGET_MGMT_DOOR "/var/run/iscsi_tgt_door" -#define ISCSI_DOOR_REQ_SIGNATURE 0x53435349 -#define ISCSI_DOOR_REQ_VERSION_1 1 -#define ISCSI_DOOR_MAX_DATA_SIZE 8192 - - -#define ISCSI_DOOR_GETIPNODEBYNAME_REQ 0x0000 -#define ISCSI_DOOR_GETIPNODEBYNAME_CNF 0x4000 -#define ISCSI_DOOR_ERROR_IND 0x8000 - -#define ISCSI_DOOR_STATUS_SUCCESS 0x00000000 -#define ISCSI_DOOR_STATUS_REQ_LENGTH 0x00000001 -#define ISCSI_DOOR_STATUS_REQ_FORMAT 0x00000002 -#define ISCSI_DOOR_STATUS_REQ_INVALID 0x00000003 -#define ISCSI_DOOR_STATUS_REQ_VERSION 0x00000004 -#define ISCSI_DOOR_STATUS_MORE 0x00000005 - -typedef struct _iscsi_door_msg_hdr { - uint32_t signature; - uint32_t version; - uint32_t opcode; - uint32_t status; -} iscsi_door_msg_hdr_t; - -typedef struct _getipnodebyname_req { - iscsi_door_msg_hdr_t hdr; - uint32_t name_offset; - uint32_t name_length; - uint32_t af; - uint32_t flags; -} getipnodebyname_req_t; - -typedef struct _getipnodebyname_cnf { - iscsi_door_msg_hdr_t hdr; - uint32_t h_size_needed; - uint32_t h_addr_list_offset; - uint32_t h_addr_list_length; - uint32_t h_addrtype; - uint32_t h_addrlen; - uint32_t h_name_offset; - uint32_t h_name_len; - uint32_t h_alias_list_offset; - uint32_t h_alias_list_length; - int32_t error_num; -} getipnodebyname_cnf_t; - -typedef union _iscsi_door_req { - iscsi_door_msg_hdr_t hdr; - getipnodebyname_req_t ginbn_req; -} iscsi_door_req_t; - -typedef union _iscsi_door_cnf { - iscsi_door_msg_hdr_t hdr; - getipnodebyname_cnf_t ginbn_cnf; -} iscsi_door_cnf_t; - -typedef union _iscsi_door_ind { - iscsi_door_msg_hdr_t hdr; - iscsi_door_msg_hdr_t error_ind; -} iscsi_door_ind_t; - -typedef union _iscsi_door_msg { - iscsi_door_msg_hdr_t hdr; - iscsi_door_req_t req; - iscsi_door_cnf_t cnf; - iscsi_door_ind_t ind; -} iscsi_door_msg_t; - -#ifdef _KERNEL - -/* Defines copied from netdb.h */ -#define HOST_NOT_FOUND 1 /* Authoritive Answer Host not found */ -#define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */ -#define NO_RECOVERY 3 /* Non recoverable errors,FORMERR,REFUSED,NOTIMP */ -#define NO_DATA 4 /* Valid name, no data record of requested type */ -#define NO_ADDRESS NO_DATA /* no address, look for MX record */ - -#define AI_V4MAPPED 0x0001 /* IPv4 mapped addresses if no IPv6 */ -#define AI_ALL 0x0002 /* IPv6 and IPv4 mapped addresses */ -#define AI_ADDRCONFIG 0x0004 /* AAAA or A records only if IPv6/IPv4 cnfgd */ - -struct hostent { - char *h_name; /* official name of host */ - char **h_aliases; /* alias list */ - int h_addrtype; /* host address type */ - int h_length; /* length of address */ - char **h_addr_list; /* list of addresses from name server */ -}; - -boolean_t -iscsi_door_ini(void); - -boolean_t -iscsi_door_term(void); - -boolean_t -iscsi_door_bind( - int did -); - -void -kfreehostent( - struct hostent *hptr -); - -struct hostent * -kgetipnodebyname( - const char *name, - int af, - int flags, - int *error_num -); - -#else /* !_KERNEL */ - -#define kfreehostent freehostent -#define kgetipnodebyname getipnodebyname - -#endif /* _KERNEL */ - -#ifdef __cplusplus -} -#endif - -#endif /* _ISCSI_DOOR_H */
--- a/usr/src/cmd/iscsi/common/local_types.h Wed Nov 15 19:19:07 2006 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _LOCAL_TYPES_H -#define _LOCAL_TYPES_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Block comment which describes the contents of this file. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef MIN -#define MIN(x, y) ((x) < (y) ? (x) : (y)) -#endif -#ifndef MAX -#define MAX(x, y) ((x) > (y) ? (x) : (y)) -#endif - -/* - * Solaris typedefs boolean_t to be an enum with B_TRUE and B_FALSE. - * MacOS X typedefs boolean_t to be an int with #defines for TRUE & FALSE - * I like the use of enum's for return codes so that compilers can catch - * sloppy coding practices so I've defined a Boolean_t which is unique here. - */ -typedef enum { - False = 0, - True = 1 -} Boolean_t; - -#ifndef DTYPE_OSD -#define DTYPE_OSD 0x11 -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _LOCAL_TYPES_H */
--- a/usr/src/cmd/iscsi/common/xml.c Wed Nov 15 19:19:07 2006 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,968 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <inttypes.h> -#include <assert.h> -#include <libxml/xmlreader.h> -#include <strings.h> -#include <ctype.h> -#include <stdlib.h> -#include <syslog.h> -#include <sys/stat.h> - -#include "xml.h" - -/* - * Forward declarations - */ -static char *strip_space(char *value); -static xml_node_t *node_alloc(); -static void node_free(xml_node_t *x); -static Boolean_t node_name(xml_node_t *x, const xmlChar *n); -static Boolean_t node_value(xml_node_t *x, const xmlChar *n, Boolean_t s); -static xml_node_t *node_parent(xml_node_t *x); -static xml_node_t *node_child(xml_node_t *x); -static xml_node_t *node_alloc_attr(xml_node_t *x); - -#define XML_COMMENT_STR "!--" -#define XML_COMMENT_END "--" - -void -xml_tree_free(xml_node_t *n) -{ - xml_node_t *c, - *c1; - if (n == NULL) - return; - for (c = n->x_child; c; ) { - c1 = c->x_sibling; - xml_tree_free(c); - c = c1; - } - for (c = n->x_attr; c; ) { - c1 = c->x_sibling; - node_free(c); - c = c1; - } - node_free(n); - -} - -void -xml_walk(xml_node_t *n, int depth) -{ - int i; - xml_node_t *c; - - if (n == NULL) - return; - for (i = 0; i < depth; i++) - (void) printf(" "); - if (n->x_name && n->x_value) { - if (strcmp(n->x_name, XML_COMMENT_STR) == 0) { - (void) printf("%s%s%s\n", XML_COMMENT_STR, n->x_value, - XML_COMMENT_END); - } else if (n->x_attr != NULL) { - (void) printf("%s(", n->x_name); - for (c = n->x_attr; c; c = c->x_sibling) - (void) printf("%s='%s'%c", c->x_name, - c->x_value, - (c->x_sibling != NULL) ? ',' : '\0'); - (void) printf(")=%s\n", n->x_value); - } else { - (void) printf("%s=%s\n", n->x_name, n->x_value); - } - } else if (n->x_name) { - if (n->x_attr != NULL) { - (void) printf("%s (", n->x_name); - for (c = n->x_attr; c; c = c->x_sibling) { - if (c != n->x_attr) - (void) printf(" "); - (void) printf("%s='%s'", c->x_name, - c->x_value); - } - (void) printf(")...\n"); - } else - (void) printf("%s...\n", n->x_name); - } - for (c = n->x_child; c; c = c->x_sibling) - xml_walk(c, depth + 1); -} - -void -xml_walk_to_buf(xml_node_t *n, char **buf) -{ - xml_node_t *c; - - if (n == NULL) - return; - if (strcmp(n->x_name, XML_COMMENT_STR) == 0) { - xml_add_comment(buf, n->x_value); - return; - } - buf_add_node_attr(buf, n); - if (n->x_value != NULL) - buf_add_tag(buf, n->x_value, Tag_String); - for (c = n->x_child; c; c = c->x_sibling) - xml_walk_to_buf(c, buf); - buf_add_tag(buf, n->x_name, Tag_End); -} - -/* - * []---- - * | xml_update_config -- dump out in core node tree to XML parsable file - * | - * | The depth argument is only used to pad the output with white space - * | for indentation. This is meant to help the readability of the file - * | for humans. - * []---- - */ -void -xml_update_config(xml_node_t *t, int depth, FILE *output) -{ - int i; - xml_node_t *c; - - if (t == NULL) - return; - - for (i = 0; i < depth; i++) - (void) fprintf(output, " "); - if (strcmp(t->x_name, XML_COMMENT_STR) == 0) { - (void) fprintf(output, "<%s%s%s>\n", XML_COMMENT_STR, - t->x_value, XML_COMMENT_END); - return; - } - if ((t->x_child == NULL) && (t->x_value != NULL) && - (t->x_attr == NULL) && - (((depth * 4) + ((strlen(t->x_name) * 2) + 5) + - strlen(t->x_value)) < 80)) { - - (void) fprintf(output, "<%s>%s</%s>\n", t->x_name, t->x_value, - t->x_name); - - } else { - (void) fprintf(output, "<%s", t->x_name); - for (c = t->x_attr; c; c = c->x_sibling) - (void) fprintf(output, " %s='%s'", c->x_name, - c->x_value); - (void) fprintf(output, ">\n"); - if (t->x_value) { - for (i = 0; i < depth + 1; i++) - (void) fprintf(output, " "); - (void) fprintf(output, "%s\n", t->x_value); - } - for (c = t->x_child; c; c = c->x_sibling) - xml_update_config(c, depth + 1, output); - for (i = 0; i < depth; i++) - (void) fprintf(output, " "); - (void) fprintf(output, "</%s>\n", t->x_name); - } -} - -Boolean_t -xml_dump2file(xml_node_t *root, char *path) -{ - FILE *output; - - if ((output = fopen(path, "wb")) == NULL) { - syslog(LOG_ERR, "Cannot open the file: %s\n", path); - return (False); - } else { - xml_update_config(root, 0, output); - (void) fclose(output); - - /* - * Make sure only root can access the file since we're - * optionally keeping CHAP secrets located here. - */ - (void) chmod(path, 0600); - - return (True); - } -} - -char *common_attr_list[] = { - "name", - "version", - 0 -}; - -Boolean_t -xml_process_node(xmlTextReaderPtr r, xml_node_t **node) -{ - const xmlChar *name, - *value; - char **ap; - xmlElementType node_type; - xml_node_t *n, - *an; - - n = *node; - if (n == NULL) { - n = node_alloc(); - if (n == NULL) - return (False); - *node = n; - } - - name = (xmlChar *)xmlTextReaderConstName(r); - if (name == NULL) { - node_free(n); - return (False); - } - - node_type = (xmlElementType)xmlTextReaderNodeType(r); - - if (xmlTextReaderAttributeCount(r) > 0) { - - for (ap = common_attr_list; *ap; ap++) { - value = xmlTextReaderGetAttribute(r, (xmlChar *)*ap); - if (value != NULL) { - - if ((an = node_alloc_attr(n)) == NULL) - return (False); - if (node_name(an, (xmlChar *)*ap) == False) { - node_free(an); - return (False); - } - if (node_value(an, value, True) == False) { - node_free(an); - return (False); - } - free((char *)value); - } - } - } - value = (xmlChar *)xmlTextReaderConstValue(r); - - if (node_type == XML_ELEMENT_NODE) { - if (n->x_state != NodeAlloc) { - n = node_child(n); - *node = n; - if (n == NULL) - return (False); - } - if (node_name(n, name) == False) { - node_free(n); - return (False); - } - } else if ((value != NULL) && (node_type == XML_TEXT_NODE)) { - if (node_value(n, value, True) == False) { - node_free(n); - return (False); - } - } else if (node_type == XML_ELEMENT_DECL) { - n = node_parent(n); - if (n == NULL) - return (False); - *node = n; - } else if (node_type == XML_COMMENT_NODE) { - n = node_child(n); - if (node_name(n, (xmlChar *)XML_COMMENT_STR) == False) { - node_free(n); - return (False); - } - if (node_value(n, (xmlChar *)value, False) == False) { - node_free(n); - return (False); - } - } else if (node_type != XML_DTD_NODE) { - node_free(n); - return (False); - } - return (True); -} - -Boolean_t -xml_find_attr_str(xml_node_t *n, char *attr, char **value) -{ - xml_node_t *a; - - if ((n == NULL) || (n->x_attr == NULL)) - return (False); - - for (a = n->x_attr; a; a = a->x_sibling) - if (strcmp(a->x_name, attr) == 0) { - *value = a->x_value ? strdup(a->x_value) : NULL; - return (True); - } - return (False); -} - -Boolean_t -xml_find_value_str(xml_node_t *n, char *name, char **value) -{ - xml_node_t *c; - - if ((n == NULL) || (n->x_name == NULL)) - return (False); - - if (strcmp(n->x_name, name) == 0) { - *value = n->x_value ? strdup(n->x_value) : NULL; - return (True); - } - for (c = n->x_child; c; c = c->x_sibling) { - if (xml_find_value_str(c, name, value) == True) - return (True); - } - return (False); -} - -Boolean_t -xml_find_value_int(xml_node_t *n, char *name, int *value) -{ - xml_node_t *c; - - if ((n == NULL) || (n->x_name == NULL)) - return (False); - - if (strcmp(n->x_name, name) == 0) { - if (n->x_value == NULL) - return (False); - *value = strtol(n->x_value, NULL, 0); - return (True); - } - for (c = n->x_child; c; c = c->x_sibling) { - if (xml_find_value_int(c, name, value) == True) - return (True); - } - return (False); -} - -/* - * []---- - * | xml_find_value_intchk -- if node exists, check to see if value is okay - * []---- - */ -Boolean_t -xml_find_value_intchk(xml_node_t *n, char *name, int *value) -{ - char *str, - chk[32]; - Boolean_t rval; - - if (xml_find_value_str(n, name, &str) == True) { - - *value = strtol(str, NULL, 0); - /* - * Validate that the input string hasn't overrun what - * what an integer can handle. This is done by simply - * printing out the result of the conversion into a buffer - * and comparing it to the incoming string. That way when - * someone enters 4294967296 which strtol returns as 0 - * we'll catch it. - */ - if ((str[0] == '0') && (str[1] != '\0')) { - if (str[1] == 'x') - snprintf(chk, sizeof (chk), "0x%x", *value); - else if (str[1] == 'X') - snprintf(chk, sizeof (chk), "0X%x", *value); - else - snprintf(chk, sizeof (chk), "0%o", *value); - } else - snprintf(chk, sizeof (chk), "%d", *value); - if (strcmp(chk, str) == 0) - rval = True; - else - rval = False; - free(str); - return (rval); - } else - return (True); -} - -Boolean_t -xml_find_value_boolean(xml_node_t *n, char *name, Boolean_t *value) -{ - xml_node_t *c; - - if ((n == NULL) || (n->x_name == NULL)) - return (False); - - if (strcmp(n->x_name, name) == 0) { - if (n->x_value == NULL) - return (False); - *value = strcmp(n->x_value, "true") == 0 ? True : False; - return (True); - } - for (c = n->x_child; c; c = c->x_sibling) { - if (xml_find_value_boolean(c, name, value) == True) - return (True); - } - return (False); -} - -xml_node_t * -xml_node_next(xml_node_t *n, char *name, xml_node_t *cur) -{ - xml_node_t *x, - *p; - - if (n == NULL) - return (NULL); - - if (cur != NULL) { - for (x = cur->x_sibling; x; x = x->x_sibling) - if (strcmp(x->x_name, name) == 0) - return (x); - return (NULL); - } - - if (n->x_name == NULL) - return (NULL); - - if (strcmp(n->x_name, name) == 0) - return (n); - for (x = n->x_child; x; x = x->x_sibling) - if ((p = xml_node_next(x, name, 0)) != NULL) - return (p); - return (NULL); -} - -xml_node_t * -xml_node_next_child(xml_node_t *n, char *name, xml_node_t *cur) -{ - if (cur != NULL) { - n = cur->x_sibling; - } else { - if (n != NULL) - n = n->x_child; - else - return (NULL); - } - while (n) { - if (strcmp(n->x_name, name) == 0) - return (n); - n = n->x_sibling; - } - return (NULL); -} - -Boolean_t -xml_add_child(xml_node_t *p, xml_node_t *c) -{ - xml_node_t *s; - if ((p == NULL) || (c == NULL)) - return (False); - - if (p->x_child == NULL) - p->x_child = c; - else { - for (s = p->x_child; s->x_sibling; s = s->x_sibling) - ; - s->x_sibling = c; - } - return (True); -} - -xml_node_t * -xml_alloc_node(char *name, xml_val_type_t type, void *value) -{ - xml_node_t *d = node_alloc(); - int value_len; - char *value_str; - - if (d == NULL) - return (NULL); - switch (type) { - case String: - value_len = strlen((char *)value) + 1; - break; - case Int: - value_len = sizeof (int) * 2 + 3; - break; - case Uint64: - value_len = sizeof (uint64_t) * 2 + 3; - break; - } - if ((value_str = (char *)calloc(sizeof (char), value_len)) == NULL) - return (NULL); - if (node_name(d, (xmlChar *)name) == False) { - free(value_str); - return (NULL); - } - switch (type) { - case String: - (void) snprintf(value_str, value_len, "%s", (char *)value); - break; - case Int: - (void) snprintf(value_str, value_len, "0x%x", *(int *)value); - break; - case Uint64: - (void) snprintf(value_str, value_len, "0x%llx", - *(uint64_t *)value); - break; - } - (void) node_value(d, (xmlChar *)value_str, True); - - return (d); -} - -Boolean_t -xml_encode_bytes(uint8_t *ip, size_t ip_size, char **buf, size_t *buf_size) -{ - char *bp; - *buf_size = (ip_size * 2) + 1; - - if ((*buf = (char *)malloc(*buf_size)) == NULL) { - *buf_size = 0; - return (False); - } - - for (bp = *buf; ip_size; ip_size--) { - (void) sprintf(bp, "%.2x", *ip); - ip++; - bp += 2; - } - - return (True); -} - -Boolean_t -xml_decode_bytes(char *buf, uint8_t **ip, size_t *ip_size) -{ - uint8_t *i; - size_t buf_size = strlen(buf); - *ip_size = buf_size / 2; - - if ((*ip = (uint8_t *)malloc(*ip_size)) == NULL) { - *ip_size = 0; - return (False); - } - - for (i = *ip; buf_size; buf_size -= 2) { - char x[3]; - bcopy(buf, x, 2); - x[2] = 0; - *i++ = strtol(x, NULL, 16); - buf += 2; - } - return (True); -} - -void -xml_free_node(xml_node_t *node) -{ - node_free(node); -} - -Boolean_t -xml_remove_child(xml_node_t *parent, xml_node_t *child, match_type_t m) -{ - xml_node_t *s, - *c = NULL; - - if ((parent == NULL) || (child == NULL)) - return (False); - - for (s = parent->x_child; s; c = s, s = s->x_sibling) { - - /* - * See if the new child node matches one of the children - * in the parent. - */ - if ((strcmp(s->x_name, child->x_name) == 0) && - ((m == MatchName) || (strcmp(s->x_value, - child->x_value) == 0))) { - - if (parent->x_child == s) { - parent->x_child = s->x_sibling; - } else { - c->x_sibling = s->x_sibling; - } - xml_tree_free(s); - break; - } - } - if (s == NULL) - return (False); - else - return (True); -} - -void -xml_replace_child(xml_node_t *parent, xml_node_t *child, match_type_t m) -{ - xml_node_t *s, - *c; - - if ((parent == NULL) || (child == NULL)) - return; - - for (s = parent->x_child; s; s = s->x_sibling) { - - /* - * See if the new child node matches one of the children - * in the parent. - */ - if ((strcmp(s->x_name, child->x_name) == 0) && - ((m == MatchName) || (strcmp(s->x_value, - child->x_value) == 0))) { - - /* - * We have a match. Now save the values of the new - * child in this current node. - */ - free(s->x_name); - free(s->x_value); - s->x_name = strdup(child->x_name); - s->x_value = strdup(child->x_value); - if (s->x_child) { - xml_tree_free(s->x_child); - s->x_child = NULL; - } - for (c = child->x_child; c; c = c->x_sibling) - (void) xml_add_child(s, xml_node_dup(c)); - break; - } - } - - if (s == NULL) { - /* - * Never found the child so add it - */ - (void) xml_add_child(parent, xml_node_dup(child)); - } -} - -#ifdef notused -/* - * Update node value when value type is usigned long long - */ -Boolean_t -xml_update_value_ull(xml_node_t *node, char *name, uint64_t value) -{ - if (node == NULL || strcmp(name, node->x_name)) - return (False); - - if (strtoll(node->x_value, NULL, 0) == value) - return (True); - (void) snprintf(node->x_value, 64, "0x%llx", value); - return (True); -} -#endif - -Boolean_t -xml_update_value_str(xml_node_t *node, char *name, char *str) -{ - if ((node == NULL) || (strcmp(name, node->x_name) != 0)) - return (False); - if (node->x_value != NULL) - free(node->x_value); - node->x_value = strdup(str); - node->x_state = NodeValue; - return (True); -} - -xml_node_t * -xml_find_child(xml_node_t *n, char *name) -{ - xml_node_t *rval; - - for (rval = n->x_child; rval; rval = rval->x_sibling) - if (strcmp(rval->x_name, name) == 0) - break; - return (rval); -} - -xml_node_t * -xml_node_dup(xml_node_t *n) -{ - xml_node_t *d = node_alloc(), - *c; - - if (d == NULL) - return (NULL); - if (node_name(d, (xmlChar *)n->x_name) == False) - return (NULL); - if (node_value(d, (xmlChar *)n->x_value, True) == False) - return (NULL); - for (c = n->x_child; c; c = c->x_sibling) - (void) xml_add_child(d, xml_node_dup(c)); - return (d); -} - -/* - * []---- - * | Utility functions - * []---- - */ -static xml_node_t * -node_alloc() -{ - xml_node_t *x = (xml_node_t *)calloc(sizeof (xml_node_t), 1); - - if (x == NULL) - return (NULL); - - x->x_state = NodeAlloc; - return (x); -} - -static void -node_free(xml_node_t *x) -{ - x->x_state = NodeFree; - if (x->x_name) - free(x->x_name); - if (x->x_value) - free(x->x_value); - free(x); -} - -static Boolean_t -node_name(xml_node_t *x, const xmlChar *n) -{ - assert(x->x_state == NodeAlloc); - if ((n == NULL) || (strlen((char *)n) == 0)) - return (False); - - x->x_state = NodeName; - x->x_name = strip_space((char *)n); - return (True); -} - -static Boolean_t -node_value(xml_node_t *x, const xmlChar *n, Boolean_t do_strip) -{ - assert(x->x_state == NodeName); - if ((n == NULL) || (strlen((char *)n) == NULL)) - return (False); - - x->x_state = NodeValue; - x->x_value = (do_strip == True) ? - strip_space((char *)n) : strdup((char *)n); - return (True); -} - -static xml_node_t * -node_parent(xml_node_t *x) -{ - return (x->x_parent); -} - -static xml_node_t * -node_child(xml_node_t *x) -{ - xml_node_t *n, - *next; - - n = node_alloc(); - if (x->x_child == NULL) { - x->x_child = n; - } else { - for (next = x->x_child; next->x_sibling; next = next->x_sibling) - ; - next->x_sibling = n; - } - if (n != NULL) - n->x_parent = x; - return (n); -} - -static xml_node_t * -node_alloc_attr(xml_node_t *x) -{ - xml_node_t *n, - *next; - - n = node_alloc(); - if (x->x_attr == NULL) { - x->x_attr = n; - } else { - for (next = x->x_attr; next->x_sibling; next = next->x_sibling) - ; - next->x_sibling = n; - } - if (n != NULL) - n->x_parent = x; - return (n); -} - -void -buf_add_str(char **b, char *str) -{ - int len, - olen = 0; - char *p = *b; - - /* - * Make sure we have enough room for the string and tag characters - * plus a NULL byte. - */ - if (str == NULL) - return; - - len = strlen(str) + 1; - if (p == NULL) { - p = malloc(len); - } else { - olen = strlen(p); - p = realloc(p, olen + len); - } - (void) strcpy(p + olen, str); - *b = p; -} - -/* - * []---- - * | buf_add_tag -- adds string to buffer allocating space, sets up tags too - * | - * | Helper function to build a string by allocating memory as we go. - * | If the string argument 'str' is defined to be a start or end tag - * | as declared by 'type' argument add the appropriate characters. - * []---- - */ -void -buf_add_tag(char **b, char *str, val_type_t type) -{ - char *buf; - int len; - - /* - * We will add potentially up to 3 extra characters plus the NULL byte - */ - len = strlen(str) + 4; - if ((buf = malloc(len)) == NULL) - return; - - (void) snprintf(buf, len, "%s%s%s%s", type == Tag_String ? "" : "<", - type == Tag_End ? "/" : "", str, type == Tag_String ? "" : ">"); - buf_add_str(b, buf); - free(buf); -} - -/* - * []---- - * | buf_add_tag_and_attr -- variant on buf_add_tag which also gives attr - * []---- - */ -void -buf_add_tag_and_attr(char **b, char *str, char *attr) -{ - char *buf; - int len; - - /* - * In addition to the 'str' and 'attr' strings the code will add - * three characters plus a null byte. - */ - len = strlen(str) + strlen(attr) + 4; - if ((buf = malloc(len)) == NULL) - return; - - (void) snprintf(buf, len, "<%s %s>", str, attr); - buf_add_str(b, buf); - free(buf); -} - -void -buf_add_node_attr(char **b, xml_node_t *x) -{ - char *buf; - xml_node_t *n; - int len; - - /* ---- null byte and starting '<' character ---- */ - len = strlen(x->x_name) + 2; - if ((buf = malloc(len)) == NULL) - return; - (void) snprintf(buf, len, "<%s", x->x_name); - buf_add_str(b, buf); - free(buf); - - for (n = x->x_attr; n; n = n->x_sibling) { - len = strlen(n->x_name) + strlen(n->x_value) + 5; - if ((buf = malloc(len)) == NULL) - return; - (void) snprintf(buf, len, " %s='%s'", n->x_name, n->x_value); - buf_add_str(b, buf); - free(buf); - } - buf_add_str(b, ">"); -} - -void -xml_add_comment(char **b, char *comment) -{ - char *p = *b; - int len, - olen; - - if (comment == NULL) - return; - - /* - * Room for the strings, plus the brackets and NULL byte - */ - len = strlen(comment) + strlen(XML_COMMENT_STR) + - strlen(XML_COMMENT_END) + 3; - - if (p == NULL) - p = malloc(len); - else { - olen = strlen(p); - p = realloc(p, olen + len); - } - (void) snprintf(p + olen, len, "<%s%s%s>", XML_COMMENT_STR, comment, - XML_COMMENT_END); - *b = p; -} - -void -xml_add_tag(char **b, char *element, char *cdata) -{ - buf_add_tag(b, element, Tag_Start); - if (cdata != NULL) - buf_add_tag(b, cdata, Tag_String); - buf_add_tag(b, element, Tag_End); -} - -static char * -strip_space(char *value) -{ - char *p, - *n; - - for (p = value; p && *p; p++) - if (!isspace(*p)) - break; - if ((p == NULL) || (*p == '\0')) - return (NULL); - - p = strdup(p); - for (n = (p + strlen(p) - 1); n >= p; n--) - if (!isspace(*n)) { - n++; - break; - } - *n = '\0'; - return (p); -}
--- a/usr/src/cmd/iscsi/common/xml.h Wed Nov 15 19:19:07 2006 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,179 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _TARGET_XML_H -#define _TARGET_XML_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Block comment which describes the contents of this file. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include <libxml/xmlreader.h> - -#include "local_types.h" - -/* - * XML element defines. - */ -#define XML_ELEMENT_ERROR "error" -#define XML_ELEMENT_CODE "code" -#define XML_ELEMENT_MESSAGE "message" -#define XML_ELEMENT_TRANSVERS "transport-version" -#define XML_ELEMENT_PROPS "props" -#define XML_ELEMENT_DATAOUT "data-out-size" -#define XML_ELEMENT_BASEDIR "base-directory" -#define XML_ELEMENT_CHAPSECRET "chap-secret" -#define XML_ELEMENT_CHAPNAME "chap-name" -#define XML_ELEMENT_RAD_ACCESS "radius-access" -#define XML_ELEMENT_RAD_SERV "radius-server" -#define XML_ELEMENT_RAD_SECRET "radius-secret" -#define XML_ELEMENT_ISNS_ACCESS "isns-access" -#define XML_ELEMENT_FAST "fast-write-ack" -#define XML_ELEMENT_NAME "name" -#define XML_ELEMENT_ACL "acl" -#define XML_ELEMENT_ACLLIST "acl-list" -#define XML_ELEMENT_TPGT "tpgt" -#define XML_ELEMENT_TPGTLIST "tpgt-list" -#define XML_ELEMENT_SIZE "size" -#define XML_ELEMENT_LUN "lun" -#define XML_ELEMENT_LUNLIST "lun-list" -#define XML_ELEMENT_TYPE "type" -#define XML_ELEMENT_ALIAS "alias" -#define XML_ELEMENT_BACK "backing-store" -#define XML_ELEMENT_DELETE_BACK "delete-backing-store" -#define XML_ELEMENT_TARG "target" -#define XML_ELEMENT_INIT "initiator" -#define XML_ELEMENT_ADMIN "admin" -#define XML_ELEMENT_INAME "iscsi-name" -#define XML_ELEMENT_MAXRECV "maxrecv" -#define XML_ELEMENT_IPADDR "ip-address" -#define XML_ELEMENT_ALL "all" -#define XML_ELEMENT_VERBOSE "verbose" -#define XML_ELEMENT_LIST "list" -#define XML_ELEMENT_RESULT "result" -#define XML_ELEMENT_TIMECON "time-connected" -#define XML_ELEMENT_READCMDS "read-commands" -#define XML_ELEMENT_WRITECMDS "write-commands" -#define XML_ELEMENT_READBLKS "read-blks" -#define XML_ELEMENT_WRITEBLKS "write-blks" -#define XML_ELEMENT_STATS "statistics" -#define XML_ELEMENT_CONN "connection" -#define XML_ELEMENT_LUNINFO "lun-information" -#define XML_ELEMENT_VID "vid" -#define XML_ELEMENT_PID "pid" -#define XML_ELEMENT_GUID "guid" -#define XML_ELEMENT_DTYPE "dtype" -#define XML_ELEMENT_IOSTAT "iostat" -#define XML_ELEMENT_MACADDR "mac-addr" -#define XML_ELEMENT_MGMTPORT "mgmt-port" -#define XML_ELEMENT_ISCSIPORT "iscsi-port" -#define XML_ELEMENT_TARGLOG "target-log" -#define XML_ELEMENT_DBGLVL "dbg-lvl" -#define XML_ELEMENT_LOGLVL "qlog-lvl" -#define XML_ELEMENT_DBGDAEMON "daemonize" -#define XML_ELEMENT_ENFORCE "enforce-strict-guid" -#define XML_ELEMENT_VERS "version" -#define XML_ELEMENT_MMAP_LUN "mmap-lun" -#define XML_ELEMENT_RPM "rpm" -#define XML_ELEMENT_HEADS "heads" -#define XML_ELEMENT_CYLINDERS "cylinders" -#define XML_ELEMENT_SPT "spt" -#define XML_ELEMENT_BPS "bps" -#define XML_ELEMENT_INTERLEAVE "interleave" -#define XML_ELEMENT_PARAMS "params" -#define XML_ELEMENT_MAXCMDS "max-outstanding-cmds" -#define XML_ELEMENT_THIN_PROVO "thin-provisioning" -#define XML_ELEMENT_DISABLE_TPGS "disable-tpgs" -#define XML_ELEMENT_STATUS "status" -#define XML_ELEMENT_PROGRESS "progress" -#define XML_ELEMENT_TIMESTAMPS "time-stamps" - -typedef enum { - NodeFree, - NodeAlloc, - NodeName, - NodeValue -} xml_node_state; - -typedef enum { MatchName, MatchBoth } match_type_t; - -typedef struct xml_node { - struct xml_node *x_parent, - *x_child, - *x_sibling, - *x_attr; - char *x_name, - *x_value; - xml_node_state x_state; -} xml_node_t; - -typedef enum val_type { Tag_String, Tag_Start, Tag_End } val_type_t; -typedef enum xml_val_type { String, Int, Uint64 } xml_val_type_t; - -void xml_tree_free(xml_node_t *x); -void xml_walk(xml_node_t *x, int depth); -void xml_walk_to_buf(xml_node_t *n, char **buf); -void xml_update_config(xml_node_t *t, int depth, FILE *output); -void buf_add_str(char **b, char *str); -void buf_add_tag(char **b, char *str, val_type_t type); -void buf_add_tag_and_attr(char **b, char *str, char *attr); -void buf_add_node_attr(char **b, xml_node_t *x); -void xml_add_tag(char **b, char *element, char *cdata); -void xml_add_comment(char **b, char *comment); -void xml_replace_child(xml_node_t *parent, xml_node_t *child, match_type_t m); -Boolean_t xml_remove_child(xml_node_t *parent, xml_node_t *child, - match_type_t m); -Boolean_t xml_encode_bytes(uint8_t *ip, size_t ip_size, char **buf, - size_t *buf_size); -Boolean_t xml_decode_bytes(char *buf, uint8_t **ip, size_t *ip_size); -Boolean_t xml_find_value_str(xml_node_t *n, char *name, char **value); -Boolean_t xml_find_value_int(xml_node_t *n, char *name, int *value); -Boolean_t xml_find_value_intchk(xml_node_t *n, char *name, int *value); -Boolean_t xml_update_value_ull(xml_node_t *root, char *name, uint64_t value); -Boolean_t xml_dump2file(xml_node_t *root, char *path); -Boolean_t xml_find_value_boolean(xml_node_t *n, char *name, Boolean_t *value); -Boolean_t xml_find_attr_str(xml_node_t *n, char *attr, char **value); -Boolean_t xml_process_node(xmlTextReaderPtr r, xml_node_t **node); -Boolean_t xml_add_child(xml_node_t *p, xml_node_t *c); -xml_node_t *xml_alloc_node(char *name, xml_val_type_t type, void *value); -void xml_free_node(xml_node_t *node); -xml_node_t *xml_node_next(xml_node_t *n, char *name, xml_node_t *cur); -xml_node_t *xml_node_next_child(xml_node_t *n, char *name, xml_node_t *cur); -xml_node_t *xml_node_dup(xml_node_t *n); -xml_node_t *xml_find_child(xml_node_t *n, char *name); -Boolean_t xml_update_value_str(xml_node_t *node, char *name, char *str); - -#ifdef __cplusplus -} -#endif - -#endif /* _TARGET_XML_H */
--- a/usr/src/cmd/iscsi/iscsitadm/Makefile Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitadm/Makefile Wed Nov 15 19:25:44 2006 -0800 @@ -27,13 +27,13 @@ PROG = iscsitadm OBJS = main.o helper.o cmdparse.o -SRCS =$(OBJS:%.o=%.c) $(COMMON_SRCS) +SRCS =$(OBJS:%.o=%.c) POFILES= $(OBJS:%.o=%.po) include $(SRC)/cmd/Makefile.cmd include $(SRC)/cmd/iscsi/Makefile.iscsi -LDLIBS += -lxml2 -lsocket -lnsl -ldoor -lscf +LDLIBS += -liscsitgt -lxml2 CFLAGS += $(CCVERBOSE) -I${ISCSICOMMONDIR} FILEMODE= 0555 GROUP= bin
--- a/usr/src/cmd/iscsi/iscsitadm/helper.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitadm/helper.c Wed Nov 15 19:25:44 2006 -0800 @@ -44,7 +44,6 @@ #include <netinet/in.h> #include <sys/iscsi_protocol.h> #include <door.h> -#include <iscsi_door.h> #include <sys/scsi/generic/inquiry.h> #include <sys/mman.h> #include <sys/filio.h> @@ -52,64 +51,15 @@ #include <libscf.h> #include <fcntl.h> -#include "local_types.h" +#include <iscsitgt_impl.h> #include "cmdparse.h" #include "utility.h" -#include "xml.h" #include "helper.h" extern char *cmdName; -#define WAIT_FOR_SERVICE 15 -#define WAIT_FOR_DOOR 15 -static char *service = "system/iscsitgt:default"; static stat_delta_t *stat_head; -static Boolean_t -is_online() -{ - char *s; - Boolean_t rval = False; - - if ((s = smf_get_state(service)) != NULL) { - if (strcmp(s, SCF_STATE_STRING_ONLINE) == 0) - rval = True; - free(s); - } - - return (rval); -} - -Boolean_t -check_and_online() -{ - int i, - fd; - - if (is_online() == False) { - if (smf_enable_instance(service, 0) != 0) { - return (False); - } - for (i = 0; i < WAIT_FOR_SERVICE; i++) { - if (is_online() == True) - break; - (void) sleep(1); - } - if (i == WAIT_FOR_SERVICE) { - return (False); - } - } - - for (i = 0; i < WAIT_FOR_DOOR; i++) { - if ((fd = open(ISCSI_TARGET_MGMT_DOOR, 0)) >= 0) { - (void) close(fd); - return (True); - } - (void) sleep(1); - } - return (False); -} - /* * []---- * | buffer_xml -- buffer incoming XML response until complete @@ -120,9 +70,9 @@ * []---- */ Boolean_t -buffer_xml(char *s, char **storage, xml_node_t **np) +buffer_xml(char *s, char **storage, tgt_node_t **np) { - xml_node_t *node = NULL; + tgt_node_t *node = NULL; xmlTextReaderPtr r; char *p, *e, @@ -201,7 +151,7 @@ return (False); while (xmlTextReaderRead(r) == 1) { - if (xml_process_node(r, &node) == False) + if (tgt_node_process(r, &node) == False) break; } @@ -220,118 +170,6 @@ return (True); } -xml_node_t * -send_data(char *hostname, char *first_str) -{ - struct sockaddr_in sin; - struct hostent *hp; - int s, - min, - nmsgs, - nbytes, - error_num, - port = 3269; - struct pollfd fds[1]; - nfds_t nfds = 1; - char input[128], - *storage = NULL; - xml_node_t *node = NULL; - - if (hostname != NULL) { - if ((hp = getipnodebyname(hostname, AF_INET, - AI_ALL | AI_ADDRCONFIG | AI_V4MAPPED, - &error_num)) == NULL) { - (void) printf("Can't find IP addr for %s\n", hostname); - exit(1); - } - - bzero(&sin, sizeof (sin)); - sin.sin_family = hp->h_addrtype; - sin.sin_port = ntohs(port); - bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length); - - if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { - (void) printf("Failed to open socket\n"); - exit(1); - } - - if (connect(s, (struct sockaddr *)&sin, sizeof (sin)) < 0) { - (void) printf("Failed to connect\n"); - exit(1); - } - - fds[0].fd = s; - fds[0].events = POLLIN; - fds[0].revents = 0; - - if (write(s, first_str, strlen(first_str)) != - strlen(first_str)) { - perror("Failed to send request"); - exit(1); - } - while (poll(fds, nfds, -1) != -1) { - if ((nmsgs = ioctl(s, FIONREAD, &nbytes)) < 0) - exit(1); - if ((nmsgs == 0) && (nbytes == 0)) - exit(1); - min = MIN(nbytes, sizeof (input) - 1); - if (read(s, input, min) != min) - exit(1); - input[min] = '\0'; - - if (buffer_xml(input, &storage, &node) == True) { - break; - } - } - } else { - door_arg_t d; - xmlTextReaderPtr r; - - d.data_ptr = first_str; - d.data_size = strlen(first_str) + 1; - d.desc_ptr = NULL; - d.desc_num = 0; - d.rbuf = NULL; - d.rsize = 0; - - if (((s = open(ISCSI_TARGET_MGMT_DOOR, 0)) < 0) || - (door_call(s, &d) < 0)) { - if (s != -1) - (void) close(s); - - if (check_and_online() == False) { - (void) fprintf(stderr, - "iscsitadm: SMF service unavailable\n"); - exit(1); - } - - if ((s = open(ISCSI_TARGET_MGMT_DOOR, 0)) < 0) { - (void) fprintf(stderr, - "iscsitadm: Failed to open iSCSI target" - " management door\n"); - exit(1); - } - if (door_call(s, &d) < 0) { - perror("door_call"); - exit(1); - } - } - - if ((r = (xmlTextReaderPtr)xmlReaderForMemory(d.rbuf, - strlen(d.rbuf), NULL, NULL, 0)) == NULL) { - perror("xmlReaderForMemory"); - exit(1); - } - while (xmlTextReaderRead(r) == 1) - if (xml_process_node(r, &node) == False) - break; - xmlFreeTextReader(r); - (void) munmap(d.rbuf, d.rsize); - } - (void) close(s); - return (node); -} - /* * Retrieve CHAP secret from input */ @@ -573,34 +411,34 @@ } void -stats_load_counts(xml_node_t *n, stat_delta_t *d) +stats_load_counts(tgt_node_t *n, stat_delta_t *d) { - xml_node_t *conn = NULL, + tgt_node_t *conn = NULL, *lun; char *val; bzero(d, sizeof (*d)); d->device = n->x_value; - while (conn = xml_node_next(n, XML_ELEMENT_CONN, conn)) { + while (conn = tgt_node_next(n, XML_ELEMENT_CONN, conn)) { lun = NULL; - while (lun = xml_node_next(conn, XML_ELEMENT_LUN, lun)) { - if (xml_find_value_str(lun, XML_ELEMENT_READCMDS, + while (lun = tgt_node_next(conn, XML_ELEMENT_LUN, lun)) { + if (tgt_find_value_str(lun, XML_ELEMENT_READCMDS, &val) == True) { d->read_cmds += strtoll(val, NULL, 0); free(val); } - if (xml_find_value_str(lun, XML_ELEMENT_WRITECMDS, + if (tgt_find_value_str(lun, XML_ELEMENT_WRITECMDS, &val) == True) { d->write_cmds += strtoll(val, NULL, 0); free(val); } - if (xml_find_value_str(lun, XML_ELEMENT_READBLKS, + if (tgt_find_value_str(lun, XML_ELEMENT_READBLKS, &val) == True) { d->read_blks += strtoll(val, NULL, 0); free(val); } - if (xml_find_value_str(lun, XML_ELEMENT_WRITEBLKS, + if (tgt_find_value_str(lun, XML_ELEMENT_WRITEBLKS, &val) == True) { d->write_blks += strtoll(val, NULL, 0); free(val);
--- a/usr/src/cmd/iscsi/iscsitadm/helper.h Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitadm/helper.h Wed Nov 15 19:25:44 2006 -0800 @@ -69,7 +69,7 @@ /* helper functions */ int getSecret(char *, int *, int, int); -xml_node_t *send_data(char *hostname, char *first_str); +tgt_node_t *send_data(char *hostname, char *first_str); int parseAddress(char *address_port_str, uint16_t defaultPort, char *address_str, size_t address_str_len, uint16_t *port, boolean_t *isIpv6); @@ -78,7 +78,7 @@ unsigned long long number, int unit_from, int scale); -void stats_load_counts(xml_node_t *n, stat_delta_t *d); +void stats_load_counts(tgt_node_t *n, stat_delta_t *d); stat_delta_t *stats_prev_counts(stat_delta_t *cp); void stats_update_counts(stat_delta_t *p, stat_delta_t *c); void stats_free();
--- a/usr/src/cmd/iscsi/iscsitadm/main.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitadm/main.c Wed Nov 15 19:25:44 2006 -0800 @@ -39,8 +39,8 @@ #include <sys/stat.h> #include <zone.h> +#include <iscsitgt_impl.h> #include "cmdparse.h" -#include "xml.h" #include "helper.h" #define CREATE SUBCOMMAND(0) @@ -100,7 +100,6 @@ /* globals */ char *cmdName; -static char *hostname = NULL; /* * Add new options here @@ -358,15 +357,15 @@ } static int -formatErrString(xml_node_t *node) +formatErrString(tgt_node_t *node) { int code = 0, rtn = 0; char *msg = NULL; if ((strcmp(node->x_name, XML_ELEMENT_ERROR) == 0) && - (xml_find_value_int(node, XML_ELEMENT_CODE, &code) == B_TRUE) && - (xml_find_value_str(node, XML_ELEMENT_MESSAGE, &msg) == B_TRUE)) { + (tgt_find_value_int(node, XML_ELEMENT_CODE, &code) == B_TRUE) && + (tgt_find_value_str(node, XML_ELEMENT_MESSAGE, &msg) == B_TRUE)) { /* * 1000 is the success code, so we don't need to display @@ -392,15 +391,15 @@ createTarget(int operandLen, char *operand[], cmdOptions_t *options) { char *first_str = NULL; - xml_node_t *node; + tgt_node_t *node; cmdOptions_t *optionList = options; if (operand == NULL) return (1); - buf_add_tag(&first_str, "create", Tag_Start); - buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start); - xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]); + tgt_buf_add_tag(&first_str, "create", Tag_Start); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start); + tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); for (; optionList->optval; optionList++) { switch (optionList->optval) { @@ -415,25 +414,25 @@ free(first_str); return (1); } else { - xml_add_tag(&first_str, + tgt_buf_add(&first_str, XML_ELEMENT_TYPE, optionList->optarg); } break; case 'z': /* size */ - xml_add_tag(&first_str, XML_ELEMENT_SIZE, + tgt_buf_add(&first_str, XML_ELEMENT_SIZE, optionList->optarg); break; case 'u': /* lun number */ - xml_add_tag(&first_str, XML_ELEMENT_LUN, + tgt_buf_add(&first_str, XML_ELEMENT_LUN, optionList->optarg); break; case 'a': /* alias */ - xml_add_tag(&first_str, XML_ELEMENT_ALIAS, + tgt_buf_add(&first_str, XML_ELEMENT_ALIAS, optionList->optarg); break; case 'b': /* backing store */ - xml_add_tag(&first_str, XML_ELEMENT_BACK, + tgt_buf_add(&first_str, XML_ELEMENT_BACK, optionList->optarg); break; default: @@ -445,10 +444,10 @@ } } - buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End); - buf_add_tag(&first_str, "create", Tag_End); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End); + tgt_buf_add_tag(&first_str, "create", Tag_End); - node = send_data(hostname, first_str); + node = tgt_door_call(first_str, 0); free(first_str); return (formatErrString(node)); } @@ -458,7 +457,7 @@ createInitiator(int operandLen, char *operand[], cmdOptions_t *options) { char *first_str = NULL; - xml_node_t *node; + tgt_node_t *node; cmdOptions_t *optionList = options; if (operand == NULL) @@ -466,13 +465,13 @@ if (options == NULL) return (1); - buf_add_tag(&first_str, "create", Tag_Start); - buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start); - xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]); + tgt_buf_add_tag(&first_str, "create", Tag_Start); + tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start); + tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); switch (optionList->optval) { case 'n': /* iqn */ - xml_add_tag(&first_str, XML_ELEMENT_INAME, optionList->optarg); + tgt_buf_add(&first_str, XML_ELEMENT_INAME, optionList->optarg); break; default: (void) fprintf(stderr, "%s: %c: %s\n", @@ -482,10 +481,10 @@ return (1); } - buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End); - buf_add_tag(&first_str, "create", Tag_End); + tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End); + tgt_buf_add_tag(&first_str, "create", Tag_End); - node = send_data(hostname, first_str); + node = tgt_door_call(first_str, 0); free(first_str); return (formatErrString(node)); } @@ -495,18 +494,18 @@ createTpgt(int operandLen, char *operand[], cmdOptions_t *options) { char *first_str = NULL; - xml_node_t *node; + tgt_node_t *node; if (operand == NULL) return (1); - buf_add_tag(&first_str, "create", Tag_Start); - buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start); - xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]); - buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End); - buf_add_tag(&first_str, "create", Tag_End); + tgt_buf_add_tag(&first_str, "create", Tag_Start); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start); + tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End); + tgt_buf_add_tag(&first_str, "create", Tag_End); - node = send_data(hostname, first_str); + node = tgt_door_call(first_str, 0); free(first_str); return (formatErrString(node)); } @@ -516,40 +515,40 @@ modifyTarget(int operandLen, char *operand[], cmdOptions_t *options) { char *first_str = NULL; - xml_node_t *node; + tgt_node_t *node; cmdOptions_t *optionList = options; if (operand == NULL) return (1); - buf_add_tag(&first_str, "modify", Tag_Start); - buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start); - xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]); + tgt_buf_add_tag(&first_str, "modify", Tag_Start); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start); + tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); for (; optionList->optval; optionList++) { switch (optionList->optval) { case 'p': /* tpgt number */ - xml_add_tag(&first_str, XML_ELEMENT_TPGT, + tgt_buf_add(&first_str, XML_ELEMENT_TPGT, optionList->optarg); break; case 'l': /* acl */ - xml_add_tag(&first_str, XML_ELEMENT_ACL, + tgt_buf_add(&first_str, XML_ELEMENT_ACL, optionList->optarg); break; case 'a': /* alias */ - xml_add_tag(&first_str, XML_ELEMENT_ALIAS, + tgt_buf_add(&first_str, XML_ELEMENT_ALIAS, optionList->optarg); break; case 'm': /* max recv */ - xml_add_tag(&first_str, XML_ELEMENT_MAXRECV, + tgt_buf_add(&first_str, XML_ELEMENT_MAXRECV, optionList->optarg); break; case 'z': /* grow lun size */ - xml_add_tag(&first_str, XML_ELEMENT_SIZE, + tgt_buf_add(&first_str, XML_ELEMENT_SIZE, optionList->optarg); break; case 'u': - xml_add_tag(&first_str, XML_ELEMENT_LUN, + tgt_buf_add(&first_str, XML_ELEMENT_LUN, optionList->optarg); break; default: @@ -561,10 +560,10 @@ } } - buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End); - buf_add_tag(&first_str, "modify", Tag_End); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End); + tgt_buf_add_tag(&first_str, "modify", Tag_End); - node = send_data(hostname, first_str); + node = tgt_door_call(first_str, 0); free(first_str); return (formatErrString(node)); } @@ -574,7 +573,7 @@ modifyInitiator(int operandLen, char *operand[], cmdOptions_t *options) { char *first_str = NULL; - xml_node_t *node; + tgt_node_t *node; cmdOptions_t *optionList = options; char chapSecret[MAX_CHAP_SECRET_LEN]; int secretLen = 0; @@ -585,14 +584,14 @@ if (options == NULL) return (1); - buf_add_tag(&first_str, "modify", Tag_Start); - buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start); - xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]); + tgt_buf_add_tag(&first_str, "modify", Tag_Start); + tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start); + tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); for (; optionList->optval; optionList++) { switch (optionList->optval) { case 'H': /* chap-name */ - xml_add_tag(&first_str, XML_ELEMENT_CHAPNAME, + tgt_buf_add(&first_str, XML_ELEMENT_CHAPNAME, optionList->optarg); break; case 'C': /* chap-secret */ @@ -604,7 +603,7 @@ return (ret); } chapSecret[secretLen] = '\0'; - xml_add_tag(&first_str, XML_ELEMENT_CHAPSECRET, + tgt_buf_add(&first_str, XML_ELEMENT_CHAPSECRET, chapSecret); break; default: @@ -615,10 +614,10 @@ return (1); } } - buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End); - buf_add_tag(&first_str, "modify", Tag_End); + tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End); + tgt_buf_add_tag(&first_str, "modify", Tag_End); - node = send_data(hostname, first_str); + node = tgt_door_call(first_str, 0); free(first_str); return (formatErrString(node)); } @@ -628,7 +627,7 @@ modifyTpgt(int operandLen, char *operand[], cmdOptions_t *options) { char *first_str = NULL; - xml_node_t *node; + tgt_node_t *node; cmdOptions_t *optionList = options; boolean_t isIpv6 = B_FALSE; uint16_t port; @@ -639,9 +638,9 @@ if (optionList == NULL) return (1); - buf_add_tag(&first_str, "modify", Tag_Start); - buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start); - xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]); + tgt_buf_add_tag(&first_str, "modify", Tag_Start); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start); + tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); switch (optionList->optval) { case 'i': /* ip address */ @@ -650,7 +649,7 @@ PARSE_ADDR_OK) { return (1); } - xml_add_tag(&first_str, XML_ELEMENT_IPADDR, IpAddress); + tgt_buf_add(&first_str, XML_ELEMENT_IPADDR, IpAddress); break; default: (void) fprintf(stderr, "%s: %c: %s\n", @@ -660,10 +659,10 @@ return (1); } - buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End); - buf_add_tag(&first_str, "modify", Tag_End); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End); + tgt_buf_add_tag(&first_str, "modify", Tag_End); - node = send_data(hostname, first_str); + node = tgt_door_call(first_str, 0); free(first_str); return (formatErrString(node)); } @@ -673,7 +672,7 @@ modifyAdmin(int operandLen, char *operand[], cmdOptions_t *options) { char *first_str = NULL; - xml_node_t *node; + tgt_node_t *node; cmdOptions_t *optionList = options; char chapSecret[MAX_CHAP_SECRET_LEN], olddir[MAXPATHLEN], @@ -686,9 +685,9 @@ if (options == NULL) return (1); - buf_add_tag(&first_str, "modify", Tag_Start); - buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_Start); - xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]); + tgt_buf_add_tag(&first_str, "modify", Tag_Start); + tgt_buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_Start); + tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); for (; optionList->optval; optionList++) { switch (optionList->optval) { @@ -713,12 +712,12 @@ return (1); } (void) getcwd(newdir, sizeof (newdir)); - xml_add_tag(&first_str, XML_ELEMENT_BASEDIR, + tgt_buf_add(&first_str, XML_ELEMENT_BASEDIR, newdir); chdir(olddir); break; case 'H': /* chap name */ - xml_add_tag(&first_str, XML_ELEMENT_CHAPNAME, + tgt_buf_add(&first_str, XML_ELEMENT_CHAPNAME, optionList->optarg); break; case 'C': /* chap secert */ @@ -734,18 +733,18 @@ return (ret); } chapSecret[secretLen] = '\0'; - xml_add_tag(&first_str, XML_ELEMENT_CHAPSECRET, + tgt_buf_add(&first_str, XML_ELEMENT_CHAPSECRET, chapSecret); break; case 'R': /* radius access */ if (strcmp(optionList->optarg, OPT_ENABLE) == 0) { - xml_add_tag(&first_str, + tgt_buf_add(&first_str, XML_ELEMENT_RAD_ACCESS, OPT_TRUE); } else if (strcmp(optionList->optarg, OPT_DISABLE) == 0) { - xml_add_tag(&first_str, + tgt_buf_add(&first_str, XML_ELEMENT_RAD_ACCESS, OPT_FALSE); } else { (void) fprintf(stderr, "%s: %s\n", @@ -757,7 +756,7 @@ } break; case 'r': /* radius server */ - xml_add_tag(&first_str, XML_ELEMENT_RAD_SERV, + tgt_buf_add(&first_str, XML_ELEMENT_RAD_SERV, optionList->optarg); break; case 'P': /* radius secret */ @@ -773,18 +772,18 @@ return (ret); } chapSecret[secretLen] = '\0'; - xml_add_tag(&first_str, XML_ELEMENT_RAD_SECRET, + tgt_buf_add(&first_str, XML_ELEMENT_RAD_SECRET, chapSecret); break; case 'S': /* iSNS access */ if (strcmp(optionList->optarg, OPT_ENABLE) == 0) { - xml_add_tag(&first_str, + tgt_buf_add(&first_str, XML_ELEMENT_ISNS_ACCESS, OPT_TRUE); } else if (strcmp(optionList->optarg, OPT_DISABLE) == 0) { - xml_add_tag(&first_str, + tgt_buf_add(&first_str, XML_ELEMENT_ISNS_ACCESS, OPT_FALSE); } else { (void) fprintf(stderr, "%s: %s\n", @@ -798,12 +797,12 @@ case 'f': /* fast write back */ if (strcmp(optionList->optarg, OPT_ENABLE) == 0) { - xml_add_tag(&first_str, + tgt_buf_add(&first_str, XML_ELEMENT_FAST, OPT_TRUE); } else if (strcmp(optionList->optarg, OPT_DISABLE) == 0) { - xml_add_tag(&first_str, + tgt_buf_add(&first_str, XML_ELEMENT_FAST, OPT_FALSE); } else { (void) fprintf(stderr, "%s: %s\n", @@ -823,10 +822,10 @@ } } - buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_End); - buf_add_tag(&first_str, "modify", Tag_End); + tgt_buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_End); + tgt_buf_add_tag(&first_str, "modify", Tag_End); - node = send_data(hostname, first_str); + node = tgt_door_call(first_str, 0); free(first_str); return (formatErrString(node)); } @@ -836,7 +835,7 @@ deleteTarget(int operandLen, char *operand[], cmdOptions_t *options) { char *first_str = NULL; - xml_node_t *node; + tgt_node_t *node; cmdOptions_t *optionList = options; if (operand == NULL) @@ -844,19 +843,19 @@ if (options == NULL) return (1); - buf_add_tag(&first_str, "delete", Tag_Start); - buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start); - xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]); + tgt_buf_add_tag(&first_str, "delete", Tag_Start); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start); + tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); switch (optionList->optval) { case 'u': /* all */ - xml_add_tag(&first_str, XML_ELEMENT_LUN, optionList->optarg); + tgt_buf_add(&first_str, XML_ELEMENT_LUN, optionList->optarg); break; case 'l': /* acl */ - xml_add_tag(&first_str, XML_ELEMENT_ACL, optionList->optarg); + tgt_buf_add(&first_str, XML_ELEMENT_ACL, optionList->optarg); break; case 'p': /* tpgt number */ - xml_add_tag(&first_str, XML_ELEMENT_TPGT, optionList->optarg); + tgt_buf_add(&first_str, XML_ELEMENT_TPGT, optionList->optarg); break; default: (void) fprintf(stderr, "%s: %c: %s\n", @@ -866,10 +865,10 @@ return (1); } - buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End); - buf_add_tag(&first_str, "delete", Tag_End); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End); + tgt_buf_add_tag(&first_str, "delete", Tag_End); - node = send_data(hostname, first_str); + node = tgt_door_call(first_str, 0); free(first_str); return (formatErrString(node)); } @@ -879,7 +878,7 @@ deleteInitiator(int operandLen, char *operand[], cmdOptions_t *options) { char *first_str = NULL; - xml_node_t *node; + tgt_node_t *node; cmdOptions_t *optionList = options; if (operand == NULL) @@ -887,13 +886,13 @@ if (options == NULL) return (1); - buf_add_tag(&first_str, "delete", Tag_Start); - buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start); - xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]); + tgt_buf_add_tag(&first_str, "delete", Tag_Start); + tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start); + tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); switch (optionList->optval) { case 'A': /* all */ - xml_add_tag(&first_str, XML_ELEMENT_ALL, optionList->optarg); + tgt_buf_add(&first_str, XML_ELEMENT_ALL, optionList->optarg); break; default: (void) fprintf(stderr, "%s: %c: %s\n", @@ -903,10 +902,10 @@ return (1); } - buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End); - buf_add_tag(&first_str, "delete", Tag_End); + tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End); + tgt_buf_add_tag(&first_str, "delete", Tag_End); - node = send_data(hostname, first_str); + node = tgt_door_call(first_str, 0); free(first_str); return (formatErrString(node)); } @@ -916,7 +915,7 @@ deleteTpgt(int operandLen, char *operand[], cmdOptions_t *options) { char *first_str = NULL; - xml_node_t *node; + tgt_node_t *node; cmdOptions_t *optionList = options; boolean_t isIpv6 = B_FALSE; uint16_t port; @@ -927,13 +926,13 @@ if (options == NULL) return (1); - buf_add_tag(&first_str, "delete", Tag_Start); - buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start); - xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]); + tgt_buf_add_tag(&first_str, "delete", Tag_Start); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start); + tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); switch (optionList->optval) { case 'A': /* all */ - xml_add_tag(&first_str, XML_ELEMENT_ALL, optionList->optarg); + tgt_buf_add(&first_str, XML_ELEMENT_ALL, optionList->optarg); break; case 'i': /* ip address */ if (parseAddress(optionList->optarg, 0, @@ -941,7 +940,7 @@ PARSE_ADDR_OK) { return (1); } - xml_add_tag(&first_str, XML_ELEMENT_IPADDR, IpAddress); + tgt_buf_add(&first_str, XML_ELEMENT_IPADDR, IpAddress); break; default: (void) fprintf(stderr, "%s: %c: %s\n", @@ -951,10 +950,10 @@ return (1); } - buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End); - buf_add_tag(&first_str, "delete", Tag_End); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End); + tgt_buf_add_tag(&first_str, "delete", Tag_End); - node = send_data(hostname, first_str); + node = tgt_door_call(first_str, 0); free(first_str); return (formatErrString(node)); } @@ -963,11 +962,11 @@ listTarget(int operandLen, char *operand[], cmdOptions_t *options) { char *first_str = NULL; - xml_node_t *node = NULL; - xml_node_t *n1 = NULL; /* pointer to node (depth=1) */ - xml_node_t *n2 = NULL; /* pointer to node (depth=2) */ - xml_node_t *n3 = NULL; /* pointer to node (depth=3) */ - xml_node_t *n4 = NULL; /* pointer to node (depth=4) */ + tgt_node_t *node = NULL; + tgt_node_t *n1 = NULL; /* pointer to node (depth=1) */ + tgt_node_t *n2 = NULL; /* pointer to node (depth=2) */ + tgt_node_t *n3 = NULL; /* pointer to node (depth=3) */ + tgt_node_t *n4 = NULL; /* pointer to node (depth=4) */ int conns; char buf[32]; Boolean_t verbose = False; @@ -975,25 +974,25 @@ if (operand == NULL) return (1); - buf_add_tag(&first_str, "list", Tag_Start); - buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start); + tgt_buf_add_tag(&first_str, "list", Tag_Start); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start); if (operandLen) - xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]); + tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); /* * Always retrieve the iostats which will give us the * connection count information even if we're not doing * a verbose output. */ - xml_add_tag(&first_str, XML_ELEMENT_IOSTAT, OPT_TRUE); + tgt_buf_add(&first_str, XML_ELEMENT_IOSTAT, OPT_TRUE); if (options) { switch (options->optval) { case 0: break; case 'v': - xml_add_tag(&first_str, XML_ELEMENT_LUNINFO, OPT_TRUE); + tgt_buf_add(&first_str, XML_ELEMENT_LUNINFO, OPT_TRUE); verbose = True; break; default: @@ -1004,10 +1003,10 @@ } } - buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End); - buf_add_tag(&first_str, "list", Tag_End); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End); + tgt_buf_add_tag(&first_str, "list", Tag_End); - node = send_data(hostname, first_str); + node = tgt_door_call(first_str, 0); free(first_str); if (strcmp(node->x_name, XML_ELEMENT_RESULT)) { @@ -1017,18 +1016,18 @@ } n1 = NULL; - while ((n1 = xml_node_next_child(node, XML_ELEMENT_TARG, n1)) != NULL) { + while ((n1 = tgt_node_next_child(node, XML_ELEMENT_TARG, n1)) != NULL) { (void) printf("%s: %s\n", gettext("Target"), n1->x_value); - n2 = xml_node_next_child(n1, XML_ELEMENT_INAME, NULL); + n2 = tgt_node_next_child(n1, XML_ELEMENT_INAME, NULL); (void) printf("%s%s: %s\n", dospace(1), gettext("iSCSI Name"), n2 ? n2->x_value : gettext("Not set")); - if ((n2 = xml_node_next_child(n1, XML_ELEMENT_ALIAS, NULL)) != + if ((n2 = tgt_node_next_child(n1, XML_ELEMENT_ALIAS, NULL)) != NULL) (void) printf("%s%s: %s\n", dospace(1), gettext("Alias"), n2->x_value); - if ((n2 = xml_node_next_child(n1, XML_ELEMENT_MAXRECV, NULL)) != + if ((n2 = tgt_node_next_child(n1, XML_ELEMENT_MAXRECV, NULL)) != NULL) (void) printf("%s%s: %s\n", dospace(1), gettext("MaxRecv"), n2->x_value); @@ -1038,7 +1037,7 @@ */ n2 = NULL; conns = 0; - while (n2 = xml_node_next_child(n1, XML_ELEMENT_CONN, n2)) + while (n2 = tgt_node_next_child(n1, XML_ELEMENT_CONN, n2)) conns++; (void) printf("%s%s: %d\n", dospace(1), gettext("Connections"), conns); @@ -1053,30 +1052,30 @@ * indicating connections are coming next. */ n2 = NULL; - while (n2 = xml_node_next_child(n1, XML_ELEMENT_CONN, n2)) { + while (n2 = tgt_node_next_child(n1, XML_ELEMENT_CONN, n2)) { (void) printf("%s%s:\n", dospace(2), gettext("Initiator")); (void) printf("%s%s: %s\n", dospace(3), gettext("iSCSI Name"), n2->x_value); - n3 = xml_node_next_child(n2, XML_ELEMENT_ALIAS, NULL); + n3 = tgt_node_next_child(n2, XML_ELEMENT_ALIAS, NULL); (void) printf("%s%s: %s\n", dospace(3), gettext("Alias"), n3 ? n3->x_value : gettext("unknown")); } (void) printf("%s%s:\n", dospace(1), gettext("ACL list")); - n2 = xml_node_next_child(n1, XML_ELEMENT_ACLLIST, NULL); + n2 = tgt_node_next_child(n1, XML_ELEMENT_ACLLIST, NULL); n3 = NULL; - while (n3 = xml_node_next_child(n2, XML_ELEMENT_INIT, n3)) { + while (n3 = tgt_node_next_child(n2, XML_ELEMENT_INIT, n3)) { (void) printf("%s%s: %s\n", dospace(2), gettext("Initiator"), n3->x_value); } (void) printf("%s%s:\n", dospace(1), gettext("TPGT list")); - n2 = xml_node_next_child(n1, XML_ELEMENT_TPGTLIST, NULL); + n2 = tgt_node_next_child(n1, XML_ELEMENT_TPGTLIST, NULL); n3 = NULL; - while (n3 = xml_node_next_child(n2, XML_ELEMENT_TPGT, n3)) { + while (n3 = tgt_node_next_child(n2, XML_ELEMENT_TPGT, n3)) { (void) printf("%s%s: %s\n", dospace(2), gettext("TPGT"), n3->x_value); @@ -1084,29 +1083,29 @@ (void) printf("%s%s:\n", dospace(1), gettext("LUN information")); - n2 = xml_node_next_child(n1, XML_ELEMENT_LUNINFO, NULL); + n2 = tgt_node_next_child(n1, XML_ELEMENT_LUNINFO, NULL); n3 = NULL; - while (n3 = xml_node_next_child(n2, XML_ELEMENT_LUN, n3)) { + while (n3 = tgt_node_next_child(n2, XML_ELEMENT_LUN, n3)) { (void) printf("%s%s: %s\n", dospace(2), gettext("LUN"), n3->x_value); - n4 = xml_node_next_child(n3, XML_ELEMENT_GUID, NULL); + n4 = tgt_node_next_child(n3, XML_ELEMENT_GUID, NULL); (void) printf("%s%s: %s\n", dospace(3), gettext("GUID"), n4 ? n4->x_value : gettext("unknown")); - n4 = xml_node_next_child(n3, XML_ELEMENT_VID, NULL); + n4 = tgt_node_next_child(n3, XML_ELEMENT_VID, NULL); (void) printf("%s%s: %s\n", dospace(3), gettext("VID"), n4 ? n4->x_value : gettext("unknown")); - n4 = xml_node_next_child(n3, XML_ELEMENT_PID, NULL); + n4 = tgt_node_next_child(n3, XML_ELEMENT_PID, NULL); (void) printf("%s%s: %s\n", dospace(3), gettext("PID"), n4 ? n4->x_value : gettext("unknown")); - n4 = xml_node_next_child(n3, XML_ELEMENT_DTYPE, NULL); + n4 = tgt_node_next_child(n3, XML_ELEMENT_DTYPE, NULL); (void) printf("%s%s: %s\n", dospace(3), gettext("Type"), n4 ? n4->x_value : gettext("unknown")); - n4 = xml_node_next_child(n3, XML_ELEMENT_SIZE, NULL); + n4 = tgt_node_next_child(n3, XML_ELEMENT_SIZE, NULL); if (n4 && (strtol(n4->x_value, NULL, 0) != 0)) { (void) printf("%s%s: %s\n", dospace(3), gettext("Size"), @@ -1118,13 +1117,13 @@ gettext("Size"), gettext("unknown")); } - n4 = xml_node_next_child(n3, XML_ELEMENT_BACK, NULL); + n4 = tgt_node_next_child(n3, XML_ELEMENT_BACK, NULL); if (n4) { (void) printf("%s%s: %s\n", dospace(3), gettext("Backing store"), n4->x_value); } - n4 = xml_node_next_child(n3, XML_ELEMENT_STATUS, NULL); + n4 = tgt_node_next_child(n3, XML_ELEMENT_STATUS, NULL); (void) printf("%s%s: %s\n", dospace(3), gettext("Status"), n4 ? n4->x_value : gettext("unknown")); @@ -1138,20 +1137,20 @@ listInitiator(int operandLen, char *operand[], cmdOptions_t *options) { char *first_str = NULL; - xml_node_t *node; - xml_node_t *n1 = NULL; /* pointer to node (depth=1) */ - xml_node_t *n2 = NULL; /* pointer to node (depth=2) */ + tgt_node_t *node; + tgt_node_t *n1 = NULL; /* pointer to node (depth=1) */ + tgt_node_t *n2 = NULL; /* pointer to node (depth=2) */ Boolean_t verbose = False; cmdOptions_t *optionList = options; if (operand == NULL) return (1); - buf_add_tag(&first_str, "list", Tag_Start); - buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start); + tgt_buf_add_tag(&first_str, "list", Tag_Start); + tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_Start); if (operandLen) { - xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]); + tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); } if (optionList) { switch (optionList->optval) { @@ -1159,7 +1158,7 @@ break; case 'v': verbose = True; - xml_add_tag(&first_str, + tgt_buf_add(&first_str, XML_ELEMENT_VERBOSE, OPT_TRUE); break; @@ -1172,10 +1171,10 @@ } } - buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End); - buf_add_tag(&first_str, "list", Tag_End); + tgt_buf_add_tag(&first_str, XML_ELEMENT_INIT, Tag_End); + tgt_buf_add_tag(&first_str, "list", Tag_End); - node = send_data(hostname, first_str); + node = tgt_door_call(first_str, 0); free(first_str); if (strcmp(node->x_name, XML_ELEMENT_RESULT)) { @@ -1185,19 +1184,19 @@ } n1 = NULL; - while (n1 = xml_node_next_child(node, XML_ELEMENT_INIT, n1)) { + while (n1 = tgt_node_next_child(node, XML_ELEMENT_INIT, n1)) { (void) printf("%s: %s\n", gettext("Initiator"), n1->x_value); - n2 = xml_node_next_child(n1, XML_ELEMENT_INAME, NULL); + n2 = tgt_node_next_child(n1, XML_ELEMENT_INAME, NULL); (void) printf("%s%s: %s\n", dospace(1), gettext("iSCSI Name"), n2 ? n2->x_value : gettext("Not set")); - n2 = xml_node_next_child(n1, XML_ELEMENT_CHAPNAME, NULL); + n2 = tgt_node_next_child(n1, XML_ELEMENT_CHAPNAME, NULL); (void) printf("%s%s: %s\n", dospace(1), gettext("CHAP Name"), n2 ? n2->x_value : gettext("Not set")); if (verbose == True) { - n2 = xml_node_next_child(n1, XML_ELEMENT_CHAPSECRET, + n2 = tgt_node_next_child(n1, XML_ELEMENT_CHAPSECRET, NULL); (void) printf("%s%s: %s\n", dospace(1), gettext("CHAP Secret"), @@ -1213,9 +1212,9 @@ listTpgt(int operandLen, char *operand[], cmdOptions_t *options) { char *first_str = NULL; - xml_node_t *node = NULL; - xml_node_t *n1 = NULL; /* pointer to node (depth=1) */ - xml_node_t *n2 = NULL; /* pointer to node (depth=2) */ + tgt_node_t *node = NULL; + tgt_node_t *n1 = NULL; /* pointer to node (depth=1) */ + tgt_node_t *n2 = NULL; /* pointer to node (depth=2) */ cmdOptions_t *optionList = options; Boolean_t verbose = False; int addrs; @@ -1223,18 +1222,18 @@ if (operand == NULL) return (1); - buf_add_tag(&first_str, "list", Tag_Start); - buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start); + tgt_buf_add_tag(&first_str, "list", Tag_Start); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start); if (operandLen) - xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]); + tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); if (optionList) { switch (optionList->optval) { case 0: /* no options, treat as --verbose */ break; case 'v': verbose = True; - xml_add_tag(&first_str, + tgt_buf_add(&first_str, XML_ELEMENT_VERBOSE, OPT_TRUE); break; default: @@ -1246,10 +1245,10 @@ } } - buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End); - buf_add_tag(&first_str, "list", Tag_End); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End); + tgt_buf_add_tag(&first_str, "list", Tag_End); - node = send_data(hostname, first_str); + node = tgt_door_call(first_str, 0); free(first_str); if (strcmp(node->x_name, XML_ELEMENT_RESULT)) { @@ -1259,11 +1258,11 @@ } n1 = NULL; - while (n1 = xml_node_next_child(node, XML_ELEMENT_TPGT, n1)) { + while (n1 = tgt_node_next_child(node, XML_ELEMENT_TPGT, n1)) { (void) printf("%s: %s\n", gettext("TPGT"), n1->x_value); n2 = NULL; addrs = 0; - while (n2 = xml_node_next_child(n1, XML_ELEMENT_IPADDR, n2)) { + while (n2 = tgt_node_next_child(n1, XML_ELEMENT_IPADDR, n2)) { if (verbose == True) (void) printf("%s%s: %s\n", dospace(1), gettext("IP Address"), @@ -1294,19 +1293,19 @@ showAdmin(int operandLen, char *operand[], cmdOptions_t *options) { char *first_str = NULL; - xml_node_t *node = NULL; - xml_node_t *n1 = NULL; /* pointer to node (depth=1) */ - xml_node_t *n2 = NULL; /* pointer to node (depth=2) */ + tgt_node_t *node = NULL; + tgt_node_t *n1 = NULL; /* pointer to node (depth=1) */ + tgt_node_t *n2 = NULL; /* pointer to node (depth=2) */ if (operand == NULL) return (1); - buf_add_tag(&first_str, "list", Tag_Start); - buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_Start); - buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_End); - buf_add_tag(&first_str, "list", Tag_End); + tgt_buf_add_tag(&first_str, "list", Tag_Start); + tgt_buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_Start); + tgt_buf_add_tag(&first_str, XML_ELEMENT_ADMIN, Tag_End); + tgt_buf_add_tag(&first_str, "list", Tag_End); - node = send_data(hostname, first_str); + node = tgt_door_call(first_str, 0); free(first_str); if (strcmp(node->x_name, XML_ELEMENT_RESULT)) { @@ -1317,22 +1316,22 @@ (void) printf("%s:\n", cmdName); - n1 = xml_node_next_child(node, XML_ELEMENT_ADMIN, NULL); + n1 = tgt_node_next_child(node, XML_ELEMENT_ADMIN, NULL); if (n1 == NULL) { (void) fprintf(stderr, "%s: %s\n", cmdName, gettext("Bad XML response")); return (1); } - n2 = xml_node_next_child(n1, XML_ELEMENT_BASEDIR, NULL); + n2 = tgt_node_next_child(n1, XML_ELEMENT_BASEDIR, NULL); (void) printf("%s%s: %s\n", dospace(1), gettext("Base Directory"), n2 ? n2->x_value : gettext("Not set")); - n2 = xml_node_next_child(n1, XML_ELEMENT_CHAPNAME, NULL); + n2 = tgt_node_next_child(n1, XML_ELEMENT_CHAPNAME, NULL); (void) printf("%s%s: %s\n", dospace(1), gettext("CHAP Name"), n2 ? n2->x_value : gettext("Not set")); - n2 = xml_node_next_child(n1, XML_ELEMENT_RAD_ACCESS, NULL); + n2 = tgt_node_next_child(n1, XML_ELEMENT_RAD_ACCESS, NULL); (void) printf("%s%s: ", dospace(1), gettext("RADIUS Access")); if (n2) { if (strcmp(n2->x_value, OPT_TRUE) == 0) @@ -1342,11 +1341,11 @@ } else (void) printf("%s\n", gettext("Not set")); - n2 = xml_node_next_child(n1, XML_ELEMENT_RAD_SERV, NULL); + n2 = tgt_node_next_child(n1, XML_ELEMENT_RAD_SERV, NULL); (void) printf("%s%s: %s\n", dospace(1), gettext("RADIUS Server"), n2 ? n2->x_value : gettext("Not set")); - n2 = xml_node_next_child(n1, XML_ELEMENT_ISNS_ACCESS, NULL); + n2 = tgt_node_next_child(n1, XML_ELEMENT_ISNS_ACCESS, NULL); (void) printf("%s%s: ", dospace(1), gettext("iSNS Access")); if (n2) { if (strcmp(n2->x_value, OPT_TRUE) == 0) @@ -1356,7 +1355,7 @@ } else (void) printf("%s\n", gettext("Not set")); - n2 = xml_node_next_child(n1, XML_ELEMENT_FAST, NULL); + n2 = tgt_node_next_child(n1, XML_ELEMENT_FAST, NULL); (void) printf("%s%s: ", dospace(1), gettext("Fast Write ACK")); if (n2) { if (strcmp(n2->x_value, OPT_TRUE) == 0) @@ -1374,7 +1373,7 @@ { char *first_str = NULL, scale_buf[16]; - xml_node_t *node, + tgt_node_t *node, *n1; int interval = -1, count = -1, @@ -1382,12 +1381,12 @@ stat_delta_t cur_data, *pd; - buf_add_tag(&first_str, "list", Tag_Start); - buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start); + tgt_buf_add_tag(&first_str, "list", Tag_Start); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_Start); - xml_add_tag(&first_str, XML_ELEMENT_IOSTAT, OPT_TRUE); + tgt_buf_add(&first_str, XML_ELEMENT_IOSTAT, OPT_TRUE); if (operandLen) - xml_add_tag(&first_str, XML_ELEMENT_NAME, operand[0]); + tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]); for (; options->optval; options++) { switch (options->optval) { @@ -1419,8 +1418,8 @@ } } - buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End); - buf_add_tag(&first_str, "list", Tag_End); + tgt_buf_add_tag(&first_str, XML_ELEMENT_TARG, Tag_End); + tgt_buf_add_tag(&first_str, "list", Tag_End); header = 1; /*CONSTANTCONDITION*/ @@ -1437,23 +1436,23 @@ "-----", "-----"); header = 20; } - node = send_data(hostname, first_str); + node = tgt_door_call(first_str, 0); if (strcmp(node->x_name, XML_ELEMENT_RESULT)) { (void) fprintf(stderr, "%s: %s\n", cmdName, gettext("Bad XML response")); free(first_str); - xml_tree_free(node); + tgt_node_free(node); stats_free(); return (1); } n1 = NULL; - while (n1 = xml_node_next_child(node, XML_ELEMENT_TARG, n1)) { + while (n1 = tgt_node_next_child(node, XML_ELEMENT_TARG, n1)) { stats_load_counts(n1, &cur_data); if ((pd = stats_prev_counts(&cur_data)) == NULL) { free(first_str); - xml_tree_free(node); + tgt_node_free(node); return (1); } (void) printf("%-20s ", pd->device); @@ -1471,7 +1470,7 @@ cur_data.write_blks - pd->write_blks, 512, 1024)); stats_update_counts(pd, &cur_data); } - xml_tree_free(node); + tgt_node_free(node); if (count == -1) { if (interval == -1)
--- a/usr/src/cmd/iscsi/iscsitgtd/Makefile Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/Makefile Wed Nov 15 19:25:44 2006 -0800 @@ -18,13 +18,13 @@ # # CDDL HEADER END # -# -#ident "%Z%%M% %I% %E% SMI" + # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# cmd/iscsi/iscsitgtd/Makefile +# ident "%Z%%M% %I% %E% SMI" +# PROG= iscsitgtd OBJS = main.o mgmt.o mgmt_create.o mgmt_list.o mgmt_modify.o mgmt_remove.o @@ -42,6 +42,7 @@ $(BUILD64)SUBDIRS += $(MACH64) MANIFEST = iscsi_target.xml +SVCMETHOD = svc-iscsitgt ROOTMANIFESTDIR = $(ROOTSVCSYSTEM) $(ROOTSVCSYSTEM)/iscsi_target.xml := OWNER = root @@ -62,7 +63,7 @@ clean clobber lint: $(SUBDIRS) -install: $(SUBDIRS) $(ROOTMANIFEST) +install: $(SUBDIRS) $(ROOTMANIFEST) $(ROOTSVCMETHOD) -$(RM) $(ROOTUSRSBINPROG) -$(LN) $(ISAEXEC) $(ROOTUSRSBINPROG)
--- a/usr/src/cmd/iscsi/iscsitgtd/Makefile.com Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/Makefile.com Wed Nov 15 19:25:44 2006 -0800 @@ -40,7 +40,7 @@ SUFFIX_LINT = .ln CFLAGS += $(CCVERBOSE) -CPPFLAGS += -D_LARGEFILE64_SOURCE=1 -I$(ISCSICOMMONDIR) -I/usr/include/libxml2 +CPPFLAGS += -D_LARGEFILE64_SOURCE=1 -I/usr/include/libxml2 CFLAGS64 += $(CCVERBOSE) GROUP=sys @@ -52,6 +52,8 @@ all: $(PROG) LDLIBS += -luuid -lxml2 -lsocket -lnsl -ldoor -lavl -lmd5 -ladm -lefi +LDLIBS += -liscsitgt -lzfs + $(PROG): $(OBJS) $(COMMON_OBJS) $(LINK.c) $(OBJS) $(COMMON_OBJS) -o $@ $(LDLIBS) $(POST_PROCESS)
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_authglue.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/iscsi_authglue.c Wed Nov 15 19:25:44 2006 -0800 @@ -45,10 +45,10 @@ #include <sys/iscsi_protocol.h> #include <sys/iscsi_authclient.h> #include <sys/types.h> +#include <iscsitgt_impl.h> #include "radius.h" #include "queue.h" #include "iscsi_sess.h" -#include "xml.h" #include "target.h" #define DEFAULT_RADIUS_PORT 1812 @@ -67,7 +67,7 @@ radius->r_radius_config_valid = B_FALSE; /* Load RADIUS access option: enable/disable */ - if (xml_find_value_boolean(main_config, XML_ELEMENT_RAD_ACCESS, + if (tgt_find_value_boolean(main_config, XML_ELEMENT_RAD_ACCESS, &bRadiusAccess) == False) { return (B_FALSE); } @@ -76,7 +76,7 @@ } /* Load RADIUS server: ipaddr[:port] */ - if (xml_find_value_str(main_config, XML_ELEMENT_RAD_SERV, + if (tgt_find_value_str(main_config, XML_ELEMENT_RAD_SERV, &szRadiusServer) == False) { return (B_FALSE); } @@ -109,7 +109,7 @@ */ /* Load RADIUS shared secret */ - if (xml_find_value_str(main_config, XML_ELEMENT_RAD_SECRET, + if (tgt_find_value_str(main_config, XML_ELEMENT_RAD_SECRET, &szRadiusSecret) == False) { freeaddrinfo(res); return (B_FALSE);
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_cmd.h Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/iscsi_cmd.h Wed Nov 15 19:25:44 2006 -0800 @@ -41,7 +41,7 @@ #include <sys/avl.h> #include <aio.h> -#include "local_types.h" +#include <iscsitgt_impl.h> #include "t10.h" #define CMD_MAXOUTSTANDING 64
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_conn.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/iscsi_conn.c Wed Nov 15 19:25:44 2006 -0800 @@ -41,7 +41,7 @@ #include <syslog.h> #include <sys/iscsi_protocol.h> -#include "local_types.h" +#include <iscsitgt_impl.h> #include "iscsi_conn.h" #include "iscsi_sess.h" #include "iscsi_login.h" @@ -269,7 +269,7 @@ else { (void) pthread_mutex_lock( &mgmt->m_resp_mutex); - xml_add_tag(mgmt->m_u.m_resp, + tgt_buf_add(mgmt->m_u.m_resp, "connection", NULL); (void) pthread_mutex_unlock( &mgmt->m_resp_mutex);
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_login.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/iscsi_login.c Wed Nov 15 19:25:44 2006 -0800 @@ -32,13 +32,12 @@ #include <stdlib.h> #include <unistd.h> #include <sys/iscsi_protocol.h> - +#include <iscsitgt_impl.h> #include "queue.h" #include "iscsi_conn.h" #include "iscsi_sess.h" #include "iscsi_login.h" #include "utility.h" -#include "xml.h" #include "target.h" typedef enum auth_action { @@ -144,7 +143,7 @@ transit = 0, rc = 0; auth_action_t auth_action = LOGIN_DROP; - xml_node_t *tnode = NULL; + tgt_node_t *tnode = NULL; if (read(c->c_fd, &lh, sizeof (lh)) != sizeof (lh)) { queue_str(c->c_mgmtq, Q_CONN_ERRS, msg_log, @@ -694,9 +693,9 @@ static auth_action_t login_set_auth(iscsi_sess_t *s) { - xml_node_t *xnInitiator = NULL; - xml_node_t *xnTarget = NULL; - xml_node_t *xnAcl = NULL; + tgt_node_t *xnInitiator = NULL; + tgt_node_t *xnTarget = NULL; + tgt_node_t *xnAcl = NULL; char *szIniAlias = NULL; char *szIscsiName = NULL; char *szChapName = NULL; @@ -710,13 +709,13 @@ sess_auth->password_length_in = 0; /* Load alias, iscsi-name, chap-name, chap-secret from config file */ - while ((xnInitiator = xml_node_next(main_config, XML_ELEMENT_INIT, + while ((xnInitiator = tgt_node_next(main_config, XML_ELEMENT_INIT, xnInitiator)) != NULL) { - (void) xml_find_value_str(xnInitiator, XML_ELEMENT_INIT, + (void) tgt_find_value_str(xnInitiator, XML_ELEMENT_INIT, &szIniAlias); - if (xml_find_value_str(xnInitiator, XML_ELEMENT_INAME, + if (tgt_find_value_str(xnInitiator, XML_ELEMENT_INAME, &szIscsiName) == True) { comp = strcmp(s->s_i_name, szIscsiName); @@ -725,7 +724,7 @@ if (comp == 0) { - if (xml_find_value_str(xnInitiator, + if (tgt_find_value_str(xnInitiator, XML_ELEMENT_CHAPNAME, &szChapName) == True) { /*CSTYLED*/ @@ -734,7 +733,7 @@ free(szChapName); } - if (xml_find_value_str(xnInitiator, + if (tgt_find_value_str(xnInitiator, XML_ELEMENT_CHAPSECRET, &szChapSecret) == True) { /*CSTYLED*/ @@ -769,10 +768,10 @@ * If a CHAP secret exists for the initiator, it must be authed. */ - while ((xnTarget = xml_node_next(targets_config, XML_ELEMENT_TARG, + while ((xnTarget = tgt_node_next(targets_config, XML_ELEMENT_TARG, xnTarget)) != NULL) { - if ((xml_find_value_str(xnTarget, XML_ELEMENT_INAME, + if ((tgt_find_value_str(xnTarget, XML_ELEMENT_INAME, &szIscsiName) == False) || (szIscsiName == NULL)) { return (LOGIN_DROP); } @@ -783,7 +782,7 @@ if (comp == 0) { - if ((xnAcl = xml_node_next(xnTarget, + if ((xnAcl = tgt_node_next(xnTarget, XML_ELEMENT_ACLLIST, 0)) == NULL) { /* * No acl_list found, return True for no auth @@ -797,10 +796,10 @@ * this session. */ xnInitiator = NULL; - while ((xnInitiator = xml_node_next(xnAcl, + while ((xnInitiator = tgt_node_next(xnAcl, XML_ELEMENT_INIT, xnInitiator)) != NULL) { - if ((xml_find_value_str(xnInitiator, + if ((tgt_find_value_str(xnInitiator, XML_ELEMENT_INIT, &possible) == False) || (possible == NULL)) continue;
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.c Wed Nov 15 19:25:44 2006 -0800 @@ -33,11 +33,11 @@ #include <strings.h> #include <syslog.h> +#include <iscsitgt_impl.h> #include "iscsi_conn.h" #include "iscsi_sess.h" #include "t10.h" #include "utility.h" -#include "xml.h" #include "target.h" pthread_mutex_t sess_mutex; @@ -185,18 +185,18 @@ Boolean_t convert_i_local(char *ip, char **rtn) { - xml_node_t *inode = NULL; + tgt_node_t *inode = NULL; char *iname, *name; - while ((inode = xml_node_next(main_config, XML_ELEMENT_INIT, inode)) != + while ((inode = tgt_node_next(main_config, XML_ELEMENT_INIT, inode)) != NULL) { - if (xml_find_value_str(inode, XML_ELEMENT_INAME, &iname) == + if (tgt_find_value_str(inode, XML_ELEMENT_INAME, &iname) == False) { continue; } if (strcmp(iname, ip) == 0) { - if (xml_find_value_str(inode, XML_ELEMENT_INIT, + if (tgt_find_value_str(inode, XML_ELEMENT_INIT, &name) == False) { free(iname); return (False); @@ -483,10 +483,11 @@ (mgmt->m_request == mgmt_full_phase_statistics) && (strcmp(s->s_t_name, mgmt->m_targ_name) == 0)) { - buf_add_tag(buf, XML_ELEMENT_CONN, Tag_Start); - buf_add_tag(buf, s->s_i_name, Tag_String); + tgt_buf_add_tag(buf, XML_ELEMENT_CONN, + Tag_Start); + tgt_buf_add_tag(buf, s->s_i_name, Tag_String); if (s->s_i_alias != NULL) { - xml_add_tag(buf, XML_ELEMENT_ALIAS, + tgt_buf_add(buf, XML_ELEMENT_ALIAS, s->s_i_alias); } @@ -499,15 +500,17 @@ (void) snprintf(local_buf, sizeof (local_buf), "%d", mgmt->m_time - s->s_conn_head->c_up_at); - xml_add_tag(buf, XML_ELEMENT_TIMECON, + tgt_buf_add(buf, XML_ELEMENT_TIMECON, local_buf); - buf_add_tag(buf, XML_ELEMENT_STATS, Tag_Start); + tgt_buf_add_tag(buf, XML_ELEMENT_STATS, + Tag_Start); t10_targ_stat(s->s_t10, buf); - buf_add_tag(buf, XML_ELEMENT_STATS, Tag_End); - buf_add_tag(buf, XML_ELEMENT_CONN, Tag_End); + tgt_buf_add_tag(buf, XML_ELEMENT_STATS, + Tag_End); + tgt_buf_add_tag(buf, XML_ELEMENT_CONN, Tag_End); } (void) pthread_mutex_unlock(&mgmt->m_resp_mutex); @@ -610,7 +613,7 @@ sess_set_auth(iscsi_sess_t *isp) { IscsiAuthClient *auth_client = NULL; - xml_node_t *node = NULL; + tgt_node_t *node = NULL; if (isp == (iscsi_sess_t *)NULL) return; @@ -620,13 +623,13 @@ isp->sess_auth.auth_enabled = B_TRUE; /* Load CHAP name */ - node = xml_node_next_child(main_config, XML_ELEMENT_CHAPNAME, NULL); + node = tgt_node_next_child(main_config, XML_ELEMENT_CHAPNAME, NULL); if (node == NULL) return; (void) strcpy(isp->sess_auth.username, node->x_value); /* Load CHAP secret */ - node = xml_node_next_child(main_config, XML_ELEMENT_CHAPSECRET, NULL); + node = tgt_node_next_child(main_config, XML_ELEMENT_CHAPSECRET, NULL); if (node == NULL) return; (void) strcpy((char *)isp->sess_auth.password, node->x_value);
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_target.xml Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/iscsi_target.xml Wed Nov 15 19:25:44 2006 -0800 @@ -56,7 +56,7 @@ <exec_method type='method' name='start' - exec='/usr/sbin/iscsitgtd' + exec='/lib/svc/method/svc-iscsitgt %m' timeout_seconds='60'> <method_context> <method_credential @@ -69,7 +69,7 @@ <exec_method type='method' name='stop' - exec=':kill' + exec='/lib/svc/method/svc-iscsitgt %m %{restarter/contract}' timeout_seconds='60'> <method_context> <method_credential @@ -79,11 +79,17 @@ </method_context> </exec_method> + <property_group name='application' type='framework'> + <stability value='Unstable' /> + <propval name='auto_enable' type='boolean' value='true' /> + </property_group> + <stability value='Unstable' /> <template> <common_name> - <loctext xml:lang='C'> Solaris iSCSI Target + <loctext xml:lang='C'> + iSCSI Target </loctext> </common_name> <documentation>
--- a/usr/src/cmd/iscsi/iscsitgtd/main.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/main.c Wed Nov 15 19:25:44 2006 -0800 @@ -45,7 +45,6 @@ #include <assert.h> #include <errno.h> #include <door.h> -#include <iscsi_door.h> #include <signal.h> #include <siginfo.h> #include <sys/ethernet.h> @@ -56,12 +55,12 @@ #include <sys/resource.h> #include <syslog.h> #include <sys/select.h> +#include <iscsitgt_impl.h> #include "queue.h" #include "port.h" #include "iscsi_conn.h" #include "target.h" -#include "xml.h" #include "utility.h" #include "iscsi_ffp.h" #include "errcode.h" @@ -70,7 +69,7 @@ #define EMPTY_CONFIG "<config version='1.0'>\n</config>\n" /* ---- Forward declarations ---- */ -static void variable_handler(xml_node_t *, target_queue_t *, target_queue_t *); +static void variable_handler(tgt_node_t *, target_queue_t *, target_queue_t *); /* ---- Global configuration data. ---- */ @@ -78,7 +77,7 @@ char *target_log = DEFAULT_TARGET_LOG; char *config_file = DEFAULT_CONFIG_LOCATION; int iscsi_port = 3260; /* defined by the spec */ -xml_node_t *main_config, +tgt_node_t *main_config, *targets_config; Boolean_t enforce_strict_guid = True, thin_provisioning = False, @@ -114,7 +113,7 @@ typedef struct cmd_table { char *c_name; - void (*c_func)(xml_node_t *, target_queue_t *, target_queue_t *); + void (*c_func)(tgt_node_t *, target_queue_t *, target_queue_t *); } cmd_table_t; admin_table_t admin_prop_list[] = { @@ -165,7 +164,7 @@ char path[MAXPATHLEN], *target = NULL; struct stat ss; - xml_node_t *node = NULL, + tgt_node_t *node = NULL, *next = NULL; int xml_fd = -1; @@ -230,7 +229,7 @@ if (r != NULL) { while (xmlTextReaderRead(r) == 1) { - if (xml_process_node(r, &node) == False) + if (tgt_node_process(r, &node) == False) break; } @@ -248,9 +247,9 @@ } targets_config = node; - while ((next = xml_node_next(node, XML_ELEMENT_TARG, + while ((next = tgt_node_next(node, XML_ELEMENT_TARG, next)) != NULL) { - if (xml_find_value_str(next, XML_ELEMENT_INAME, + if (tgt_find_value_str(next, XML_ELEMENT_INAME, &target) == False) { continue; } @@ -297,7 +296,7 @@ xmlTextReaderPtr r; int ret, xml_fd = -1; - xml_node_t *node = NULL; + tgt_node_t *node = NULL; #ifndef lint LIBXML_TEST_VERSION; @@ -318,7 +317,7 @@ if (r != NULL) { ret = xmlTextReaderRead(r); while (ret == 1) { - if (xml_process_node(r, &node) == False) { + if (tgt_node_process(r, &node) == False) { break; } ret = xmlTextReaderRead(r); @@ -341,7 +340,7 @@ * can start without it, but the daemon can't really do * anything until the administrator sets the value. */ - (void) xml_find_value_str(node, XML_ELEMENT_BASEDIR, + (void) tgt_find_value_str(node, XML_ELEMENT_BASEDIR, &target_basedir); /* @@ -349,20 +348,20 @@ * these has a default value which can be overwritten in * the configuration file. */ - (void) xml_find_value_str(node, XML_ELEMENT_TARGLOG, + (void) tgt_find_value_str(node, XML_ELEMENT_TARGLOG, &target_log); - (void) xml_find_value_int(node, XML_ELEMENT_ISCSIPORT, + (void) tgt_find_value_int(node, XML_ELEMENT_ISCSIPORT, &iscsi_port); - (void) xml_find_value_int(node, XML_ELEMENT_DBGLVL, &dbg_lvl); - (void) xml_find_value_boolean(node, XML_ELEMENT_ENFORCE, + (void) tgt_find_value_int(node, XML_ELEMENT_DBGLVL, &dbg_lvl); + (void) tgt_find_value_boolean(node, XML_ELEMENT_ENFORCE, &enforce_strict_guid); - (void) xml_find_value_boolean(node, XML_ELEMENT_THIN_PROVO, + (void) tgt_find_value_boolean(node, XML_ELEMENT_THIN_PROVO, &thin_provisioning); - (void) xml_find_value_boolean(node, XML_ELEMENT_DISABLE_TPGS, + (void) tgt_find_value_boolean(node, XML_ELEMENT_DISABLE_TPGS, &disable_tpgs); - (void) xml_find_value_boolean(node, XML_ELEMENT_TIMESTAMPS, + (void) tgt_find_value_boolean(node, XML_ELEMENT_TIMESTAMPS, &dbg_timestamps); - if (xml_find_value_int(node, XML_ELEMENT_LOGLVL, + if (tgt_find_value_int(node, XML_ELEMENT_LOGLVL, &qlog_lvl) == True) queue_log(True); @@ -488,11 +487,11 @@ */ /*ARGSUSED*/ void -variable_handler(xml_node_t *x, target_queue_t *reply, target_queue_t *mgmt) +variable_handler(tgt_node_t *x, target_queue_t *reply, target_queue_t *mgmt) { char *reply_buf = NULL; var_table_t *v; - xml_node_t *c; + tgt_node_t *c; for (c = x->x_child; c; c = c->x_sibling) { @@ -518,7 +517,7 @@ * []---- */ static void -parse_xml(xml_node_t *x, target_queue_t *reply, target_queue_t *mgmt) +parse_xml(tgt_node_t *x, target_queue_t *reply, target_queue_t *mgmt) { char *reply_msg = NULL; cmd_table_t *c; @@ -589,7 +588,7 @@ target_queue_t *mgmtq = (target_queue_t *)cookie; mgmt_request_t m; msg_t *msg = NULL; - xml_node_t *node = NULL; + tgt_node_t *node = NULL; xmlTextReaderPtr r; char *err_rply = NULL; @@ -598,7 +597,7 @@ if ((r = (xmlTextReaderPtr)xmlReaderForMemory(argp, strlen(argp), NULL, NULL, 0)) != NULL) { while (xmlTextReaderRead(r)) { - if (xml_process_node(r, &node) == False) + if (tgt_node_process(r, &node) == False) break; } if (node != NULL) { @@ -643,7 +642,7 @@ } if (node != NULL) - xml_tree_free(node); + tgt_node_free(node); if (err_rply != NULL) { strcpy(argp, err_rply); free(err_rply); @@ -777,7 +776,7 @@ if (process_target_config() == False) exit(SMF_EXIT_ERR_CONFIG); - (void) xml_find_value_boolean(main_config, XML_ELEMENT_DBGDAEMON, + (void) tgt_find_value_boolean(main_config, XML_ELEMENT_DBGDAEMON, &daemonize); if (daemonize == True) { switch (fork()) { @@ -837,7 +836,7 @@ (void) pthread_create(&junk, NULL, port_watcher, &port1); setup_door(q, door_name); - if ((xml_find_value_int(main_config, XML_ELEMENT_MGMTPORT, + if ((tgt_find_value_int(main_config, XML_ELEMENT_MGMTPORT, &port2.port_num) == True) && (port2.port_num != -1)) { port2.port_mgmtq = q; port2.port_dataq = queue_alloc();
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/mgmt.c Wed Nov 15 19:25:44 2006 -0800 @@ -40,11 +40,11 @@ #include <synch.h> #include <sys/stropts.h> #include <libxml/xmlreader.h> +#include <iscsitgt_impl.h> #include "queue.h" #include "port.h" #include "utility.h" -#include "xml.h" static void mgmt_monitor_queue(port_args_t *p) @@ -65,7 +65,7 @@ case msg_log: data = (char *)m->msg_data; output = NULL; - xml_add_tag(&output, "log", data); + tgt_buf_add(&output, "log", data); (void) write(p->port_socket, output, strlen(output)); free(output); break; @@ -73,7 +73,7 @@ case msg_mgmt_rply: data = (char *)m->msg_data; output = NULL; - xml_add_tag(&output, "mgmt", data); + tgt_buf_add(&output, "mgmt", data); (void) write(p->port_socket, output, strlen(output)); free(output); free(data); @@ -103,7 +103,7 @@ nfds_t nfds = 1; struct pollfd fds[1]; xmlTextReaderPtr r; - xml_node_t *node = NULL; + tgt_node_t *node = NULL; mgmt_request_t m; fds[0].fd = p->port_socket; @@ -143,7 +143,7 @@ if (r != NULL) { ret = xmlTextReaderRead(r); while (ret == 1) { - if (xml_process_node(r, &node) == False) + if (tgt_node_process(r, &node) == False) break; ret = xmlTextReaderRead(r); } @@ -153,6 +153,7 @@ msg_mgmt_rqst, &m); } xmlFreeTextReader(r); + tgt_node_free(node); node = NULL; }
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c Wed Nov 15 19:25:44 2006 -0800 @@ -43,8 +43,10 @@ #include <sys/scsi/impl/uscsi.h> #include <sys/scsi/generic/commands.h> #include <sys/scsi/impl/commands.h> +#include <libzfs.h> +#include <syslog.h> -#include "xml.h" +#include <iscsitgt_impl.h> #include "queue.h" #include "target.h" #include "iscsi_cmd.h" @@ -54,9 +56,10 @@ extern char *getfullrawname(); -static char *create_target(xml_node_t *); -static char *create_initiator(xml_node_t *); -static char *create_tpgt(xml_node_t *); +static char *create_target(tgt_node_t *); +static char *create_initiator(tgt_node_t *); +static char *create_tpgt(tgt_node_t *); +static char *create_zfs(tgt_node_t *); static Boolean_t create_target_dir(char *targ_name, char *local_name); static char *create_node_name(char *local_nick, char *alias); static Boolean_t create_lun(char *targ_name, char *type, int lun, @@ -67,7 +70,9 @@ FILE *fp, uint64_t *size); static Boolean_t setup_raw_backing(err_code_t *code, char *path, char *backing, uint64_t *size); +static void zfs_lun(tgt_node_t *l, uint64_t size, char *dataset); +#define ZVOL_PATH "/dev/zvol/rdsk/" /* * []---- @@ -76,9 +81,9 @@ */ /*ARGSUSED*/ void -create_func(xml_node_t *p, target_queue_t *reply, target_queue_t *mgmt) +create_func(tgt_node_t *p, target_queue_t *reply, target_queue_t *mgmt) { - xml_node_t *x; + tgt_node_t *x; char msgbuf[80], *reply_msg = NULL; @@ -95,6 +100,8 @@ reply_msg = create_initiator(x); } else if (strcmp(x->x_name, XML_ELEMENT_TPGT) == 0) { reply_msg = create_tpgt(x); + } else if (strcmp(x->x_name, XML_ELEMENT_ZFS) == 0) { + reply_msg = create_zfs(x); } else { (void) snprintf(msgbuf, sizeof (msgbuf), "Unknown object '%s' for create element", @@ -105,8 +112,11 @@ queue_message_set(reply, 0, msg_mgmt_rply, reply_msg); } +/* + * create_target -- an administrative request to create a target + */ static char * -create_target(xml_node_t *x) +create_target(tgt_node_t *x) { char *msg = NULL, *name = NULL, @@ -118,14 +128,14 @@ path[MAXPATHLEN]; int lun = 0, /* default to LUN 0 */ i; - xml_node_t *n, + tgt_node_t *n, *c, *l; err_code_t code; - (void) xml_find_value_str(x, XML_ELEMENT_BACK, &backing); - (void) xml_find_value_str(x, XML_ELEMENT_ALIAS, &alias); - if (xml_find_value_intchk(x, XML_ELEMENT_LUN, &lun) == False) { + (void) tgt_find_value_str(x, XML_ELEMENT_BACK, &backing); + (void) tgt_find_value_str(x, XML_ELEMENT_ALIAS, &alias); + if (tgt_find_value_intchk(x, XML_ELEMENT_LUN, &lun) == False) { xml_rtn_msg(&msg, ERR_LUN_INVALID_RANGE); goto error; } @@ -133,7 +143,7 @@ /* * We've got to have a name element or all bets are off. */ - if (xml_find_value_str(x, XML_ELEMENT_NAME, &name) == False) { + if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); goto error; } @@ -157,7 +167,7 @@ name[i] = tolower(name[i]); } - if (xml_find_value_str(x, XML_ELEMENT_TYPE, &type) == False) { + if (tgt_find_value_str(x, XML_ELEMENT_TYPE, &type) == False) { /* * If a type hasn't been specified default to disk emulation. * We use strdup() since at the end of this routine the code @@ -171,7 +181,7 @@ goto error; } - if (xml_find_value_str(x, XML_ELEMENT_SIZE, &size) == False) { + if (tgt_find_value_str(x, XML_ELEMENT_SIZE, &size) == False) { if (backing != NULL) { /* @@ -218,31 +228,31 @@ xml_rtn_msg(&msg, ERR_CREATE_TARGET_DIR_FAILED); goto error; } - n = xml_alloc_node(XML_ELEMENT_TARG, String, name); - c = xml_alloc_node(XML_ELEMENT_INAME, String, node_name); - (void) xml_add_child(n, c); - c = xml_alloc_node(XML_ELEMENT_LUNLIST, String, ""); - l = xml_alloc_node(XML_ELEMENT_LUN, Int, &lun); - (void) xml_add_child(c, l); - (void) xml_add_child(n, c); + n = tgt_node_alloc(XML_ELEMENT_TARG, String, name); + c = tgt_node_alloc(XML_ELEMENT_INAME, String, node_name); + tgt_node_add(n, c); + c = tgt_node_alloc(XML_ELEMENT_LUNLIST, String, ""); + l = tgt_node_alloc(XML_ELEMENT_LUN, Int, &lun); + tgt_node_add(c, l); + tgt_node_add(n, c); if (alias != NULL) { - c = xml_alloc_node(XML_ELEMENT_ALIAS, String, alias); - (void) xml_add_child(n, c); + c = tgt_node_alloc(XML_ELEMENT_ALIAS, String, alias); + tgt_node_add(n, c); } - (void) xml_add_child(targets_config, n); + tgt_node_add(targets_config, n); } else { - if (xml_find_value_str(n, XML_ELEMENT_INAME, + if (tgt_find_value_str(n, XML_ELEMENT_INAME, &node_name) == False) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_INAME); goto error; } - if ((c = xml_node_next(n, XML_ELEMENT_LUNLIST, NULL)) == NULL) { + if ((c = tgt_node_next(n, XML_ELEMENT_LUNLIST, NULL)) == NULL) { xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); goto error; } - l = xml_alloc_node(XML_ELEMENT_LUN, Int, &lun); - (void) xml_add_child(c, l); + l = tgt_node_alloc(XML_ELEMENT_LUN, Int, &lun); + tgt_node_add(c, l); } if (create_lun(node_name, type, lun, size, backing, &code) == True) { @@ -262,9 +272,9 @@ (void) snprintf(path, sizeof (path), "%s/%s", target_basedir, name); unlink(path); - xml_remove_child(targets_config, n, MatchBoth); + tgt_node_remove(targets_config, n, MatchBoth); } else - xml_remove_child(c, l, MatchBoth); + tgt_node_remove(c, l, MatchBoth); xml_rtn_msg(&msg, code); @@ -286,20 +296,20 @@ } static char * -create_initiator(xml_node_t *x) +create_initiator(tgt_node_t *x) { char *msg = NULL, *name = NULL, *iscsi_name = NULL; - xml_node_t *inode = NULL, + tgt_node_t *inode = NULL, *n, *c; - if (xml_find_value_str(x, XML_ELEMENT_NAME, &name) == False) { + if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); goto error; } - if (xml_find_value_str(x, XML_ELEMENT_INAME, &iscsi_name) == False) { + if (tgt_find_value_str(x, XML_ELEMENT_INAME, &iscsi_name) == False) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_INAME); goto error; } @@ -308,7 +318,7 @@ goto error; } - while ((inode = xml_node_next(main_config, XML_ELEMENT_INIT, + while ((inode = tgt_node_next(main_config, XML_ELEMENT_INIT, inode)) != NULL) { if (strcmp(inode->x_value, name) == 0) { xml_rtn_msg(&msg, ERR_INIT_EXISTS); @@ -316,10 +326,10 @@ } } - n = xml_alloc_node(XML_ELEMENT_INIT, String, name); - c = xml_alloc_node(XML_ELEMENT_INAME, String, iscsi_name); - (void) xml_add_child(n, c); - (void) xml_add_child(main_config, n); + n = tgt_node_alloc(XML_ELEMENT_INIT, String, name); + c = tgt_node_alloc(XML_ELEMENT_INAME, String, iscsi_name); + tgt_node_add(n, c); + tgt_node_add(main_config, n); if (update_config_main(&msg) == True) xml_rtn_msg(&msg, ERR_SUCCESS); @@ -334,16 +344,16 @@ } static char * -create_tpgt(xml_node_t *x) +create_tpgt(tgt_node_t *x) { char *msg = NULL, *tpgt = NULL, *extra = NULL; - xml_node_t *tnode = NULL, + tgt_node_t *tnode = NULL, *n; int tpgt_val; - if (xml_find_value_str(x, XML_ELEMENT_NAME, &tpgt) == False) { + if (tgt_find_value_str(x, XML_ELEMENT_NAME, &tpgt) == False) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); goto error; } @@ -356,7 +366,7 @@ goto error; } - while ((tnode = xml_node_next(main_config, XML_ELEMENT_TPGT, + while ((tnode = tgt_node_next(main_config, XML_ELEMENT_TPGT, tnode)) != NULL) { if (strcmp(tnode->x_value, tpgt) == 0) { xml_rtn_msg(&msg, ERR_TPGT_EXISTS); @@ -364,8 +374,8 @@ } } - n = xml_alloc_node(XML_ELEMENT_TPGT, String, tpgt); - (void) xml_add_child(main_config, n); + n = tgt_node_alloc(XML_ELEMENT_TPGT, String, tpgt); + tgt_node_add(main_config, n); if (update_config_main(&msg) == True) xml_rtn_msg(&msg, ERR_SUCCESS); @@ -377,6 +387,230 @@ return (msg); } +static char * +create_zfs(tgt_node_t *x) +{ + char *msg = NULL, + *dataset = NULL, + *node_name = NULL, + *prop = NULL, + path[MAXPATHLEN], + *cp, /* current pair */ + *np, /* next pair */ + *vp; /* value pointer */ + tgt_node_t *dnode = NULL, + *n, + *c, + *attr, + *ll, + *l; + libzfs_handle_t *zh = NULL; + zfs_handle_t *zfsh = NULL; + uint64_t size; + size_t prop_len; + int lun = 0; + xmlTextReaderPtr r; + + if (tgt_find_value_str(x, XML_ELEMENT_NAME, &dataset) == False) { + xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); + goto error; + } + + while ((dnode = tgt_node_next(targets_config, XML_ELEMENT_TARG, + dnode)) != NULL) { + if (strcmp(dnode->x_value, dataset) == 0) { + xml_rtn_msg(&msg, ERR_LUN_EXISTS); + goto error; + } + } + + if (((zh = libzfs_init()) == NULL) || + ((zfsh = zfs_open(zh, dataset, ZFS_TYPE_ANY)) == NULL)) { + xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); + goto error; + } + + prop_len = 1024; + if ((prop = malloc(prop_len)) == NULL) { + xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); + goto error; + } + + /* + * In case zfs_prop_get returns no contents. + */ + *prop = '\0'; + + /* + * If we fail to get the shareiscsi property or the property is + * set to "off" return an error. + */ + if (zfs_prop_get(zfsh, ZFS_PROP_SHAREISCSI, prop, prop_len, NULL, + NULL, 0, B_TRUE)) { + xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); + goto error; + } + + /* + * The options property is a string with name/value pairs separated + * by comma characters. Stand alone values of 'on' and 'off' are + * also permitted, but having the property set to off when share() + * is called is an error. + * Currently we only look for 'type=<value>' and ignore others. + */ + cp = prop; + while (cp) { + if (np = strchr(cp, ',')) + *np++ = '\0'; + if (strcmp(cp, "on") == 0) { + cp = np; + continue; + } + if (strcmp(cp, "off") == 0) { + xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); + goto error; + } + if (vp = strchr(cp, '=')) + *vp++ = '\0'; + /* + * Only support 'disk' emulation at this point. + */ + if ((strcmp(cp, "type") == 0) && (strcmp(vp, "disk") != 0)) { + xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); + goto error; + } + + cp = np; + } + + /* + * In case zfs_prop_get returns no contents. + */ + *prop = '\0'; + + if (zfs_prop_get(zfsh, ZFS_PROP_ISCSIOPTIONS, prop, prop_len, NULL, + NULL, 0, B_TRUE)) { + xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); + goto error; + } + + /* + * Pick up the current size of the volume. + */ + size = zfs_prop_get_int(zfsh, ZFS_PROP_VOLSIZE); + if (strlen(prop)) { + n = NULL; + if ((r = (xmlTextReaderPtr)xmlReaderForMemory(prop, + strlen(prop), NULL, NULL, 0)) != NULL) { + while (xmlTextReaderRead(r)) { + if (tgt_node_process(r, &n) == False) + break; + } + xmlTextReaderClose(r); + xmlFreeTextReader(r); + xmlCleanupParser(); + + /* + * Pick up the LU node from the LU List which hangs + * off of the target node. If either is NULL there's + * an internal error someplace. + * 'l' will be used later. + */ + if (((ll = tgt_node_next(n, XML_ELEMENT_LUNLIST, NULL)) + == NULL) || + ((l = tgt_node_next(ll, XML_ELEMENT_LUN, NULL)) == + NULL)) { + xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); + goto error; + } + + } else { + xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); + goto error; + } + } else { + if ((node_name = create_node_name(NULL, NULL)) == NULL) { + xml_rtn_msg(&msg, ERR_CREATE_NAME_TO_LONG); + goto error; + } + + n = tgt_node_alloc(XML_ELEMENT_TARG, String, NULL); + attr = tgt_node_alloc(XML_ELEMENT_INCORE, String, + XML_VALUE_TRUE); + tgt_node_add_attr(n, attr); + attr = tgt_node_alloc(XML_ELEMENT_VERS, String, "1.0"); + tgt_node_add_attr(n, attr); + + c = tgt_node_alloc(XML_ELEMENT_INAME, String, node_name); + tgt_node_add(n, c); + + c = tgt_node_alloc(XML_ELEMENT_LUNLIST, String, ""); + tgt_node_add(n, c); + + l = tgt_node_alloc(XML_ELEMENT_LUN, Int, &lun); + tgt_node_add(c, l); + attr = tgt_node_alloc(XML_ELEMENT_VERS, String, "1.0"); + tgt_node_add_attr(l, attr); + + zfs_lun(l, size, dataset); + + /* + * Now store this information on the ZVOL property so that + * next time we get a share request the same data will be + * used. + */ + free(prop); + prop = NULL; + tgt_dump2buf(n, &prop); + if (zfs_prop_set(zfsh, zfs_prop_to_name(ZFS_PROP_ISCSIOPTIONS), + prop)) { + xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); + goto error; + } + } + + /* + * NOTE: 'n' is expected to be the target node for this + * ZVOL at this point. + */ + + /* + * Several elements can change everytime we share + * the dataset. The TargetAlias and backing store + * can change since these are based on the dataset + * and the size of the volume. Therefore, these + * pieces of information are not stored as part + * of the iscsioptions properity. + */ + tgt_update_value_str(n, XML_ELEMENT_TARG, dataset); + c = tgt_node_alloc(XML_ELEMENT_ALIAS, String, dataset); + tgt_node_add(n, c); + + (void) snprintf(path, sizeof (path), "%s%s", ZVOL_PATH, dataset); + c = tgt_node_alloc(XML_ELEMENT_BACK, String, path); + tgt_node_add(l, c); + + size /= 512LL; + c = tgt_node_alloc(XML_ELEMENT_SIZE, Uint64, &size); + tgt_node_add(l, c); + + tgt_node_add(targets_config, n); + + xml_rtn_msg(&msg, ERR_SUCCESS); +error: + if (zfsh) + zfs_close(zfsh); + if (zh) + libzfs_fini(zh); + if (dataset) + free(dataset); + if (node_name) + free(node_name); + if (prop) + free(prop); + return (msg); +} + /* * []------------------------------------------------------------------[] * | Utility functions used by the routines above. | @@ -393,7 +627,8 @@ { uuid_t id; char id_str[37], - *p; + *p, + *anp; /* alias or nick pointer */ if ((p = (char *)malloc(ISCSI_MAX_NAME_LEN)) == NULL) return (NULL); @@ -411,12 +646,26 @@ */ uuid_generate(id); uuid_unparse(id, id_str); - if (snprintf(p, ISCSI_MAX_NAME_LEN, "iqn.1986-03.com.sun:%02d:%s.%s", - TARGET_NAME_VERS, id_str, alias != NULL ? alias : local_nick) > - ISCSI_MAX_NAME_LEN) { + if (snprintf(p, ISCSI_MAX_NAME_LEN, "iqn.1986-03.com.sun:%02d:%s", + TARGET_NAME_VERS, id_str) > ISCSI_MAX_NAME_LEN) { free(p); return (NULL); } + if (local_nick || alias) { + anp = (alias != NULL) ? alias : local_nick; + + /* + * Make sure we still have room to add the alias or + * local nickname, a '.', and NULL character to the + * buffer. + */ + if ((strlen(p) + strlen(anp) + 2) > ISCSI_MAX_NAME_LEN) { + free(p); + return (NULL); + } + (void) strcat(p, "."); + (void) strcat(p, anp); + } return (p); } @@ -632,7 +881,7 @@ char path[MAXPATHLEN], buf[512]; struct statvfs fs; - xml_node_t *node = NULL, + tgt_node_t *node = NULL, *c; xmlTextReaderPtr r; @@ -732,18 +981,18 @@ target_basedir, targ_name, PARAMBASE, lun); if (r = (xmlTextReaderPtr)xmlReaderForFile(path, NULL, 0)) { while (xmlTextReaderRead(r) == 1) - if (xml_process_node(r, &node) == False) + if (tgt_node_process(r, &node) == False) break; - c = xml_alloc_node(XML_ELEMENT_STATUS, String, + c = tgt_node_alloc(XML_ELEMENT_STATUS, String, TGT_STATUS_ONLINE); - xml_replace_child(node, c, MatchName); - xml_tree_free(c); - if (xml_dump2file(node, path) == False) { + tgt_node_replace(node, c, MatchName); + tgt_node_free(c); + if (tgt_dump2file(node, path) == False) { queue_prt(mgmtq, Q_STE_ERRS, "GEN%d failed to dump out params", lun); goto error; } - xml_tree_free(node); + tgt_node_free(node); xmlTextReaderClose(r); xmlFreeTextReader(r); xmlCleanupParser(); @@ -999,3 +1248,52 @@ (void) close(fd); return (rval); } + +static void +zfs_lun(tgt_node_t *l, uint64_t size, char *dataset) +{ + tgt_node_t *c; + int cylinders, + heads, + spt, + val, + guid; + create_geom(size, &cylinders, &heads, &spt); + + guid = 0; + c = tgt_node_alloc(XML_ELEMENT_GUID, Int, &guid); + tgt_node_add(l, c); + + c = tgt_node_alloc(XML_ELEMENT_PID, String, DEFAULT_PID); + tgt_node_add(l, c); + + c = tgt_node_alloc(XML_ELEMENT_VID, String, DEFAULT_VID); + tgt_node_add(l, c); + + c = tgt_node_alloc(XML_ELEMENT_DTYPE, String, TGT_TYPE_DISK); + tgt_node_add(l, c); + + val = DEFAULT_RPM; + c = tgt_node_alloc(XML_ELEMENT_RPM, Int, &val); + tgt_node_add(l, c); + + c = tgt_node_alloc(XML_ELEMENT_HEADS, Int, &heads); + tgt_node_add(l, c); + + c = tgt_node_alloc(XML_ELEMENT_CYLINDERS, Int, &cylinders); + tgt_node_add(l, c); + + c = tgt_node_alloc(XML_ELEMENT_SPT, Int, &spt); + tgt_node_add(l, c); + + val = DEFAULT_BYTES_PER; + c = tgt_node_alloc(XML_ELEMENT_BPS, Int, &val); + tgt_node_add(l, c); + + val = DEFAULT_INTERLEAVE; + c = tgt_node_alloc(XML_ELEMENT_INTERLEAVE, Int, &val); + tgt_node_add(l, c); + + c = tgt_node_alloc(XML_ELEMENT_STATUS, String, TGT_STATUS_ONLINE); + tgt_node_add(l, c); +}
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_list.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/mgmt_list.c Wed Nov 15 19:25:44 2006 -0800 @@ -36,8 +36,8 @@ #include <strings.h> #include <dirent.h> +#include <iscsitgt_impl.h> #include "utility.h" -#include <xml.h> #include "queue.h" #include "target.h" #include "iscsi_cmd.h" @@ -45,18 +45,18 @@ #include "port.h" #include "errcode.h" -static char *list_targets(xml_node_t *x); -static char *list_initiator(xml_node_t *x); -static char *list_tpgt(xml_node_t *x); -static char *list_admin(xml_node_t *x); -static void target_info(char **msg, char *targ_name, xml_node_t *tnode); +static char *list_targets(tgt_node_t *x); +static char *list_initiator(tgt_node_t *x); +static char *list_tpgt(tgt_node_t *x); +static char *list_admin(tgt_node_t *x); +static void target_info(char **msg, char *targ_name, tgt_node_t *tnode); static void target_stat(char **msg, char *iname, mgmt_type_t type); /*ARGSUSED*/ void -list_func(xml_node_t *p, target_queue_t *reply, target_queue_t *mgmt) +list_func(tgt_node_t *p, target_queue_t *reply, target_queue_t *mgmt) { - xml_node_t *x; + tgt_node_t *x; char msgbuf[80], *reply_msg = NULL; @@ -86,12 +86,12 @@ } static char * -list_targets(xml_node_t *x) +list_targets(tgt_node_t *x) { char *msg = NULL, *prop = NULL, *iname = NULL; - xml_node_t *targ = NULL; + tgt_node_t *targ = NULL; Boolean_t luninfo = False, dostat = False; @@ -100,153 +100,156 @@ * administrator wants a complete list of targets. However if a * "name" is supplied then there must be a value for that element. */ - if ((xml_find_value_str(x, XML_ELEMENT_NAME, &prop) == True) && + if ((tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == True) && (prop == NULL)) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); return (msg); } /* ---- optional arguments ---- */ - (void) xml_find_value_boolean(x, XML_ELEMENT_LUNINFO, &luninfo); - (void) xml_find_value_boolean(x, XML_ELEMENT_IOSTAT, &dostat); + (void) tgt_find_value_boolean(x, XML_ELEMENT_LUNINFO, &luninfo); + (void) tgt_find_value_boolean(x, XML_ELEMENT_IOSTAT, &dostat); - buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'"); - while ((targ = xml_node_next(targets_config, XML_ELEMENT_TARG, + tgt_buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'"); + while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG, targ)) != NULL) { if (targ->x_value == NULL) { - xml_add_tag(&msg, XML_ELEMENT_TARG, + tgt_buf_add(&msg, XML_ELEMENT_TARG, "bogus entry"); continue; } - if (xml_find_value_str(targ, XML_ELEMENT_INAME, &iname) == + if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &iname) == False) { - xml_add_tag(&msg, XML_ELEMENT_TARG, + tgt_buf_add(&msg, XML_ELEMENT_TARG, "missing iscsi-name"); continue; } if (prop != NULL) { if (strcmp(prop, targ->x_value) == 0) { - buf_add_tag(&msg, XML_ELEMENT_TARG, Tag_Start); - buf_add_tag(&msg, targ->x_value, Tag_String); - xml_add_tag(&msg, XML_ELEMENT_INAME, iname); + tgt_buf_add_tag(&msg, XML_ELEMENT_TARG, + Tag_Start); + tgt_buf_add_tag(&msg, targ->x_value, + Tag_String); + tgt_buf_add(&msg, XML_ELEMENT_INAME, iname); if (luninfo == True) target_info(&msg, iname, targ); if (dostat == True) target_stat(&msg, iname, mgmt_full_phase_statistics); - buf_add_tag(&msg, XML_ELEMENT_TARG, Tag_End); + tgt_buf_add_tag(&msg, XML_ELEMENT_TARG, + Tag_End); } } else { - buf_add_tag(&msg, XML_ELEMENT_TARG, Tag_Start); - buf_add_tag(&msg, targ->x_value, Tag_String); - xml_add_tag(&msg, XML_ELEMENT_INAME, iname); + tgt_buf_add_tag(&msg, XML_ELEMENT_TARG, Tag_Start); + tgt_buf_add_tag(&msg, targ->x_value, Tag_String); + tgt_buf_add(&msg, XML_ELEMENT_INAME, iname); if (dostat == True) target_stat(&msg, iname, mgmt_full_phase_statistics); if (luninfo == True) target_info(&msg, iname, targ); - buf_add_tag(&msg, XML_ELEMENT_TARG, Tag_End); + tgt_buf_add_tag(&msg, XML_ELEMENT_TARG, Tag_End); } free(iname); } - buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End); + tgt_buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End); free(prop); return (msg); } static char * -list_initiator(xml_node_t *x) +list_initiator(tgt_node_t *x) { char *msg = NULL, *attr, *prop = NULL; Boolean_t verbose = False; - xml_node_t *init = NULL; + tgt_node_t *init = NULL; /* ---- Optional arguments ---- */ - if ((xml_find_value_str(x, XML_ELEMENT_NAME, &prop) == True) && + if ((tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == True) && (prop == NULL)) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); return (msg); } - (void) xml_find_value_boolean(x, XML_ELEMENT_VERBOSE, &verbose); + (void) tgt_find_value_boolean(x, XML_ELEMENT_VERBOSE, &verbose); - buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'"); - while ((init = xml_node_next(main_config, XML_ELEMENT_INIT, init)) != + tgt_buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'"); + while ((init = tgt_node_next(main_config, XML_ELEMENT_INIT, init)) != NULL) { if ((prop == NULL) || ((prop != NULL) && (strcmp(prop, init->x_value) == 0))) { - buf_add_tag(&msg, XML_ELEMENT_INIT, Tag_Start); - buf_add_tag(&msg, init->x_value, Tag_String); + tgt_buf_add_tag(&msg, XML_ELEMENT_INIT, Tag_Start); + tgt_buf_add_tag(&msg, init->x_value, Tag_String); - if (xml_find_value_str(init, XML_ELEMENT_INAME, + if (tgt_find_value_str(init, XML_ELEMENT_INAME, &attr) == True) { - xml_add_tag(&msg, XML_ELEMENT_INAME, attr); + tgt_buf_add(&msg, XML_ELEMENT_INAME, attr); free(attr); } - if (xml_find_value_str(init, XML_ELEMENT_CHAPSECRET, + if (tgt_find_value_str(init, XML_ELEMENT_CHAPSECRET, &attr) == True) { - xml_add_tag(&msg, XML_ELEMENT_CHAPSECRET, + tgt_buf_add(&msg, XML_ELEMENT_CHAPSECRET, attr); free(attr); } - if (xml_find_value_str(init, XML_ELEMENT_CHAPNAME, + if (tgt_find_value_str(init, XML_ELEMENT_CHAPNAME, &attr) == True) { - xml_add_tag(&msg, XML_ELEMENT_CHAPNAME, attr); + tgt_buf_add(&msg, XML_ELEMENT_CHAPNAME, attr); free(attr); } - buf_add_tag(&msg, XML_ELEMENT_INIT, Tag_End); + tgt_buf_add_tag(&msg, XML_ELEMENT_INIT, Tag_End); } } if (prop != NULL) free(prop); - buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End); + tgt_buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End); return (msg); } static char * -list_tpgt(xml_node_t *x) +list_tpgt(tgt_node_t *x) { char *msg = NULL, *prop = NULL; Boolean_t verbose = False; - xml_node_t *tpgt = NULL, + tgt_node_t *tpgt = NULL, *ip = NULL; /* ---- Optional arguments ---- */ - if ((xml_find_value_str(x, XML_ELEMENT_NAME, &prop) == True) && + if ((tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == True) && (prop == NULL)) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); return (msg); } - (void) xml_find_value_boolean(x, XML_ELEMENT_VERBOSE, &verbose); + (void) tgt_find_value_boolean(x, XML_ELEMENT_VERBOSE, &verbose); - buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'"); - while ((tpgt = xml_node_next(main_config, XML_ELEMENT_TPGT, tpgt)) != + tgt_buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'"); + while ((tpgt = tgt_node_next(main_config, XML_ELEMENT_TPGT, tpgt)) != NULL) { if ((prop == NULL) || ((prop != NULL) && (strcmp(prop, tpgt->x_value) == 0))) { - buf_add_tag(&msg, XML_ELEMENT_TPGT, Tag_Start); - buf_add_tag(&msg, tpgt->x_value, Tag_String); + tgt_buf_add_tag(&msg, XML_ELEMENT_TPGT, Tag_Start); + tgt_buf_add_tag(&msg, tpgt->x_value, Tag_String); - while ((ip = xml_node_next(tpgt, XML_ELEMENT_IPADDR, + while ((ip = tgt_node_next(tpgt, XML_ELEMENT_IPADDR, ip)) != NULL) { - xml_add_tag(&msg, ip->x_name, ip->x_value); + tgt_buf_add(&msg, ip->x_name, ip->x_value); } - buf_add_tag(&msg, XML_ELEMENT_TPGT, Tag_End); + tgt_buf_add_tag(&msg, XML_ELEMENT_TPGT, Tag_End); } } - buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End); + tgt_buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End); if (prop != NULL) free(prop); @@ -255,25 +258,25 @@ /*ARGSUSED*/ static char * -list_admin(xml_node_t *x) +list_admin(tgt_node_t *x) { char *msg = NULL; admin_table_t *p; - xml_node_t *node = NULL; + tgt_node_t *node = NULL; - buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'"); - buf_add_tag(&msg, XML_ELEMENT_ADMIN, Tag_Start); + tgt_buf_add_tag_and_attr(&msg, XML_ELEMENT_RESULT, "version='1.0'"); + tgt_buf_add_tag(&msg, XML_ELEMENT_ADMIN, Tag_Start); node = NULL; for (p = admin_prop_list; p->name != NULL; p++) { - node = xml_node_next_child(main_config, p->name, NULL); + node = tgt_node_next_child(main_config, p->name, NULL); if (node) { - xml_add_tag(&msg, p->name, node->x_value); + tgt_buf_add(&msg, p->name, node->x_value); } } - buf_add_tag(&msg, XML_ELEMENT_ADMIN, Tag_End); - buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End); + tgt_buf_add_tag(&msg, XML_ELEMENT_ADMIN, Tag_End); + tgt_buf_add_tag(&msg, XML_ELEMENT_RESULT, Tag_End); return (msg); } @@ -335,113 +338,128 @@ } static void -target_info(char **msg, char *targ_name, xml_node_t *tnode) +target_info(char **msg, char *targ_name, tgt_node_t *tnode) { char path[MAXPATHLEN], lun_buf[16], *prop; xmlTextReaderPtr r; - xml_node_t *lnode, /* list node */ + tgt_node_t *lnode, /* list node */ *lnp, /* list node pointer */ *lun, *params; int xml_fd, lun_num; + Boolean_t incore; - if ((lnode = xml_node_next(tnode, XML_ELEMENT_ACLLIST, NULL)) != + if ((lnode = tgt_node_next(tnode, XML_ELEMENT_ACLLIST, NULL)) != NULL) { lnp = NULL; - buf_add_tag(msg, XML_ELEMENT_ACLLIST, Tag_Start); - while ((lnp = xml_node_next(lnode, XML_ELEMENT_INIT, lnp)) != + tgt_buf_add_tag(msg, XML_ELEMENT_ACLLIST, Tag_Start); + while ((lnp = tgt_node_next(lnode, XML_ELEMENT_INIT, lnp)) != NULL) - xml_add_tag(msg, XML_ELEMENT_INIT, lnp->x_value); - buf_add_tag(msg, XML_ELEMENT_ACLLIST, Tag_End); + tgt_buf_add(msg, XML_ELEMENT_INIT, lnp->x_value); + tgt_buf_add_tag(msg, XML_ELEMENT_ACLLIST, Tag_End); } - if ((lnode = xml_node_next(tnode, XML_ELEMENT_TPGTLIST, NULL)) != + if ((lnode = tgt_node_next(tnode, XML_ELEMENT_TPGTLIST, NULL)) != NULL) { lnp = NULL; - buf_add_tag(msg, XML_ELEMENT_TPGTLIST, Tag_Start); - while ((lnp = xml_node_next(lnode, XML_ELEMENT_TPGT, lnp)) != + tgt_buf_add_tag(msg, XML_ELEMENT_TPGTLIST, Tag_Start); + while ((lnp = tgt_node_next(lnode, XML_ELEMENT_TPGT, lnp)) != NULL) - xml_add_tag(msg, XML_ELEMENT_TPGT, lnp->x_value); - buf_add_tag(msg, XML_ELEMENT_TPGTLIST, Tag_End); + tgt_buf_add(msg, XML_ELEMENT_TPGT, lnp->x_value); + tgt_buf_add_tag(msg, XML_ELEMENT_TPGTLIST, Tag_End); } - if ((lnode = xml_node_next(tnode, XML_ELEMENT_ALIAS, NULL)) != NULL) - xml_add_tag(msg, XML_ELEMENT_ALIAS, lnode->x_value); + if ((lnode = tgt_node_next(tnode, XML_ELEMENT_ALIAS, NULL)) != NULL) + tgt_buf_add(msg, XML_ELEMENT_ALIAS, lnode->x_value); - if ((lnode = xml_node_next(tnode, XML_ELEMENT_MAXRECV, NULL)) != NULL) - xml_add_tag(msg, XML_ELEMENT_MAXRECV, lnode->x_value); + if ((lnode = tgt_node_next(tnode, XML_ELEMENT_MAXRECV, NULL)) != NULL) + tgt_buf_add(msg, XML_ELEMENT_MAXRECV, lnode->x_value); - if ((lnode = xml_node_next(tnode, XML_ELEMENT_LUNLIST, NULL)) == NULL) + if ((lnode = tgt_node_next(tnode, XML_ELEMENT_LUNLIST, NULL)) == NULL) return; - buf_add_tag(msg, XML_ELEMENT_LUNINFO, Tag_Start); + if (tgt_find_attr_str(tnode, XML_ELEMENT_INCORE, &prop) == True) { + if (strcmp(prop, "true") == 0) + incore = True; + else + incore = False; + free(prop); + } else + incore = False; + + tgt_buf_add_tag(msg, XML_ELEMENT_LUNINFO, Tag_Start); lun = NULL; - while ((lun = xml_node_next(lnode, XML_ELEMENT_LUN, lun)) != NULL) { - if ((xml_find_value_int(lun, XML_ELEMENT_LUN, &lun_num)) == + while ((lun = tgt_node_next(lnode, XML_ELEMENT_LUN, lun)) != NULL) { + if ((tgt_find_value_int(lun, XML_ELEMENT_LUN, &lun_num)) == False) continue; - (void) snprintf(path, sizeof (path), "%s/%s/%s%d", - target_basedir, targ_name, PARAMBASE, lun_num); - if ((xml_fd = open(path, O_RDONLY)) < 0) - continue; - if ((r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd, - NULL, NULL, 0)) == NULL) - continue; + if (incore == False) { + (void) snprintf(path, sizeof (path), "%s/%s/%s%d", + target_basedir, targ_name, PARAMBASE, lun_num); + if ((xml_fd = open(path, O_RDONLY)) < 0) + continue; + if ((r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd, + NULL, NULL, 0)) == NULL) + continue; - params = NULL; - while (xmlTextReaderRead(r) == 1) { - if (xml_process_node(r, ¶ms) == False) - break; + params = NULL; + while (xmlTextReaderRead(r) == 1) { + if (tgt_node_process(r, ¶ms) == False) + break; + } + (void) close(xml_fd); + xmlTextReaderClose(r); + xmlFreeTextReader(r); + } else { + params = lun; } - (void) close(xml_fd); - xmlTextReaderClose(r); - xmlFreeTextReader(r); - - buf_add_tag(msg, XML_ELEMENT_LUN, Tag_Start); - snprintf(lun_buf, sizeof (lun_buf), "%d", lun_num); - buf_add_tag(msg, lun_buf, Tag_String); - if (xml_find_value_str(params, XML_ELEMENT_GUID, &prop) == + tgt_buf_add_tag(msg, XML_ELEMENT_LUN, Tag_Start); + snprintf(lun_buf, sizeof (lun_buf), "%d", lun_num); + tgt_buf_add_tag(msg, lun_buf, Tag_String); + + if (tgt_find_value_str(params, XML_ELEMENT_GUID, &prop) == True) { - xml_add_tag(msg, XML_ELEMENT_GUID, prop); - free(prop); - } - if (xml_find_value_str(params, XML_ELEMENT_VID, &prop) == - True) { - xml_add_tag(msg, XML_ELEMENT_VID, prop); + tgt_buf_add(msg, XML_ELEMENT_GUID, prop); free(prop); } - if (xml_find_value_str(params, XML_ELEMENT_PID, &prop) == + if (tgt_find_value_str(params, XML_ELEMENT_VID, &prop) == True) { - xml_add_tag(msg, XML_ELEMENT_PID, prop); + tgt_buf_add(msg, XML_ELEMENT_VID, prop); free(prop); } - if (xml_find_value_str(params, XML_ELEMENT_DTYPE, &prop) == + if (tgt_find_value_str(params, XML_ELEMENT_PID, &prop) == True) { - xml_add_tag(msg, XML_ELEMENT_DTYPE, prop); + tgt_buf_add(msg, XML_ELEMENT_PID, prop); free(prop); } - if (xml_find_value_str(params, XML_ELEMENT_SIZE, &prop) == + if (tgt_find_value_str(params, XML_ELEMENT_DTYPE, &prop) == True) { - xml_add_tag(msg, XML_ELEMENT_SIZE, prop); + tgt_buf_add(msg, XML_ELEMENT_DTYPE, prop); free(prop); } - if (xml_find_value_str(params, XML_ELEMENT_STATUS, &prop) == + if (tgt_find_value_str(params, XML_ELEMENT_SIZE, &prop) == True) { - xml_add_tag(msg, XML_ELEMENT_STATUS, prop); + tgt_buf_add(msg, XML_ELEMENT_SIZE, prop); + free(prop); + } + if (tgt_find_value_str(params, XML_ELEMENT_STATUS, &prop) == + True) { + tgt_buf_add(msg, XML_ELEMENT_STATUS, prop); free(prop); } - if (xml_find_value_str(params, XML_ELEMENT_BACK, &prop) == + if (tgt_find_value_str(params, XML_ELEMENT_BACK, &prop) == True) { - xml_add_tag(msg, XML_ELEMENT_BACK, prop); + tgt_buf_add(msg, XML_ELEMENT_BACK, prop); free(prop); } - buf_add_tag(msg, XML_ELEMENT_LUN, Tag_End); + tgt_buf_add_tag(msg, XML_ELEMENT_LUN, Tag_End); - xml_tree_free(params); + if (incore == False) + tgt_node_free(params); } - buf_add_tag(msg, XML_ELEMENT_LUNINFO, Tag_End); + tgt_buf_add_tag(msg, XML_ELEMENT_LUNINFO, Tag_End); }
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_modify.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/mgmt_modify.c Wed Nov 15 19:25:44 2006 -0800 @@ -38,19 +38,21 @@ #include <assert.h> #include <sys/socket.h> #include <netdb.h> +#include <libzfs.h> -#include "xml.h" +#include <iscsitgt_impl.h> #include "queue.h" #include "utility.h" #include "iscsi_cmd.h" #include "target.h" #include "errcode.h" -static char *modify_target(xml_node_t *x); -static char *modify_initiator(xml_node_t *x); -static char *modify_admin(xml_node_t *x); -static char *modify_tpgt(xml_node_t *x); -static Boolean_t modify_element(char *, char *, xml_node_t *, match_type_t); +static char *modify_target(tgt_node_t *x); +static char *modify_initiator(tgt_node_t *x); +static char *modify_admin(tgt_node_t *x); +static char *modify_tpgt(tgt_node_t *x); +static char *modify_zfs(tgt_node_t *x); +static Boolean_t modify_element(char *, char *, tgt_node_t *, match_type_t); /* * []---- @@ -59,9 +61,9 @@ */ /*ARGSUSED*/ void -modify_func(xml_node_t *p, target_queue_t *reply, target_queue_t *mgmt) +modify_func(tgt_node_t *p, target_queue_t *reply, target_queue_t *mgmt) { - xml_node_t *x; + tgt_node_t *x; char *reply_msg = NULL; if (p->x_child == NULL) { @@ -80,6 +82,8 @@ reply_msg = modify_admin(x); } else if (strcmp(x->x_name, XML_ELEMENT_TPGT) == 0) { reply_msg = modify_tpgt(x); + } else if (strcmp(x->x_name, XML_ELEMENT_ZFS) == 0) { + reply_msg = modify_zfs(x); } else { xml_rtn_msg(&reply_msg, ERR_INVALID_OBJECT); } @@ -93,7 +97,7 @@ * []---- */ static char * -modify_target(xml_node_t *x) +modify_target(tgt_node_t *x) { char *msg = NULL, *name = NULL, @@ -103,7 +107,7 @@ path[MAXPATHLEN], *m, buf[512]; /* one sector size block */ - xml_node_t *t = NULL, + tgt_node_t *t = NULL, *list = NULL, *c = NULL, *node; @@ -117,12 +121,12 @@ struct stat st; xmlTextReaderPtr r; - if (xml_find_value_str(x, XML_ELEMENT_NAME, &name) == False) { + if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); return (msg); } - while ((t = xml_node_next(targets_config, XML_ELEMENT_TARG, + while ((t = tgt_node_next(targets_config, XML_ELEMENT_TARG, t)) != NULL) { if (strcmp(t->x_value, name) == 0) { break; @@ -146,7 +150,7 @@ * layer so that the LU thread can remap the smaller size without * anyone accessing the data. */ - if (xml_find_value_str(x, XML_ELEMENT_SIZE, &prop) == True) { + if (tgt_find_value_str(x, XML_ELEMENT_SIZE, &prop) == True) { if (prop == NULL) { xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT); return (msg); @@ -163,13 +167,13 @@ } new_lu_size /= 512LL; - if (xml_find_value_str(x, XML_ELEMENT_INAME, &iscsi) == False) { + if (tgt_find_value_str(x, XML_ELEMENT_INAME, &iscsi) == False) { xml_rtn_msg(&msg, ERR_TARGCFG_MISSING_INAME); return (msg); } /* ---- default to LUN 0 ---- */ - (void) xml_find_value_int(x, XML_ELEMENT_LUN, &lun); + (void) tgt_find_value_int(x, XML_ELEMENT_LUN, &lun); /* ---- read in current paramaters ---- */ snprintf(path, sizeof (path), "%s/%s/%s%d", target_basedir, @@ -182,7 +186,7 @@ 0)) != NULL) { node = NULL; while (xmlTextReaderRead(r) == 1) - if (xml_process_node(r, &node) == False) + if (tgt_node_process(r, &node) == False) break; } else { xml_rtn_msg(&msg, ERR_INIT_XML_READER_FAILED); @@ -194,7 +198,7 @@ xmlFreeTextReader(r); /* ---- validate that we're indeed growing the LU ---- */ - if (xml_find_value_str(node, XML_ELEMENT_SIZE, &prop) == + if (tgt_find_value_str(node, XML_ELEMENT_SIZE, &prop) == False) { xml_rtn_msg(&msg, ERR_INIT_XML_READER_FAILED); return (msg); @@ -212,7 +216,7 @@ } /* ---- check that this LU is of type 'disk' or 'tape' ---- */ - if (xml_find_value_str(node, XML_ELEMENT_DTYPE, &prop) == + if (tgt_find_value_str(node, XML_ELEMENT_DTYPE, &prop) == False) { xml_rtn_msg(&msg, ERR_INIT_XML_READER_FAILED); return (msg); @@ -239,18 +243,18 @@ /* ---- update the parameter node with new size ---- */ snprintf(size_str, sizeof (size_str), "0x%llx", new_lu_size); - if ((c = xml_alloc_node(XML_ELEMENT_SIZE, Uint64, size_str)) == + if ((c = tgt_node_alloc(XML_ELEMENT_SIZE, Uint64, size_str)) == False) { xml_rtn_msg(&msg, ERR_NO_MEM); return (msg); } - xml_replace_child(node, c, MatchName); - xml_tree_free(c); + tgt_node_replace(node, c, MatchName); + tgt_node_free(c); /* ---- now update params file ---- */ snprintf(path, sizeof (path), "%s/%s/%s%d", target_basedir, iscsi, PARAMBASE, lun); - if (xml_dump2file(node, path) == False) { + if (tgt_dump2file(node, path) == False) { xml_rtn_msg(&msg, ERR_UPDATE_TARGCFG_FAILED); return (msg); } @@ -275,10 +279,10 @@ free(iscsi); prop = NULL; - xml_tree_free(node); + tgt_node_free(node); } - if (xml_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) { + if (tgt_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) { if (prop == NULL) { xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ACL); return (msg); @@ -295,68 +299,68 @@ return (msg); } - if ((c = xml_alloc_node(XML_ELEMENT_TPGT, String, prop)) == + if ((c = tgt_node_alloc(XML_ELEMENT_TPGT, String, prop)) == NULL) { free(prop); xml_rtn_msg(&msg, ERR_NO_MEM); return (msg); } - if ((list = xml_node_next(t, XML_ELEMENT_TPGTLIST, + if ((list = tgt_node_next(t, XML_ELEMENT_TPGTLIST, NULL)) != NULL) { - xml_replace_child(list, c, MatchBoth); + tgt_node_replace(list, c, MatchBoth); /* - * xml_replace_child will duplicate the child node - * xml_add_child which is used below just links it + * tgt_node_replace will duplicate the child node + * tgt_node_add which is used below just links it * into the tree. */ - xml_tree_free(c); + tgt_node_free(c); } else { - list = xml_alloc_node(XML_ELEMENT_TPGTLIST, String, ""); + list = tgt_node_alloc(XML_ELEMENT_TPGTLIST, String, ""); if (list == NULL) { free(prop); xml_rtn_msg(&msg, ERR_NO_MEM); return (msg); } - (void) xml_add_child(list, c); - (void) xml_add_child(t, list); + tgt_node_add(list, c); + tgt_node_add(t, list); } free(prop); prop = NULL; change_made = True; } - if (xml_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) { + if (tgt_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) { if (prop == NULL) { xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ACL); return (msg); } - c = xml_alloc_node(XML_ELEMENT_INIT, String, prop); + c = tgt_node_alloc(XML_ELEMENT_INIT, String, prop); if (c == NULL) { xml_rtn_msg(&msg, ERR_NO_MEM); return (msg); } - if ((list = xml_node_next(t, XML_ELEMENT_ACLLIST, + if ((list = tgt_node_next(t, XML_ELEMENT_ACLLIST, NULL)) != NULL) { - xml_replace_child(list, c, MatchBoth); + tgt_node_replace(list, c, MatchBoth); /* ---- See above usage ---- */ - xml_tree_free(c); + tgt_node_free(c); } else { - list = xml_alloc_node(XML_ELEMENT_ACLLIST, String, ""); + list = tgt_node_alloc(XML_ELEMENT_ACLLIST, String, ""); if (list == NULL) { xml_rtn_msg(&msg, ERR_NO_MEM); return (msg); } - (void) xml_add_child(list, c); - (void) xml_add_child(t, list); + tgt_node_add(list, c); + tgt_node_add(t, list); } free(prop); prop = NULL; change_made = True; } - if (xml_find_value_str(x, XML_ELEMENT_ALIAS, &prop) == True) { + if (tgt_find_value_str(x, XML_ELEMENT_ALIAS, &prop) == True) { if (prop == NULL) { xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ALIAS); return (msg); @@ -372,7 +376,7 @@ change_made = True; } - if (xml_find_value_str(x, XML_ELEMENT_MAXRECV, &prop) == True) { + if (tgt_find_value_str(x, XML_ELEMENT_MAXRECV, &prop) == True) { if (prop == NULL) { xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_MAXRECV); return (msg); @@ -418,20 +422,20 @@ * []---- */ static char * -modify_initiator(xml_node_t *x) +modify_initiator(tgt_node_t *x) { char *msg = NULL, *name = NULL, *prop = NULL; - xml_node_t *inode = NULL; + tgt_node_t *inode = NULL; Boolean_t changes_made = False; - if (xml_find_value_str(x, XML_ELEMENT_NAME, &name) == False) { + if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); return (msg); } - while ((inode = xml_node_next(main_config, XML_ELEMENT_INIT, + while ((inode = tgt_node_next(main_config, XML_ELEMENT_INIT, inode)) != NULL) { if (strcmp(inode->x_value, name) == 0) break; @@ -449,7 +453,7 @@ return (msg); } - if (xml_find_value_str(x, XML_ELEMENT_CHAPSECRET, &prop) == True) { + if (tgt_find_value_str(x, XML_ELEMENT_CHAPSECRET, &prop) == True) { if (prop == NULL) { xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_CHAPSECRET); return (msg); @@ -464,7 +468,7 @@ changes_made = True; } - if (xml_find_value_str(x, XML_ELEMENT_CHAPNAME, &prop) == True) { + if (tgt_find_value_str(x, XML_ELEMENT_CHAPNAME, &prop) == True) { if (prop == NULL) { xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_CHAPNAME); return (msg); @@ -495,7 +499,7 @@ * []---- */ static char * -modify_admin(xml_node_t *x) +modify_admin(tgt_node_t *x) { char *msg = NULL, *prop; @@ -503,7 +507,7 @@ admin_table_t *ap; for (ap = admin_prop_list; ap->name; ap++) { - if (xml_find_value_str(x, ap->name, &prop) == True) { + if (tgt_find_value_str(x, ap->name, &prop) == True) { if ((prop == NULL) || (strlen(prop) == 0)) break; @@ -542,19 +546,19 @@ * []---- */ static char * -modify_tpgt(xml_node_t *x) +modify_tpgt(tgt_node_t *x) { struct addrinfo *res = NULL; char *msg = NULL, *name = NULL, *ip_str = NULL; - xml_node_t *tnode = NULL; + tgt_node_t *tnode = NULL; - if (xml_find_value_str(x, XML_ELEMENT_NAME, &name) == False) { + if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); goto error; } - if (xml_find_value_str(x, XML_ELEMENT_IPADDR, &ip_str) == False) { + if (tgt_find_value_str(x, XML_ELEMENT_IPADDR, &ip_str) == False) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_IPADDR); goto error; } @@ -562,7 +566,7 @@ xml_rtn_msg(&msg, ERR_INVALID_IP); goto error; } - while ((tnode = xml_node_next(main_config, XML_ELEMENT_TPGT, + while ((tnode = tgt_node_next(main_config, XML_ELEMENT_TPGT, tnode)) != NULL) { if (strcmp(tnode->x_value, name) == 0) break; @@ -588,6 +592,52 @@ return (msg); } +static char * +modify_zfs(tgt_node_t *x) +{ + char *msg = NULL, + *prop = NULL, + *dataset = NULL; + libzfs_handle_t *zh = NULL; + zfs_handle_t *zfsh = NULL; + tgt_node_t *n = NULL; + + if (tgt_find_value_str(x, XML_ELEMENT_NAME, &dataset) == False) { + xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); + return (msg); + } + + if (((zh = libzfs_init()) == NULL) || + ((zfsh = zfs_open(zh, dataset, ZFS_TYPE_ANY)) == NULL)) { + xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND); + goto error; + } + + while ((n = tgt_node_next(targets_config, XML_ELEMENT_TARG, n)) != + NULL) { + if (strcmp(n->x_value, dataset) == 0) + break; + } + if (n == NULL) { + xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND); + goto error; + } + + xml_rtn_msg(&msg, ERR_SUCCESS); + +error: + if (zfsh) + zfs_close(zfsh); + if (prop) + free(prop); + if (zh) + libzfs_fini(zh); + if (dataset) + free(dataset); + + return (msg); +} + /* * []---- * | modify_element -- helper function to create node and add it to parent @@ -596,15 +646,15 @@ * []---- */ static Boolean_t -modify_element(char *name, char *value, xml_node_t *p, match_type_t m) +modify_element(char *name, char *value, tgt_node_t *p, match_type_t m) { - xml_node_t *c; + tgt_node_t *c; - if ((c = xml_alloc_node(name, String, value)) == NULL) + if ((c = tgt_node_alloc(name, String, value)) == NULL) return (False); else { - xml_replace_child(p, c, m); - xml_tree_free(c); + tgt_node_replace(p, c, m); + tgt_node_free(c); return (True); } } @@ -625,7 +675,7 @@ char * update_basedir(char *name, char *prop) { - xml_node_t *targ = NULL; + tgt_node_t *targ = NULL; int count = 0; char *msg = NULL; @@ -634,7 +684,7 @@ return (msg); } - while ((targ = xml_node_next(targets_config, XML_ELEMENT_TARG, + while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG, targ)) != NULL) { count++; }
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c Wed Nov 15 19:25:44 2006 -0800 @@ -36,22 +36,24 @@ #include <strings.h> #include <unistd.h> +#include <iscsitgt_impl.h> #include "utility.h" -#include "xml.h" #include "queue.h" #include "target.h" #include "iscsi_cmd.h" #include "errcode.h" -static char *remove_target(xml_node_t *x); -static char *remove_initiator(xml_node_t *x); -static char *remove_tpgt(xml_node_t *x); +static char *remove_target(tgt_node_t *x); +static char *remove_initiator(tgt_node_t *x); +static char *remove_tpgt(tgt_node_t *x); +static char *remove_zfs(tgt_node_t *x); + /*ARGSUSED*/ void -remove_func(xml_node_t *p, target_queue_t *reply, target_queue_t *mgmt) +remove_func(tgt_node_t *p, target_queue_t *reply, target_queue_t *mgmt) { - xml_node_t *x; + tgt_node_t *x; char msgbuf[80], *reply_msg = NULL; @@ -68,6 +70,8 @@ reply_msg = remove_initiator(x); } else if (strcmp(x->x_name, XML_ELEMENT_TPGT) == 0) { reply_msg = remove_tpgt(x); + } else if (strcmp(x->x_name, XML_ELEMENT_ZFS) == 0) { + reply_msg = remove_zfs(x); } else { (void) snprintf(msgbuf, sizeof (msgbuf), "Unknown object '%s' for delete element", @@ -79,22 +83,71 @@ } static char * -remove_target(xml_node_t *x) +remove_zfs(tgt_node_t *x) +{ + char *prop, + *msg = NULL; + tgt_node_t *targ = NULL; + + if (tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) { + xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); + return (msg); + } + + while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG, targ)) + != NULL) { + if (strcmp(targ->x_value, prop) == 0) + break; + } + free(prop); + if (targ == NULL) { + /* + * We're unsharing a target. If we don't have a reference + * then there's no problem. + */ + xml_rtn_msg(&msg, ERR_SUCCESS); + return (msg); + } + if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &prop) == + False) { + xml_rtn_msg(&msg, ERR_TARGCFG_MISSING_INAME); + return (msg); + } + + tgt_node_remove(targets_config, targ, MatchBoth); + + /* + * Wait until here to issue a logout to any initiators that + * might be logged into the target. Certain initiators are + * sneaky in that if asked to logout they will, but turn right + * around and log back into the target. By waiting until here + * to issue the logout we'll have removed reference to the target + * such that this can't happen. + */ + logout_targ(prop); + free(prop); + + xml_rtn_msg(&msg, ERR_SUCCESS); + return (msg); +} + +static char * +remove_target(tgt_node_t *x) { char *msg = NULL, *prop = NULL; - xml_node_t *targ = NULL, + tgt_node_t *targ = NULL, *list, *c = NULL; Boolean_t change_made = False; int lun_num; - if (xml_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) { + if (tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); return (msg); } - while ((targ = xml_node_next(targets_config, XML_ELEMENT_TARG, targ)) != + while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG, targ)) != NULL) { if (strcmp(targ->x_value, prop) == 0) break; @@ -104,53 +157,53 @@ xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND); return (msg); } - if (xml_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) { + if (tgt_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) { if (prop == NULL) { xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ACL); return (msg); } - if ((list = xml_node_next(targ, XML_ELEMENT_ACLLIST, NULL)) == + if ((list = tgt_node_next(targ, XML_ELEMENT_ACLLIST, NULL)) == NULL) { free(prop); xml_rtn_msg(&msg, ERR_ACL_NOT_FOUND); return (msg); } - c = xml_alloc_node(XML_ELEMENT_INIT, String, prop); - if (xml_remove_child(list, c, MatchBoth) == False) { + c = tgt_node_alloc(XML_ELEMENT_INIT, String, prop); + if (tgt_node_remove(list, c, MatchBoth) == False) { xml_rtn_msg(&msg, ERR_INIT_NOT_FOUND); goto error; } - xml_free_node(c); + tgt_node_free(c); if (list->x_child == NULL) - (void) xml_remove_child(targ, list, MatchName); + (void) tgt_node_remove(targ, list, MatchName); free(prop); change_made = True; } - if (xml_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) { + if (tgt_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) { if (prop == NULL) { xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT); return (msg); } - if ((list = xml_node_next(targ, XML_ELEMENT_TPGTLIST, NULL)) == + if ((list = tgt_node_next(targ, XML_ELEMENT_TPGTLIST, NULL)) == NULL) { free(prop); xml_rtn_msg(&msg, ERR_ACL_NOT_FOUND); return (msg); } - c = xml_alloc_node(XML_ELEMENT_TPGT, String, prop); - if (xml_remove_child(list, c, MatchBoth) == False) { + c = tgt_node_alloc(XML_ELEMENT_TPGT, String, prop); + if (tgt_node_remove(list, c, MatchBoth) == False) { xml_rtn_msg(&msg, ERR_TPGT_NOT_FOUND); goto error; } - xml_free_node(c); + tgt_node_free(c); if (list->x_child == NULL) - (void) xml_remove_child(targ, list, MatchName); + (void) tgt_node_remove(targ, list, MatchName); free(prop); change_made = True; } - if (xml_find_value_int(x, XML_ELEMENT_LUN, &lun_num) == True) { + if (tgt_find_value_int(x, XML_ELEMENT_LUN, &lun_num) == True) { - if (xml_find_value_intchk(x, XML_ELEMENT_LUN, &lun_num) == + if (tgt_find_value_intchk(x, XML_ELEMENT_LUN, &lun_num) == False) { xml_rtn_msg(&msg, ERR_LUN_INVALID_RANGE); return (msg); @@ -159,7 +212,7 @@ /* * Save the iscsi-name which we'll need to remove LUNs. */ - if (xml_find_value_str(targ, XML_ELEMENT_INAME, &prop) == + if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &prop) == False) { xml_rtn_msg(&msg, ERR_TARGCFG_MISSING_INAME); return (msg); @@ -188,24 +241,24 @@ error: if (c != NULL) - xml_free_node(c); + tgt_node_free(c); if (prop != NULL) free(prop); return (msg); } static char * -remove_initiator(xml_node_t *x) +remove_initiator(tgt_node_t *x) { char *msg = NULL, *name; - xml_node_t *node = NULL; + tgt_node_t *node = NULL; - if (xml_find_value_str(x, XML_ELEMENT_NAME, &name) == False) { + if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); return (msg); } - while ((node = xml_node_next(main_config, XML_ELEMENT_INIT, node)) != + while ((node = tgt_node_next(main_config, XML_ELEMENT_INIT, node)) != NULL) { if (strcmp(node->x_value, name) == 0) break; @@ -215,11 +268,11 @@ xml_rtn_msg(&msg, ERR_INIT_NOT_FOUND); return (msg); } - if (xml_find_value_str(x, XML_ELEMENT_ALL, &name) == False) { + if (tgt_find_value_str(x, XML_ELEMENT_ALL, &name) == False) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_ALL); return (msg); } - (void) xml_remove_child(main_config, node, MatchBoth); + (void) tgt_node_remove(main_config, node, MatchBoth); if (update_config_main(&msg) == True) xml_rtn_msg(&msg, ERR_SUCCESS); @@ -228,19 +281,19 @@ } static char * -remove_tpgt(xml_node_t *x) +remove_tpgt(tgt_node_t *x) { char *msg = NULL, *prop = NULL; - xml_node_t *node = NULL, + tgt_node_t *node = NULL, *c = NULL; Boolean_t change_made = False; - if (xml_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) { + if (tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) { xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); return (msg); } - while ((node = xml_node_next(main_config, XML_ELEMENT_TPGT, node)) != + while ((node = tgt_node_next(main_config, XML_ELEMENT_TPGT, node)) != NULL) { if (strcmp(node->x_value, prop) == 0) break; @@ -250,23 +303,23 @@ xml_rtn_msg(&msg, ERR_TPGT_NOT_FOUND); return (msg); } - if (xml_find_value_str(x, XML_ELEMENT_IPADDR, &prop) == True) { + if (tgt_find_value_str(x, XML_ELEMENT_IPADDR, &prop) == True) { if (prop == NULL) { xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_IPADDR); return (msg); } - c = xml_alloc_node(XML_ELEMENT_IPADDR, String, prop); - if (xml_remove_child(node, c, MatchBoth) == False) { + c = tgt_node_alloc(XML_ELEMENT_IPADDR, String, prop); + if (tgt_node_remove(node, c, MatchBoth) == False) { xml_rtn_msg(&msg, ERR_INVALID_IP); goto error; } - xml_free_node(c); + tgt_node_free(c); free(prop); change_made = True; } if ((change_made != True) && - (xml_find_value_str(x, XML_ELEMENT_ALL, &prop) == True)) { - xml_remove_child(main_config, node, MatchBoth); + (tgt_find_value_str(x, XML_ELEMENT_ALL, &prop) == True)) { + tgt_node_remove(main_config, node, MatchBoth); change_made = True; } @@ -281,7 +334,7 @@ error: if (c != NULL) - xml_free_node(c); + tgt_node_free(c); if (prop != NULL) free(prop); return (msg);
--- a/usr/src/cmd/iscsi/iscsitgtd/queue.h Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/queue.h Wed Nov 15 19:25:44 2006 -0800 @@ -36,10 +36,9 @@ #include <pthread.h> #include <sys/time.h> #include <stdarg.h> -#include <xml.h> #include <synch.h> -#include "local_types.h" +#include <iscsitgt_impl.h> #define Q_CONN_ERRS 0x00001 #define Q_CONN_LOGIN 0x00002 @@ -243,7 +242,7 @@ pthread_mutex_t m_resp_mutex; union { char **m_resp; - xml_node_t *m_node; + tgt_node_t *m_node; } m_u; } mgmt_request_t;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/iscsi/iscsitgtd/svc-iscsitgt Wed Nov 15 19:25:44 2006 -0800 @@ -0,0 +1,67 @@ +#!/sbin/sh +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +. /lib/svc/share/smf_include.sh +zone=`smf_zonename` + +case "$1" in +'start') + if smf_is_nonglobalzone; then + /usr/sbin/svcadm disable -t svc:/system/iscsitgt + echo "The iSCSI target is not supported in a local zone" + sleep 5 & + exit $SMF_EXIT_OK + fi + + /usr/sbin/iscsitgtd + + if [ $? -ne 0 ]; then + echo "Failed to start iSCSI daemon" + exit 1 + fi + + if [ -x /usr/sbin/zfs ]; then + /usr/sbin/zfs share -a iscsi + fi + + ;; + +'stop') + # Kill any processes in the service contract + smf_kill_contract $2 TERM 1 + [ $? -ne 0 ] && exit 1 + ;; + +*) + echo "Usage: $0 { start | stop }" + exit 1 + ;; +esac + +exit $SMF_EXIT_OK
--- a/usr/src/cmd/iscsi/iscsitgtd/t10.h Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/t10.h Wed Nov 15 19:25:44 2006 -0800 @@ -325,7 +325,8 @@ /* * Parameter information in XML format. */ - xml_node_t *l_root; + tgt_node_t *l_root; + Boolean_t l_root_okay_to_free; /* * File descriptor for the open file which is the backing store @@ -499,6 +500,15 @@ char *cmd_name; } scsi_cmd_table_t; +typedef struct sam_device_table { + Boolean_t (*t_common_init)(t10_lu_common_t *); + void (*t_common_fini)(t10_lu_common_t *); + void (*t_per_init)(t10_lu_impl_t *); + void (*t_per_fini)(t10_lu_impl_t *); + void (*t_task_mgmt)(t10_lu_common_t *, TaskOp_t); + char *t_type_name; +} sam_device_table_t; + /* * []---- * | Interfaces @@ -611,24 +621,26 @@ * | Declaration of emulation entry points | * []------------------------------------------------------------------[] */ -Boolean_t sbc_init_common(t10_lu_common_t *lu); -void sbc_fini_common(t10_lu_common_t *lu); +Boolean_t sbc_common_init(t10_lu_common_t *lu); +void sbc_common_fini(t10_lu_common_t *lu); void sbc_task_mgmt(t10_lu_common_t *lu, TaskOp_t op); -void sbc_init_per(t10_lu_impl_t *itl); -void sbc_fini_per(t10_lu_impl_t *itl); -Boolean_t ssc_init_common(t10_lu_common_t *lu); -void ssc_fini_common(t10_lu_common_t *lu); +void sbc_per_init(t10_lu_impl_t *itl); +void sbc_per_fini(t10_lu_impl_t *itl); +Boolean_t ssc_common_init(t10_lu_common_t *lu); +void ssc_common_fini(t10_lu_common_t *lu); void ssc_task_mgmt(t10_lu_common_t *lu, TaskOp_t op); -void ssc_init_per(t10_lu_impl_t *itl); -void ssc_fini_per(t10_lu_impl_t *itl); -Boolean_t raw_init_common(t10_lu_common_t *lu); -void raw_fini_common(t10_lu_common_t *lu); -void raw_init_per(t10_lu_impl_t *itl); -void raw_fini_per(t10_lu_impl_t *itl); -Boolean_t osd_init_common(t10_lu_common_t *lu); -void osd_fini_common(t10_lu_common_t *lu); -void osd_init_per(t10_lu_impl_t *itl); -void osd_fini_per(t10_lu_impl_t *itl); +void ssc_per_init(t10_lu_impl_t *itl); +void ssc_per_fini(t10_lu_impl_t *itl); +Boolean_t raw_common_init(t10_lu_common_t *lu); +void raw_common_fini(t10_lu_common_t *lu); +void raw_per_init(t10_lu_impl_t *itl); +void raw_per_fini(t10_lu_impl_t *itl); +void raw_task_mgmt(t10_lu_common_t *lu, TaskOp_t op); +Boolean_t osd_common_init(t10_lu_common_t *lu); +void osd_common_fini(t10_lu_common_t *lu); +void osd_per_init(t10_lu_impl_t *itl); +void osd_per_fini(t10_lu_impl_t *itl); +void osd_task_mgmt(t10_lu_common_t *lu, TaskOp_t op); #ifdef __cplusplus }
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_osd.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/t10_osd.c Wed Nov 15 19:25:44 2006 -0800 @@ -72,16 +72,16 @@ */ /*ARGSUSED*/ Boolean_t -osd_init_common(t10_lu_common_t *lu) +osd_common_init(t10_lu_common_t *lu) { osd_params_t *o; char *str; - xml_node_t *node = lu->l_root; + tgt_node_t *node = lu->l_root; if ((o = (osd_params_t *)calloc(1, sizeof (*o))) == NULL) return (False); - if (xml_find_value_str(node, XML_ELEMENT_SIZE, &str) == True) { + if (tgt_find_value_str(node, XML_ELEMENT_SIZE, &str) == True) { o->o_size = strtoll(str, NULL, 0); free(str); } else { @@ -95,7 +95,7 @@ /*ARGSUSED*/ void -osd_fini_common(t10_lu_common_t *lu) +osd_common_fini(t10_lu_common_t *lu) { free(lu->l_dtype_params); } @@ -107,7 +107,7 @@ */ /*ARGSUSED*/ void -osd_init_per(t10_lu_impl_t *itl) +osd_per_init(t10_lu_impl_t *itl) { itl->l_cmd = osd_cmd; itl->l_data = osd_data; @@ -124,7 +124,13 @@ /*ARGSUSED*/ void -osd_fini_per(t10_lu_impl_t *itl) +osd_per_fini(t10_lu_impl_t *itl) +{ +} + +/*ARGSUSED*/ +void +osd_task_mgmt(t10_lu_common_t *lu, TaskOp_t op) { }
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_raw_if.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/t10_raw_if.c Wed Nov 15 19:25:44 2006 -0800 @@ -96,16 +96,16 @@ * []---- */ Boolean_t -raw_init_common(t10_lu_common_t *lu) +raw_common_init(t10_lu_common_t *lu) { - xml_node_t *node = lu->l_root; + tgt_node_t *node = lu->l_root; char *str; raw_params_t *r; if ((r = (raw_params_t *)calloc(1, sizeof (*r))) == NULL) return (False); - if (xml_find_value_str(node, XML_ELEMENT_SIZE, &str) == True) { + if (tgt_find_value_str(node, XML_ELEMENT_SIZE, &str) == True) { r->r_size = strtoll(str, NULL, 0); free(str); } @@ -114,7 +114,7 @@ } void -raw_fini_common(t10_lu_common_t *lu) +raw_common_fini(t10_lu_common_t *lu) { free(lu->l_dtype_params); } @@ -125,7 +125,7 @@ * []---- */ void -raw_init_per(t10_lu_impl_t *itl) +raw_per_init(t10_lu_impl_t *itl) { itl->l_cmd = raw_cmd; itl->l_data = raw_data; @@ -142,7 +142,13 @@ /*ARGSUSED*/ void -raw_fini_per(t10_lu_impl_t *itl) +raw_per_fini(t10_lu_impl_t *itl) +{ +} + +/*ARGSUSED*/ +void +raw_task_mgmt(t10_lu_common_t *t, TaskOp_t op) { }
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_sam.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/t10_sam.c Wed Nov 15 19:25:44 2006 -0800 @@ -29,6 +29,7 @@ #include <aio.h> #include <sys/aio.h> #include <sys/asynch.h> +#include <stdio.h> #include <stddef.h> #include <strings.h> #include <pthread.h> @@ -44,6 +45,8 @@ #include <unistd.h> #include <signal.h> #include <sys/ucontext.h> +#include <libzfs.h> +#include <assert.h> #include <sys/scsi/generic/sense.h> #include <sys/scsi/generic/status.h> @@ -89,6 +92,7 @@ static int find_lu_by_guid(const void *v1, const void *v2); static int find_lu_by_targ(const void *v1, const void *v2); static int find_cmd_by_addr(const void *v1, const void *v2); +static sam_device_table_t sam_emul_table[]; /* * Global variables @@ -765,18 +769,18 @@ itl = avl_first(&t->s_open_lu); while (itl) { - buf_add_tag(buf, XML_ELEMENT_LUN, Tag_Start); + tgt_buf_add_tag(buf, XML_ELEMENT_LUN, Tag_Start); (void) snprintf(lb, sizeof (lb), "%d", itl->l_common->l_num); - buf_add_tag(buf, lb, Tag_String); + tgt_buf_add_tag(buf, lb, Tag_String); (void) snprintf(lb, sizeof (lb), "%lld", itl->l_cmds_read); - xml_add_tag(buf, XML_ELEMENT_READCMDS, lb); + tgt_buf_add(buf, XML_ELEMENT_READCMDS, lb); (void) snprintf(lb, sizeof (lb), "%lld", itl->l_cmds_write); - xml_add_tag(buf, XML_ELEMENT_WRITECMDS, lb); + tgt_buf_add(buf, XML_ELEMENT_WRITECMDS, lb); (void) snprintf(lb, sizeof (lb), "%lld", itl->l_sects_read); - xml_add_tag(buf, XML_ELEMENT_READBLKS, lb); + tgt_buf_add(buf, XML_ELEMENT_READBLKS, lb); (void) snprintf(lb, sizeof (lb), "%lld", itl->l_sects_write); - xml_add_tag(buf, XML_ELEMENT_WRITEBLKS, lb); + tgt_buf_add(buf, XML_ELEMENT_WRITEBLKS, lb); switch (itl->l_common->l_state) { case lu_online: @@ -789,9 +793,9 @@ p = TGT_STATUS_ERRORED; break; } - xml_add_tag(buf, XML_ELEMENT_STATUS, p); + tgt_buf_add(buf, XML_ELEMENT_STATUS, p); - buf_add_tag(buf, XML_ELEMENT_LUN, Tag_End); + tgt_buf_add_tag(buf, XML_ELEMENT_LUN, Tag_End); itl = AVL_NEXT(&t->s_open_lu, itl); } } @@ -824,7 +828,7 @@ msg_t *m = NULL; target_queue_t *rq = NULL; char path[MAXPATHLEN]; - xml_node_t *n1; + tgt_node_t *n1; Boolean_t rval = False; struct statvfs fs; @@ -935,21 +939,22 @@ target_basedir, cmd->c_lu->l_targ->s_targ_base, PARAMBASE, lun); - if ((n1 = xml_find_child(cmd->c_lu->l_common->l_root, + cmd->c_lu->l_common->l_state = lu_online; + if ((n1 = tgt_node_find(cmd->c_lu->l_common->l_root, XML_ELEMENT_STATUS)) == NULL) { queue_prt(mgmtq, Q_STE_ERRS, "STE%x couldn't find <status>\n", lun); goto error; } - if (xml_update_value_str(n1, XML_ELEMENT_STATUS, + if (tgt_update_value_str(n1, XML_ELEMENT_STATUS, TGT_STATUS_ONLINE) == False) { queue_prt(mgmtq, Q_STE_ERRS, "STE%x Could update <status> to online\n", lun); goto error; } - if (xml_dump2file(cmd->c_lu->l_common->l_root, path) == + if (tgt_dump2file(cmd->c_lu->l_common->l_root, path) == False) { queue_prt(mgmtq, Q_STE_ERRS, "STE%x failed to dump out params\n", lun); @@ -1312,14 +1317,21 @@ search; avl_index_t wc = 0, /* where common */ wt = 0; /* where target */ - char *guid = NULL; + char *guid = NULL, + *str, + *dataset = NULL; t10_lu_common_t lc, *common = NULL; - xml_node_t *n = NULL, - *n1; + tgt_node_t *n = NULL, + *n1, + *targ, + *ll; xmlTextReaderPtr r = NULL; char path[MAXPATHLEN]; int xml_fd = -1; + libzfs_handle_t *zh; + zfs_handle_t *zfsh; + Boolean_t okay_to_free = True; bzero(&lc, sizeof (lc)); @@ -1365,76 +1377,138 @@ l->l_targ = t; l->l_targ_lun = lun; - /* - * To locate the common LUN structure we need to find the GUID - * for this LUN. That's the only parsing this section of code will - * do to the params file. - */ - (void) snprintf(path, sizeof (path), "%s/%s/%s%d", - target_basedir, t->s_targ_base, PARAMBASE, lun); - - (void) pthread_mutex_lock(&lu_list_mutex); - if ((xml_fd = open(path, O_RDONLY)) < 0) { - (void) pthread_mutex_unlock(&lu_list_mutex); - spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0); - /* ---- ACCESS DENIED - INVALID LU IDENTIFIER ---- */ - spc_sense_ascq(cmd, 0x20, 0x9); - goto error; - } - if ((r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd, NULL, NULL, - 0)) != NULL) { - while (xmlTextReaderRead(r) == 1) - if (xml_process_node(r, &n) == False) - break; - } else { - (void) pthread_mutex_unlock(&lu_list_mutex); - spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0); - goto error; + targ = NULL; + while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG, targ)) + != NULL) { + if ((tgt_find_value_str(targ, XML_ELEMENT_INAME, &str) == + True) && (strcmp(str, t->s_targ_base) == 0)) { + free(str); + break; + } else if (str) { + free(str); + str = NULL; + } } - (void) close(xml_fd); - /* - * Set xml_fd back to -1 so that if an error occurs later we don't - * attempt to close a file descriptor that another thread might have - * opened. - */ - xml_fd = -1; + if ((ll = tgt_node_next(targ, XML_ELEMENT_LUNLIST, NULL)) == NULL) + goto error; + if ((n = tgt_node_next(ll, XML_ELEMENT_LUN, NULL)) == NULL) + goto error; + if (tgt_find_value_str(n, XML_ELEMENT_GUID, &guid) == False) { + /* + * Set the targ variable back to NULL to indicate that + * we don't have an incore copy of the information. + * If the guid is currently 0, we'll update that value + * and update the ZFS property if targ is not NULL. + * Otherwise will update parameter file. + */ + targ = NULL; + + /* + * To locate the common LUN structure we need to find the GUID + * for this LUN. That's the only parsing this section of code + * will do to the params file. + */ + (void) snprintf(path, sizeof (path), "%s/%s/%s%d", + target_basedir, t->s_targ_base, PARAMBASE, lun); - xmlTextReaderClose(r); - xmlFreeTextReader(r); - r = NULL; + (void) pthread_mutex_lock(&lu_list_mutex); + if ((xml_fd = open(path, O_RDONLY)) < 0) { + (void) pthread_mutex_unlock(&lu_list_mutex); + spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0); + /* ---- ACCESS DENIED - INVALID LU IDENTIFIER ---- */ + spc_sense_ascq(cmd, 0x20, 0x9); + goto error; + } + n = NULL; + if ((r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd, NULL, NULL, + 0)) != NULL) { + while (xmlTextReaderRead(r) == 1) + if (tgt_node_process(r, &n) == False) + break; + } else { + (void) pthread_mutex_unlock(&lu_list_mutex); + spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0); + goto error; + } - if (xml_find_value_str(n, XML_ELEMENT_GUID, &guid) == False) { - (void) pthread_mutex_unlock(&lu_list_mutex); - spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0); - goto error; - } + (void) close(xml_fd); + /* + * Set xml_fd back to -1 so that if an error occurs later we + * don't attempt to close a file descriptor that another thread + * might have opened. + */ + xml_fd = -1; - if (strcmp(guid, "0") == 0) { + xmlTextReaderClose(r); + xmlFreeTextReader(r); + r = NULL; + okay_to_free = True; + + if (tgt_find_value_str(n, XML_ELEMENT_GUID, &guid) == False) { + (void) pthread_mutex_unlock(&lu_list_mutex); + spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0); + goto error; + } + + } else + okay_to_free = False; + + if ((strcmp(guid, "0") == 0) || (strcmp(guid, "0x0") == 0)) { free(guid); if (util_create_guid(&guid) == False) { (void) pthread_mutex_unlock(&lu_list_mutex); spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0); goto error; } - if ((n1 = xml_find_child(n, XML_ELEMENT_GUID)) == NULL) { + if ((n1 = tgt_node_find(n, XML_ELEMENT_GUID)) == NULL) { + (void) pthread_mutex_unlock(&lu_list_mutex); + spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0); + goto error; + } + if (tgt_update_value_str(n1, XML_ELEMENT_GUID, guid) == False) { (void) pthread_mutex_unlock(&lu_list_mutex); spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0); goto error; } - if (xml_update_value_str(n1, XML_ELEMENT_GUID, guid) == False) { - (void) pthread_mutex_unlock(&lu_list_mutex); - spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0); - goto error; - } - if (xml_dump2file(n, path) == False) { + if (targ != NULL) { + str = NULL; + tgt_dump2buf(targ, &str); + + if (tgt_find_value_str(targ, XML_ELEMENT_ALIAS, + &dataset) == False || + (zh = libzfs_init()) == NULL) + goto error; + + if ((zfsh = zfs_open(zh, dataset, ZFS_TYPE_ANY)) == + NULL) { + libzfs_fini(zh); + goto error; + } + + if (zfs_prop_set(zfsh, + zfs_prop_to_name(ZFS_PROP_ISCSIOPTIONS), + str) != 0) { + zfs_close(zfsh); + libzfs_fini(zh); + goto error; + } + + zfs_close(zfsh); + libzfs_fini(zh); + free(dataset); + free(str); + dataset = NULL; + str = NULL; + + } else if (tgt_dump2file(n, path) == False) { (void) pthread_mutex_unlock(&lu_list_mutex); spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0); goto error; } } - if (xml_decode_bytes(guid, &lc.l_guid, &lc.l_guid_len) == False) { + if (tgt_xml_decode(guid, &lc.l_guid, &lc.l_guid_len) == False) { (void) pthread_mutex_unlock(&lu_list_mutex); spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0); goto error; @@ -1463,6 +1537,9 @@ common->l_guid_len = lc.l_guid_len; common->l_fd = -1; /* not open yet */ common->l_mmap = MAP_FAILED; + common->l_root = n; + common->l_root_okay_to_free = okay_to_free; + n = NULL; (void) pthread_mutex_init(&common->l_common_mutex, NULL); @@ -1499,6 +1576,18 @@ * since the LU needs the information. */ free(lc.l_guid); + + /* + * A similar condition exists with the xml tree. If there's + * already a common LU then this node *may* have been created + * here if it's not a ZVOL. If it is a ZVOL tree then it will + * have the same address as that found in l_root so don't + * free it. + */ + if (okay_to_free == True) { + tgt_node_free(n); + n = NULL; + } lc.l_guid = NULL; queue_prt(mgmtq, Q_STE_NONIO, "SAM%x Found existing LU[%d.%d]\n", t->s_targ_num, @@ -1530,7 +1619,6 @@ queue_message_set(common->l_from_transports, 0, msg_lu_add, (void *)l); free(guid); - xml_tree_free(n); cmd->c_lu = l; return (True); @@ -1545,13 +1633,15 @@ xmlFreeTextReader(r); } if (n) - xml_tree_free(n); + tgt_node_free(n); if (l) free(l); if (lc.l_guid) free(lc.l_guid); if (common) free(common); + if (dataset) + free(dataset); return (False); } @@ -1559,30 +1649,24 @@ t10_lu_initialize(t10_lu_common_t *lu, char *basedir) { char *str = NULL; + int dtype; if (load_params(lu, basedir) == False) return (False); - if (xml_find_value_str(lu->l_root, XML_ELEMENT_DTYPE, &str) == True) { - if (strcmp(str, TGT_TYPE_DISK) == 0) { - lu->l_dtype = DTYPE_DIRECT; - if (sbc_init_common(lu) == False) - goto error; - } else if (strcmp(str, TGT_TYPE_RAW) == 0) { - lu->l_dtype = DTYPE_UNKNOWN; - if (raw_init_common(lu) == False) - goto error; - } else if (strcmp(str, TGT_TYPE_TAPE) == 0) { - lu->l_dtype = DTYPE_SEQUENTIAL; - if (ssc_init_common(lu) == False) - goto error; - } else if (strcmp(str, TGT_TYPE_OSD) == 0) { - lu->l_dtype = DTYPE_OSD; - if (osd_init_common(lu) == False) - goto error; + if (tgt_find_value_str(lu->l_root, XML_ELEMENT_DTYPE, &str) == True) { + for (dtype = 0; sam_emul_table[dtype].t_type_name != NULL; + dtype++) { + if (strcmp(sam_emul_table[dtype].t_type_name, + str) == 0) { + lu->l_dtype = dtype; + if ((*sam_emul_table[dtype].t_common_init)(lu) + == False) + goto error; + else + break; + } } - if (lu->l_dtype_params == NULL) - goto error; free(str); } else goto error; @@ -1680,23 +1764,7 @@ case msg_lu_add: itl = (t10_lu_impl_t *)m->msg_data; - switch (lu->l_dtype) { - case DTYPE_DIRECT: - sbc_init_per(itl); - break; - - case DTYPE_SEQUENTIAL: - ssc_init_per(itl); - break; - - case DTYPE_OSD: - osd_init_per(itl); - break; - - case DTYPE_UNKNOWN: - raw_init_per(itl); - break; - } + (*sam_emul_table[lu->l_dtype].t_per_init)(itl); break; case msg_reset_lu: @@ -1711,26 +1779,8 @@ * receive a CHECK_CONDITION on their next * command. */ - switch (lu->l_dtype) { - case DTYPE_DIRECT: - sbc_fini_per(itl); - sbc_init_per(itl); - break; - - case DTYPE_SEQUENTIAL: - ssc_fini_per(itl); - ssc_init_per(itl); - break; - - case DTYPE_UNKNOWN: - raw_fini_per(itl); - raw_init_per(itl); - break; - - case DTYPE_OSD: - osd_fini_per(itl); - osd_init_per(itl); - } + (*sam_emul_table[lu->l_dtype].t_per_fini)(itl); + (*sam_emul_table[lu->l_dtype].t_per_init)(itl); itl = AVL_NEXT(&lu->l_all_open, itl); } while (itl != NULL); @@ -1749,23 +1799,8 @@ queue_walker_free(lu->l_from_transports, lu_remove_cmds, (void *)itl); - switch (lu->l_dtype) { - case DTYPE_DIRECT: - sbc_fini_per(itl); - break; - - case DTYPE_SEQUENTIAL: - ssc_fini_per(itl); - break; + (*sam_emul_table[lu->l_dtype].t_per_fini)(itl); - case DTYPE_OSD: - osd_fini_per(itl); - break; - - case DTYPE_UNKNOWN: - raw_fini_per(itl); - break; - } /* * Don't remove reference to l_common area until after * the emulation routines are finished since they @@ -1789,19 +1824,9 @@ "LU_%x Failed to close fd, " "errno=%d\n", lu->l_internal_num, errno); - switch (lu->l_dtype) { - case DTYPE_DIRECT: - sbc_fini_common(lu); - break; + /*CSTYLED*/ + (*sam_emul_table[lu->l_dtype].t_common_fini)(lu); - case DTYPE_SEQUENTIAL: - ssc_fini_common(lu); - break; - - case DTYPE_UNKNOWN: - raw_fini_common(lu); - break; - } avl_remove(&lu_list, (void *)lu); util_title(mgmtq, Q_STE_NONIO, lu->l_internal_num, "End LU"); @@ -1809,7 +1834,8 @@ (void) pthread_mutex_unlock( &lu->l_common_mutex); (void) pthread_mutex_unlock(&lu_list_mutex); - xml_tree_free(lu->l_root); + if (lu->l_root_okay_to_free == True) + tgt_node_free(lu->l_root); free(lu->l_pid); free(lu->l_vid); free(lu->l_guid); @@ -1903,15 +1929,8 @@ target_basedir, itl->l_targ->s_targ_base); (void) load_params(lu, path); free(path); - switch (lu->l_dtype) { - case DTYPE_DIRECT: - sbc_task_mgmt(lu, CapacityChange); - break; - - case DTYPE_SEQUENTIAL: - ssc_task_mgmt(lu, CapacityChange); - break; - } + (*sam_emul_table[lu->l_dtype].t_task_mgmt)(lu, + CapacityChange); (void) pthread_mutex_lock(&lu->l_common_mutex); itl = avl_first(&lu->l_all_open); while (itl != NULL) { @@ -1937,27 +1956,12 @@ target_basedir, itl->l_targ->s_targ_base); (void) load_params(lu, path); free(path); - switch (lu->l_dtype) { - case DTYPE_DIRECT: - sbc_task_mgmt(lu, DeviceOnline); - break; - - case DTYPE_SEQUENTIAL: - ssc_task_mgmt(lu, DeviceOnline); - break; - } + (*sam_emul_table[lu->l_dtype].t_task_mgmt)(lu, + DeviceOnline); (void) pthread_mutex_lock(&lu->l_common_mutex); itl = avl_first(&lu->l_all_open); while (itl != NULL) { - switch (lu->l_dtype) { - case DTYPE_DIRECT: - sbc_init_per(itl); - break; - - case DTYPE_SEQUENTIAL: - ssc_init_per(itl); - break; - } + (*sam_emul_table[lu->l_dtype].t_per_init)(itl); itl = AVL_NEXT(&lu->l_all_open, itl); } (void) pthread_mutex_unlock(&lu->l_common_mutex); @@ -2098,15 +2102,13 @@ static Boolean_t load_params(t10_lu_common_t *lu, char *basedir) { - char file[MAXPATHLEN], - *str; - int oflags = O_RDWR|O_LARGEFILE|O_NDELAY; - Boolean_t mmap_lun = True; - xml_node_t *node = NULL; - int version_maj = XML_VERS_LUN_MAJ, - version_min = XML_VERS_LUN_MIN, - xml_fd; - xmlTextReaderPtr r; + char file[MAXPATHLEN], + *str; + int oflags = O_RDWR|O_LARGEFILE|O_NDELAY; + Boolean_t mmap_lun = True; + tgt_node_t *node = NULL; + int version_maj = XML_VERS_LUN_MAJ, + version_min = XML_VERS_LUN_MIN; /* * Clean up from previous call to this function. This occurs if @@ -2114,38 +2116,18 @@ */ if (lu->l_mmap != MAP_FAILED) munmap(lu->l_mmap, lu->l_size); - if (lu->l_root != NULL) { - xml_tree_free(lu->l_root); - lu->l_root = NULL; - } if (lu->l_fd != -1) close(lu->l_fd); - (void) snprintf(file, sizeof (file), "%s/%s%d", basedir, PARAMBASE, - lu->l_num); - - if ((xml_fd = open(file, O_RDONLY)) < 0) - return (False); - if ((r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd, NULL, NULL, - 0)) != NULL) { - while (xmlTextReaderRead(r) == 1) - if (xml_process_node(r, &node) == False) - break; - lu->l_root = node; - } else - return (False); - - (void) close(xml_fd); - xmlTextReaderClose(r); - xmlFreeTextReader(r); + node = lu->l_root; if (validate_version(node, &version_maj, &version_min) == False) + fprintf(stderr, "Failed version check\n"); + + if (tgt_find_value_str(node, XML_ELEMENT_PID, &lu->l_pid) == False) goto error; - if (xml_find_value_str(node, XML_ELEMENT_PID, &lu->l_pid) == False) - goto error; - - if (xml_find_value_str(node, XML_ELEMENT_VID, &lu->l_vid) == False) + if (tgt_find_value_str(node, XML_ELEMENT_VID, &lu->l_vid) == False) goto error; /* @@ -2153,7 +2135,7 @@ * file and there's no need to treat it as an error. Just mark * the device as online. */ - if (xml_find_value_str(node, XML_ELEMENT_STATUS, &str) == True) { + if (tgt_find_value_str(node, XML_ELEMENT_STATUS, &str) == True) { if (strcmp(str, TGT_STATUS_ONLINE) == 0) lu->l_state = lu_online; else if (strcmp(str, TGT_STATUS_OFFLINE) == 0) @@ -2197,9 +2179,9 @@ * The per LU bit is settable via a SCSI command. */ lu->l_fast_write_ack = False; - (void) xml_find_value_boolean(main_config, XML_ELEMENT_FAST, + (void) tgt_find_value_boolean(main_config, XML_ELEMENT_FAST, &lu->l_fast_write_ack); - (void) xml_find_value_boolean(node, XML_ELEMENT_FAST, + (void) tgt_find_value_boolean(node, XML_ELEMENT_FAST, &lu->l_fast_write_ack); if (lu->l_fast_write_ack == False) oflags |= O_SYNC; @@ -2211,7 +2193,7 @@ * not just a single file to be opened, but potentially thousands. * Therefore, stop here if we've got an OSD dtype. */ - if (xml_find_value_str(node, XML_ELEMENT_DTYPE, &str) == False) + if (tgt_find_value_str(node, XML_ELEMENT_DTYPE, &str) == False) goto error; if (strcmp(str, TGT_TYPE_OSD) == 0) { free(str); @@ -2219,10 +2201,17 @@ } else free(str); - (void) snprintf(file, sizeof (file), "%s/%s%d", basedir, LUNBASE, - lu->l_num); - if ((lu->l_fd = open(file, oflags)) == -1) - goto error; + if (tgt_find_value_str(node, XML_ELEMENT_BACK, &str) == True) { + lu->l_fd = open(str, oflags); + free(str); + if (lu->l_fd == -1) + goto error; + } else { + (void) snprintf(file, sizeof (file), "%s/%s%d", basedir, + LUNBASE, lu->l_num); + if ((lu->l_fd = open(file, oflags)) == -1) + goto error; + } #ifndef _LP64 /* @@ -2231,8 +2220,8 @@ */ mmap_lun = False; #endif - (void) xml_find_value_boolean(node, XML_ELEMENT_MMAP_LUN, &mmap_lun); - if (xml_find_value_str(node, XML_ELEMENT_SIZE, &str) == True) { + (void) tgt_find_value_boolean(node, XML_ELEMENT_MMAP_LUN, &mmap_lun); + if (tgt_find_value_str(node, XML_ELEMENT_SIZE, &str) == True) { lu->l_size = strtoll(str, NULL, 0) * 512LL; free(str); } else @@ -2257,14 +2246,18 @@ } return (True); error: - if (lu->l_root) - xml_tree_free(lu->l_root); - if (lu->l_pid) + if (lu->l_pid) { free(lu->l_pid); - if (lu->l_vid) + lu->l_pid = NULL; + } + if (lu->l_vid) { free(lu->l_vid); - if (lu->l_fd != -1) + lu->l_vid = NULL; + } + if (lu->l_fd != -1) { (void) close(lu->l_fd); + lu->l_fd = -1; + } return (False); } @@ -2440,6 +2433,21 @@ return (0); } +/*ARGSUSED*/ +static Boolean_t +sam_common_init(t10_lu_common_t *t) +{ + assert(0); + return (False); +} + +/*ARGSUSED*/ +static void +sam_common_fini(t10_lu_common_t *t) +{ + assert(0); +} + #ifdef FULL_DEBUG static char * state_to_str(t10_cmd_state_t s) @@ -2470,3 +2478,97 @@ } return ("Invalid Event"); } + +/*ARGSUSED*/ +static void +sam_per_init(t10_lu_impl_t *t) +{ + assert(0); +} + +/*ARGSUSED*/ +static void +sam_per_fini(t10_lu_impl_t *t) +{ + assert(0); +} + +/*ARGSUSED*/ +static void +sam_task_mgmt(t10_lu_common_t *t, TaskOp_t op) +{ + assert(0); +} + +static sam_device_table_t sam_emul_table[] = { + /* 0x00: DTYPE_DIRECT */ + { sbc_common_init, sbc_common_fini, sbc_per_init, sbc_per_fini, + sbc_task_mgmt, TGT_TYPE_DISK }, + /* 0x01: DTYPE_SEQUENTIAL */ + { ssc_common_init, ssc_common_fini, ssc_per_init, ssc_per_fini, + ssc_task_mgmt, TGT_TYPE_TAPE }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + /* 0x11: DTYPE_OSD */ + { osd_common_init, osd_common_fini, osd_per_init, osd_per_fini, + osd_task_mgmt, TGT_TYPE_OSD }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + { sam_common_init, sam_common_fini, sam_per_init, sam_per_fini, + sam_task_mgmt, TGT_TYPE_INVALID }, + /* 0x1f: DTYPE_UNKNOWN */ + { raw_common_init, raw_common_fini, raw_per_init, raw_per_fini, + raw_task_mgmt, TGT_TYPE_RAW }, + /* End-of-Table marker */ + { 0, 0, 0, 0, 0, NULL } +};
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.c Wed Nov 15 19:25:44 2006 -0800 @@ -81,25 +81,25 @@ * []---- */ Boolean_t -sbc_init_common(t10_lu_common_t *lu) +sbc_common_init(t10_lu_common_t *lu) { disk_params_t *d; - xml_node_t *node = lu->l_root; + tgt_node_t *node = lu->l_root; if ((d = (disk_params_t *)calloc(1, sizeof (*d))) == NULL) return (False); - (void) xml_find_value_int(node, XML_ELEMENT_BPS, + (void) tgt_find_value_int(node, XML_ELEMENT_BPS, (int *)&d->d_bytes_sect); - (void) xml_find_value_int(node, XML_ELEMENT_HEADS, + (void) tgt_find_value_int(node, XML_ELEMENT_HEADS, (int *)&d->d_heads); - (void) xml_find_value_int(node, XML_ELEMENT_SPT, + (void) tgt_find_value_int(node, XML_ELEMENT_SPT, (int *)&d->d_spt); - (void) xml_find_value_int(node, XML_ELEMENT_CYLINDERS, + (void) tgt_find_value_int(node, XML_ELEMENT_CYLINDERS, (int *)&d->d_cyl); - (void) xml_find_value_int(node, XML_ELEMENT_RPM, + (void) tgt_find_value_int(node, XML_ELEMENT_RPM, (int *)&d->d_rpm); - (void) xml_find_value_int(node, XML_ELEMENT_INTERLEAVE, + (void) tgt_find_value_int(node, XML_ELEMENT_INTERLEAVE, (int *)&d->d_interleave); d->d_fast_write = lu->l_fast_write_ack; d->d_size = lu->l_size / (uint64_t)d->d_bytes_sect; @@ -121,7 +121,7 @@ } void -sbc_fini_common(t10_lu_common_t *lu) +sbc_common_fini(t10_lu_common_t *lu) { disk_params_t *d = lu->l_dtype_params; @@ -153,7 +153,7 @@ * []---- */ void -sbc_init_per(t10_lu_impl_t *itl) +sbc_per_init(t10_lu_impl_t *itl) { disk_params_t *d = (disk_params_t *)itl->l_common->l_dtype_params; @@ -166,7 +166,7 @@ } void -sbc_fini_per(t10_lu_impl_t *itl) +sbc_per_fini(t10_lu_impl_t *itl) { disk_params_t *d = (disk_params_t *)itl->l_common->l_dtype_params; t10_lu_impl_t *lu;
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_spc.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/t10_spc.c Wed Nov 15 19:25:44 2006 -0800 @@ -550,7 +550,7 @@ lun_idx, lun_val; char *str; - xml_node_t *targ, + tgt_node_t *targ, *lun_list, *lun; @@ -581,9 +581,9 @@ select = cdb[2]; targ = NULL; - while ((targ = xml_node_next(targets_config, XML_ELEMENT_TARG, targ)) != + while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG, targ)) != NULL) { - if (xml_find_value_str(targ, XML_ELEMENT_INAME, &str) == + if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &str) == False) { goto error; } @@ -595,11 +595,11 @@ } if (!targ) goto error; - if ((lun_list = xml_node_next(targ, XML_ELEMENT_LUNLIST, NULL)) == NULL) + if ((lun_list = tgt_node_next(targ, XML_ELEMENT_LUNLIST, NULL)) == NULL) goto error; lun = NULL; - while ((lun = xml_node_next(lun_list, XML_ELEMENT_LUN, lun)) != NULL) + while ((lun = tgt_node_next(lun_list, XML_ELEMENT_LUN, lun)) != NULL) entries++; @@ -616,9 +616,9 @@ lun_idx = SCSI_REPORTLUNS_ADDRESS_SIZE; lun = NULL; - while ((lun = xml_node_next(lun_list, XML_ELEMENT_LUN, lun)) != + while ((lun = tgt_node_next(lun_list, XML_ELEMENT_LUN, lun)) != NULL) { - if (xml_find_value_int(lun, XML_ELEMENT_LUN, + if (tgt_find_value_int(lun, XML_ELEMENT_LUN, &lun_val) == False) goto error; if (spc_encode_lu_addr(&buf[lun_idx], select,
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_ssc.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/t10_ssc.c Wed Nov 15 19:25:44 2006 -0800 @@ -69,7 +69,7 @@ * []---- */ Boolean_t -ssc_init_common(t10_lu_common_t *lu) +ssc_common_init(t10_lu_common_t *lu) { ssc_params_t *s; ssc_obj_mark_t mark; @@ -102,7 +102,7 @@ * []---- */ void -ssc_fini_common(t10_lu_common_t *lu) +ssc_common_fini(t10_lu_common_t *lu) { free(lu->l_dtype_params); } @@ -128,7 +128,7 @@ * []---- */ void -ssc_init_per(t10_lu_impl_t *itl) +ssc_per_init(t10_lu_impl_t *itl) { ssc_params_t *s = (ssc_params_t *)itl->l_common->l_dtype_params; @@ -147,7 +147,7 @@ */ /*ARGSUSED*/ void -ssc_fini_per(t10_lu_impl_t *itl) +ssc_per_fini(t10_lu_impl_t *itl) { }
--- a/usr/src/cmd/iscsi/iscsitgtd/target.h Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/target.h Wed Nov 15 19:25:44 2006 -0800 @@ -55,6 +55,7 @@ #define TGT_TYPE_TAPE "tape" #define TGT_TYPE_OSD "osd" #define TGT_TYPE_RAW "raw" +#define TGT_TYPE_INVALID "invalid" /* * During the creation phase of a LU it starts out offline during block @@ -166,13 +167,13 @@ } admin_table_t; #include <sys/socket.h> -#include "xml.h" +#include <iscsitgt_impl.h> #include "queue.h" -void create_func(xml_node_t *, target_queue_t *, target_queue_t *); -void modify_func(xml_node_t *, target_queue_t *, target_queue_t *); -void remove_func(xml_node_t *, target_queue_t *, target_queue_t *); -void list_func(xml_node_t *, target_queue_t *, target_queue_t *); +void create_func(tgt_node_t *, target_queue_t *, target_queue_t *); +void modify_func(tgt_node_t *, target_queue_t *, target_queue_t *); +void remove_func(tgt_node_t *, target_queue_t *, target_queue_t *); +void list_func(tgt_node_t *, target_queue_t *, target_queue_t *); void logout_targ(char *targ); char *update_basedir(char *, char *); char *valid_radius_srv(char *name, char *prop); @@ -185,8 +186,8 @@ extern char *target_basedir; extern char *target_log; extern char *config_file; -extern xml_node_t *targets_config; -extern xml_node_t *main_config; +extern tgt_node_t *targets_config; +extern tgt_node_t *main_config; extern uchar_t *mac_addr; extern size_t mac_len; extern int main_vers_maj,
--- a/usr/src/cmd/iscsi/iscsitgtd/util.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/util.c Wed Nov 15 19:25:44 2006 -0800 @@ -42,11 +42,10 @@ #include <fcntl.h> #include <syslog.h> -#include "local_types.h" +#include <iscsitgt_impl.h> #include "target.h" #include "utility.h" #include "errcode.h" -#include "xml.h" #include <sys/scsi/generic/commands.h> #define CRC32_STR "CRC32C" @@ -73,9 +72,9 @@ * []---- */ Boolean_t -check_access(xml_node_t *targ, char *initiator_name, Boolean_t req_chap) +check_access(tgt_node_t *targ, char *initiator_name, Boolean_t req_chap) { - xml_node_t *acl, + tgt_node_t *acl, *inode = NULL, *tgt_initiator = NULL; char *dummy; @@ -85,20 +84,20 @@ /* * If there's no ACL for this target everyone has access. */ - if ((acl = xml_node_next(targ, XML_ELEMENT_ACLLIST, NULL)) == NULL) + if ((acl = tgt_node_next(targ, XML_ELEMENT_ACLLIST, NULL)) == NULL) return (True); /* * Find the local initiator name and also save the knowledge * if the initiator had a CHAP secret. */ - while ((inode = xml_node_next(main_config, XML_ELEMENT_INIT, + while ((inode = tgt_node_next(main_config, XML_ELEMENT_INIT, inode)) != NULL) { - if (xml_find_value_str(inode, XML_ELEMENT_INAME, &dummy) == + if (tgt_find_value_str(inode, XML_ELEMENT_INAME, &dummy) == True) { if (strcmp(dummy, initiator_name) == 0) { free(dummy); - if (xml_find_value_str(inode, + if (tgt_find_value_str(inode, XML_ELEMENT_CHAPSECRET, &dummy) == True) { free(dummy); found_chap = True; @@ -113,7 +112,7 @@ if ((acl != NULL) && (inode == NULL)) return (False); - while ((tgt_initiator = xml_node_next(acl, XML_ELEMENT_INIT, + while ((tgt_initiator = tgt_node_next(acl, XML_ELEMENT_INIT, tgt_initiator)) != NULL) { if (strcmp(inode->x_value, tgt_initiator->x_value) == 0) { @@ -154,12 +153,12 @@ static Boolean_t convert_local_tpgt(char **text, int *text_length, char *local_tpgt) { - xml_node_t *tpgt = NULL, + tgt_node_t *tpgt = NULL, *x; char buf[80]; char ipaddr[4]; - while ((tpgt = xml_node_next(main_config, XML_ELEMENT_TPGT, + while ((tpgt = tgt_node_next(main_config, XML_ELEMENT_TPGT, tpgt)) != NULL) { if (strcmp(tpgt->x_value, local_tpgt) == 0) { @@ -206,9 +205,9 @@ */ static void add_target_address(iscsi_conn_t *c, char **text, int *text_length, - xml_node_t *targ) + tgt_node_t *targ) { - xml_node_t *tpgt_list, + tgt_node_t *tpgt_list, *tpgt = NULL; struct sockaddr_in *sp4; struct sockaddr_in6 *sp6; @@ -218,14 +217,14 @@ char buf[INET6_ADDRSTRLEN + 7], net_buf[INET6_ADDRSTRLEN]; - if ((tpgt_list = xml_node_next(targ, XML_ELEMENT_TPGTLIST, + if ((tpgt_list = tgt_node_next(targ, XML_ELEMENT_TPGTLIST, NULL)) == NULL) { if_target_address(text, text_length, (struct sockaddr *)&c->c_target_sockaddr); return; } - while ((tpgt = xml_node_next(tpgt_list, XML_ELEMENT_TPGT, + while ((tpgt = tgt_node_next(tpgt_list, XML_ELEMENT_TPGT, tpgt)) != NULL) { if (convert_local_tpgt(text, text_length, tpgt->x_value) == False) { @@ -264,16 +263,16 @@ static Boolean_t add_targets(iscsi_conn_t *c, char **text, int *text_length) { - xml_node_t *targ = NULL; + tgt_node_t *targ = NULL; Boolean_t rval = True; char *targ_name = NULL; - while ((rval == True) && ((targ = xml_node_next(targets_config, + while ((rval == True) && ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG, targ)) != NULL)) { if (check_access(targ, c->c_sess->s_i_name, False) == True) { - if (xml_find_value_str(targ, XML_ELEMENT_INAME, + if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &targ_name) == False) { rval = False; break; @@ -823,7 +822,7 @@ find_main_tpgt(struct sockaddr_storage *pst) { char ip_addr[16]; - xml_node_t *tpgt = NULL, + tgt_node_t *tpgt = NULL, *ip_node = NULL; struct in_addr addr; struct in6_addr addr6; @@ -835,11 +834,11 @@ addr = ((struct sockaddr_in *)pst)->sin_addr; addr6 = ((struct sockaddr_in6 *)pst)->sin6_addr; - while ((tpgt = xml_node_next(main_config, XML_ELEMENT_TPGT, + while ((tpgt = tgt_node_next(main_config, XML_ELEMENT_TPGT, tpgt)) != NULL) { ip_node = NULL; - while ((ip_node = xml_node_next(tpgt, XML_ELEMENT_IPADDR, + while ((ip_node = tgt_node_next(tpgt, XML_ELEMENT_IPADDR, ip_node)) != NULL) { if (pst->ss_family == AF_INET) { @@ -879,9 +878,9 @@ * return zero which will break the connection. */ static int -convert_to_tpgt(iscsi_conn_t *c, xml_node_t *targ) +convert_to_tpgt(iscsi_conn_t *c, tgt_node_t *targ) { - xml_node_t *list, + tgt_node_t *list, *tpgt = NULL; int addr_tpgt, pos_tpgt; @@ -890,7 +889,7 @@ * If this target doesn't have a list of target portal group tags * just return the default which is 1. */ - list = xml_node_next(targ, XML_ELEMENT_TPGTLIST, NULL); + list = tgt_node_next(targ, XML_ELEMENT_TPGTLIST, NULL); if (list == NULL) return (1); @@ -900,8 +899,8 @@ */ addr_tpgt = find_main_tpgt(&(c->c_target_sockaddr)); - while ((tpgt = xml_node_next(list, XML_ELEMENT_TPGT, tpgt)) != NULL) { - (void) xml_find_value_int(tpgt, XML_ELEMENT_TPGT, &pos_tpgt); + while ((tpgt = tgt_node_next(list, XML_ELEMENT_TPGT, tpgt)) != NULL) { + (void) tgt_find_value_int(tpgt, XML_ELEMENT_TPGT, &pos_tpgt); if (pos_tpgt == addr_tpgt) { return (addr_tpgt); } @@ -915,15 +914,15 @@ * | find_target_node -- given a target IQN name, return the XML node * []---- */ -xml_node_t * +tgt_node_t * find_target_node(char *targ_name) { - xml_node_t *tnode = NULL; + tgt_node_t *tnode = NULL; char *iname; - while ((tnode = xml_node_next(targets_config, XML_ELEMENT_TARG, + while ((tnode = tgt_node_next(targets_config, XML_ELEMENT_TARG, tnode)) != NULL) { - if (xml_find_value_str(tnode, XML_ELEMENT_INAME, &iname) == + if (tgt_find_value_str(tnode, XML_ELEMENT_INAME, &iname) == True) { if (strcmp(iname, targ_name) == 0) { free(iname); @@ -939,7 +938,7 @@ static Boolean_t connection_parameters_get(iscsi_conn_t *c, char *targ_name) { - xml_node_t *targ, + tgt_node_t *targ, *alias; Boolean_t rval = False; @@ -954,16 +953,16 @@ */ if ((c->c_tpgt = convert_to_tpgt(c, targ)) == 0) return (False); - if ((alias = xml_node_next(targ, XML_ELEMENT_ALIAS, NULL)) == + if ((alias = tgt_node_next(targ, XML_ELEMENT_ALIAS, NULL)) == NULL) { - (void) xml_find_value_str(targ, XML_ELEMENT_TARG, + (void) tgt_find_value_str(targ, XML_ELEMENT_TARG, &c->c_targ_alias); } else { - (void) xml_find_value_str(alias, XML_ELEMENT_ALIAS, + (void) tgt_find_value_str(alias, XML_ELEMENT_ALIAS, &c->c_targ_alias); } - (void) xml_find_value_int(targ, XML_ELEMENT_MAXCMDS, + (void) tgt_find_value_int(targ, XML_ELEMENT_MAXCMDS, &c->c_maxcmdsn); rval = True; } @@ -972,14 +971,14 @@ } Boolean_t -validate_version(xml_node_t *node, int *maj_p, int *min_p) +validate_version(tgt_node_t *node, int *maj_p, int *min_p) { char *vers_str = NULL, *minor_part; int maj, min; - if ((xml_find_attr_str(node, XML_ELEMENT_VERS, &vers_str) == False) || + if ((tgt_find_attr_str(node, XML_ELEMENT_VERS, &vers_str) == False) || (vers_str == NULL)) return (False); @@ -1026,7 +1025,7 @@ Boolean_t update_config_main(char **msg) { - if (xml_dump2file(main_config, config_file) == False) { + if (tgt_dump2file(main_config, config_file) == False) { xml_rtn_msg(msg, ERR_UPDATE_MAINCFG_FAILED); return (False); } else @@ -1039,7 +1038,7 @@ char path[MAXPATHLEN]; (void) snprintf(path, sizeof (path), "%s/config.xml", target_basedir); - if (xml_dump2file(targets_config, path) == False) { + if (tgt_dump2file(targets_config, path) == False) { if (msg != NULL) xml_rtn_msg(msg, ERR_UPDATE_TARGCFG_FAILED); return (False); @@ -1109,7 +1108,7 @@ sleep(1); } - if (xml_encode_bytes((uint8_t *)&eui, sizeof (eui), guid, + if (tgt_xml_encode((uint8_t *)&eui, sizeof (eui), guid, &guid_size) == False) { return (False); } else @@ -1162,6 +1161,20 @@ return; } } + + /* + * At this point we've got a size which will not fit into + * any values where C * H * S = size. So, set the heads and + * sectors per track values to their largest which will make + * a single cylinder 8GB. Then divide that into the size to + * get the number of cylinders. + */ + h = 0xff; + s = 0xffff; + c = sects / (h * s); + *heads = (int)h; + *spt = (int)s; + *cylinder = (int)c; } /* @@ -1274,11 +1287,11 @@ { char lbuf[16]; - buf_add_tag_and_attr(buf, XML_ELEMENT_ERROR, "version='1.0'"); + tgt_buf_add_tag_and_attr(buf, XML_ELEMENT_ERROR, "version='1.0'"); (void) snprintf(lbuf, sizeof (lbuf), "%d", code); - xml_add_tag(buf, XML_ELEMENT_CODE, lbuf); - xml_add_tag(buf, XML_ELEMENT_MESSAGE, errcode_to_str(code)); - buf_add_tag(buf, XML_ELEMENT_ERROR, Tag_End); + tgt_buf_add(buf, XML_ELEMENT_CODE, lbuf); + tgt_buf_add(buf, XML_ELEMENT_MESSAGE, errcode_to_str(code)); + tgt_buf_add_tag(buf, XML_ELEMENT_ERROR, Tag_End); } /* @@ -1462,7 +1475,7 @@ void remove_target_common(char *name, int lun_num, char **msg) { - xml_node_t *targ = NULL, + tgt_node_t *targ = NULL, *list, *lun, *node, @@ -1477,7 +1490,7 @@ xmlTextReaderPtr r; (void) pthread_mutex_lock(&targ_config_mutex); - while ((targ = xml_node_next(targets_config, XML_ELEMENT_TARG, targ)) != + while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG, targ)) != NULL) { /* ---- Look for a match on the friendly name ---- */ if (strcmp(targ->x_value, name) == 0) { @@ -1486,7 +1499,7 @@ } /* ---- Check to see if they gave the IQN name instead ---- */ - if ((xml_find_value_str(targ, XML_ELEMENT_INAME, &iname) == + if ((tgt_find_value_str(targ, XML_ELEMENT_INAME, &iname) == True) && (strcmp(iname, name) == 0)) break; else { @@ -1508,7 +1521,7 @@ if (tname == NULL) tname = targ->x_value; if (iname == NULL) { - if (xml_find_value_str(targ, XML_ELEMENT_INAME, &iname) == + if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &iname) == False) { xml_rtn_msg(msg, ERR_INTERNAL_ERROR); (void) pthread_mutex_unlock(&targ_config_mutex); @@ -1516,7 +1529,7 @@ } } - if ((list = xml_node_next(targ, XML_ELEMENT_LUNLIST, NULL)) == NULL) + if ((list = tgt_node_next(targ, XML_ELEMENT_LUNLIST, NULL)) == NULL) goto error; if (lun_num == 0) { @@ -1526,9 +1539,9 @@ * see if others are still present. */ lun = NULL; - while ((lun = xml_node_next(list, XML_ELEMENT_LUN, lun)) != + while ((lun = tgt_node_next(list, XML_ELEMENT_LUN, lun)) != NULL) { - if (xml_find_value_int(lun, XML_ELEMENT_LUN, &chk) == + if (tgt_find_value_int(lun, XML_ELEMENT_LUN, &chk) == False) goto error; @@ -1543,17 +1556,17 @@ * Make sure the LU exists that's being removed */ lun = NULL; - while ((lun = xml_node_next(list, XML_ELEMENT_LUN, lun)) != + while ((lun = tgt_node_next(list, XML_ELEMENT_LUN, lun)) != NULL) { - if (xml_find_value_int(lun, XML_ELEMENT_LUN, &chk) == + if (tgt_find_value_int(lun, XML_ELEMENT_LUN, &chk) == False) goto error; if (chk == lun_num) { - lun = xml_alloc_node(XML_ELEMENT_LUN, Int, + lun = tgt_node_alloc(XML_ELEMENT_LUN, Int, &lun_num); - (void) xml_remove_child(list, lun, MatchBoth); - xml_free_node(lun); + (void) tgt_node_remove(list, lun, MatchBoth); + tgt_node_free(lun); break; } } @@ -1580,20 +1593,20 @@ NULL) { node = NULL; while (xmlTextReaderRead(r) == 1) - if (xml_process_node(r, &node) == False) + if (tgt_node_process(r, &node) == False) break; close(xml_fd); xmlTextReaderClose(r); xmlFreeTextReader(r); xmlCleanupParser(); - (void) xml_find_value_str(node, XML_ELEMENT_BACK, &bs_path); - if ((xml_find_value_boolean(node, XML_ELEMENT_DELETE_BACK, + (void) tgt_find_value_str(node, XML_ELEMENT_BACK, &bs_path); + if ((tgt_find_value_boolean(node, XML_ELEMENT_DELETE_BACK, &bs_delete) == True) && (bs_delete == True)) unlink(bs_path); if (bs_path != NULL) free(bs_path); - xml_tree_free(node); + tgt_node_free(node); } (void) unlink(path); @@ -1619,12 +1632,12 @@ /* * 'tname' is just a reference to the memory within - * the targets_config structure. So once the xml_remove_child + * the targets_config structure. So once the tgt_node_remove() * is called 'tname' is no longer valid. */ - c = xml_alloc_node(XML_ELEMENT_TARG, String, tname); - (void) xml_remove_child(targets_config, c, MatchBoth); - xml_free_node(c); + c = tgt_node_alloc(XML_ELEMENT_TARG, String, tname); + (void) tgt_node_remove(targets_config, c, MatchBoth); + tgt_node_free(c); } /*
--- a/usr/src/cmd/iscsi/iscsitgtd/util_ifname.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/util_ifname.c Wed Nov 15 19:25:44 2006 -0800 @@ -45,7 +45,7 @@ #include <netinet/in.h> #include <arpa/inet.h> -#include "local_types.h" +#include <iscsitgt_impl.h> #include "target.h" #include "queue.h" #include "utility.h"
--- a/usr/src/cmd/iscsi/iscsitgtd/util_queue.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/util_queue.c Wed Nov 15 19:25:44 2006 -0800 @@ -424,7 +424,7 @@ case msg_mgmt_rqst: mq = (mgmt_request_t *)m->msg_data; (void) pthread_mutex_lock(&mq->m_resp_mutex); - xml_add_tag(mq->m_u.m_resp, "queue_freed", NULL); + tgt_buf_add(mq->m_u.m_resp, "queue_freed", NULL); (void) pthread_mutex_unlock(&mq->m_resp_mutex); queue_message_set(mq->m_q, 0, msg_mgmt_rply, 0); break; @@ -432,8 +432,8 @@ case msg_mgmt_rply: mq = (mgmt_request_t *)m->msg_data; buf = mq->m_u.m_resp; - buf_add_tag(buf, XML_ELEMENT_STATS, Tag_End); - buf_add_tag(buf, XML_ELEMENT_CONN, Tag_End); + tgt_buf_add_tag(buf, XML_ELEMENT_STATS, Tag_End); + tgt_buf_add_tag(buf, XML_ELEMENT_CONN, Tag_End); (void) pthread_mutex_unlock(&mq->m_resp_mutex); queue_message_set(mq->m_q, 0, msg_mgmt_rply, 0); @@ -469,7 +469,7 @@ mq = (mgmt_request_t *)m->msg_data; (void) pthread_mutex_lock(&mq->m_resp_mutex); if (mq->m_u.m_resp != NULL) - xml_add_tag(mq->m_u.m_resp, "queue_freed", NULL); + tgt_buf_add(mq->m_u.m_resp, "queue_freed", NULL); (void) pthread_mutex_unlock(&mq->m_resp_mutex); queue_message_set(mq->m_q, 0, msg_mgmt_rply, 0); break;
--- a/usr/src/cmd/iscsi/iscsitgtd/utility.h Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/iscsi/iscsitgtd/utility.h Wed Nov 15 19:25:44 2006 -0800 @@ -74,11 +74,11 @@ Boolean_t update_config_targets(char **msg); Boolean_t update_config_main(char **msg); Boolean_t add_target_alias(iscsi_conn_t *c, char **text, int *test_length); -Boolean_t validate_version(xml_node_t *node, int *maj, int *min); +Boolean_t validate_version(tgt_node_t *node, int *maj, int *min); char *create_tpgt_list(char *tname); -Boolean_t check_access(xml_node_t *targ, char *initiator_name, +Boolean_t check_access(tgt_node_t *targ, char *initiator_name, Boolean_t req_chap); -xml_node_t *find_target_node(char *targ_name); +tgt_node_t *find_target_node(char *targ_name); void util_title(target_queue_t *q, int type, int num, char *title); Boolean_t util_create_guid(char **guid); Boolean_t strtoll_multiplier(char *str, uint64_t *sp);
--- a/usr/src/cmd/zfs/zfs_main.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/zfs/zfs_main.c Wed Nov 15 19:25:44 2006 -0800 @@ -18,6 +18,7 @@ * * CDDL HEADER END */ + /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -77,7 +78,7 @@ * debugging facilities. */ const char * -_umem_debug_init() +_umem_debug_init(void) { return ("default,verbose"); /* $UMEM_DEBUG setting */ } @@ -1919,7 +1920,7 @@ (void) fprintf(stderr, gettext("property may be set " "but unable to remount filesystem\n")); break; - case EZFS_SHAREFAILED: + case EZFS_SHARENFSFAILED: (void) fprintf(stderr, gettext("property may be set " "but unable to reshare filesystem\n")); break; @@ -2190,17 +2191,27 @@ zfs_handle_t **cb_handles; size_t cb_alloc; size_t cb_used; + uint_t cb_types; } get_all_cbdata_t; static int -get_one_filesystem(zfs_handle_t *zhp, void *data) +get_one_dataset(zfs_handle_t *zhp, void *data) { get_all_cbdata_t *cbp = data; + zfs_type_t type = zfs_get_type(zhp); /* - * Skip any zvols + * Interate over any nested datasets. */ - if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { + if (type == ZFS_TYPE_FILESYSTEM && + zfs_iter_filesystems(zhp, get_one_dataset, data) != 0) { + return (1); + } + + /* + * Skip any datasets whose type does not match. + */ + if ((type & cbp->cb_types) == 0) { zfs_close(zhp); return (0); } @@ -2226,34 +2237,46 @@ cbp->cb_handles[cbp->cb_used++] = zhp; - return (zfs_iter_filesystems(zhp, get_one_filesystem, data)); + return (0); } static void -get_all_filesystems(zfs_handle_t ***fslist, size_t *count) +get_all_datasets(uint_t types, zfs_handle_t ***dslist, size_t *count) { get_all_cbdata_t cb = { 0 }; - - (void) zfs_iter_root(g_zfs, get_one_filesystem, &cb); - - *fslist = cb.cb_handles; + cb.cb_types = types; + + (void) zfs_iter_root(g_zfs, get_one_dataset, &cb); + + *dslist = cb.cb_handles; *count = cb.cb_used; } static int -mountpoint_compare(const void *a, const void *b) +dataset_cmp(const void *a, const void *b) { zfs_handle_t **za = (zfs_handle_t **)a; zfs_handle_t **zb = (zfs_handle_t **)b; char mounta[MAXPATHLEN]; char mountb[MAXPATHLEN]; - - verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta, - sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0); - verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb, - sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0); - - return (strcmp(mounta, mountb)); + boolean_t gota, gotb; + + if ((gota = (zfs_get_type(*za) == ZFS_TYPE_FILESYSTEM)) != 0) + verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta, + sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0); + if ((gotb = (zfs_get_type(*zb) == ZFS_TYPE_FILESYSTEM)) != 0) + verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb, + sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0); + + if (gota && gotb) + return (strcmp(mounta, mountb)); + + if (gota) + return (-1); + if (gotb) + return (1); + + return (strcmp(zfs_get_name(a), zfs_get_name(b))); } /* @@ -2264,69 +2287,63 @@ #define OP_SHARE 0x1 #define OP_MOUNT 0x2 -typedef struct share_mount_cbdata { - int cb_type; - int cb_explicit; - int cb_flags; - const char *cb_options; -} share_mount_cbdata_t; - /* - * Share or mount the filesystem. + * Share or mount a dataset. */ static int -share_mount_callback(zfs_handle_t *zhp, void *data) +share_mount_one(zfs_handle_t *zhp, int op, int flags, boolean_t explicit, + const char *options) { char mountpoint[ZFS_MAXPROPLEN]; char shareopts[ZFS_MAXPROPLEN]; - share_mount_cbdata_t *cbp = data; - const char *cmdname = cbp->cb_type == OP_SHARE ? "share" : "mount"; + const char *cmdname = op == OP_SHARE ? "share" : "mount"; struct mnttab mnt; uint64_t zoned, canmount; - - if (cbp->cb_options == NULL) - mnt.mnt_mntopts = ""; - else - mnt.mnt_mntopts = (char *)cbp->cb_options; - - /* - * Check to make sure we can mount/share this dataset. If we are in the - * global zone and the filesystem is exported to a local zone, or if we - * are in a local zone and the filesystem is not exported, then it is an - * error. - */ - zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); - - if (zoned && getzoneid() == GLOBAL_ZONEID) { - if (!cbp->cb_explicit) - return (0); - - (void) fprintf(stderr, gettext("cannot %s '%s': dataset is " - "exported to a local zone\n"), cmdname, zfs_get_name(zhp)); - return (1); - - } else if (!zoned && getzoneid() != GLOBAL_ZONEID) { - if (!cbp->cb_explicit) - return (0); - - (void) fprintf(stderr, gettext("cannot %s '%s': permission " - "denied\n"), cmdname, zfs_get_name(zhp)); - return (1); - } - - /* - * Inore any filesystems which don't apply to us. This includes those - * with a legacy mountpoint, or those with legacy share options. - */ - verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, - sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0); - verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts, - sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0); - canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT); - - if (cbp->cb_type == OP_SHARE) { - if (strcmp(shareopts, "off") == 0) { - if (!cbp->cb_explicit) + zfs_type_t type = zfs_get_type(zhp); + + assert(type & (ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)); + + if (type == ZFS_TYPE_FILESYSTEM) { + /* + * Check to make sure we can mount/share this dataset. If we + * are in the global zone and the filesystem is exported to a + * local zone, or if we are in a local zone and the + * filesystem is not exported, then it is an error. + */ + zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); + + if (zoned && getzoneid() == GLOBAL_ZONEID) { + if (!explicit) + return (0); + + (void) fprintf(stderr, gettext("cannot %s '%s': " + "dataset is exported to a local zone\n"), cmdname, + zfs_get_name(zhp)); + return (1); + + } else if (!zoned && getzoneid() != GLOBAL_ZONEID) { + if (!explicit) + return (0); + + (void) fprintf(stderr, gettext("cannot %s '%s': " + "permission denied\n"), cmdname, + zfs_get_name(zhp)); + return (1); + } + + /* + * Ignore any filesystems which don't apply to us. This + * includes those with a legacy mountpoint, or those with + * legacy share options. + */ + verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, + sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0); + verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts, + sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0); + canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT); + + if (op == OP_SHARE && strcmp(shareopts, "off") == 0) { + if (!explicit) return (0); (void) fprintf(stderr, gettext("cannot share '%s': " @@ -2335,123 +2352,150 @@ "share this filesystem\n")); return (1); } - } - - /* - * We cannot share or mount legacy filesystems. If the shareopts is - * non-legacy but the mountpoint is legacy, we treat it as a legacy - * share. - */ - if (strcmp(mountpoint, "legacy") == 0) { - if (!cbp->cb_explicit) - return (0); - - (void) fprintf(stderr, gettext("cannot %s '%s': " - "legacy mountpoint\n"), cmdname, zfs_get_name(zhp)); - (void) fprintf(stderr, gettext("use %s to " - "%s this filesystem\n"), cbp->cb_type == OP_SHARE ? - "share(1M)" : "mount(1M)", cmdname); - return (1); - } - - if (strcmp(mountpoint, "none") == 0) { - if (!cbp->cb_explicit) - return (0); - - (void) fprintf(stderr, gettext("cannot %s '%s': no " - "mountpoint set\n"), cmdname, zfs_get_name(zhp)); - return (1); - } - - if (!canmount) { - if (!cbp->cb_explicit) - return (0); - - (void) fprintf(stderr, gettext("cannot %s '%s': 'canmount' " - "property is set to 'off'\n"), cmdname, zfs_get_name(zhp)); - return (1); - } - - /* - * At this point, we have verified that the mountpoint and/or shareopts - * are appropriate for auto management. Determine if the filesystem is - * currently mounted or shared, and abort if this is an explicit - * request. - */ - switch (cbp->cb_type) { - case OP_SHARE: - if (zfs_is_shared(zhp, NULL)) { - if (cbp->cb_explicit) { + + /* + * We cannot share or mount legacy filesystems. If the + * shareopts is non-legacy but the mountpoint is legacy, we + * treat it as a legacy share. + */ + if (strcmp(mountpoint, "legacy") == 0) { + if (!explicit) + return (0); + + (void) fprintf(stderr, gettext("cannot %s '%s': " + "legacy mountpoint\n"), cmdname, zfs_get_name(zhp)); + (void) fprintf(stderr, gettext("use %s to " + "%s this filesystem\n"), op == OP_SHARE ? + "share(1M)" : "mount(1M)", cmdname); + return (1); + } + + if (strcmp(mountpoint, "none") == 0) { + if (!explicit) + return (0); + + (void) fprintf(stderr, gettext("cannot %s '%s': no " + "mountpoint set\n"), cmdname, zfs_get_name(zhp)); + return (1); + } + + if (!canmount) { + if (!explicit) + return (0); + + (void) fprintf(stderr, gettext("cannot %s '%s': " + "'canmount' property is set to 'off'\n"), cmdname, + zfs_get_name(zhp)); + return (1); + } + + /* + * At this point, we have verified that the mountpoint and/or + * shareopts are appropriate for auto management. If the + * filesystem is already mounted or shared, return (failing + * for explicit requests); otherwise mount or share the + * filesystem. + */ + switch (op) { + case OP_SHARE: + if (zfs_is_shared_nfs(zhp, NULL)) { + if (!explicit) + return (0); + (void) fprintf(stderr, gettext("cannot share " "'%s': filesystem already shared\n"), zfs_get_name(zhp)); return (1); - } else { - return (0); } - } - break; - - case OP_MOUNT: - if (!hasmntopt(&mnt, MNTOPT_REMOUNT) && - zfs_is_mounted(zhp, NULL)) { - if (cbp->cb_explicit) { + + if (!zfs_is_mounted(zhp, NULL) && + zfs_mount(zhp, NULL, 0) != 0) + return (1); + + if (zfs_share_nfs(zhp) != 0) + return (1); + break; + + case OP_MOUNT: + if (options == NULL) + mnt.mnt_mntopts = ""; + else + mnt.mnt_mntopts = (char *)options; + + if (!hasmntopt(&mnt, MNTOPT_REMOUNT) && + zfs_is_mounted(zhp, NULL)) { + if (!explicit) + return (0); + (void) fprintf(stderr, gettext("cannot mount " "'%s': filesystem already mounted\n"), zfs_get_name(zhp)); return (1); - } else { - return (0); } + + if (zfs_mount(zhp, options, flags) != 0) + return (1); + break; } - break; - } - - /* - * Mount and optionally share the filesystem. - */ - switch (cbp->cb_type) { - case OP_SHARE: - { - if (!zfs_is_mounted(zhp, NULL) && - zfs_mount(zhp, NULL, 0) != 0) - return (1); - - if (zfs_share(zhp) != 0) - return (1); + } else { + assert(op == OP_SHARE); + + /* + * Ignore any volumes that aren't shared. + */ + verify(zfs_prop_get(zhp, ZFS_PROP_SHAREISCSI, shareopts, + sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0); + + if (strcmp(shareopts, "off") == 0) { + if (!explicit) + return (0); + + (void) fprintf(stderr, gettext("cannot share '%s': " + "'shareiscsi' property not set\n"), + zfs_get_name(zhp)); + (void) fprintf(stderr, gettext("set 'shareiscsi' " + "property or use iscsitadm(1M) to share this " + "volume\n")); + return (1); } - break; - - case OP_MOUNT: - if (zfs_mount(zhp, cbp->cb_options, cbp->cb_flags) != 0) + + if (zfs_is_shared_iscsi(zhp)) { + if (!explicit) + return (0); + + (void) fprintf(stderr, gettext("cannot share " + "'%s': volume already shared\n"), + zfs_get_name(zhp)); return (1); - break; + } + + if (zfs_share_iscsi(zhp) != 0) + return (1); } return (0); } static int -share_or_mount(int type, int argc, char **argv) +share_mount(int op, int argc, char **argv) { int do_all = 0; int c, ret = 0; - share_mount_cbdata_t cb = { 0 }; - - cb.cb_type = type; + const char *options = NULL; + int types, flags = 0; /* check options */ - while ((c = getopt(argc, argv, type == OP_MOUNT ? ":ao:O" : "a")) + while ((c = getopt(argc, argv, op == OP_MOUNT ? ":ao:O" : "a")) != -1) { switch (c) { case 'a': do_all = 1; break; case 'o': - cb.cb_options = optarg; + options = optarg; break; case 'O': - cb.cb_flags |= MS_OVERLAY; + flags |= MS_OVERLAY; break; case ':': (void) fprintf(stderr, gettext("missing argument for " @@ -2470,34 +2514,52 @@ /* check number of arguments */ if (do_all) { - zfs_handle_t **fslist = NULL; + zfs_handle_t **dslist = NULL; size_t i, count = 0; + if (op == OP_MOUNT) { + types = ZFS_TYPE_FILESYSTEM; + } else if (argc > 0) { + if (strcmp(argv[0], "nfs") == 0) { + types = ZFS_TYPE_FILESYSTEM; + } else if (strcmp(argv[0], "iscsi") == 0) { + types = ZFS_TYPE_VOLUME; + } else { + (void) fprintf(stderr, gettext("share type " + "must be 'nfs' or 'iscsi'\n")); + usage(B_FALSE); + } + + argc--; + argv++; + } else { + types = ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME; + } + if (argc != 0) { (void) fprintf(stderr, gettext("too many arguments\n")); usage(B_FALSE); } - get_all_filesystems(&fslist, &count); + get_all_datasets(types, &dslist, &count); if (count == 0) return (0); - qsort(fslist, count, sizeof (void *), mountpoint_compare); + qsort(dslist, count, sizeof (void *), dataset_cmp); for (i = 0; i < count; i++) { - if (share_mount_callback(fslist[i], &cb) != 0) + if (share_mount_one(dslist[i], op, flags, B_FALSE, + options) != 0) ret = 1; + zfs_close(dslist[i]); } - for (i = 0; i < count; i++) - zfs_close(fslist[i]); - - free(fslist); + free(dslist); } else if (argc == 0) { struct mnttab entry; - if (type == OP_SHARE) { + if (op == OP_SHARE) { (void) fprintf(stderr, gettext("missing filesystem " "argument\n")); usage(B_FALSE); @@ -2521,18 +2583,21 @@ } else { zfs_handle_t *zhp; + types = ZFS_TYPE_FILESYSTEM; + if (op == OP_SHARE) + types |= ZFS_TYPE_VOLUME; + if (argc > 1) { (void) fprintf(stderr, gettext("too many arguments\n")); usage(B_FALSE); } - if ((zhp = zfs_open(g_zfs, argv[0], - ZFS_TYPE_FILESYSTEM)) == NULL) + if ((zhp = zfs_open(g_zfs, argv[0], types)) == NULL) { ret = 1; - else { - cb.cb_explicit = B_TRUE; - ret = share_mount_callback(zhp, &cb); + } else { + ret = share_mount_one(zhp, op, flags, B_TRUE, + options); zfs_close(zhp); } } @@ -2541,7 +2606,7 @@ } /* - * zfs mount -a + * zfs mount -a [nfs | iscsi] * zfs mount filesystem * * Mount all filesystems, or mount the given filesystem. @@ -2549,11 +2614,11 @@ static int zfs_do_mount(int argc, char **argv) { - return (share_or_mount(OP_MOUNT, argc, argv)); + return (share_mount(OP_MOUNT, argc, argv)); } /* - * zfs share -a + * zfs share -a [nfs | iscsi] * zfs share filesystem * * Share all filesystems, or share the given filesystem. @@ -2561,7 +2626,7 @@ static int zfs_do_share(int argc, char **argv) { - return (share_or_mount(OP_SHARE, argc, argv)); + return (share_mount(OP_SHARE, argc, argv)); } typedef struct unshare_unmount_node { @@ -2586,13 +2651,13 @@ * and unmount it appropriately. */ static int -unshare_unmount_path(int type, char *path, int flags, boolean_t is_manual) +unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual) { zfs_handle_t *zhp; int ret; struct stat64 statbuf; struct extmnttab entry; - const char *cmdname = (type == OP_SHARE) ? "unshare" : "unmount"; + const char *cmdname = (op == OP_SHARE) ? "unshare" : "unmount"; char property[ZFS_MAXPROPLEN]; /* @@ -2632,23 +2697,23 @@ ZFS_TYPE_FILESYSTEM)) == NULL) return (1); - verify(zfs_prop_get(zhp, type == OP_SHARE ? + verify(zfs_prop_get(zhp, op == OP_SHARE ? ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, property, sizeof (property), NULL, NULL, 0, B_FALSE) == 0); - if (type == OP_SHARE) { + if (op == OP_SHARE) { if (strcmp(property, "off") == 0) { (void) fprintf(stderr, gettext("cannot unshare " "'%s': legacy share\n"), path); (void) fprintf(stderr, gettext("use " "unshare(1M) to unshare this filesystem\n")); ret = 1; - } else if (!zfs_is_shared(zhp, NULL)) { + } else if (!zfs_is_shared_nfs(zhp, NULL)) { (void) fprintf(stderr, gettext("cannot unshare '%s': " "not currently shared\n"), path); ret = 1; } else { - ret = zfs_unshareall(zhp); + ret = zfs_unshareall_nfs(zhp); } } else { if (is_manual) { @@ -2674,17 +2739,17 @@ * Generic callback for unsharing or unmounting a filesystem. */ static int -unshare_unmount(int type, int argc, char **argv) +unshare_unmount(int op, int argc, char **argv) { int do_all = 0; int flags = 0; int ret = 0; - int c; + int types, c; zfs_handle_t *zhp; char property[ZFS_MAXPROPLEN]; /* check options */ - while ((c = getopt(argc, argv, type == OP_SHARE ? "a" : "af")) != -1) { + while ((c = getopt(argc, argv, op == OP_SHARE ? "a" : "af")) != -1) { switch (c) { case 'a': do_all = 1; @@ -2702,22 +2767,6 @@ argc -= optind; argv += optind; - /* ensure correct number of arguments */ - if (do_all) { - if (argc != 0) { - (void) fprintf(stderr, gettext("too many arguments\n")); - usage(B_FALSE); - } - } else if (argc != 1) { - if (argc == 0) - (void) fprintf(stderr, - gettext("missing filesystem argument\n")); - else - (void) fprintf(stderr, - gettext("too many arguments\n")); - usage(B_FALSE); - } - if (do_all) { /* * We could make use of zfs_for_each() to walk all datasets in @@ -2740,6 +2789,11 @@ uu_avl_index_t idx; uu_avl_walk_t *walk; + if (argc != 0) { + (void) fprintf(stderr, gettext("too many arguments\n")); + usage(B_FALSE); + } + if ((pool = uu_avl_pool_create("unmount_pool", sizeof (unshare_unmount_node_t), offsetof(unshare_unmount_node_t, un_avlnode), @@ -2773,15 +2827,15 @@ continue; } - verify(zfs_prop_get(zhp, type == OP_SHARE ? + verify(zfs_prop_get(zhp, op == OP_SHARE ? ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, property, sizeof (property), NULL, NULL, 0, B_FALSE) == 0); /* Ignore legacy mounts and shares */ - if ((type == OP_SHARE && + if ((op == OP_SHARE && strcmp(property, "off") == 0) || - (type == OP_MOUNT && + (op == OP_MOUNT && strcmp(property, "legacy") == 0)) { zfs_close(zhp); continue; @@ -2822,9 +2876,9 @@ while ((node = uu_avl_walk_next(walk)) != NULL) { uu_avl_remove(tree, node); - switch (type) { + switch (op) { case OP_SHARE: - if (zfs_unshare(node->un_zhp, + if (zfs_unshare_nfs(node->un_zhp, node->un_mountp) != 0) ret = 1; break; @@ -2844,7 +2898,40 @@ uu_avl_walk_end(walk); uu_avl_destroy(tree); uu_avl_pool_destroy(pool); + + if (op == OP_SHARE) { + /* + * Finally, unshare any volumes shared via iSCSI. + */ + zfs_handle_t **dslist = NULL; + size_t i, count = 0; + + get_all_datasets(ZFS_TYPE_VOLUME, &dslist, &count); + + if (count != 0) { + qsort(dslist, count, sizeof (void *), + dataset_cmp); + + for (i = 0; i < count; i++) { + if (zfs_unshare_iscsi(dslist[i]) != 0) + ret = 1; + zfs_close(dslist[i]); + } + + free(dslist); + } + } } else { + if (argc != 1) { + if (argc == 0) + (void) fprintf(stderr, + gettext("missing filesystem argument\n")); + else + (void) fprintf(stderr, + gettext("too many arguments\n")); + usage(B_FALSE); + } + /* * We have an argument, but it may be a full path or a ZFS * filesystem. Pass full paths off to unmount_path() (shared by @@ -2852,49 +2939,81 @@ * zfs_unmount(). */ if (argv[0][0] == '/') - return (unshare_unmount_path(type, argv[0], + return (unshare_unmount_path(op, argv[0], flags, B_FALSE)); - if ((zhp = zfs_open(g_zfs, argv[0], - ZFS_TYPE_FILESYSTEM)) == NULL) + types = ZFS_TYPE_FILESYSTEM; + if (op == OP_SHARE) + types |= ZFS_TYPE_VOLUME; + + if ((zhp = zfs_open(g_zfs, argv[0], types)) == NULL) return (1); - verify(zfs_prop_get(zhp, type == OP_SHARE ? - ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, property, - sizeof (property), NULL, NULL, 0, B_FALSE) == 0); - - switch (type) { - case OP_SHARE: + if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) { + verify(zfs_prop_get(zhp, op == OP_SHARE ? + ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, property, + sizeof (property), NULL, NULL, 0, B_FALSE) == 0); + + switch (op) { + case OP_SHARE: + if (strcmp(property, "off") == 0) { + (void) fprintf(stderr, gettext("cannot " + "unshare '%s': legacy share\n"), + zfs_get_name(zhp)); + (void) fprintf(stderr, gettext("use " + "unshare(1M) to unshare this " + "filesystem\n")); + ret = 1; + } else if (!zfs_is_shared_nfs(zhp, NULL)) { + (void) fprintf(stderr, gettext("cannot " + "unshare '%s': not currently " + "shared\n"), zfs_get_name(zhp)); + ret = 1; + } else if (zfs_unshareall_nfs(zhp) != 0) { + ret = 1; + } + break; + + case OP_MOUNT: + if (strcmp(property, "legacy") == 0) { + (void) fprintf(stderr, gettext("cannot " + "unmount '%s': legacy " + "mountpoint\n"), zfs_get_name(zhp)); + (void) fprintf(stderr, gettext("use " + "umount(1M) to unmount this " + "filesystem\n")); + ret = 1; + } else if (!zfs_is_mounted(zhp, NULL)) { + (void) fprintf(stderr, gettext("cannot " + "unmount '%s': not currently " + "mounted\n"), + zfs_get_name(zhp)); + ret = 1; + } else if (zfs_unmountall(zhp, flags) != 0) { + ret = 1; + } + break; + } + } else { + assert(op == OP_SHARE); + + verify(zfs_prop_get(zhp, ZFS_PROP_SHAREISCSI, property, + sizeof (property), NULL, NULL, 0, B_FALSE) == 0); + if (strcmp(property, "off") == 0) { (void) fprintf(stderr, gettext("cannot unshare " - "'%s': legacy share\n"), zfs_get_name(zhp)); - (void) fprintf(stderr, gettext("use unshare(1M)" - " to unshare this filesystem\n")); + "'%s': 'shareiscsi' property not set\n"), + zfs_get_name(zhp)); + (void) fprintf(stderr, gettext("set " + "'shareiscsi' property or use " + "iscsitadm(1M) to share this volume\n")); ret = 1; - } else if (!zfs_is_shared(zhp, NULL)) { - (void) fprintf(stderr, gettext("cannot unshare " - "'%s': not currently shared\n"), + } else if (!zfs_is_shared_iscsi(zhp)) { + (void) fprintf(stderr, gettext("cannot " + "unshare '%s': not currently shared\n"), zfs_get_name(zhp)); ret = 1; - } else if (zfs_unshareall(zhp) != 0) { - ret = 1; - } - break; - - case OP_MOUNT: - if (strcmp(property, "legacy") == 0) { - (void) fprintf(stderr, gettext("cannot unmount " - "'%s': legacy mountpoint\n"), - zfs_get_name(zhp)); - (void) fprintf(stderr, gettext("use umount(1M) " - "to unmount this filesystem\n")); - ret = 1; - } else if (!zfs_is_mounted(zhp, NULL)) { - (void) fprintf(stderr, gettext("cannot unmount " - "'%s': not currently mounted\n"), - zfs_get_name(zhp)); - ret = 1; - } else if (zfs_unmountall(zhp, flags) != 0) { + } else if (zfs_unshare_iscsi(zhp) != 0) { ret = 1; } }
--- a/usr/src/cmd/zpool/zpool_main.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/cmd/zpool/zpool_main.c Wed Nov 15 19:25:44 2006 -0800 @@ -678,7 +678,7 @@ ZFS_PROP_MOUNTPOINT), mountpoint) == 0); if (zfs_mount(pool, NULL, 0) == 0) - ret = zfs_share(pool); + ret = zfs_share_nfs(pool); zfs_close(pool); } zpool_log_history(g_zfs, argc + optind, argv - optind, @@ -749,7 +749,7 @@ return (1); } - if (zpool_unmount_datasets(zhp, force) != 0) { + if (zpool_disable_datasets(zhp, force) != 0) { (void) fprintf(stderr, gettext("could not destroy '%s': " "could not unmount datasets\n"), zpool_get_name(zhp)); return (1); @@ -812,7 +812,7 @@ continue; } - if (zpool_unmount_datasets(zhp, force) != 0) { + if (zpool_disable_datasets(zhp, force) != 0) { ret = 1; zpool_close(zhp); continue; @@ -1134,7 +1134,7 @@ verify((zhp = zpool_open(g_zfs, name)) != NULL); - if (zpool_mount_datasets(zhp, mntopts, 0) != 0) { + if (zpool_enable_datasets(zhp, mntopts, 0) != 0) { zpool_close(zhp); return (1); }
--- a/usr/src/common/zfs/zfs_prop.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/common/zfs/zfs_prop.c Wed Nov 15 19:25:44 2006 -0800 @@ -118,6 +118,9 @@ { "sharenfs", prop_type_string, 0, "off", prop_inherit, ZFS_TYPE_FILESYSTEM, "on | off | share(1M) options", "SHARENFS", B_FALSE }, + { "shareiscsi", prop_type_string, 0, "off", prop_inherit, + ZFS_TYPE_ANY, + "on | off | type=<type>", "SHAREISCSI", B_FALSE }, { "checksum", prop_type_index, ZIO_CHECKSUM_DEFAULT, "on", prop_inherit, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "on | off | fletcher2 | fletcher4 | sha256", "CHECKSUM", B_TRUE }, @@ -159,6 +162,8 @@ ZFS_TYPE_ANY, NULL, NULL, B_FALSE}, { "name", prop_type_string, 0, NULL, prop_readonly, ZFS_TYPE_ANY, NULL, "NAME", B_FALSE }, + { "iscsioptions", prop_type_string, 0, NULL, prop_inherit, + ZFS_TYPE_VOLUME, NULL, "ISCSIOPTIONS", B_FALSE }, }; zfs_proptype_t
--- a/usr/src/lib/Makefile Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/lib/Makefile Wed Nov 15 19:25:44 2006 -0800 @@ -108,6 +108,7 @@ libinetcfg \ libinetutil \ libipmp \ + libiscsitgt \ libkmf \ libkstat \ libkvm \ @@ -335,6 +336,7 @@ libinetutil \ libipmp \ libipp \ + libiscsitgt \ libkstat \ libkvm \ liblaadm \ @@ -500,7 +502,7 @@ pkcs11: libcryptoutil print: libldap5 udapl/udapl_tavor: udapl/libdat -libzfs: libdevinfo libdevid libgen libnvpair libuutil +libzfs: libdevinfo libdevid libgen libnvpair libuutil libiscsitgt libzfs_jni: libdiskmgt libnvpair libzfs libzpool: libavl libumem libnvpair libsec: libavl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libiscsitgt/Makefile Wed Nov 15 19:25:44 2006 -0800 @@ -0,0 +1,56 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.lib + +SUBDIRS = $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) + +all := TARGET= all +clean := TARGET= clean +clobber := TARGET= clobber +install := TARGET= install +lint := TARGET= lint +test := TARGET= test + +HDRS= libiscsitgt.h iscsitgt_impl.h +HDRDIR= common + +.KEEP_STATE: + +all clean clobber install lint: $(SUBDIRS) + +install_h: $(ROOTHDRS) + +check: $(CHECKHDRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include ../Makefile.targ
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libiscsitgt/Makefile.com Wed Nov 15 19:25:44 2006 -0800 @@ -0,0 +1,53 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +LIBRARY= libiscsitgt.a +VERS= .1 +OBJECTS= if_zfs.o if_gen.o xml.o gen.o + +include ../../Makefile.lib +include ../../Makefile.rootfs + +SRCDIR = ../common + +LIBS = $(DYNLIB) $(LINTLIB) +LDLIBS += -lscf -lc +$(DYNLIB) := LDLIBS += -lxml2 +SRCS = $(OBJECTS:%.o=$(SRCDIR)/%.c) + +$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) + +CFLAGS += $(CCVERBOSE) +CPPFLAGS += -I/usr/include/libxml2 -I$(SRCDIR) + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +include ../../Makefile.targ
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libiscsitgt/amd64/Makefile Wed Nov 15 19:25:44 2006 -0800 @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libiscsitgt/common/gen.c Wed Nov 15 19:25:44 2006 -0800 @@ -0,0 +1,160 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Support routines for library + */ +#include <errno.h> +#include <strings.h> +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +#include <libscf.h> +#include <door.h> +#include <libxml/xmlreader.h> +#include <sys/mman.h> + +#include "iscsitgt_impl.h" + +#define WAIT_FOR_SERVICE 15 +#define WAIT_FOR_DOOR 15 +static char *service = "system/iscsitgt:default"; +static char *bad_call_str = "<error><code>1</code>" + "<message>Can't call daemon</message></error>"; + +static Boolean_t check_and_online(int); + +tgt_node_t * +tgt_door_call(char *str, int smf_flags) +{ + tgt_node_t *n = NULL; + door_arg_t d; + int s; + xmlTextReaderPtr r; + + d.data_ptr = str; + d.data_size = strlen(str) + 1; + d.desc_ptr = NULL; + d.desc_num = 0; + d.rbuf = NULL; + d.rsize = 0; + + if (((s = open(ISCSI_TARGET_MGMT_DOOR, 0)) < 0) || + (door_call(s, &d) < 0)) { + if (s != -1) + (void) close(s); + if (check_and_online(smf_flags) == False) { + d.rbuf = bad_call_str; + } else if ((s = open(ISCSI_TARGET_MGMT_DOOR, 0)) < 0) { + d.rbuf = bad_call_str; + } else if (door_call(s, &d) < 0) + d.rbuf = bad_call_str; + } + if ((r = (xmlTextReaderPtr)xmlReaderForMemory(d.rbuf, strlen(d.rbuf), + NULL, NULL, 0)) == NULL) + return (NULL); + + while (xmlTextReaderRead(r) == 1) + if (tgt_node_process(r, &n) == False) + break; + xmlFreeTextReader(r); + if (d.rbuf != bad_call_str) + (void) munmap(d.rbuf, d.rsize); + (void) close(s); + + return (n); +} + +static Boolean_t +is_online(void) +{ + char *s; + Boolean_t rval = False; + + if ((s = smf_get_state(service)) != NULL) { + if (strcmp(s, SCF_STATE_STRING_ONLINE) == 0) + rval = True; + free(s); + } + + return (rval); +} + +static Boolean_t +is_auto_enabled(void) +{ + scf_simple_prop_t *prop; + uint8_t *ret; + Boolean_t rval = True; + + if ((prop = scf_simple_prop_get(NULL, service, "application", + "auto_enable")) == NULL) + return (True); + + if ((ret = scf_simple_prop_next_boolean(prop)) != NULL) + rval = (*ret != 0); + + scf_simple_prop_free(prop); + + return (rval); +} + +static Boolean_t +check_and_online(int smf_flags) +{ + int i, + fd; + + if (!is_online()) { + if (!is_auto_enabled()) + return (False); + + if (smf_enable_instance(service, smf_flags) != 0) + return (False); + + for (i = 0; i < WAIT_FOR_SERVICE; i++) { + if (is_online() == True) + break; + (void) sleep(1); + } + + if (i == WAIT_FOR_SERVICE) + return (False); + } + + for (i = 0; i < WAIT_FOR_DOOR; i++) { + if ((fd = open(ISCSI_TARGET_MGMT_DOOR, 0)) >= 0) { + (void) close(fd); + return (True); + } + if (!is_online()) + break; + (void) sleep(1); + } + return (False); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libiscsitgt/common/if_gen.c Wed Nov 15 19:25:44 2006 -0800 @@ -0,0 +1,48 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <libiscsitgt.h> + +/* + * iscsitgt_init -- Create a handle for each daemon + */ +/*ARGSUSED*/ +iscsit_handle_t +iscsitgt_init(char *host) +{ + return (NULL); +} + +/* + * iscsitgt_fini -- free resources allocated by iscsitgt_init() + */ +/*ARGSUSED*/ +void +iscsitgt_fini(iscsit_handle_t h) +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libiscsitgt/common/if_zfs.c Wed Nov 15 19:25:44 2006 -0800 @@ -0,0 +1,123 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Methods for ZFS to notify the iSCSI Target about which ZVOLs + * need to be made available. + */ + +#include <libiscsitgt.h> +#include <strings.h> +#include <errno.h> +#include <libscf.h> + +#include "iscsitgt_impl.h" + +/* + * iscsitgt_zfs_share -- share a ZFS volume as an iSCSI target + */ +int +iscsitgt_zfs_share(const char *dataset) +{ + char *str = NULL; + tgt_node_t *n; + int code; + + tgt_buf_add_tag(&str, "create", Tag_Start); + tgt_buf_add_tag(&str, "zfs", Tag_Start); + tgt_buf_add(&str, "name", dataset); + tgt_buf_add_tag(&str, "zfs", Tag_End); + tgt_buf_add_tag(&str, "create", Tag_End); + + n = tgt_door_call(str, SMF_TEMPORARY); + if (strcmp(n->x_name, XML_ELEMENT_ERROR) == 0 && + tgt_find_value_int(n, XML_ELEMENT_CODE, &code) == True && + code == 1000) { + tgt_node_free(n); + return (0); + } + + errno = EINVAL; + tgt_node_free(n); + return (-1); +} + +/* + * iscsitgt_zfs_unshare -- unshare a ZFS volume + */ +int +iscsitgt_zfs_unshare(const char *dataset) +{ + char *str = NULL; + tgt_node_t *n; + int code; + + tgt_buf_add_tag(&str, "delete", Tag_Start); + tgt_buf_add_tag(&str, "zfs", Tag_Start); + tgt_buf_add(&str, "name", dataset); + tgt_buf_add_tag(&str, "zfs", Tag_End); + tgt_buf_add_tag(&str, "delete", Tag_End); + + n = tgt_door_call(str, SMF_TEMPORARY); + if (strcmp(n->x_name, XML_ELEMENT_ERROR) == 0 && + tgt_find_value_int(n, XML_ELEMENT_CODE, &code) == True && + code == 1000) { + tgt_node_free(n); + return (0); + } + + tgt_node_free(n); + errno = EINVAL; + return (-1); +} + +int +iscsitgt_zfs_is_shared(const char *dataset) +{ + char *str = NULL; + tgt_node_t *n; + int code; + + tgt_buf_add_tag(&str, "modify", Tag_Start); + tgt_buf_add_tag(&str, "zfs", Tag_Start); + tgt_buf_add(&str, "name", dataset); + tgt_buf_add(&str, XML_ELEMENT_VALIDATE, XML_VALUE_TRUE); + tgt_buf_add_tag(&str, "zfs", Tag_End); + tgt_buf_add_tag(&str, "modify", Tag_End); + + n = tgt_door_call(str, SMF_TEMPORARY); + if (strcmp(n->x_name, XML_ELEMENT_ERROR) == 0 && + tgt_find_value_int(n, XML_ELEMENT_CODE, &code) == True && + code == 1000) { + tgt_node_free(n); + return (1); + } + + tgt_node_free(n); + return (0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libiscsitgt/common/iscsitgt_impl.h Wed Nov 15 19:25:44 2006 -0800 @@ -0,0 +1,202 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _ISCSITGT_IMPL_H +#define _ISCSITGT_IMPL_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Block comment which describes the contents of this file. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libxml/xmlreader.h> + +#ifndef MIN +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#endif +#ifndef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#endif + +/* + * Solaris typedefs boolean_t to be an enum with B_TRUE and B_FALSE. + * MacOS X typedefs boolean_t to be an int with #defines for TRUE & FALSE + * I like the use of enum's for return codes so that compilers can catch + * sloppy coding practices so I've defined a Boolean_t which is unique here. + */ +typedef enum { + False = 0, + True = 1 +} Boolean_t; + +#ifndef DTYPE_OSD +#define DTYPE_OSD 0x11 +#endif + +#define ISCSI_TARGET_MGMT_DOOR "/var/run/iscsi_tgt_door" +/* + * XML element defines. + */ +#define XML_ELEMENT_ERROR "error" +#define XML_ELEMENT_CODE "code" +#define XML_ELEMENT_MESSAGE "message" +#define XML_ELEMENT_TRANSVERS "transport-version" +#define XML_ELEMENT_PROPS "props" +#define XML_ELEMENT_DATAOUT "data-out-size" +#define XML_ELEMENT_BASEDIR "base-directory" +#define XML_ELEMENT_CHAPSECRET "chap-secret" +#define XML_ELEMENT_CHAPNAME "chap-name" +#define XML_ELEMENT_RAD_ACCESS "radius-access" +#define XML_ELEMENT_RAD_SERV "radius-server" +#define XML_ELEMENT_RAD_SECRET "radius-secret" +#define XML_ELEMENT_ISNS_ACCESS "isns-access" +#define XML_ELEMENT_FAST "fast-write-ack" +#define XML_ELEMENT_NAME "name" +#define XML_ELEMENT_ACL "acl" +#define XML_ELEMENT_ACLLIST "acl-list" +#define XML_ELEMENT_TPGT "tpgt" +#define XML_ELEMENT_TPGTLIST "tpgt-list" +#define XML_ELEMENT_SIZE "size" +#define XML_ELEMENT_LUN "lun" +#define XML_ELEMENT_LUNLIST "lun-list" +#define XML_ELEMENT_TYPE "type" +#define XML_ELEMENT_ALIAS "alias" +#define XML_ELEMENT_BACK "backing-store" +#define XML_ELEMENT_DELETE_BACK "delete-backing-store" +#define XML_ELEMENT_TARG "target" +#define XML_ELEMENT_INIT "initiator" +#define XML_ELEMENT_ZFS "zfs" +#define XML_ELEMENT_ADMIN "admin" +#define XML_ELEMENT_INAME "iscsi-name" +#define XML_ELEMENT_MAXRECV "maxrecv" +#define XML_ELEMENT_IPADDR "ip-address" +#define XML_ELEMENT_ALL "all" +#define XML_ELEMENT_VERBOSE "verbose" +#define XML_ELEMENT_LIST "list" +#define XML_ELEMENT_RESULT "result" +#define XML_ELEMENT_TIMECON "time-connected" +#define XML_ELEMENT_READCMDS "read-commands" +#define XML_ELEMENT_WRITECMDS "write-commands" +#define XML_ELEMENT_READBLKS "read-blks" +#define XML_ELEMENT_WRITEBLKS "write-blks" +#define XML_ELEMENT_STATS "statistics" +#define XML_ELEMENT_CONN "connection" +#define XML_ELEMENT_LUNINFO "lun-information" +#define XML_ELEMENT_VID "vid" +#define XML_ELEMENT_PID "pid" +#define XML_ELEMENT_GUID "guid" +#define XML_ELEMENT_DTYPE "dtype" +#define XML_ELEMENT_IOSTAT "iostat" +#define XML_ELEMENT_MACADDR "mac-addr" +#define XML_ELEMENT_MGMTPORT "mgmt-port" +#define XML_ELEMENT_ISCSIPORT "iscsi-port" +#define XML_ELEMENT_TARGLOG "target-log" +#define XML_ELEMENT_DBGLVL "dbg-lvl" +#define XML_ELEMENT_LOGLVL "qlog-lvl" +#define XML_ELEMENT_DBGDAEMON "daemonize" +#define XML_ELEMENT_ENFORCE "enforce-strict-guid" +#define XML_ELEMENT_VERS "version" +#define XML_ELEMENT_MMAP_LUN "mmap-lun" +#define XML_ELEMENT_RPM "rpm" +#define XML_ELEMENT_HEADS "heads" +#define XML_ELEMENT_CYLINDERS "cylinders" +#define XML_ELEMENT_SPT "spt" +#define XML_ELEMENT_BPS "bps" +#define XML_ELEMENT_INTERLEAVE "interleave" +#define XML_ELEMENT_PARAMS "params" +#define XML_ELEMENT_MAXCMDS "max-outstanding-cmds" +#define XML_ELEMENT_THIN_PROVO "thin-provisioning" +#define XML_ELEMENT_DISABLE_TPGS "disable-tpgs" +#define XML_ELEMENT_STATUS "status" +#define XML_ELEMENT_PROGRESS "progress" +#define XML_ELEMENT_TIMESTAMPS "time-stamps" +#define XML_ELEMENT_INCORE "in-core" +#define XML_ELEMENT_VALIDATE "validate" +#define XML_VALUE_TRUE "true" + +typedef enum { + NodeFree, + NodeAlloc, + NodeName, + NodeValue +} tgt_node_state; + +typedef enum { MatchName, MatchBoth } match_type_t; + +typedef struct tgt_node { + struct tgt_node *x_parent, + *x_child, + *x_sibling, + *x_attr; + char *x_name, + *x_value; + tgt_node_state x_state; +} tgt_node_t; + +typedef enum val_type { Tag_String, Tag_Start, Tag_End } val_type_t; +typedef enum xml_val_type { String, Int, Uint64 } xml_val_type_t; + +tgt_node_t *tgt_door_call(char *str, int smf_flags); +Boolean_t tgt_dump2file(tgt_node_t *t, char *path); +void tgt_dump2buf(tgt_node_t *t, char **buf); + +tgt_node_t *tgt_node_alloc(char *name, xml_val_type_t type, void *value); +void tgt_node_free(tgt_node_t *x); +void tgt_node_replace(tgt_node_t *parent, tgt_node_t *child, match_type_t m); +Boolean_t tgt_node_remove(tgt_node_t *parent, tgt_node_t *child, + match_type_t m); +tgt_node_t *tgt_node_next(tgt_node_t *n, char *name, tgt_node_t *cur); +tgt_node_t *tgt_node_next_child(tgt_node_t *n, char *name, tgt_node_t *cur); +tgt_node_t *tgt_node_dup(tgt_node_t *n); +tgt_node_t *tgt_node_find(tgt_node_t *n, char *name); +void tgt_node_add(tgt_node_t *p, tgt_node_t *c); +void tgt_node_add_attr(tgt_node_t *p, tgt_node_t *a); +Boolean_t tgt_node_process(xmlTextReaderPtr r, tgt_node_t **node); + +void tgt_buf_add(char **b, char *element, const char *cdata); +void tgt_buf_add_tag(char **b, const char *str, val_type_t type); +void tgt_buf_add_tag_and_attr(char **b, char *str, char *attr); + +Boolean_t tgt_xml_encode(uint8_t *ip, size_t ip_size, char **buf, + size_t *buf_size); +Boolean_t tgt_xml_decode(char *buf, uint8_t **ip, size_t *ip_size); +Boolean_t tgt_find_value_str(tgt_node_t *n, char *name, char **value); +Boolean_t tgt_find_value_int(tgt_node_t *n, char *name, int *value); +Boolean_t tgt_find_value_intchk(tgt_node_t *n, char *name, int *value); +Boolean_t tgt_find_value_boolean(tgt_node_t *n, char *name, Boolean_t *value); +Boolean_t tgt_find_attr_str(tgt_node_t *n, char *attr, char **value); +Boolean_t tgt_update_value_str(tgt_node_t *node, char *name, char *str); + +#ifdef __cplusplus +} +#endif + +#endif /* _ISCSITGT_IMPL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libiscsitgt/common/libiscsitgt.h Wed Nov 15 19:25:44 2006 -0800 @@ -0,0 +1,573 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _LIBISCSITGT_H +#define _LIBISCSITGT_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Management API for the iSCSI Target. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * These includes resolve + */ +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/iscsi_protocol.h> +#include <sys/scsi/generic/inquiry.h> + +#define EUI64_SIZE 16 +#define VID_SIZE 8 +#define PID_SIZE 16 + +/* + * []------------------------------------------------------------------[] + * | Structures and enums returned by the list functions | + * []------------------------------------------------------------------[] + */ + +typedef enum { LU_Offline, LU_Online } iscsit_status_t; +typedef enum { Target, Initiator, TPGT } iscsit_obj_type_t; + +/* + * Logical Unit (LU) Structure. + * Each iSCSI Target has one or more Logical Units. + */ +typedef struct iscsit_lu { + /* This is the LU number for SCSI commands */ + int l_num; + + /* Globally unique identifier */ + uint8_t l_guid[EUI64_SIZE]; + + /* + * VID/PID used in SCSI INQUIRY responses + */ + char l_vid[VID_SIZE], + l_pid[PID_SIZE]; + /* + * Value will be one of DTYPE_DIRECT, DTYPE_SEQUENTIAL, etc ... + * Look at sys/scsi/generic/inquiry.h for full list + */ + uint8_t l_dtype; + + /* Size of device in blocks */ + diskaddr_t l_size; + + iscsit_status_t l_status; +} iscsit_lu_t; + +/* + * iSCSI Session information. + */ +typedef struct iscsit_conn { + char c_name[ISCSI_MAX_NAME_LEN], + *c_alias; +} iscsit_conn_t; + +typedef struct iscsit_target { + /* This is the full IQN name of the target */ + char t_name[ISCSI_MAX_NAME_LEN]; + + /* + * The Alias which is the same as "friendly name" used during the + * creation of the target. + */ + char *t_alias; + + /* + * The number of Logical Units associated with this target. + * There will always be at least one LU with a value of 0. + * If there are more than LU the order is not guaranteed. + */ + int t_lu_count; + iscsit_lu_t **t_lu_list; + + /* + * A list of initiator which may access this target. This list + * may be 0 in length. + */ + int t_acl_count; + char **t_acl_list; + + /* + * Target Portal Group Tags. A value of zero for the count + * is valid. + */ + int t_tpgt_count; + char **t_tpgt_list; + + /* + * The number of sessions that are currently attached to the + * target. Zero is valid. + */ + int t_conn_count; + iscsit_conn_t **t_conn_list; +} iscsit_target_t; + +/* + * Information stored locally about initiators. Local initiator information + * is setup when administrators wish to control access to each target. The + * use of iSNS will be the prefered method once it's supported. + */ +typedef struct iscsit_initiator { + char i_name[ISCSI_MAX_NAME_LEN], + *i_chap_name; + /* + * While the target daemon has the CHAP secret available it's + * never returned. The CHAP name and secret can be changed at + * any time. This boolean will indicate if the CHAP secret is set + * and if so will cause the daemon to perform unidirectional + * authentication. + */ + boolean_t i_chap_secret_set; +} iscsit_initiator_t; + +/* + * The list of IP addresses associated with a Target Portal Group Tag + */ +typedef struct iscsit_tpgt { + int t_ip_count; + struct sockaddr_storage **t_ip_list; +} iscsit_tpgt_t; + +/* + * These are values which are used globally through the target daemon. + */ +typedef struct iscsit_admin { + /* + * This is the targets CHAP information. When an initiator needs + * to authenticate the target these values are used when creating + * the response. + */ + char *a_chap_name; + boolean_t a_chap_secret_set; + + /* + * The location of the target configuration and default storage for LUs + */ + char *a_base_directory; + + struct sockaddr_storage a_radius_server; + boolean_t a_radius_secret_set, + a_isns_discovery; + struct sockaddr_storage a_isns_ip; + boolean_t a_fast_write_ack; +} iscsit_admin_t; + +typedef void *iscsit_handle_t; + +/* + * []------------------------------------------------------------------[] + * | Funtion Prototypes | + * []------------------------------------------------------------------[] + */ + +/* + * []------------------------------------------------------------------[] + * | Functions for ZFS | + * []------------------------------------------------------------------[] + */ +/* + * iscsitgt_zfs_share -- advertise a ZFS volume through iSCSI + * iscsitgt_zfs_unshare -- unadvertise a ZFS volume through iSCSI + * + * dataset = this must be a valid ZFS dataset which has a "type" property + * of "volume". + * + * These functions will return 0 on success and -1 on failure setting errno + * thusly: + * + * ENODEV - dataset not found + * EINVAL - a share parameter has an invalid value + * ENOSYS - the option string cannot be understood for any other reason + */ +int iscsitgt_zfs_share(const char *dataset); +int iscsitgt_zfs_unshare(const char *dataset); + +/* + * iscsitgt_zfs_is_shared -- returns 1 and 0 otherwise + */ +int iscsitgt_zfs_is_shared(const char *dataset); + +/* + * []------------------------------------------------------------------[] + * | Functions to create handles which are used by methods defined below| + * []------------------------------------------------------------------[] + */ +/* + * iscsitgt_init -- Create a handle for each daemon + * + * A future release will enable this library to work to control multiple + * daemons on different hosts. For now, the argument 'host' should be + * set to NULL which will indicate the local host. + */ +iscsit_handle_t iscsitgt_init(char *host); + +/* + * iscsitgt_fini -- free resources allocated by iscsitgt_init() + */ +void iscsitgt_fini(iscsit_handle_t h); + +/* + * []------------------------------------------------------------------[] + * | Funtions for creating base objects | + * []------------------------------------------------------------------[] + */ +/* + * iscsitgt_creat_target -- creates a new target/lu + * + * h = This is handle which indicates to which target the request is sent. + * If NULL, the target daemon on the current host is used. + * friendly_name = any ASCII string with the following restrictions. + * - it must be no more than 163 characters + * - it must only contain charcters from the set of 'a-z', 'A-Z', '0-9', + * ':', '.', or '-' + * The friendly_name will also be used as the iSCSI TargetAlias which + * is sent to the initiator as part of the log in parameters. + * lun = If the friendly_name has never been used before then lun must be 0. + * If friendly_name has already been created other luns will be created + * under that target. 0 <= lun <= 65535. NOTE: Using LUNs larger than + * 255 is not guaranteed to work for all initiators. + * size = The requested size for the device in blocks. There must be + * available space on the device for the create to succeed. size may + * be zero if, and only if, a 'backing' argument is given which exists. + * dtype = This indicates which type of emulation is performed by the + * daemon. Currently DTYPE_DIRECT, DTYPE_SEQUENTIAL, and DTYPE_UNKNOWN + * are supported. A dtype of DTYPE_UNKNOWN indicates to the daemon + * that a pass through mode should be used. For the pass through mode + * to work 'backing' must be a character device which supports the USCSI + * ioctl. For ZVOLs the dtype should be DTYPE_DIRECT. + * backing = optional location for the backing store. Normally the storage + * for the LU is created in the directory supplied to iscsit_mod_adm_store(). + * If the 'backing' file name doesn't exist *and* a valid device 'size' is + * given then the backing store will be created in that location. When the + * target/lu is removed this backing store will also be removed. + * + * Return codes: + * EINVAL = one or more of the arguments are invalid + * ENOSPC = No space remains to create the backing store. + * EEXIST = A target with the same friendly_name already exists + */ +int iscsitgt_creat_target(iscsit_handle_t h, char *friendly_name, + int lun, diskaddr_t size, int dtype, char *backing); + +/* + * iscsitgt_creat_initiator -- creates an initiator object + * + * Associates a fully compliant iSCSI name (IQN or EUI type) with + * a really human readable name. + * + * h = Handle used to communicate with remote target daemons. A NULL + * value may be used to indicate that the local host target daemon + * friendly_name = Any ASCII string. + * iqn_name = An initiator IQN or EUI string. There will be no validation + * of the name to determine if it complies with RFC3720. This way if + * an initiator has a poorly formed name we can still be configured to + * work with it. + * + * Return codes: + * 0 = success + * EEXIST = The friendly_name is already used. + */ +int iscsitgt_creat_initiator(iscsit_handle_t h, char *friendly_name, + char *iqn_name); + +/* + * iscsitgt_creat_tpgt -- Create a Target Portal Group Tag + * + * Once a TPGT object has been created iscsitgt_add_tpgt_ip would be used + * to associate certain IP addresses with this TPGT. This is used to + * limit which NICs connections are accepted on for a given target. + * Once a TPGT is setup it can be added to a target using: + * iscsitgt_add_target_tpgt(). + * + * h = See iscsitgt_creat_target + * tpgt_num = a value between 1 and 65535 inclusive + * + * Return codes: + * 0 = success + * EEXIST = A tpgt with that number already exists. + * EINVAL = TPGT must be a value between 1 and 65535 inclusive + */ +int iscsitgt_creat_tpgt(iscsit_handle_t h, int tpgt_num); + +/* + * []------------------------------------------------------------------[] + * | Funtions for removing base objects | + * []------------------------------------------------------------------[] + */ + +/* + * iscsitgt_rem_target -- Removes a target/LU from the system + * + * Logical Unit Number 0 *must* be the last LUN removed from a target + * If not, an error will be returned. When LUN0 is removed all references + * to friendly_name are also removed from the system. e.g. Once the LU's + * are removed there's nothing else required to remove the target. + * + * h = See iscsitgt_creat_target() + * friendly_name = This is the same name used during the creation of + * the target. + * lun = Logical Unit Number + * + * Return codes: + * 0 = success + * ENOENT = either friendly_name wasn't found or lun not found + * EINVAL = attempt made to remove LUN0 while other LUs still exist. + */ +int iscsitgt_rem_target(iscsit_handle_t h, char *friendly_name, + int lun); + +/* + * iscsitgt_rem_initiator -- Removes initiator object + * + * This method removes just the initiator object, but not any references + * to this object. For example let's say an initiator was called + * payroll_server and that this server was replaced with a new server + * that had the same function, but with a new IQN value and CHAP secret. + * The user of this library could then remove the initiator object + * and create a new one with the changes *without* needing to update all + * of the target objects that have a reference to 'payroll_server' in + * their ACLs. This is a security feature. If a target has a reference + * to an initiator object which doesn't exist, nobody will be able to + * log into the target. If the daemon we're to remove all references + * along with the object it would then be possible for an initiator to + * log into the target during the time the target didn't have a reference. + * + * h = See iscsitgt_creat_target() + * friendly_name = same value as that used during create. + * + * Return codes: + * 0 = success + * ENOENT = Can't find friendly_name + */ +int iscsitgt_rem_initiator(iscsit_handle_t h, char *friendly_name); + +/* + * iscsitgt_rem_tpgt -- Removes a tpgt object + * + * Similar in function to iscsitgt_rem_initiator. This method only + * removes the TPGT object, but not any references to the object. This + * alows the administrator to remove an old TPGT and create a new one + * without needing to update each and every target first. + * + * h = See iscsitgt_creat_target + * tpgt_num = value used during create + * + * Return codes: + * 0 = success + * ENOENT = tpgt_num wasn't found + * EINVAL = a value outside of the accepted range for tpgt_num was used. + */ +int iscsitgt_rem_tpgt(iscsit_handle_t h, int tpgt_num); + +/* + * []------------------------------------------------------------------[] + * | Funtions for adding attributes to base objects | + * []------------------------------------------------------------------[] + */ +/* + * iscsitgt_add_target_initiator -- Adds an initiator object to ACL for target + * + * h = See iscsitgt_creat_target + * friendly_name = Existing target + * initiator = name of initiator object which doesn't need to exist before + * it's added. + * + * Return codes: + * 0 = success + * ENOENT = friendly_name doesn't exist. + */ +int iscsitgt_add_target_initiator(iscsit_handle_t h, char *friendly_name, + char *initiator); + +/* + * iscsitgt_add_target_tpgt -- adds TPGT to the target + * + * h = See iscsitgt_creat_target() + * friendly_name = Must be a valid target object name + * tpgt_num = While the TPGT object doesn't need to exist, the value will + * be validated to see if it's within the valid range of 1 to 65535 inclusive + * + * Return codes: + * 0 = success + * ENOENT = friendly_name not found + * EINVAL = tpgt_num is not within the valid range. + */ +int iscsitgt_add_target_tpgt(iscsit_handle_t h, char *friendly_name, + int tpgt_num); + +/* + * iscsitgt_add_tpgt_ip -- Adds IP address to TPGT object + * + * Return codes: + * 0 = success + * ENOENT = tpgt_num doesn't exist + * EINVAL = tpgt_num is not within the valid range + */ +int iscsitgt_add_tpgt_ip(iscsit_handle_t h, int tpgt_num, + struct sockaddr_storage *s); + +/* + * []------------------------------------------------------------------[] + * | Funtions for deleting attributes from base objects | + * []------------------------------------------------------------------[] + */ +/* + * iscsitgt_del_target_initiator -- Removes initiator from target ACL + * + * h = See iscsitgt_creat_target() + * friendly_name = target object + * initiator = initiator object to remove from ACL + * + * Return codes: + * 0 = success + * ENOENT = friendly_name or initiator don't exist + */ +int iscsitgt_del_target_initiator(iscsit_handle_t h, char *friendly_name, + char *initiator); + +/* + * iscsitgt_del_target_tpgt -- Removes TPGT from specific target + * + * Return codes: + * 0 = success + * ENOENT = Either friendly_name or tpgt_num doesn't exist as a valid + * type + * EINVAL = tpgt_num is outside of the valid range (1 to 65535) + */ +int iscsitgt_del_target_tpgt(iscsit_handle_t h, char *friendly_name, + int tpgt_num); + +/* + * iscsitgt_del_tpgt_ip -- Removes IP address from TPGT + * + * Return codes: + * 0 = success + * ENOENT = tpgt_num wasn't found or the IP address wasn't found within a valid + * tpgt + * EINVAL = tpgt_num is outside of the valid range (1 to 65535) + */ +int iscsitgt_del_tpgt_ip(iscsit_handle_t h, int tpgt_num, + struct sockaddr_storage *s); + +/* + * []------------------------------------------------------------------[] + * | Funtions for modifying singular attributes for base objects | + * []------------------------------------------------------------------[] + */ +/* + * iscsitgt_mode_target_alias -- Modifies the TargetAlias associated with target + * + * By default the TargetAlias is the same as that given for the friendly_name. + * If another name is desired then it can be changed using this interface. + * + * h = See iscsitgt_creat_target() + * friendly_name = target object + * + * Return codes: + * 0 = success + * ENOENT = friendly_name doesn't exist + */ +int iscsitgt_mod_target_alias(iscsit_handle_t h, char *friendly_name, + char *alias); +int iscsitgt_mod_target_maxrec(iscsit_handle_t h, char *friendly_name, + size_t maxrecv); +int iscsitgt_mod_initiator_chap(iscsit_handle_t h, + char *friendly_name, char *chap_name, char *chap_secret); +int iscsitgt_mod_adm_store(iscsit_handle_t h, char *base); +int iscsitgt_mod_adm_chap(iscsit_handle_t h, char *chap_name, + char *chap_secret); +int iscsitgt_mod_adm_radius(iscsit_handle_t h, struct sockaddr_storage *s, + char *secret); +int iscsitgt_mod_adm_isns_discover(iscsit_handle_t h, + boolean_t find); +int iscsitgt_mod_adm_isns(iscsit_handle_t h, + struct sockaddr_storage *s); +int iscsitgt_mod_adm_fwa(iscsit_handle_t h, boolean_t enable); + +/* + * []------------------------------------------------------------------[] + * | Funtions for listing objects | + * | | + * | NOTE: Each of the following function have a specific free routine | + * | which must be called to free the data. | + * []------------------------------------------------------------------[] + */ +/* + * iscsit_list_find -- returns list of specific object names. + * + * There are three types of objects which are manipulated by these + * interfaces (Target, Initiator, and TPGT). This function will return + * an array of character strings which represent all of the available + * objects of the specific type. These strings are the same ones that + * where used during the creation. + * + * NOTE: Since there's no locking a call to this this function may + * return a name which then doesn't exist when the user attempts to + * get the specific information on that object. This would be caused + * when another operator deletes an object between the first and second + * calls. + */ +char **iscsit_list_find(iscsit_handle_t h, iscsit_obj_type_t t); +void iscsit_list_free(char **list); + +/* + * iscsit_list_target -- returns detailed information about a target + */ +iscsit_target_t *iscsit_list_target(iscsit_handle_t h, char *targ); +void iscsit_list_target_free(iscsit_target_t *t); + +/* + * iscsit_list_initiator -- returns detailed information about an initiator + */ +iscsit_initiator_t *iscsit_list_initiator(iscsit_handle_t h, char *initiator); +void iscsit_list_initiator_free(iscsit_initiator_t *t); + +/* + * iscsit_list_tpgt -- returns detailed information about a target port group + */ +iscsit_tpgt_t *iscsit_list_tpgt(iscsit_handle_t h, char *tpgt); +void iscsit_list_tpgt_free(iscsit_tpgt_t *t); + +/* + * iscsit_list_adm -- returns information about the global variables used. + */ +iscsit_admin_t *iscsit_list_adm(iscsit_handle_t h); +void iscsit_list_adm_free(iscsit_admin_t *t); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBISCSITGT_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libiscsitgt/common/llib-liscsitgt Wed Nov 15 19:25:44 2006 -0800 @@ -0,0 +1,30 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/*LINTLIBRARY*/ +/*PROTOLIB1*/ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <libiscsitgt.h>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libiscsitgt/common/mapfile-vers Wed Nov 15 19:25:44 2006 -0800 @@ -0,0 +1,60 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +SUNWprivate_1.1 { + global: + iscsitgt_zfs_is_shared; + iscsitgt_zfs_share; + iscsitgt_zfs_unshare; + tgt_door_call; + tgt_node_free; + tgt_dump2file; + tgt_dump2buf; + tgt_node_process; + tgt_find_attr_str; + tgt_find_value_str; + tgt_find_value_int; + tgt_find_value_intchk; + tgt_find_value_boolean; + tgt_node_next; + tgt_node_next_child; + tgt_node_add; + tgt_node_add_attr; + tgt_node_alloc; + tgt_node_remove; + tgt_node_replace; + tgt_node_find; + tgt_node_dup; + tgt_xml_encode; + tgt_xml_decode; + tgt_update_value_str; + tgt_buf_add; + tgt_buf_add_tag; + tgt_buf_add_tag_and_attr; + local: + *; +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libiscsitgt/common/xml.c Wed Nov 15 19:25:44 2006 -0800 @@ -0,0 +1,949 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <inttypes.h> +#include <assert.h> +#include <libxml/xmlreader.h> +#include <strings.h> +#include <ctype.h> +#include <stdlib.h> +#include <syslog.h> +#include <sys/stat.h> + +#include "iscsitgt_impl.h" + +/* + * Forward declarations + */ +static char *strip_space(char *value); +static tgt_node_t *node_alloc(); +static void node_free(tgt_node_t *x); +static Boolean_t node_name(tgt_node_t *x, const xmlChar *n); +static Boolean_t node_value(tgt_node_t *x, const xmlChar *n, Boolean_t s); +static tgt_node_t *node_parent(tgt_node_t *x); +static tgt_node_t *node_child(tgt_node_t *x); +static tgt_node_t *node_alloc_attr(tgt_node_t *x); +static void buf_add_node_attr(char **b, tgt_node_t *x); +static void buf_add_comment(char **b, char *comment); +static void buf_add_str(char **b, char *str); + +#define XML_COMMENT_STR "!--" +#define XML_COMMENT_END "--" + +void +tgt_node_free(tgt_node_t *n) +{ + tgt_node_t *c, + *c1; + if (n == NULL) + return; + for (c = n->x_child; c; ) { + c1 = c->x_sibling; + tgt_node_free(c); + c = c1; + } + for (c = n->x_attr; c; ) { + c1 = c->x_sibling; + node_free(c); + c = c1; + } + node_free(n); + +} + +/* + * []---- + * | xml_update_config -- dump out in core node tree to XML parsable file + * | + * | The depth argument is only used to pad the output with white space + * | for indentation. This is meant to help the readability of the file + * | for humans. + * []---- + */ +static void +xml_update_config(tgt_node_t *t, int depth, FILE *output) +{ + int i; + tgt_node_t *c; + + if (t == NULL) + return; + + /* + * If this node has an attribute which indicates it's incore only + * we don't dump it out to a file. + */ + for (c = t->x_attr; c; c = c->x_sibling) + if ((strcmp(c->x_name, XML_ELEMENT_INCORE) == 0) && + (strcmp(c->x_value, XML_VALUE_TRUE) == 0)) + return; + + for (i = 0; i < depth; i++) + (void) fprintf(output, " "); + if (strcmp(t->x_name, XML_COMMENT_STR) == 0) { + (void) fprintf(output, "<%s%s%s>\n", XML_COMMENT_STR, + t->x_value, XML_COMMENT_END); + return; + } + if ((t->x_child == NULL) && (t->x_value != NULL) && + (t->x_attr == NULL) && + (((depth * 4) + ((strlen(t->x_name) * 2) + 5) + + strlen(t->x_value)) < 80)) { + + (void) fprintf(output, "<%s>%s</%s>\n", t->x_name, t->x_value, + t->x_name); + + } else { + (void) fprintf(output, "<%s", t->x_name); + for (c = t->x_attr; c; c = c->x_sibling) + (void) fprintf(output, " %s='%s'", c->x_name, + c->x_value); + (void) fprintf(output, ">\n"); + if (t->x_value) { + for (i = 0; i < depth + 1; i++) + (void) fprintf(output, " "); + (void) fprintf(output, "%s\n", t->x_value); + } + for (c = t->x_child; c; c = c->x_sibling) + xml_update_config(c, depth + 1, output); + for (i = 0; i < depth; i++) + (void) fprintf(output, " "); + (void) fprintf(output, "</%s>\n", t->x_name); + } +} + +Boolean_t +tgt_dump2file(tgt_node_t *root, char *path) +{ + FILE *output; + + if ((output = fopen(path, "wb")) == NULL) { + syslog(LOG_ERR, "Cannot open the file: %s\n", path); + return (False); + } else { + xml_update_config(root, 0, output); + (void) fclose(output); + + /* + * Make sure only root can access the file since we're + * optionally keeping CHAP secrets located here. + */ + (void) chmod(path, 0600); + + return (True); + } +} + +/* + * tgt_dump2buf -- dumps node tree to buffer, allocating memory as it goes + * + * It is up to the caller, when finished with 'buf', to call free() + */ +void +tgt_dump2buf(tgt_node_t *n, char **buf) +{ + tgt_node_t *c; + + if (n == NULL) + return; + if (strcmp(n->x_name, XML_COMMENT_STR) == 0) { + buf_add_comment(buf, n->x_value); + return; + } + buf_add_node_attr(buf, n); + if (n->x_value != NULL) + tgt_buf_add_tag(buf, n->x_value, Tag_String); + for (c = n->x_child; c; c = c->x_sibling) + tgt_dump2buf(c, buf); + tgt_buf_add_tag(buf, n->x_name, Tag_End); +} + +char *common_attr_list[] = { + XML_ELEMENT_NAME, + XML_ELEMENT_VERS, + XML_ELEMENT_INCORE, + 0 +}; + +Boolean_t +tgt_node_process(xmlTextReaderPtr r, tgt_node_t **node) +{ + const xmlChar *name, + *value; + char **ap; + xmlElementType node_type; + tgt_node_t *n, + *an; + + n = *node; + if (n == NULL) { + n = node_alloc(); + if (n == NULL) + return (False); + *node = n; + } + + name = (xmlChar *)xmlTextReaderConstName(r); + if (name == NULL) { + node_free(n); + return (False); + } + + node_type = (xmlElementType)xmlTextReaderNodeType(r); + + value = (xmlChar *)xmlTextReaderConstValue(r); + + if (node_type == XML_ELEMENT_NODE) { + if (n->x_state != NodeAlloc) { + n = node_child(n); + *node = n; + if (n == NULL) + return (False); + } + if (xmlTextReaderAttributeCount(r) > 0) { + + for (ap = common_attr_list; *ap; ap++) { + value = xmlTextReaderGetAttribute(r, + (xmlChar *)*ap); + + if (value != NULL) { + if ((an = node_alloc_attr(n)) == NULL) + return (False); + if (node_name(an, (xmlChar *)*ap) == + False) { + node_free(an); + return (False); + } + if (node_value(an, value, True) == + False) { + node_free(an); + return (False); + } + free((char *)value); + } + } + } + + if (node_name(n, name) == False) { + node_free(n); + return (False); + } + } else if ((value != NULL) && (node_type == XML_TEXT_NODE)) { + if (node_value(n, value, True) == False) { + node_free(n); + return (False); + } + } else if (node_type == XML_ELEMENT_DECL) { + n = node_parent(n); + if (n == NULL) + return (False); + *node = n; + } else if (node_type == XML_COMMENT_NODE) { + n = node_child(n); + if (node_name(n, (xmlChar *)XML_COMMENT_STR) == False) { + node_free(n); + return (False); + } + if (node_value(n, (xmlChar *)value, False) == False) { + node_free(n); + return (False); + } + } else if (node_type != XML_DTD_NODE) { + node_free(n); + return (False); + } + return (True); +} + +Boolean_t +tgt_find_attr_str(tgt_node_t *n, char *attr, char **value) +{ + tgt_node_t *a; + + if ((n == NULL) || (n->x_attr == NULL)) + return (False); + + for (a = n->x_attr; a; a = a->x_sibling) + if (strcmp(a->x_name, attr) == 0) { + *value = a->x_value ? strdup(a->x_value) : NULL; + return (True); + } + return (False); +} + +Boolean_t +tgt_find_value_str(tgt_node_t *n, char *name, char **value) +{ + tgt_node_t *c; + + if ((n == NULL) || (n->x_name == NULL)) + return (False); + + if (strcmp(n->x_name, name) == 0) { + *value = n->x_value ? strdup(n->x_value) : NULL; + return (True); + } + for (c = n->x_child; c; c = c->x_sibling) { + if (tgt_find_value_str(c, name, value) == True) + return (True); + } + return (False); +} + +Boolean_t +tgt_find_value_int(tgt_node_t *n, char *name, int *value) +{ + tgt_node_t *c; + + if ((n == NULL) || (n->x_name == NULL)) + return (False); + + if (strcmp(n->x_name, name) == 0) { + if (n->x_value == NULL) + return (False); + *value = strtol(n->x_value, NULL, 0); + return (True); + } + for (c = n->x_child; c; c = c->x_sibling) { + if (tgt_find_value_int(c, name, value) == True) + return (True); + } + return (False); +} + +/* + * []---- + * | xml_find_value_intchk -- if node exists, check to see if value is okay + * []---- + */ +Boolean_t +tgt_find_value_intchk(tgt_node_t *n, char *name, int *value) +{ + char *str, + chk[32]; + Boolean_t rval; + + if (tgt_find_value_str(n, name, &str) == True) { + + *value = strtol(str, NULL, 0); + /* + * Validate that the input string hasn't overrun what + * what an integer can handle. This is done by simply + * printing out the result of the conversion into a buffer + * and comparing it to the incoming string. That way when + * someone enters 4294967296 which strtol returns as 0 + * we'll catch it. + */ + if ((str[0] == '0') && (str[1] != '\0')) { + if (str[1] == 'x') + (void) snprintf(chk, sizeof (chk), "0x%x", + *value); + else if (str[1] == 'X') + (void) snprintf(chk, sizeof (chk), "0X%x", + *value); + else + (void) snprintf(chk, sizeof (chk), "0%o", + *value); + } else + (void) snprintf(chk, sizeof (chk), "%d", *value); + if (strcmp(chk, str) == 0) + rval = True; + else + rval = False; + free(str); + return (rval); + } else + return (True); +} + +Boolean_t +tgt_find_value_boolean(tgt_node_t *n, char *name, Boolean_t *value) +{ + tgt_node_t *c; + + if ((n == NULL) || (n->x_name == NULL)) + return (False); + + if (strcmp(n->x_name, name) == 0) { + if (n->x_value == NULL) + return (False); + *value = strcmp(n->x_value, "true") == 0 ? True : False; + return (True); + } + for (c = n->x_child; c; c = c->x_sibling) { + if (tgt_find_value_boolean(c, name, value) == True) + return (True); + } + return (False); +} + +tgt_node_t * +tgt_node_next(tgt_node_t *n, char *name, tgt_node_t *cur) +{ + tgt_node_t *x, + *p; + + if (n == NULL) + return (NULL); + + if (cur != NULL) { + for (x = cur->x_sibling; x; x = x->x_sibling) + if (strcmp(x->x_name, name) == 0) + return (x); + return (NULL); + } + + if (n->x_name == NULL) + return (NULL); + + if (strcmp(n->x_name, name) == 0) + return (n); + for (x = n->x_child; x; x = x->x_sibling) + if ((p = tgt_node_next(x, name, 0)) != NULL) + return (p); + return (NULL); +} + +tgt_node_t * +tgt_node_next_child(tgt_node_t *n, char *name, tgt_node_t *cur) +{ + if (cur != NULL) { + n = cur->x_sibling; + } else { + if (n != NULL) + n = n->x_child; + else + return (NULL); + } + while (n) { + if (strcmp(n->x_name, name) == 0) + return (n); + n = n->x_sibling; + } + return (NULL); +} + +void +tgt_node_add(tgt_node_t *p, tgt_node_t *c) +{ + if ((p == NULL) || (c == NULL)) + return; + + if (p->x_child == NULL) + p->x_child = c; + else { + c->x_sibling = p->x_child; + p->x_child = c; + } +} + +void +tgt_node_add_attr(tgt_node_t *p, tgt_node_t *a) +{ + if ((p == NULL) || (a == NULL)) + return; + + if (p->x_attr == NULL) + p->x_attr = a; + else { + a->x_sibling = p->x_attr; + p->x_attr = a; + } +} + +tgt_node_t * +tgt_node_alloc(char *name, xml_val_type_t type, void *value) +{ + tgt_node_t *d = node_alloc(); + int value_len = 0; + char *value_str = NULL; + + if (d == NULL) + return (NULL); + switch (type) { + case String: + if (value) + value_len = strlen((char *)value) + 1; + break; + case Int: + value_len = sizeof (int) * 2 + 3; + break; + case Uint64: + value_len = sizeof (uint64_t) * 2 + 3; + break; + } + if (value_len && + (value_str = (char *)calloc(sizeof (char), value_len)) == NULL) + return (NULL); + if (node_name(d, (xmlChar *)name) == False) { + free(value_str); + return (NULL); + } + if (value_str) { + switch (type) { + case String: + (void) snprintf(value_str, value_len, "%s", + (char *)value); + break; + case Int: + (void) snprintf(value_str, value_len, "0x%x", + *(int *)value); + break; + case Uint64: + (void) snprintf(value_str, value_len, "0x%llx", + *(uint64_t *)value); + break; + } + } + (void) node_value(d, (xmlChar *)value_str, True); + + return (d); +} + +Boolean_t +tgt_xml_encode(uint8_t *ip, size_t ip_size, char **buf, size_t *buf_size) +{ + char *bp; + *buf_size = (ip_size * 2) + 1; + + if ((*buf = (char *)malloc(*buf_size)) == NULL) { + *buf_size = 0; + return (False); + } + + for (bp = *buf; ip_size; ip_size--) { + (void) sprintf(bp, "%.2x", *ip); + ip++; + bp += 2; + } + + return (True); +} + +Boolean_t +tgt_xml_decode(char *buf, uint8_t **ip, size_t *ip_size) +{ + uint8_t *i; + size_t buf_size = strlen(buf); + *ip_size = buf_size / 2; + + if ((*ip = (uint8_t *)malloc(*ip_size)) == NULL) { + *ip_size = 0; + return (False); + } + + for (i = *ip; buf_size; buf_size -= 2) { + char x[3]; + bcopy(buf, x, 2); + x[2] = 0; + *i++ = strtol(x, NULL, 16); + buf += 2; + } + return (True); +} + +Boolean_t +tgt_node_remove(tgt_node_t *parent, tgt_node_t *child, match_type_t m) +{ + tgt_node_t *s, + *c = NULL; + + if ((parent == NULL) || (child == NULL)) + return (False); + + for (s = parent->x_child; s; c = s, s = s->x_sibling) { + + /* + * See if the new child node matches one of the children + * in the parent. + */ + if ((strcmp(s->x_name, child->x_name) == 0) && + ((m == MatchName) || (strcmp(s->x_value, + child->x_value) == 0))) { + + if (parent->x_child == s) { + parent->x_child = s->x_sibling; + } else { + c->x_sibling = s->x_sibling; + } + tgt_node_free(s); + break; + } + } + if (s == NULL) + return (False); + else + return (True); +} + +void +tgt_node_replace(tgt_node_t *parent, tgt_node_t *child, match_type_t m) +{ + tgt_node_t *s, + *c; + + if ((parent == NULL) || (child == NULL)) + return; + + for (s = parent->x_child; s; s = s->x_sibling) { + + /* + * See if the new child node matches one of the children + * in the parent. + */ + if ((strcmp(s->x_name, child->x_name) == 0) && + ((m == MatchName) || (strcmp(s->x_value, + child->x_value) == 0))) { + + /* + * We have a match. Now save the values of the new + * child in this current node. + */ + free(s->x_name); + free(s->x_value); + s->x_name = strdup(child->x_name); + s->x_value = strdup(child->x_value); + if (s->x_child) { + tgt_node_free(s->x_child); + s->x_child = NULL; + } + for (c = child->x_child; c; c = c->x_sibling) + (void) tgt_node_add(s, tgt_node_dup(c)); + break; + } + } + + if (s == NULL) { + /* + * Never found the child so add it + */ + (void) tgt_node_add(parent, tgt_node_dup(child)); + } +} + +Boolean_t +tgt_update_value_str(tgt_node_t *node, char *name, char *str) +{ + if ((node == NULL) || (strcmp(name, node->x_name) != 0)) + return (False); + if (node->x_value != NULL) + free(node->x_value); + node->x_value = strdup(str); + node->x_state = NodeValue; + return (True); +} + +tgt_node_t * +tgt_node_find(tgt_node_t *n, char *name) +{ + tgt_node_t *rval; + + for (rval = n->x_child; rval; rval = rval->x_sibling) + if (strcmp(rval->x_name, name) == 0) + break; + return (rval); +} + +tgt_node_t * +tgt_node_dup(tgt_node_t *n) +{ + tgt_node_t *d = node_alloc(), + *c; + + if (d == NULL) + return (NULL); + if (node_name(d, (xmlChar *)n->x_name) == False) + return (NULL); + if (node_value(d, (xmlChar *)n->x_value, True) == False) + return (NULL); + for (c = n->x_child; c; c = c->x_sibling) + (void) tgt_node_add(d, tgt_node_dup(c)); + return (d); +} + +void +tgt_buf_add(char **b, char *element, const char *cdata) +{ + tgt_buf_add_tag(b, element, Tag_Start); + if (cdata != NULL) + tgt_buf_add_tag(b, cdata, Tag_String); + tgt_buf_add_tag(b, element, Tag_End); +} + +/* + * []---- + * | tgt_buf_add_tag -- adds string to buffer allocating space, sets up tags too + * | + * | Helper function to build a string by allocating memory as we go. + * | If the string argument 'str' is defined to be a start or end tag + * | as declared by 'type' argument add the appropriate characters. + * []---- + */ +void +tgt_buf_add_tag(char **b, const char *str, val_type_t type) +{ + char *buf; + int len; + + /* + * We will add potentially up to 3 extra characters plus the NULL byte + */ + len = strlen(str) + 4; + if ((buf = malloc(len)) == NULL) + return; + + (void) snprintf(buf, len, "%s%s%s%s", type == Tag_String ? "" : "<", + type == Tag_End ? "/" : "", str, type == Tag_String ? "" : ">"); + buf_add_str(b, buf); + free(buf); +} + +/* + * []---- + * | tgt_buf_add_tag_and_attr -- variant on tgt_buf_add_tag which also gives + * | attr + * []---- + */ +void +tgt_buf_add_tag_and_attr(char **b, char *str, char *attr) +{ + char *buf; + int len; + + /* + * In addition to the 'str' and 'attr' strings the code will add + * three characters plus a null byte. + */ + len = strlen(str) + strlen(attr) + 4; + if ((buf = malloc(len)) == NULL) + return; + + (void) snprintf(buf, len, "<%s %s>", str, attr); + buf_add_str(b, buf); + free(buf); +} + +/* + * []---- + * | Utility functions + * []---- + */ +static tgt_node_t * +node_alloc() +{ + tgt_node_t *x = (tgt_node_t *)calloc(sizeof (tgt_node_t), 1); + + if (x == NULL) + return (NULL); + + x->x_state = NodeAlloc; + return (x); +} + +static void +node_free(tgt_node_t *x) +{ + x->x_state = NodeFree; + if (x->x_name) + free(x->x_name); + if (x->x_value) + free(x->x_value); + free(x); +} + +static Boolean_t +node_name(tgt_node_t *x, const xmlChar *n) +{ + assert(x->x_state == NodeAlloc); + if ((n == NULL) || (strlen((char *)n) == 0)) + return (False); + + x->x_state = NodeName; + x->x_name = strip_space((char *)n); + return (True); +} + +static Boolean_t +node_value(tgt_node_t *x, const xmlChar *n, Boolean_t do_strip) +{ + assert(x->x_state == NodeName); + if ((n == NULL) || (strlen((char *)n) == NULL)) + return (False); + + x->x_state = NodeValue; + x->x_value = (do_strip == True) ? + strip_space((char *)n) : strdup((char *)n); + return (True); +} + +static tgt_node_t * +node_parent(tgt_node_t *x) +{ + return (x->x_parent); +} + +static tgt_node_t * +node_child(tgt_node_t *x) +{ + tgt_node_t *n; + + if ((n = node_alloc()) == NULL) + return (NULL); + + if (x->x_child == NULL) { + x->x_child = n; + } else { + n->x_sibling = x->x_child; + x->x_child = n; + } + n->x_parent = x; + return (n); +} + +static tgt_node_t * +node_alloc_attr(tgt_node_t *x) +{ + tgt_node_t *n, + *next; + + n = node_alloc(); + if (x->x_attr == NULL) { + x->x_attr = n; + } else { + for (next = x->x_attr; next->x_sibling; next = next->x_sibling) + ; + next->x_sibling = n; + } + if (n != NULL) + n->x_parent = x; + return (n); +} + +static void +buf_add_str(char **b, char *str) +{ + int len, + olen = 0; + char *p = *b; + + /* + * Make sure we have enough room for the string and tag characters + * plus a NULL byte. + */ + if (str == NULL) + return; + + len = strlen(str) + 1; + if (p == NULL) { + if ((p = malloc(len)) == NULL) + return; + } else { + olen = strlen(p); + p = realloc(p, olen + len); + } + (void) strncpy(p + olen, str, len); + *b = p; +} + +static void +buf_add_node_attr(char **b, tgt_node_t *x) +{ + char *buf; + tgt_node_t *n; + int len; + + /* ---- null byte and starting '<' character ---- */ + len = strlen(x->x_name) + 2; + if ((buf = malloc(len)) == NULL) + return; + (void) snprintf(buf, len, "<%s", x->x_name); + buf_add_str(b, buf); + free(buf); + + for (n = x->x_attr; n; n = n->x_sibling) { + len = strlen(n->x_name) + strlen(n->x_value) + 5; + if ((buf = malloc(len)) == NULL) + return; + (void) snprintf(buf, len, " %s='%s'", n->x_name, n->x_value); + buf_add_str(b, buf); + free(buf); + } + buf_add_str(b, ">"); +} + +static void +buf_add_comment(char **b, char *comment) +{ + char *p = *b; + int len, + olen; + + if (comment == NULL) + return; + + /* + * Room for the strings, plus the brackets and NULL byte + */ + len = strlen(comment) + strlen(XML_COMMENT_STR) + + strlen(XML_COMMENT_END) + 3; + + if (p == NULL) + p = malloc(len); + else { + olen = strlen(p); + p = realloc(p, olen + len); + } + (void) snprintf(p + olen, len, "<%s%s%s>", XML_COMMENT_STR, comment, + XML_COMMENT_END); + *b = p; +} + +static char * +strip_space(char *value) +{ + char *p, + *n; + + for (p = value; p && *p; p++) + if (!isspace(*p)) + break; + if ((p == NULL) || (*p == '\0')) + return (NULL); + + p = strdup(p); + for (n = (p + strlen(p) - 1); n >= p; n--) + if (!isspace(*n)) { + n++; + break; + } + *n = '\0'; + return (p); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libiscsitgt/i386/Makefile Wed Nov 15 19:25:44 2006 -0800 @@ -0,0 +1,30 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libiscsitgt/sparc/Makefile Wed Nov 15 19:25:44 2006 -0800 @@ -0,0 +1,30 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libiscsitgt/sparcv9/Makefile Wed Nov 15 19:25:44 2006 -0800 @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64)
--- a/usr/src/lib/libzfs/Makefile.com Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/lib/libzfs/Makefile.com Wed Nov 15 19:25:44 2006 -0800 @@ -49,7 +49,7 @@ C99MODE= -xc99=%all C99LMODE= -Xc99=%all -LDLIBS += -lc -lm -ldevinfo -ldevid -lgen -lnvpair -luutil +LDLIBS += -lc -lm -ldevinfo -ldevid -lgen -lnvpair -luutil -liscsitgt CPPFLAGS += $(INCS) -D_REENTRANT SRCS= $(OBJS_COMMON:%.o=$(SRCDIR)/%.c) \
--- a/usr/src/lib/libzfs/common/libzfs.h Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/lib/libzfs/common/libzfs.h Wed Nov 15 19:25:44 2006 -0800 @@ -18,6 +18,7 @@ * * CDDL HEADER END */ + /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -80,8 +81,8 @@ EZFS_ZONED, /* used improperly in local zone */ EZFS_MOUNTFAILED, /* failed to mount dataset */ EZFS_UMOUNTFAILED, /* failed to unmount dataset */ - EZFS_UNSHAREFAILED, /* unshare(1M) failed */ - EZFS_SHAREFAILED, /* share(1M) failed */ + EZFS_UNSHARENFSFAILED, /* unshare(1M) failed */ + EZFS_SHARENFSFAILED, /* share(1M) failed */ EZFS_DEVLINKS, /* failed to create zvol links */ EZFS_PERM, /* permission denied */ EZFS_NOSPC, /* out of space */ @@ -91,6 +92,8 @@ EZFS_INVALCONFIG, /* invalid vdev configuration */ EZFS_RECURSIVE, /* recursive dependency */ EZFS_NOHISTORY, /* no history object */ + EZFS_UNSHAREISCSIFAILED, /* iscsitgtd failed request to unshare */ + EZFS_SHAREISCSIFAILED, /* iscsitgtd failed request to share */ EZFS_UNKNOWN /* unknown error */ }; @@ -312,6 +315,8 @@ extern const char *zfs_type_to_name(zfs_type_t); extern void zfs_refresh_properties(zfs_handle_t *); extern int zfs_name_valid(const char *, zfs_type_t); +extern int zfs_disable(zfs_handle_t *); +extern int zfs_enable(zfs_handle_t *); /* * Mount support functions. @@ -324,10 +329,20 @@ /* * Share support functions. */ -extern boolean_t zfs_is_shared(zfs_handle_t *, char **); +extern boolean_t zfs_is_shared(zfs_handle_t *); extern int zfs_share(zfs_handle_t *); -extern int zfs_unshare(zfs_handle_t *, const char *); -extern int zfs_unshareall(zfs_handle_t *); +extern int zfs_unshare(zfs_handle_t *); + +/* + * Protocol-specifc share support functions. + */ +extern boolean_t zfs_is_shared_nfs(zfs_handle_t *, char **); +extern int zfs_share_nfs(zfs_handle_t *); +extern int zfs_unshare_nfs(zfs_handle_t *, const char *); +extern int zfs_unshareall_nfs(zfs_handle_t *); +extern boolean_t zfs_is_shared_iscsi(zfs_handle_t *); +extern int zfs_share_iscsi(zfs_handle_t *); +extern int zfs_unshare_iscsi(zfs_handle_t *); /* * When dealing with nvlists, verify() is extremely useful @@ -362,16 +377,17 @@ extern int zpool_read_label(int, nvlist_t **); /* - * Create and remove zvol /dev links + * Create and remove zvol /dev links. */ extern int zpool_create_zvol_links(zpool_handle_t *); extern int zpool_remove_zvol_links(zpool_handle_t *); /* - * Mount and unmount datasets within a pool + * Enable and disable datasets within a pool by mounting/unmounting and + * sharing/unsharing them. */ -extern int zpool_mount_datasets(zpool_handle_t *, const char *, int); -extern int zpool_unmount_datasets(zpool_handle_t *, boolean_t); +extern int zpool_enable_datasets(zpool_handle_t *, const char *, int); +extern int zpool_disable_datasets(zpool_handle_t *, boolean_t); #ifdef __cplusplus }
--- a/usr/src/lib/libzfs/common/libzfs_changelist.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/lib/libzfs/common/libzfs_changelist.c Wed Nov 15 19:25:44 2006 -0800 @@ -18,6 +18,7 @@ * * CDDL HEADER END */ + /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -97,21 +98,34 @@ for (cn = uu_list_first(clp->cl_list); cn != NULL; cn = uu_list_next(clp->cl_list, cn)) { /* - * if we are in a global zone, but this dataset is exported to - * a local zone, do nothing. + * If we are in the global zone, but this dataset is exported + * to a local zone, do nothing. */ - if ((getzoneid() == GLOBAL_ZONEID) && cn->cn_zoned) + if (getzoneid() == GLOBAL_ZONEID && cn->cn_zoned) continue; - /* - * If we have a volume and this was a rename, remove the - * /dev/zvol links - */ - if (ZFS_IS_VOLUME(cn->cn_handle) && - clp->cl_realprop == ZFS_PROP_NAME) { - if (zvol_remove_link(cn->cn_handle->zfs_hdl, - cn->cn_handle->zfs_name) != 0) - ret = -1; + if (ZFS_IS_VOLUME(cn->cn_handle)) { + switch (clp->cl_realprop) { + case ZFS_PROP_NAME: + /* + * If this was a rename, unshare the zvol, and + * remove the /dev/zvol links. + */ + (void) zfs_unshare_iscsi(cn->cn_handle); + + if (zvol_remove_link(cn->cn_handle->zfs_hdl, + cn->cn_handle->zfs_name) != 0) + ret = -1; + break; + + case ZFS_PROP_VOLSIZE: + /* + * If this was a change to the volume size, we + * need to unshare and reshare the volume. + */ + (void) zfs_unshare_iscsi(cn->cn_handle); + break; + } } else if (zfs_unmount(cn->cn_handle, NULL, clp->cl_flags) != 0) ret = -1; } @@ -120,7 +134,7 @@ } /* - * If the proeprty is 'mountpoint' or 'sharenfs', go through and remount and/or + * If the property is 'mountpoint' or 'sharenfs', go through and remount and/or * reshare the filesystems as necessary. In changelist_gather() we recorded * whether the filesystem was previously shared or mounted. The action we take * depends on the previous state, and whether the value was previously 'legacy'. @@ -132,6 +146,7 @@ changelist_postfix(prop_changelist_t *clp) { prop_changenode_t *cn; + char shareopts[ZFS_MAXPROPLEN]; int ret = 0; /* @@ -154,23 +169,36 @@ for (cn = uu_list_last(clp->cl_list); cn != NULL; cn = uu_list_prev(clp->cl_list, cn)) { /* - * if we are in a global zone, but this dataset is exported to - * a local zone, do nothing. + * If we are in the global zone, but this dataset is exported + * to a local zone, do nothing. */ - if ((getzoneid() == GLOBAL_ZONEID) && cn->cn_zoned) + if (getzoneid() == GLOBAL_ZONEID && cn->cn_zoned) continue; zfs_refresh_properties(cn->cn_handle); - /* - * If this is a volume and we're doing a rename, recreate the - * /dev/zvol links. - */ - if (ZFS_IS_VOLUME(cn->cn_handle) && - clp->cl_realprop == ZFS_PROP_NAME) { - if (zvol_create_link(cn->cn_handle->zfs_hdl, - cn->cn_handle->zfs_name) != 0) + if (ZFS_IS_VOLUME(cn->cn_handle)) { + /* + * If we're doing a rename, recreate the /dev/zvol + * links. + */ + if (clp->cl_realprop == ZFS_PROP_NAME && + zvol_create_link(cn->cn_handle->zfs_hdl, + cn->cn_handle->zfs_name) != 0) { ret = -1; + } else if (cn->cn_shared || + clp->cl_prop == ZFS_PROP_SHAREISCSI) { + if (zfs_prop_get(cn->cn_handle, + ZFS_PROP_SHAREISCSI, shareopts, + sizeof (shareopts), NULL, NULL, 0, + B_FALSE) == 0 && + strcmp(shareopts, "off") == 0) { + ret = zfs_unshare_iscsi(cn->cn_handle); + } else { + ret = zfs_share_iscsi(cn->cn_handle); + } + } + continue; } @@ -183,15 +211,15 @@ * We always re-share even if the filesystem is currently * shared, so that we can adopt any new options. */ - if ((cn->cn_shared || - (clp->cl_prop == ZFS_PROP_SHARENFS && clp->cl_waslegacy))) { - char shareopts[ZFS_MAXPROPLEN]; + if (cn->cn_shared || + (clp->cl_prop == ZFS_PROP_SHARENFS && clp->cl_waslegacy)) { if (zfs_prop_get(cn->cn_handle, ZFS_PROP_SHARENFS, shareopts, sizeof (shareopts), NULL, NULL, 0, - B_FALSE) == 0 && strcmp(shareopts, "off") == 0) - ret = zfs_unshare(cn->cn_handle, NULL); - else - ret = zfs_share(cn->cn_handle); + B_FALSE) == 0 && strcmp(shareopts, "off") == 0) { + ret = zfs_unshare_nfs(cn->cn_handle, NULL); + } else { + ret = zfs_share_nfs(cn->cn_handle); + } } } @@ -221,11 +249,11 @@ } /* - * If we rename a filesystem, and child filesystem handles are no longer valid, - * since we identify datasets by their name in the ZFS namespace. So, we have - * to go through and fix up all the names appropriately. We could do this - * automatically if libzfs kept track of all open handles, but this is a lot - * less work. + * If we rename a filesystem, child filesystem handles are no longer valid + * since we identify each dataset by its name in the ZFS namespace. As a + * result, we have to go through and fix up all the names appropriately. We + * could do this automatically if libzfs kept track of all open handles, but + * this is a lot less work. */ void changelist_rename(prop_changelist_t *clp, const char *src, const char *dst) @@ -255,8 +283,8 @@ } /* - * Given a gathered changelist for the "sharenfs" property, - * unshare all the nodes in the list. + * Given a gathered changelist for the 'sharenfs' property, unshare all the + * datasets in the list. */ int changelist_unshare(prop_changelist_t *clp) @@ -269,8 +297,7 @@ for (cn = uu_list_first(clp->cl_list); cn != NULL; cn = uu_list_next(clp->cl_list, cn)) { - - if (zfs_unshare(cn->cn_handle, NULL) != 0) + if (zfs_unshare_nfs(cn->cn_handle, NULL) != 0) ret = -1; } @@ -278,9 +305,9 @@ } /* - * Check if there is any child exported to a local zone in a - * given changelist. This information has already been recorded - * while gathering the changelist via changelist_gather(). + * Check if there is any child exported to a local zone in a given changelist. + * This information has already been recorded while gathering the changelist + * via changelist_gather(). */ int changelist_haszonedchild(prop_changelist_t *clp) @@ -349,13 +376,13 @@ zfs_source_t sourcetype; /* - * We only want to unmount/unshare those filesystems which may - * inherit from the target filesystem. If we find any filesystem - * with a locally set mountpoint, we ignore any children since changing - * the property will not affect them. If this is a rename, we iterate - * over all children regardless, since we need them unmounted in order - * to do the rename. Also, if this is a volume and we're doing a - * rename, then always add it to the changelist. + * We only want to unmount/unshare those filesystems that may inherit + * from the target filesystem. If we find any filesystem with a + * locally set mountpoint, we ignore any children since changing the + * property will not affect them. If this is a rename, we iterate + * over all children regardless, since we need them unmounted in + * order to do the rename. Also, if this is a volume and we're doing + * a rename, then always add it to the changelist. */ if (!(ZFS_IS_VOLUME(zhp) && clp->cl_realprop == ZFS_PROP_NAME) && @@ -376,11 +403,11 @@ cn->cn_handle = zhp; cn->cn_mounted = zfs_is_mounted(zhp, NULL); - cn->cn_shared = zfs_is_shared(zhp, NULL); + cn->cn_shared = zfs_is_shared(zhp); cn->cn_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); - /* indicate if any child is exported to a local zone */ - if ((getzoneid() == GLOBAL_ZONEID) && cn->cn_zoned) + /* Indicate if any child is exported to a local zone. */ + if (getzoneid() == GLOBAL_ZONEID && cn->cn_zoned) clp->cl_haszonedchild = B_TRUE; uu_list_node_init(cn, &cn->cn_listnode, clp->cl_pool); @@ -442,12 +469,12 @@ } /* - * Given a ZFS handle and a property, construct a complete list of datasets that - * need to be modified as part of this process. For anything but the + * Given a ZFS handle and a property, construct a complete list of datasets + * that need to be modified as part of this process. For anything but the * 'mountpoint' and 'sharenfs' properties, this just returns an empty list. - * Otherwise, we iterate over all children and look for any datasets which - * inherit this property. For each such dataset, we add it to the list and mark - * whether it was shared beforehand. + * Otherwise, we iterate over all children and look for any datasets that + * inherit the property. For each such dataset, we add it to the list and + * mark whether it was shared beforehand. */ prop_changelist_t * changelist_gather(zfs_handle_t *zhp, zfs_prop_t prop, int flags) @@ -499,8 +526,8 @@ * changing the mountpoint and flag it so we can catch all children in * change_one(). * - * Flag cl_alldependents to catch all children plus the - * dependents (clones) that are not in the hierarchy. + * Flag cl_alldependents to catch all children plus the dependents + * (clones) that are not in the hierarchy. */ if (prop == ZFS_PROP_NAME) { clp->cl_prop = ZFS_PROP_MOUNTPOINT; @@ -510,13 +537,16 @@ clp->cl_allchildren = B_TRUE; } else if (prop == ZFS_PROP_CANMOUNT) { clp->cl_prop = ZFS_PROP_MOUNTPOINT; + } else if (prop == ZFS_PROP_VOLSIZE) { + clp->cl_prop = ZFS_PROP_MOUNTPOINT; } else { clp->cl_prop = prop; } clp->cl_realprop = prop; if (clp->cl_prop != ZFS_PROP_MOUNTPOINT && - clp->cl_prop != ZFS_PROP_SHARENFS) + clp->cl_prop != ZFS_PROP_SHARENFS && + clp->cl_prop != ZFS_PROP_SHAREISCSI) return (clp); if (clp->cl_alldependents) { @@ -552,7 +582,7 @@ cn->cn_handle = temp; cn->cn_mounted = zfs_is_mounted(temp, NULL); - cn->cn_shared = zfs_is_shared(temp, NULL); + cn->cn_shared = zfs_is_shared(temp); cn->cn_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); uu_list_node_init(cn, &cn->cn_listnode, clp->cl_pool);
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/lib/libzfs/common/libzfs_dataset.c Wed Nov 15 19:25:44 2006 -0800 @@ -18,6 +18,7 @@ * * CDDL HEADER END */ + /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -855,6 +856,19 @@ } break; + case ZFS_PROP_SHAREISCSI: + if (strcmp(strval, "off") != 0 && + strcmp(strval, "on") != 0 && + strcmp(strval, "type=disk") != 0) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "'%s' must be 'on', 'off', or 'type=disk'"), + propname); + (void) zfs_error(hdl, EZFS_BADPROP, errbuf); + goto error; + } + + break; + case ZFS_PROP_MOUNTPOINT: if (strcmp(strval, ZFS_MOUNTPOINT_NONE) == 0 || strcmp(strval, ZFS_MOUNTPOINT_LEGACY) == 0) @@ -867,23 +881,22 @@ (void) zfs_error(hdl, EZFS_BADPROP, errbuf); goto error; } - break; - } - - /* - * For the mountpoint and sharenfs properties, check if it can - * be set in a global/non-global zone based on the zoned - * property value: - * - * global zone non-global zone - * ----------------------------------------------------- - * zoned=on mountpoint (no) mountpoint (yes) - * sharenfs (no) sharenfs (no) - * - * zoned=off mountpoint (yes) N/A - * sharenfs (yes) - */ - if (prop == ZFS_PROP_MOUNTPOINT || prop == ZFS_PROP_SHARENFS) { + /*FALLTHRU*/ + + case ZFS_PROP_SHARENFS: + /* + * For the mountpoint and sharenfs properties, check if + * it can be set in a global/non-global zone based on + * the zoned property value: + * + * global zone non-global zone + * -------------------------------------------------- + * zoned=on mountpoint (no) mountpoint (yes) + * sharenfs (no) sharenfs (no) + * + * zoned=off mountpoint (yes) N/A + * sharenfs (yes) + */ if (zoned) { if (getzoneid() == GLOBAL_ZONEID) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, @@ -912,6 +925,8 @@ (void) zfs_error(hdl, EZFS_ZONED, errbuf); goto error; } + + break; } /* @@ -958,6 +973,7 @@ errbuf); goto error; } + break; } } } @@ -1591,6 +1607,8 @@ break; case ZFS_PROP_SHARENFS: + case ZFS_PROP_SHAREISCSI: + case ZFS_PROP_ISCSIOPTIONS: (void) strlcpy(propbuf, getprop_string(zhp, prop, &source), proplen); break; @@ -2090,11 +2108,16 @@ zfs_destroy(zfs_handle_t *zhp) { zfs_cmd_t zc = { 0 }; - int ret; (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); if (ZFS_IS_VOLUME(zhp)) { + /* + * Unconditionally unshare this zvol ignoring failure as it + * indicates only that the volume wasn't shared initially. + */ + (void) zfs_unshare_iscsi(zhp); + if (zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name) != 0) return (-1); @@ -2103,8 +2126,7 @@ zc.zc_objset_type = DMU_OST_ZFS; } - ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc); - if (ret != 0) { + if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc) != 0) { return (zfs_standard_error(zhp->zfs_hdl, errno, dgettext(TEXT_DOMAIN, "cannot destroy '%s'"), zhp->zfs_name));
--- a/usr/src/lib/libzfs/common/libzfs_impl.h Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/lib/libzfs/common/libzfs_impl.h Wed Nov 15 19:25:44 2006 -0800 @@ -18,6 +18,7 @@ * * CDDL HEADER END */ + /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -124,6 +125,7 @@ int zvol_create_link(libzfs_handle_t *, const char *); int zvol_remove_link(libzfs_handle_t *, const char *); +int zpool_iter_zvol(zpool_handle_t *, int (*)(const char *, void *), void *); void namespace_clear(libzfs_handle_t *);
--- a/usr/src/lib/libzfs/common/libzfs_mount.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/lib/libzfs/common/libzfs_mount.c Wed Nov 15 19:25:44 2006 -0800 @@ -18,6 +18,7 @@ * * CDDL HEADER END */ + /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -27,33 +28,42 @@ /* * Routines to manage ZFS mounts. We separate all the nasty routines that have - * to deal with the OS. The main entry points are: + * to deal with the OS. The following functions are the main entry points -- + * they are used by mount and unmount and when changing a filesystem's + * mountpoint. * * zfs_is_mounted() * zfs_mount() * zfs_unmount() * zfs_unmountall() * - * These functions are used by mount and unmount, and when changing a - * filesystem's mountpoint. This file also contains the functions used to - * manage sharing filesystems via NFS: + * This file also contains the functions used to manage sharing filesystems via + * NFS and iSCSI: * * zfs_is_shared() * zfs_share() * zfs_unshare() - * zfs_unshareall() + * + * zfs_is_shared_nfs() + * zfs_share_nfs() + * zfs_unshare_nfs() + * zfs_unshareall_nfs() + * zfs_is_shared_iscsi() + * zfs_share_iscsi() + * zfs_unshare_iscsi() * * The following functions are available for pool consumers, and will - * mount/unmount (and share/unshare) all datasets within pool: + * mount/unmount and share/unshare all datasets within pool: * - * zpool_mount_datasets() - * zpool_unmount_datasets() + * zpool_enable_datasets() + * zpool_disable_datasets() */ #include <dirent.h> #include <errno.h> #include <libgen.h> #include <libintl.h> +#include <libiscsitgt.h> #include <stdio.h> #include <stdlib.h> #include <strings.h> @@ -288,7 +298,7 @@ /* * Unshare and unmount the filesystem */ - if (zfs_unshare(zhp, mountpoint) != 0 || + if (zfs_unshare_nfs(zhp, mountpoint) != 0 || unmount_one(zhp->zfs_hdl, mountpoint, flags) != 0) return (-1); } @@ -317,11 +327,38 @@ return (ret); } +boolean_t +zfs_is_shared(zfs_handle_t *zhp) +{ + if (ZFS_IS_VOLUME(zhp)) + return (zfs_is_shared_iscsi(zhp)); + + return (zfs_is_shared_nfs(zhp, NULL)); +} + +int +zfs_share(zfs_handle_t *zhp) +{ + if (ZFS_IS_VOLUME(zhp)) + return (zfs_share_iscsi(zhp)); + + return (zfs_share_nfs(zhp)); +} + +int +zfs_unshare(zfs_handle_t *zhp) +{ + if (ZFS_IS_VOLUME(zhp)) + return (zfs_unshare_iscsi(zhp)); + + return (zfs_unshare_nfs(zhp, NULL)); +} + /* * Check to see if the filesystem is currently shared. */ boolean_t -zfs_is_shared(zfs_handle_t *zhp, char **where) +zfs_is_shared_nfs(zfs_handle_t *zhp, char **where) { char *mountpoint; @@ -345,7 +382,7 @@ * on share(1M) to the dirty work for us. */ int -zfs_share(zfs_handle_t *zhp) +zfs_share_nfs(zfs_handle_t *zhp) { char mountpoint[ZFS_MAXPROPLEN]; char shareopts[ZFS_MAXPROPLEN]; @@ -356,7 +393,9 @@ if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL)) return (0); - /* return success if there are no share options */ + /* + * Return success if there are no share options. + */ if (zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts, sizeof (shareopts), NULL, NULL, 0, B_FALSE) != 0 || strcmp(shareopts, "off") == 0) @@ -383,7 +422,7 @@ mountpoint); if ((fp = popen(buf, "r")) == NULL) - return (zfs_error(hdl, EZFS_SHAREFAILED, + return (zfs_error(hdl, EZFS_SHARENFSFAILED, dgettext(TEXT_DOMAIN, "cannot share '%s'"), zfs_get_name(zhp))); @@ -401,7 +440,7 @@ if (colon != NULL) zfs_error_aux(hdl, colon + 2); - (void) zfs_error(hdl, EZFS_SHAREFAILED, + (void) zfs_error(hdl, EZFS_SHARENFSFAILED, dgettext(TEXT_DOMAIN, "cannot share '%s'"), zfs_get_name(zhp)); @@ -428,7 +467,7 @@ mountpoint); if ((fp = popen(buf, "r")) == NULL) - return (zfs_error(hdl, EZFS_UNSHAREFAILED, + return (zfs_error(hdl, EZFS_UNSHARENFSFAILED, dgettext(TEXT_DOMAIN, "cannot unshare '%s'"), name)); @@ -448,7 +487,7 @@ verify(pclose(fp) != 0); - return (zfs_error(hdl, EZFS_UNSHAREFAILED, + return (zfs_error(hdl, EZFS_UNSHARENFSFAILED, dgettext(TEXT_DOMAIN, "cannot unshare '%s'"), name)); } @@ -462,7 +501,7 @@ * Unshare the given filesystem. */ int -zfs_unshare(zfs_handle_t *zhp, const char *mountpoint) +zfs_unshare_nfs(zfs_handle_t *zhp, const char *mountpoint) { struct mnttab search = { 0 }, entry; @@ -485,10 +524,10 @@ } /* - * Same as zfs_unmountall(), but for unshares. + * Same as zfs_unmountall(), but for NFS unshares. */ int -zfs_unshareall(zfs_handle_t *zhp) +zfs_unshareall_nfs(zfs_handle_t *zhp) { prop_changelist_t *clp; int ret; @@ -536,14 +575,51 @@ } } -/* - * Mount and share all datasets within the given pool. This assumes that no - * datasets within the pool are currently mounted. Because users can create - * complicated nested hierarchies of mountpoints, we first gather all the - * datasets and mountpoints within the pool, and sort them by mountpoint. Once - * we have the list of all filesystems, we iterate over them in order and mount - * and/or share each one. - */ +boolean_t +zfs_is_shared_iscsi(zfs_handle_t *zhp) +{ + return (iscsitgt_zfs_is_shared(zhp->zfs_name) != 0); +} + +int +zfs_share_iscsi(zfs_handle_t *zhp) +{ + char shareopts[ZFS_MAXPROPLEN]; + const char *dataset = zhp->zfs_name; + libzfs_handle_t *hdl = zhp->zfs_hdl; + + /* + * Return success if there are no share options. + */ + if (zfs_prop_get(zhp, ZFS_PROP_SHAREISCSI, shareopts, + sizeof (shareopts), NULL, NULL, 0, B_FALSE) != 0 || + strcmp(shareopts, "off") == 0) + return (0); + + if (iscsitgt_zfs_share(dataset) != 0) + return (zfs_error(hdl, EZFS_SHAREISCSIFAILED, + dgettext(TEXT_DOMAIN, "cannot share '%s'"), dataset)); + + return (0); +} + +int +zfs_unshare_iscsi(zfs_handle_t *zhp) +{ + const char *dataset = zfs_get_name(zhp); + libzfs_handle_t *hdl = zhp->zfs_hdl; + + /* + * If this fails with ENODEV it indicates that zvol wasn't shared so + * we should return success in that case. + */ + if (iscsitgt_zfs_unshare(dataset) != 0 && errno != ENODEV) + return (zfs_error(hdl, EZFS_UNSHAREISCSIFAILED, + dgettext(TEXT_DOMAIN, "cannot unshare '%s'"), dataset)); + + return (0); +} + typedef struct mount_cbdata { zfs_handle_t **cb_datasets; int cb_used; @@ -555,7 +631,7 @@ { mount_cbdata_t *cbp = data; - if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { + if (!(zfs_get_type(zhp) & (ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME))) { zfs_close(zhp); return (0); } @@ -573,27 +649,48 @@ } cbp->cb_datasets[cbp->cb_used++] = zhp; - return (0); + + return (zfs_iter_children(zhp, mount_cb, cbp)); } static int -dataset_compare(const void *a, const void *b) +dataset_cmp(const void *a, const void *b) { zfs_handle_t **za = (zfs_handle_t **)a; zfs_handle_t **zb = (zfs_handle_t **)b; char mounta[MAXPATHLEN]; char mountb[MAXPATHLEN]; + boolean_t gota, gotb; - verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta, - sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0); - verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb, - sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0); + if ((gota = (zfs_get_type(*za) == ZFS_TYPE_FILESYSTEM)) != 0) + verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta, + sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0); + if ((gotb = (zfs_get_type(*zb) == ZFS_TYPE_FILESYSTEM)) != 0) + verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb, + sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0); - return (strcmp(mounta, mountb)); + if (gota && gotb) + return (strcmp(mounta, mountb)); + + if (gota) + return (-1); + if (gotb) + return (1); + + return (strcmp(zfs_get_name(a), zfs_get_name(b))); } +/* + * Mount and share all datasets within the given pool. This assumes that no + * datasets within the pool are currently mounted. Because users can create + * complicated nested hierarchies of mountpoints, we first gather all the + * datasets and mountpoints within the pool, and sort them by mountpoint. Once + * we have the list of all filesystems, we iterate over them in order and mount + * and/or share each one. + */ +#pragma weak zpool_mount_datasets = zpool_enable_datasets int -zpool_mount_datasets(zpool_handle_t *zhp, const char *mntopts, int flags) +zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags) { mount_cbdata_t cb = { 0 }; libzfs_handle_t *hdl = zhp->zpool_hdl; @@ -619,7 +716,7 @@ /* * Sort the datasets by mountpoint. */ - qsort(cb.cb_datasets, cb.cb_used, sizeof (void *), dataset_compare); + qsort(cb.cb_datasets, cb.cb_used, sizeof (void *), dataset_cmp); /* * And mount all the datasets. @@ -639,13 +736,27 @@ return (ret); } -/* - * Unshare and unmount all datasets within the given pool. We don't want to - * rely on traversing the DSL to discover the filesystems within the pool, - * because this may be expensive (if not all of them are mounted), and can fail - * arbitrarily (on I/O error, for example). Instead, we walk /etc/mnttab and - * gather all the filesystems that are currently mounted. - */ + +static int +zvol_cb(const char *dataset, void *data) +{ + libzfs_handle_t *hdl = data; + zfs_handle_t *zhp; + + /* + * Ignore snapshots and ignore failures from non-existant datasets. + */ + if (strchr(dataset, '@') != NULL || + (zhp = zfs_open(hdl, dataset, ZFS_TYPE_VOLUME)) == NULL) + return (0); + + (void) zfs_unshare_iscsi(zhp); + + zfs_close(zhp); + + return (0); +} + static int mountpoint_compare(const void *a, const void *b) { @@ -655,8 +766,16 @@ return (strcmp(mountb, mounta)); } +/* + * Unshare and unmount all datasets within the given pool. We don't want to + * rely on traversing the DSL to discover the filesystems within the pool, + * because this may be expensive (if not all of them are mounted), and can fail + * arbitrarily (on I/O error, for example). Instead, we walk /etc/mnttab and + * gather all the filesystems that are currently mounted. + */ +#pragma weak zpool_unmount_datasets = zpool_disable_datasets int -zpool_unmount_datasets(zpool_handle_t *zhp, boolean_t force) +zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force) { int used, alloc; struct mnttab entry; @@ -668,6 +787,12 @@ int ret = -1; int flags = (force ? MS_FORCE : 0); + /* + * First unshare all zvols. + */ + if (zpool_iter_zvol(zhp, zvol_cb, hdl) != 0) + return (-1); + namelen = strlen(zhp->zpool_name); rewind(hdl->libzfs_mnttab);
--- a/usr/src/lib/libzfs/common/libzfs_pool.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/lib/libzfs/common/libzfs_pool.c Wed Nov 15 19:25:44 2006 -0800 @@ -26,15 +26,17 @@ #pragma ident "%Z%%M% %I% %E% SMI" +#include <alloca.h> #include <assert.h> #include <ctype.h> #include <errno.h> #include <devid.h> +#include <dirent.h> #include <fcntl.h> #include <libintl.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> +#include <strings.h> #include <unistd.h> #include <sys/zfs_ioctl.h> #include <sys/zio.h> @@ -1231,26 +1233,126 @@ return (zpool_standard_error(hdl, errno, msg)); } -static int -do_zvol(zfs_handle_t *zhp, void *data) +/* + * Iterate over all zvols in a given pool by walking the /dev/zvol/dsk/<pool> + * hierarchy. + */ +int +zpool_iter_zvol(zpool_handle_t *zhp, int (*cb)(const char *, void *), + void *data) { - int linktype = (int)(uintptr_t)data; - int ret; + libzfs_handle_t *hdl = zhp->zpool_hdl; + char (*paths)[MAXPATHLEN]; + size_t size = 4; + int curr, fd, base, ret = 0; + DIR *dirp; + struct dirent *dp; + struct stat st; + + if ((base = open("/dev/zvol/dsk", O_RDONLY)) < 0) + return (errno == ENOENT ? 0 : -1); + + if (fstatat(base, zhp->zpool_name, &st, 0) != 0) { + int err = errno; + (void) close(base); + return (err == ENOENT ? 0 : -1); + } /* - * We check for volblocksize intead of ZFS_TYPE_VOLUME so that we - * correctly handle snapshots of volumes. + * Oddly this wasn't a directory -- ignore that failure since we + * know there are no links lower in the (non-existant) hierarchy. */ - if (ZFS_IS_VOLUME(zhp)) { - if (linktype) - ret = zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); - else - ret = zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name); + if (!S_ISDIR(st.st_mode)) { + (void) close(base); + return (0); + } + + if ((paths = zfs_alloc(hdl, size * sizeof (paths[0]))) == NULL) { + (void) close(base); + return (-1); } - ret = zfs_iter_children(zhp, do_zvol, data); + (void) strlcpy(paths[0], zhp->zpool_name, sizeof (paths[0])); + curr = 0; + + while (curr >= 0) { + if (fstatat(base, paths[curr], &st, AT_SYMLINK_NOFOLLOW) != 0) + goto err; + + if (S_ISDIR(st.st_mode)) { + if ((fd = openat(base, paths[curr], O_RDONLY)) < 0) + goto err; + + if ((dirp = fdopendir(fd)) == NULL) { + (void) close(fd); + goto err; + } + + while ((dp = readdir(dirp)) != NULL) { + if (dp->d_name[0] == '.') + continue; + + if (curr + 1 == size) { + paths = zfs_realloc(hdl, paths, + size * sizeof (paths[0]), + size * 2 * sizeof (paths[0])); + if (paths == NULL) { + (void) closedir(dirp); + (void) close(fd); + goto err; + } + + size *= 2; + } + + (void) strlcpy(paths[curr + 1], paths[curr], + sizeof (paths[curr + 1])); + (void) strlcat(paths[curr], "/", + sizeof (paths[curr])); + (void) strlcat(paths[curr], dp->d_name, + sizeof (paths[curr])); + curr++; + } + + (void) closedir(dirp); + + } else { + if ((ret = cb(paths[curr], data)) != 0) + break; + } + + curr--; + } + + free(paths); + (void) close(base); + + return (ret); + +err: + free(paths); + (void) close(base); + return (-1); +} + +typedef struct zvol_cb { + zpool_handle_t *zcb_pool; + boolean_t zcb_create; +} zvol_cb_t; + +/*ARGSUSED*/ +static int +do_zvol_create(zfs_handle_t *zhp, void *data) +{ + int ret; + + if (ZFS_IS_VOLUME(zhp)) + (void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name); + + ret = zfs_iter_children(zhp, do_zvol_create, NULL); zfs_close(zhp); + return (ret); } @@ -1270,32 +1372,29 @@ zhp->zpool_name)) == NULL) return (0); - ret = zfs_iter_children(zfp, do_zvol, (void *)B_TRUE); + ret = zfs_iter_children(zfp, do_zvol_create, NULL); zfs_close(zfp); return (ret); } +static int +do_zvol_remove(const char *dataset, void *data) +{ + zpool_handle_t *zhp = data; + + return (zvol_remove_link(zhp->zpool_hdl, dataset)); +} + /* - * Iterate over all zvols in the poool and remove any minor nodes. + * Iterate over all zvols in the pool and remove any minor nodes. We iterate + * by examining the /dev links so that a corrupted pool doesn't impede this + * operation. */ int zpool_remove_zvol_links(zpool_handle_t *zhp) { - zfs_handle_t *zfp; - int ret; - - /* - * If the pool is unavailable, just return success. - */ - if ((zfp = make_dataset_handle(zhp->zpool_hdl, - zhp->zpool_name)) == NULL) - return (0); - - ret = zfs_iter_children(zfp, do_zvol, (void *)B_FALSE); - - zfs_close(zfp); - return (ret); + return (zpool_iter_zvol(zhp, do_zvol_remove, zhp)); } /*
--- a/usr/src/lib/libzfs/common/libzfs_util.c Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/lib/libzfs/common/libzfs_util.c Wed Nov 15 19:25:44 2006 -0800 @@ -127,9 +127,9 @@ return (dgettext(TEXT_DOMAIN, "mount failed")); case EZFS_UMOUNTFAILED: return (dgettext(TEXT_DOMAIN, "umount failed")); - case EZFS_UNSHAREFAILED: + case EZFS_UNSHARENFSFAILED: return (dgettext(TEXT_DOMAIN, "unshare(1M) failed")); - case EZFS_SHAREFAILED: + case EZFS_SHARENFSFAILED: return (dgettext(TEXT_DOMAIN, "share(1M) failed")); case EZFS_DEVLINKS: return (dgettext(TEXT_DOMAIN, "failed to create /dev links")); @@ -150,6 +150,12 @@ return (dgettext(TEXT_DOMAIN, "recursive dataset dependency")); case EZFS_NOHISTORY: return (dgettext(TEXT_DOMAIN, "no history available")); + case EZFS_UNSHAREISCSIFAILED: + return (dgettext(TEXT_DOMAIN, + "iscsitgtd failed request to unshare")); + case EZFS_SHAREISCSIFAILED: + return (dgettext(TEXT_DOMAIN, + "iscsitgtd failed request to share")); case EZFS_UNKNOWN: return (dgettext(TEXT_DOMAIN, "unknown error")); default:
--- a/usr/src/lib/libzfs/common/mapfile-vers Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/lib/libzfs/common/mapfile-vers Wed Nov 15 19:25:44 2006 -0800 @@ -47,6 +47,8 @@ zfs_get_type; zfs_is_mounted; zfs_is_shared; + zfs_is_shared_iscsi; + zfs_is_shared_nfs; zfs_iter_children; zfs_iter_dependents; zfs_iter_filesystems; @@ -82,18 +84,24 @@ zfs_rollback; zfs_send; zfs_share; + zfs_share_nfs; + zfs_share_iscsi; zfs_snapshot; zfs_type_to_name; zfs_unmount; zfs_unmountall; zfs_unshare; - zfs_unshareall; + zfs_unshare_iscsi; + zfs_unshare_nfs; + zfs_unshareall_nfs; zpool_add; zpool_clear; zpool_close; zpool_create; zpool_create_zvol_links; zpool_destroy; + zpool_disable_datasets; + zpool_enable_datasets; zpool_export; zpool_find_import; zpool_find_vdev;
--- a/usr/src/pkgdefs/SUNWiscsitgtr/prototype_com Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/pkgdefs/SUNWiscsitgtr/prototype_com Wed Nov 15 19:25:44 2006 -0800 @@ -50,3 +50,5 @@ f manifest var/svc/manifest/system/iscsi_target.xml 0444 root sys d none etc 755 root sys d none etc/iscsi 0755 root sys +d none lib 755 root bin +f none lib/libiscsitgt.so.1 755 root bin
--- a/usr/src/pkgdefs/SUNWiscsitgtr/prototype_i386 Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/pkgdefs/SUNWiscsitgtr/prototype_i386 Wed Nov 15 19:25:44 2006 -0800 @@ -46,3 +46,5 @@ # # SUNWiscsitgtr # +d none lib/amd64 755 root bin +f none lib/amd64/libiscsitgt.so.1 755 root bin
--- a/usr/src/pkgdefs/SUNWiscsitgtr/prototype_sparc Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/pkgdefs/SUNWiscsitgtr/prototype_sparc Wed Nov 15 19:25:44 2006 -0800 @@ -45,4 +45,5 @@ # # SUNWiscsitgtr # - +d none lib/sparcv9 755 root bin +f none lib/sparcv9/libiscsitgt.so.1 755 root bin
--- a/usr/src/pkgdefs/SUNWiscsitgtu/prototype_com Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/pkgdefs/SUNWiscsitgtu/prototype_com Wed Nov 15 19:25:44 2006 -0800 @@ -42,7 +42,13 @@ # # SUNWiscsitgtu # +d none lib 0755 root bin +d none lib/svc 0755 root bin +d none lib/svc/method 0755 root bin +f none lib/svc/method/svc-iscsitgt 0555 root bin d none usr 0755 root sys +d none usr/lib 755 root bin +s none usr/lib/libiscsitgt.so.1=../../lib/libiscsitgt.so.1 d none usr/sbin 0755 root bin f none usr/sbin/iscsitadm 0555 root bin l none usr/sbin/iscsitgtd=../../usr/lib/isaexec
--- a/usr/src/pkgdefs/SUNWiscsitgtu/prototype_i386 Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/pkgdefs/SUNWiscsitgtu/prototype_i386 Wed Nov 15 19:25:44 2006 -0800 @@ -50,3 +50,5 @@ f none usr/sbin/amd64/iscsitgtd 555 root bin d none usr/sbin/i86 755 root bin f none usr/sbin/i86/iscsitgtd 555 root bin +d none usr/lib/amd64 755 root bin +s none usr/lib/amd64/libiscsitgt.so.1=../../../lib/amd64/libiscsitgt.so.1
--- a/usr/src/pkgdefs/SUNWiscsitgtu/prototype_sparc Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/pkgdefs/SUNWiscsitgtu/prototype_sparc Wed Nov 15 19:25:44 2006 -0800 @@ -47,3 +47,5 @@ # d none usr/sbin/sparcv9 755 root bin f none usr/sbin/sparcv9/iscsitgtd 555 root bin +d none usr/lib/sparcv9 755 root bin +s none usr/lib/sparcv9/libiscsitgt.so.1=../../../lib/sparcv9/libiscsitgt.so.1
--- a/usr/src/pkgdefs/etc/exception_list_i386 Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/pkgdefs/etc/exception_list_i386 Wed Nov 15 19:25:44 2006 -0800 @@ -801,3 +801,12 @@ usr/include/sys/iscsi_protocol.h i386 usr/include/sys/iscsi_authclient.h i386 usr/include/sys/iscsi_authclientglue.h i386 +usr/include/libiscsitgt.h i386 +usr/include/iscsitgt_impl.h i386 +usr/lib/libiscsitgt.so i386 +usr/lib/amd64/libiscsitgt.so i386 +lib/libiscsitgt.so i386 +lib/llib-liscsitgt i386 +lib/llib-liscsitgt.ln i386 +lib/amd64/libiscsitgt.so i386 +lib/amd64/llib-liscsitgt.ln i386
--- a/usr/src/pkgdefs/etc/exception_list_sparc Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/pkgdefs/etc/exception_list_sparc Wed Nov 15 19:25:44 2006 -0800 @@ -868,3 +868,12 @@ usr/include/sys/iscsi_protocol.h sparc usr/include/sys/iscsi_authclient.h sparc usr/include/sys/iscsi_authclientglue.h sparc +usr/include/libiscsitgt.h sparc +usr/include/iscsitgt_impl.h sparc +usr/lib/libiscsitgt.so sparc +usr/lib/sparcv9/libiscsitgt.so sparc +lib/libiscsitgt.so sparc +lib/llib-liscsitgt sparc +lib/llib-liscsitgt.ln sparc +lib/sparcv9/libiscsitgt.so sparc +lib/sparcv9/llib-liscsitgt.ln sparc
--- a/usr/src/uts/common/sys/fs/zfs.h Wed Nov 15 19:19:07 2006 -0800 +++ b/usr/src/uts/common/sys/fs/zfs.h Wed Nov 15 19:25:44 2006 -0800 @@ -73,6 +73,7 @@ ZFS_PROP_RECORDSIZE, ZFS_PROP_MOUNTPOINT, ZFS_PROP_SHARENFS, + ZFS_PROP_SHAREISCSI, ZFS_PROP_CHECKSUM, ZFS_PROP_COMPRESSION, ZFS_PROP_ATIME, @@ -91,6 +92,7 @@ */ ZFS_PROP_CREATETXG, ZFS_PROP_NAME, + ZFS_PROP_ISCSIOPTIONS, ZFS_NPROP_ALL } zfs_prop_t;