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 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _TARGET_QUEUE_H 28 #define _TARGET_QUEUE_H 29 30 #ifdef __cplusplus 31 extern "C" { 32 #endif 33 34 #include <pthread.h> 35 #include <sys/time.h> 36 #include <stdarg.h> 37 #include <synch.h> 38 #include <door.h> 39 40 #include <iscsitgt_impl.h> 41 42 /* Connections */ 43 #define Q_CONN_ERRS 0x00000001 44 #define Q_CONN_LOGIN 0x00000002 45 #define Q_CONN_NONIO 0x00000004 46 #define Q_CONN_IO 0x00000008 47 48 /* Sessions */ 49 #define Q_SESS_ERRS 0x00000010 50 #define Q_SESS_LOGIN 0x00000020 51 #define Q_SESS_NONIO 0x00000040 52 #define Q_SESS_IO 0x00000080 53 54 /* SCSI Target Emulation */ 55 #define Q_STE_ERRS 0x00000100 56 #define Q_STE_NONIO 0x00000200 57 #define Q_STE_IO 0x00000400 58 59 /* General Errors */ 60 #define Q_GEN_ERRS 0x00001000 61 #define Q_GEN_DETAILS 0x00002000 62 63 /* ISCSI Debugging */ 64 #define Q_ISNS_DBG 0x00004000 65 66 /* Persistent Reservations */ 67 #define Q_PR_ERRS 0x00010000 68 #define Q_PR_NONIO 0x00020000 69 #define Q_PR_IO 0x00040000 70 71 /* 72 * When used the queue request will be place at the head of the queue. 73 */ 74 #define Q_HIGH 0x80000000 75 76 extern int qlog_lvl; 77 78 typedef enum { 79 /* 80 * []---------------------------------------------------------------- 81 * | Messages internal to the SAM-3 portion. When the transport calls 82 * | the SAM-3 interfaces messages are enqueued to the LU. The LU 83 * | thread then dequeues these messages and calls the appropriate 84 * | function for the emulator. 85 */ 86 87 /* ---- from transport ---- */ 88 msg_cmd_send, 89 msg_cmd_data_out, 90 91 /* ---- from emulation ---- */ 92 msg_cmd_data_in, 93 msg_cmd_data_rqst, 94 msg_cmd_cmplt, 95 96 /* ---- Internal SAM-3 messages ---- */ 97 msg_lu_add, 98 msg_lu_remove, 99 msg_lu_online, 100 msg_lu_aio_done, 101 102 /* 103 * | End of SAM-3 messages 104 * []---------------------------------------------------------------- 105 */ 106 107 msg_reset_lu, 108 msg_reset_targ, 109 msg_targ_inventory_change, 110 msg_lu_capacity_change, 111 112 /* 113 * The ConnectionReader will send packet ready messages when 114 * data is available. If the socket has an error or is closed 115 * a conn_lost message will be sent. Packet ready will have the 116 * number of bytes currently available on the connection. Don't 117 * free. 118 */ 119 msg_conn_lost, 120 msg_packet_ready, 121 122 /* 123 * Shutdowns happen from the bottom up. The replies are in place 124 * so that threads can wait for the top end to disappear, at least 125 * they must no longer reference any common structures such as 126 * message queues. 127 */ 128 msg_drain_complete, 129 msg_shutdown, 130 msg_shutdown_rsp, 131 132 /* 133 * Here's a special error condition for STE. When using mmap 134 * to access the backing store of a LUN which is larger than 135 * the underlying storage it's possible to run out of room 136 * on the device (no duh). When that happens the OS will send 137 * the daemon a SIGSBUS. The STE thread catches that signal, 138 * sends a UNIT ATTENTION to the other side, and closes down 139 * the STE thread in a special manner. The transport layer 140 * can then restart another STE thread with the same queues 141 * which mean outstanding I/O restarts. 142 */ 143 msg_ste_media_error, 144 145 /* 146 * A NopIn request could be sent on the connection receive thread 147 * except for one little issue. Since both the receive and transmit 148 * threads could be issuing packets and data to the socket at the 149 * same time we must protect those writes so that all of the data 150 * for a single PDU (hdr, checksum, data, checksum) go out together. 151 * It's possible for the socket to receive so much incoming data 152 * that writes will be blocked until some of that data has been 153 * read. If the transmit grabs the lock, attempts to write, and is 154 * blocked we find a condition where the receiver is also blocked 155 * processing a nop command because it can't get the lock. So, instead 156 * we build up the packet and queue it. 157 * 158 * This will also occur with Task Management Requests. 159 */ 160 msg_send_pkt, 161 162 /* 163 * During login when the TargetName name/value pair is processed 164 * the value will be sent to STE through the session layer. 165 * STE can use the information however it sees fit. 166 * The InitiatorName will also be sent which STE can use to 167 * validate login properties. 168 */ 169 msg_target_name, 170 msg_initiator_name, 171 msg_initiator_alias, 172 173 /* 174 * Issued when causing full allocation of backing store. 175 * This is an internal message used by t10_sam.c 176 */ 177 msg_thick_provo, 178 179 /* 180 * ---------------- Debug/Management type messages ---------------- 181 */ 182 /* 183 * When a thread shutdowns someone must call pthread_join else 184 * the thread will remain in a zombie state taking up some 185 * amount of memory. 186 */ 187 msg_pthread_join, 188 189 /* 190 * Requests from and replys to the management host will be done using 191 * these messages. 192 */ 193 msg_mgmt_rqst, 194 msg_mgmt_rply, 195 196 /* 197 * General debug messages. 198 */ 199 msg_log, 200 201 /* 202 * Problem message by some of the auxiliary threads indication 203 * problems. 204 */ 205 msg_status, 206 207 msg_wait_for_destroy 208 209 } msg_type_t; 210 211 typedef struct msg { 212 struct msg *msg_next, 213 *msg_prev; 214 struct msg *msg_all_next; 215 216 msg_type_t msg_type; 217 void *msg_data; 218 219 /* 220 * This can be used either to insert a message higher into the queue 221 * or as debug level flags. 222 */ 223 uint32_t msg_pri_level; 224 } msg_t; 225 226 typedef struct target_queue { 227 msg_t *q_head, 228 *q_tail; 229 pthread_mutex_t q_mutex; 230 sema_t q_sema; 231 int q_num; 232 } target_queue_t; 233 234 typedef enum mgmt_type { 235 mgmt_full_phase_statistics, 236 mgmt_discovery_statistics, 237 mgmt_lun_information, 238 mgmt_parse_xml, 239 mgmt_logout 240 } mgmt_type_t; 241 242 typedef struct mgmt_request { 243 target_queue_t *m_q; 244 mgmt_type_t m_request; 245 time_t m_time; 246 char *m_targ_name; 247 ucred_t *m_cred; 248 249 /* 250 * This mutex protects the m_buf pointer from multiple connections 251 * attempting to update the response at the same time. One management 252 * request structure is sent to possible multiple connections when 253 * gathering statistics. The connections/sessions will lock access 254 * to the buffer. 255 */ 256 pthread_mutex_t m_resp_mutex; 257 union { 258 char **m_resp; 259 tgt_node_t *m_node; 260 } m_u; 261 } mgmt_request_t; 262 263 typedef struct name_request { 264 target_queue_t *nr_q; 265 char *nr_name; 266 } name_request_t; 267 268 void queue_init(); 269 target_queue_t *queue_alloc(); 270 void queue_message_set(target_queue_t *, uint32_t lvl, msg_type_t, void *); 271 msg_t *queue_message_get(target_queue_t *); 272 msg_t *queue_message_try_get(target_queue_t *q); 273 void queue_message_free(msg_t *); 274 void queue_walker_free(target_queue_t *q, 275 Boolean_t (*func)(msg_t *, void *v), void *v1); 276 void queue_free(target_queue_t *, void (*free_func)(msg_t *)); 277 void queue_reset(target_queue_t *q); 278 void queue_prt(target_queue_t *q, int type, char *fmt, ...); 279 void queue_str(target_queue_t *, uint32_t lvl, msg_type_t, char *); 280 void queue_log(Boolean_t on_off); 281 void ste_queue_data_remove(msg_t *m); 282 void conn_queue_data_remove(msg_t *m); 283 void sess_queue_data_remove(msg_t *m); 284 285 #ifdef __cplusplus 286 } 287 #endif 288 289 #endif /* _TARGET_QUEUE_H */ 290