Home | History | Annotate | Download | only in iscsi
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  *
     25  * iSCSI session interfaces
     26  */
     27 
     28 #include "iscsi.h"		/* main header */
     29 #include <sys/scsi/adapters/iscsi_if.h>		/* ioctl interfaces */
     30 /* protocol structs and defines */
     31 #include <sys/iscsi_protocol.h>
     32 #include "iscsi_targetparam.h"
     33 #include "persistent.h"
     34 #include <sys/scsi/adapters/iscsi_door.h>
     35 #include <sys/dlpi.h>
     36 #include <sys/ethernet.h>
     37 #include <sys/utsname.h>
     38 
     39 static iscsi_targetparams_t iscsi_targets;
     40 static iscsi_targetparam_entry_t *iscsi_targetparam_create();
     41 
     42 /*
     43  * Initializes the target list structure.  Called from iscsi_attach.
     44  */
     45 void
     46 iscsi_targetparam_init() {
     47     iscsi_targets.target_list = NULL;
     48     rw_init(&(iscsi_targets.target_list_lock), NULL,
     49 	    RW_DRIVER, NULL);
     50 }
     51 
     52 /*
     53  * Frees target param list and destroys the list lock.
     54  */
     55 void
     56 iscsi_targetparam_cleanup() {
     57 	iscsi_targetparam_entry_t *curr_entry, *tmp_entry;
     58 
     59 	iscsi_targetparam_lock_list(RW_WRITER);
     60 
     61 	curr_entry = iscsi_targets.target_list;
     62 	while (curr_entry) {
     63 		tmp_entry = curr_entry->next;
     64 		kmem_free(curr_entry, sizeof (iscsi_targetparam_entry_t));
     65 		curr_entry = tmp_entry;
     66 	}
     67 
     68 	iscsi_targetparam_unlock_list();
     69 	rw_destroy(&iscsi_targets.target_list_lock);
     70 }
     71 
     72 /*
     73  * Creates a target param entry and adds it to the target param
     74  * entry list.
     75  *
     76  */
     77 static iscsi_targetparam_entry_t *
     78 iscsi_targetparam_create(uchar_t *name) {
     79 	iscsi_targetparam_entry_t *target;
     80 
     81 	ASSERT(name != NULL);
     82 
     83 	target = kmem_alloc(sizeof (iscsi_targetparam_entry_t),
     84 		KM_SLEEP);
     85 	(void) strlcpy((char *)target->target_name, (char *)name,
     86 		sizeof (target->target_name));
     87 
     88 	/* assign unique key for the target */
     89 	mutex_enter(&iscsi_oid_mutex);
     90 	target->target_oid = iscsi_oid++;
     91 	mutex_exit(&iscsi_oid_mutex);
     92 
     93 	/* Add new target to the target list */
     94 	iscsi_targetparam_lock_list(RW_WRITER);
     95 	if (iscsi_targets.target_list == NULL) {
     96 		iscsi_targets.target_list = target;
     97 		iscsi_targets.target_list->next = NULL;
     98 	} else {
     99 		target->next = iscsi_targets.target_list;
    100 		iscsi_targets.target_list = target;
    101 	}
    102 	iscsi_targetparam_unlock_list();
    103 	return (target);
    104 }
    105 
    106 /*
    107  * Returns a target param entry's oid given the target name.  If the target
    108  * param entry cannot be found one is created and the new oid is returned.
    109  *
    110  */
    111 uint32_t
    112 iscsi_targetparam_get_oid(uchar_t *name) {
    113 	int name_length;
    114 	iscsi_targetparam_entry_t *curr_entry;
    115 
    116 	ASSERT(name != NULL);
    117 	name_length = strlen((char *)name);
    118 
    119 	iscsi_targetparam_lock_list(RW_READER);
    120 	curr_entry = iscsi_targetparam_get_next_entry(NULL);
    121 	while (curr_entry != NULL) {
    122 		if ((name_length == strlen((char *)curr_entry->target_name)) &&
    123 		(bcmp(curr_entry->target_name,
    124 		(char *)name, name_length) == 0)) {
    125 			iscsi_targetparam_unlock_list();
    126 			return (curr_entry->target_oid);
    127 		}
    128 		curr_entry = iscsi_targetparam_get_next_entry(curr_entry);
    129 	}
    130 	iscsi_targetparam_unlock_list();
    131 
    132 	curr_entry = iscsi_targetparam_create(name);
    133 	return (curr_entry->target_oid);
    134 }
    135 
    136 /*
    137  * Returns a target param entry's target name given its oid.  If the oid cannot
    138  * be found, NULL is returned.
    139  *
    140  */
    141 uchar_t *iscsi_targetparam_get_name(uint32_t oid) {
    142 	iscsi_targetparam_entry_t *curr_entry;
    143 
    144 	iscsi_targetparam_lock_list(RW_READER);
    145 	curr_entry = iscsi_targetparam_get_next_entry(NULL);
    146 	while (curr_entry != NULL) {
    147 		if (curr_entry->target_oid == oid) {
    148 		iscsi_targetparam_unlock_list();
    149 			return (curr_entry->target_name);
    150 		}
    151 		curr_entry = iscsi_targetparam_get_next_entry(curr_entry);
    152 	}
    153 	iscsi_targetparam_unlock_list();
    154 	return (NULL);
    155 }
    156 
    157 
    158 /*
    159  * Removes a target param entry from the target param entry list.  The
    160  * oid is used to lookup the entry to be removed.
    161  *
    162  */
    163 int
    164 iscsi_targetparam_remove_target(uint32_t oid) {
    165 	iscsi_targetparam_entry_t *prev_entry, *curr_entry;
    166 
    167 	prev_entry = NULL;
    168 
    169 	iscsi_targetparam_lock_list(RW_WRITER);
    170 	curr_entry = iscsi_targetparam_get_next_entry(NULL);
    171 	while (curr_entry != NULL) {
    172 		if (curr_entry->target_oid == oid) {
    173 
    174 			if (prev_entry == NULL) {
    175 				iscsi_targets.target_list = curr_entry->next;
    176 			} else if (curr_entry->next == NULL) {
    177 				ASSERT(prev_entry != NULL);
    178 				prev_entry->next = NULL;
    179 			} else {
    180 				ASSERT(prev_entry != NULL);
    181 				ASSERT(curr_entry != NULL);
    182 				prev_entry->next = curr_entry->next;
    183 			}
    184 
    185 			kmem_free(curr_entry,
    186 			sizeof (iscsi_targetparam_entry_t));
    187 
    188 			iscsi_targetparam_unlock_list();
    189 			return (0);
    190 		}
    191 
    192 		prev_entry = curr_entry;
    193 		curr_entry = iscsi_targetparam_get_next_entry(curr_entry);
    194 	}
    195 
    196 	iscsi_targetparam_unlock_list();
    197 	return (0);
    198 }
    199 
    200 /*
    201  * Returns the next element in the target param entry list.  If
    202  * NULL is passed as the reference entry then the first item in
    203  * the list is returned.  NULL will be returned when the last
    204  * element in the list is used as the reference entry.
    205  *
    206  */
    207 iscsi_targetparam_entry_t *
    208 iscsi_targetparam_get_next_entry(iscsi_targetparam_entry_t *ref_entry) {
    209     iscsi_targetparam_entry_t *entry;
    210 
    211 	if (ref_entry == NULL) {
    212 		entry = iscsi_targets.target_list;
    213 	} else {
    214 		entry = ref_entry->next;
    215 	}
    216 	return (entry);
    217 }
    218 
    219 /*
    220  * Lock target param list.
    221  *
    222  */
    223 void
    224 iscsi_targetparam_lock_list(krw_t type) {
    225 	rw_enter(&(iscsi_targets.target_list_lock), type);
    226 }
    227 
    228 /*
    229  * Unlock target param list.
    230  *
    231  */
    232 void
    233 iscsi_targetparam_unlock_list() {
    234 	rw_exit(&(iscsi_targets.target_list_lock));
    235 }
    236