1 /* 2 * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 3 * By downloading, copying, installing or using the software you agree 4 * to this license. If you do not agree to this license, do not 5 * download, install, copy or use the software. 6 * 7 * Intel License Agreement 8 * 9 * Copyright (c) 2000, Intel Corporation 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 16 * -Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 19 * -Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the 22 * distribution. 23 * 24 * -The name of Intel Corporation may not be used to endorse or 25 * promote products derived from this software without specific prior 26 * written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 31 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL 32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 35 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 36 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 37 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 38 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 */ 41 #ifndef _ISCSIUTIL_H_ 42 #define _ISCSIUTIL_H_ 43 44 #include "config.h" 45 46 #include <stdio.h> 47 #include <stdlib.h> 48 49 #ifdef HAVE_STDINT_H 50 #include <stdint.h> 51 #endif 52 53 #ifdef HAVE_STRING_H 54 #include <string.h> 55 #endif 56 57 #ifdef HAVE_PTHREAD_H 58 #include <pthread.h> 59 #endif 60 61 #ifdef HAVE_UNISTD_H 62 #include <unistd.h> 63 #endif 64 65 #ifdef HAVE_SYS_UIO_H 66 #include <sys/uio.h> 67 #endif 68 69 #ifdef HAVE_SYS_SOCKET_H 70 #include <sys/socket.h> 71 #endif 72 73 #ifdef HAVE_FCNTL_H 74 #include <fcntl.h> 75 #endif 76 77 #ifdef HAVE_SYSLOG_H 78 #include <syslog.h> 79 #endif 80 81 /* 82 * 83 */ 84 85 #define ISCSI_HTONLL6(x) (uint64_t) \ 86 ( ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x0000ff0000000000uLL) >> 40)) \ 87 | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x000000ff00000000uLL) >> 24)) \ 88 | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x00000000ff000000uLL) >> 8)) \ 89 | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x0000000000ff0000uLL) << 8)) \ 90 | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x000000000000ff00uLL) << 24)) \ 91 | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x00000000000000ffuLL) << 40))) 92 93 #define ISCSI_NTOHLL6(x) (uint64_t) \ 94 ( ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x0000ff0000000000uLL) >> 40)) \ 95 | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x000000ff00000000uLL) >> 24)) \ 96 | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x00000000ff000000uLL) >> 8)) \ 97 | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x0000000000ff0000uLL) << 8)) \ 98 | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x000000000000ff00uLL) << 24)) \ 99 | ((uint64_t)( ((uint64_t)(x) & (uint64_t)0x00000000000000ffuLL) << 40))) 100 101 /* 102 * Debugging Levels 103 */ 104 105 #define TRACE_NET_DEBUG 0x00000001 106 #define TRACE_NET_BUFF 0x00000002 107 #define TRACE_NET_IOV 0x00000004 108 #define TRACE_NET_ALL (TRACE_NET_DEBUG|TRACE_NET_BUFF|TRACE_NET_IOV) 109 110 #define TRACE_ISCSI_DEBUG 0x00000010 111 #define TRACE_ISCSI_CMD 0x00000020 112 #define TRACE_ISCSI_ARGS 0x00000040 113 #define TRACE_ISCSI_PARAM 0x00000080 114 #define TRACE_ISCSI_ALL (TRACE_ISCSI_DEBUG|TRACE_ISCSI_ARGS|TRACE_ISCSI_PARAM|TRACE_ISCSI_CMD) 115 116 #define TRACE_SCSI_DEBUG 0x00000100 117 #define TRACE_SCSI_CMD 0x00000200 118 #define TRACE_SCSI_DATA 0x00000400 119 #define TRACE_SCSI_ARGS 0x00000800 120 #define TRACE_SCSI_ALL (TRACE_SCSI_DEBUG|TRACE_SCSI_CMD|TRACE_SCSI_DATA|TRACE_SCSI_ARGS) 121 122 #define TRACE_DEBUG 0x00001000 123 #define TRACE_HASH 0x00002000 124 #define TRACE_SYNC 0x00004000 125 #define TRACE_QUEUE 0x00008000 126 #define TRACE_WARN 0x00010000 127 #define TRACE_MEM 0x00020000 128 129 #define TRACE_OSD 0x00040000 130 #define TRACE_OSDFS 0x00080000 131 #define TRACE_OSDSO 0x00100000 132 #define TRACE_ALL 0xffffffff 133 134 /* 135 * Set debugging level here. Turn on debugging in Makefile. 136 */ 137 #ifndef EXTERN 138 #define EXTERN extern 139 #endif 140 141 EXTERN uint32_t iscsi_debug_level; 142 143 /* 144 * Debugging Functions 145 */ 146 void set_debug(const char *); 147 void iscsi_trace(const int, const char *, ...) 148 __printflike(2, 3); 149 void iscsi_warn(const char *, const int, const char *, ...) 150 __printflike(3, 4); 151 void iscsi_err(const char *, const int, const char *, ...) 152 __printflike(3, 4); 153 void iscsi_print_buffer(const char *, const size_t); 154 155 156 /* 157 * Byte Order 158 */ 159 160 #ifdef HAVE_ASM_BYTEORDER_H 161 #include <asm/byteorder.h> 162 #endif 163 164 #ifdef HAVE_SYS_BYTEORDER_H 165 #include <sys/byteorder.h> 166 #endif 167 168 #ifdef HAVE_BYTESWAP_H 169 #include <byteswap.h> 170 #endif 171 172 #ifdef HAVE_MACHINE_ENDIAN_H 173 #include <machine/endian.h> 174 #endif 175 176 #define __BYTE_ORDER _BYTE_ORDER 177 #define __BIG_ENDIAN _BIG_ENDIAN 178 #define __LITTLE_ENDIAN _LITTLE_ENDIAN 179 180 #define ISCSI_NTOHLL(a) ISCSI_BE64TOH(a) 181 #define ISCSI_HTONLL(a) ISCSI_HTOBE64(a) 182 #define ISCSI_NTOHL(a) ntohl(a) 183 #define ISCSI_HTONL(a) htonl(a) 184 #define ISCSI_NTOHS(a) ntohs(a) 185 #define ISCSI_HTONS(a) htons(a) 186 187 #ifndef HAVE_SOCKLEN_T 188 typedef int socklen_t; 189 #endif 190 191 /* 192 * Memory 193 */ 194 void *iscsi_malloc(unsigned); 195 void iscsi_free(void *); 196 void *iscsi_malloc_atomic(unsigned); 197 void iscsi_free_atomic(void *); 198 199 /* 200 * Comparison 201 */ 202 203 #ifndef MIN 204 #define MIN(A,B) (((A)<(B))?(A):(B)) 205 #endif 206 207 #define MIN_3(A,B,C) (((A)<(B))?(((A)<(C))?(A):(C)):(((B)<(C))?(B):(C))) 208 209 /* Spin locks */ 210 211 typedef pthread_mutex_t iscsi_spin_t; 212 213 int iscsi_spin_init(iscsi_spin_t * ); 214 int iscsi_spin_lock(iscsi_spin_t * ); 215 int iscsi_spin_unlock(iscsi_spin_t * ); 216 int iscsi_spin_lock_irqsave(iscsi_spin_t * , uint32_t *); 217 int iscsi_spin_unlock_irqrestore(iscsi_spin_t * , uint32_t *); 218 int iscsi_spin_destroy(iscsi_spin_t * ); 219 220 /* 221 * End of ISCSI spin routines 222 */ 223 224 /* 225 * Tags 226 */ 227 228 #define ISCSI_SET_TAG(tag) do { \ 229 iscsi_spin_lock(&g_tag_spin); \ 230 *tag = g_tag++; \ 231 iscsi_spin_unlock(&g_tag_spin); \ 232 } while (/* CONSTCOND */ 0) 233 234 #define ISCSI_SET_TAG_IN_INTR(tag) do { \ 235 uint32_t flags; \ 236 iscsi_spin_lock_irqsave(&g_tag_spin, &flags); \ 237 *tag = g_tag++; \ 238 iscsi_spin_unlock_irqrestore(&g_tag_spin, &flags); \ 239 } while (/* CONSTCOND */ 0) 240 241 242 243 /* 244 * Hashing 245 */ 246 247 248 typedef struct hash_t { 249 struct initiator_cmd_t **bucket; 250 int collisions; 251 int insertions; 252 int n; 253 iscsi_spin_t lock; 254 } hash_t; 255 256 int hash_init(hash_t * , int ); 257 int hash_insert(hash_t * , struct initiator_cmd_t * , uint32_t ); 258 struct initiator_cmd_t *hash_remove(hash_t * , uint32_t ); 259 int hash_destroy(hash_t * ); 260 261 /* 262 * Queuing 263 */ 264 265 typedef struct iscsi_queue_t { 266 int head; 267 int tail; 268 int count; 269 void **elem; 270 int depth; 271 iscsi_spin_t lock; 272 } iscsi_queue_t; 273 274 int iscsi_queue_init(iscsi_queue_t * , int ); 275 void iscsi_queue_destroy(iscsi_queue_t * ); 276 int iscsi_queue_insert(iscsi_queue_t * , void *); 277 void *iscsi_queue_remove(iscsi_queue_t * ); 278 int iscsi_queue_depth(iscsi_queue_t * ); 279 int iscsi_queue_full(iscsi_queue_t * ); 280 281 /* 282 * Socket Abstraction 283 */ 284 285 /* Turning off Nagle's Algorithm doesn't always seem to work, */ 286 /* so we combine two messages into one when the second's size */ 287 /* is less than or equal to ISCSI_SOCK_HACK_CROSSOVER. */ 288 289 #define ISCSI_SOCK_HACK_CROSSOVER 1024 290 #define ISCSI_SOCK_CONNECT_NONBLOCK 0 291 #define ISCSI_SOCK_CONNECT_TIMEOUT 1 292 #define ISCSI_SOCK_MSG_BYTE_ALIGN 4 293 294 int iscsi_sock_create(int *); 295 int iscsi_socks_establish(int *, int *, int *, char *, int); 296 int iscsi_waitfor_connection(int *, int, const char *cf, int *); 297 const char *iscsi_address_family(int); 298 int iscsi_sock_setsockopt(int * , int , int , void *, unsigned); 299 int iscsi_sock_getsockopt(int * , int , int , void *, unsigned *); 300 int iscsi_sock_bind(int , int); 301 int iscsi_sock_listen(int); 302 int iscsi_sock_connect(int , char *, int); 303 int iscsi_sock_accept(int , int *); 304 int iscsi_sock_shutdown(int , int); 305 int iscsi_sock_close(int); 306 int iscsi_sock_msg(int , int , unsigned , void *, int); 307 int iscsi_sock_send_header_and_data(int , 308 void *, unsigned , 309 const void *, unsigned , int); 310 int iscsi_sock_getsockname(int , struct sockaddr * , unsigned *); 311 int iscsi_sock_getpeername(int , struct sockaddr * , unsigned *); 312 int modify_iov(struct iovec ** , int *, uint32_t , uint32_t); 313 314 315 /* 316 * Mutexes 317 */ 318 319 typedef pthread_mutex_t iscsi_mutex_t; 320 321 int iscsi_mutex_init(iscsi_mutex_t *); 322 int iscsi_mutex_lock(iscsi_mutex_t *); 323 int iscsi_mutex_unlock(iscsi_mutex_t *); 324 int iscsi_mutex_destroy(iscsi_mutex_t *); 325 326 #define ISCSI_LOCK(M, ELSE) do { \ 327 if (iscsi_mutex_lock(M) != 0) { \ 328 iscsi_err(__FILE__, __LINE__, "iscsi_mutex_lock() failed\n"); \ 329 ELSE; \ 330 } \ 331 } while (/* CONSTCOND */ 0) 332 333 #define ISCSI_UNLOCK(M, ELSE) do { \ 334 if (iscsi_mutex_unlock(M) != 0) { \ 335 iscsi_err(__FILE__, __LINE__, "iscsi_mutex_unlock() failed\n"); \ 336 ELSE; \ 337 } \ 338 } while (/* CONSTCOND */ 0) 339 340 #define ISCSI_MUTEX_INIT(M, ELSE) do { \ 341 if (iscsi_mutex_init(M) != 0) { \ 342 iscsi_err(__FILE__, __LINE__, "iscsi_mutex_init() failed\n"); \ 343 ELSE; \ 344 } \ 345 } while (/* CONSTCOND */ 0) 346 347 #define ISCSI_MUTEX_DESTROY(M, ELSE) do { \ 348 if (iscsi_mutex_destroy(M) != 0) { \ 349 iscsi_err(__FILE__, __LINE__, "iscsi_mutex_destroy() failed\n"); \ 350 ELSE; \ 351 } \ 352 } while (/* CONSTCOND */ 0) 353 354 /* 355 * Condition Variable 356 */ 357 358 typedef pthread_cond_t iscsi_cond_t; 359 360 int iscsi_cond_init(iscsi_cond_t *); 361 int iscsi_cond_wait(iscsi_cond_t * , iscsi_mutex_t *); 362 int iscsi_cond_signal(iscsi_cond_t *); 363 int iscsi_cond_destroy(iscsi_cond_t *); 364 365 #define ISCSI_COND_INIT(C, ELSE) do { \ 366 if (iscsi_cond_init(C) != 0) { \ 367 ELSE; \ 368 } \ 369 } while (/* CONSTCOND */ 0) 370 371 #define ISCSI_WAIT(C, M, ELSE) do { \ 372 if (iscsi_cond_wait(C, M) != 0) { \ 373 ELSE; \ 374 } \ 375 } while (/* CONSTCOND */ 0) 376 377 #define ISCSI_SIGNAL(C, ELSE) do { \ 378 if (iscsi_cond_signal(C) != 0) { \ 379 ELSE; \ 380 } \ 381 } while (/* CONSTCOND */ 0) 382 383 #define ISCSI_COND_DESTROY(C, ELSE) do { \ 384 if (iscsi_cond_destroy(C) != 0) { \ 385 ELSE; \ 386 } \ 387 } while (/* CONSTCOND */ 0) 388 389 /* 390 * Threading Routines 391 */ 392 393 typedef struct iscsi_thread_t { 394 pthread_t pthread; 395 } iscsi_thread_t; 396 397 int iscsi_thread_create(iscsi_thread_t * , void *(*proc) (void *), void *); 398 399 #define ISCSI_SET_THREAD(ME) /* for user pthread id set by pthread_create 400 * in iscsi_thread_create */ 401 #define ISCSI_THREAD_START(NAME) 402 403 /* 404 * Worker Thread 405 */ 406 407 #define ISCSI_WORKER_STATE_STARTED 1 408 #define ISCSI_WORKER_STATE_ERROR 2 409 #define ISCSI_WORKER_STATE_EXITING 4 410 411 typedef struct { 412 iscsi_thread_t thread; 413 iscsi_mutex_t work_mutex; 414 iscsi_cond_t work_cond; 415 iscsi_mutex_t exit_mutex; 416 iscsi_cond_t exit_cond; 417 int id; 418 int pid; 419 volatile uint32_t state; 420 } iscsi_worker_t; 421 422 #define ISCSI_WORKER_EXIT(ME) do { \ 423 iscsi_trace(TRACE_ISCSI_DEBUG, "%s:%d: %s", __FILE__, __LINE__, "exiting\n");\ 424 (ME)->state |= ISCSI_WORKER_STATE_EXITING; \ 425 return 0; \ 426 /* NOTREACHED */ \ 427 } while (/* CONSTCOND */ 0) 428 429 /* 430 * Spin Lock 431 */ 432 #define ISCSI_SPIN 433 434 /* 435 * Pre/Post condition checking 436 */ 437 438 #define NO_CLEANUP {} 439 440 #if 0 441 #define RETURN_NOT_EQUAL(NAME, V1, V2, CU, RC) \ 442 if ((V1)!=(V2)) { \ 443 iscsi_err(__FILE__, __LINE__, "Bad \"%s\": Got %u expected %u.\n", NAME, V1, V2); \ 444 CU; \ 445 return RC; \ 446 } 447 #endif 448 449 #if 0 450 #define ERROR_NOT_EQUAL(NAME, V1, V2, CU) do { \ 451 if ((V1)!=(V2)) { \ 452 iscsi_err(__FILE__, __LINE__, \ 453 "Bad \"%s\": Got %u expected %u.\n", NAME, V1, V2); \ 454 CU; \ 455 } \ 456 } while(/* CONSTCOND */0) 457 #endif 458 459 /* 460 * Misc. Functions 461 */ 462 463 uint32_t iscsi_atoi(char *); 464 int HexTextToData(const char *, uint32_t , uint8_t *, uint32_t); 465 int HexDataToText(uint8_t *, uint32_t , char *, uint32_t); 466 void GenRandomData(uint8_t *, uint32_t); 467 468 /* this is the maximum number of iovecs which we can use in 469 * iscsi_sock_send_header_and_data */ 470 #ifndef ISCSI_MAX_IOVECS 471 #define ISCSI_MAX_IOVECS 32 472 #endif 473 474 enum { 475 /* used in iscsi_sock_msg() */ 476 Receive = 0, 477 Transmit = 1 478 }; 479 480 int allow_netmask(const char *, const char *); 481 482 #endif /* _ISCSIUTIL_H_ */ 483