iscsiutil.h revision 1.4.2.1 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 * Debugging Levels
83 */
84
85 #define TRACE_NET_DEBUG 0x00000001
86 #define TRACE_NET_BUFF 0x00000002
87 #define TRACE_NET_IOV 0x00000004
88 #define TRACE_NET_ALL (TRACE_NET_DEBUG|TRACE_NET_BUFF|TRACE_NET_IOV)
89
90 #define TRACE_ISCSI_DEBUG 0x00000010
91 #define TRACE_ISCSI_CMD 0x00000020
92 #define TRACE_ISCSI_ARGS 0x00000040
93 #define TRACE_ISCSI_PARAM 0x00000080
94 #define TRACE_ISCSI_ALL (TRACE_ISCSI_DEBUG|TRACE_ISCSI_ARGS|TRACE_ISCSI_PARAM|TRACE_ISCSI_CMD)
95
96 #define TRACE_SCSI_DEBUG 0x00000100
97 #define TRACE_SCSI_CMD 0x00000200
98 #define TRACE_SCSI_DATA 0x00000400
99 #define TRACE_SCSI_ARGS 0x00000800
100 #define TRACE_SCSI_ALL (TRACE_SCSI_DEBUG|TRACE_SCSI_CMD|TRACE_SCSI_DATA|TRACE_SCSI_ARGS)
101
102 #define TRACE_DEBUG 0x00001000
103 #define TRACE_HASH 0x00002000
104 #define TRACE_SYNC 0x00004000
105 #define TRACE_QUEUE 0x00008000
106 #define TRACE_WARN 0x00010000
107 #define TRACE_MEM 0x00020000
108
109 #define TRACE_OSD 0x00040000
110 #define TRACE_OSDFS 0x00080000
111 #define TRACE_OSDSO 0x00100000
112 #define TRACE_ALL 0xffffffff
113
114 /*
115 * Set debugging level here. Turn on debugging in Makefile.
116 */
117 #ifndef EXTERN
118 #define EXTERN extern
119 #endif
120
121 EXTERN uint32_t iscsi_debug_level;
122
123 /*
124 * Debugging Functions
125 */
126 void set_debug(const char *);
127 void iscsi_trace(const int, const char *, ...)
128 __printflike(2, 3);
129 void iscsi_warn(const char *, const int, const char *, ...)
130 __printflike(3, 4);
131 void iscsi_err(const char *, const int, const char *, ...)
132 __printflike(3, 4);
133 void iscsi_print_buffer(const char *, const size_t);
134
135
136 /*
137 * Byte Order
138 */
139
140 #ifdef HAVE_ASM_BYTEORDER_H
141 #include <asm/byteorder.h>
142 #endif
143
144 #ifdef HAVE_SYS_BYTEORDER_H
145 #include <sys/byteorder.h>
146 #endif
147
148 #ifdef HAVE_BYTESWAP_H
149 #include <byteswap.h>
150 #endif
151
152 #ifdef HAVE_MACHINE_ENDIAN_H
153 #include <machine/endian.h>
154 #endif
155
156 #define __BYTE_ORDER _BYTE_ORDER
157 #define __BIG_ENDIAN _BIG_ENDIAN
158 #define __LITTLE_ENDIAN _LITTLE_ENDIAN
159
160 #define ISCSI_NTOHLL(a) ISCSI_BE64TOH(a)
161 #define ISCSI_HTONLL(a) ISCSI_HTOBE64(a)
162 #define ISCSI_NTOHL(a) ntohl(a)
163 #define ISCSI_HTONL(a) htonl(a)
164 #define ISCSI_NTOHS(a) ntohs(a)
165 #define ISCSI_HTONS(a) htons(a)
166
167 #ifndef HAVE_SOCKLEN_T
168 typedef int socklen_t;
169 #endif
170
171 /*
172 * Memory
173 */
174 void *iscsi_malloc(unsigned);
175 void iscsi_free(void *);
176 void *iscsi_malloc_atomic(unsigned);
177 void iscsi_free_atomic(void *);
178
179 /*
180 * Comparison
181 */
182
183 #ifndef MIN
184 #define MIN(A,B) (((A)<(B))?(A):(B))
185 #endif
186
187 #define MIN_3(A,B,C) (((A)<(B))?(((A)<(C))?(A):(C)):(((B)<(C))?(B):(C)))
188
189 /* Spin locks */
190
191 typedef pthread_mutex_t iscsi_spin_t;
192
193 int iscsi_spin_init(iscsi_spin_t * );
194 int iscsi_spin_lock(iscsi_spin_t * );
195 int iscsi_spin_unlock(iscsi_spin_t * );
196 int iscsi_spin_lock_irqsave(iscsi_spin_t * , uint32_t *);
197 int iscsi_spin_unlock_irqrestore(iscsi_spin_t * , uint32_t *);
198 int iscsi_spin_destroy(iscsi_spin_t * );
199
200 /*
201 * End of ISCSI spin routines
202 */
203
204 /*
205 * Tags
206 */
207
208 #define ISCSI_SET_TAG(tag) do { \
209 iscsi_spin_lock(&g_tag_spin); \
210 *tag = g_tag++; \
211 iscsi_spin_unlock(&g_tag_spin); \
212 } while (/* CONSTCOND */ 0)
213
214 #define ISCSI_SET_TAG_IN_INTR(tag) do { \
215 uint32_t flags; \
216 iscsi_spin_lock_irqsave(&g_tag_spin, &flags); \
217 *tag = g_tag++; \
218 iscsi_spin_unlock_irqrestore(&g_tag_spin, &flags); \
219 } while (/* CONSTCOND */ 0)
220
221
222
223 /*
224 * Hashing
225 */
226
227
228 typedef struct hash_t {
229 struct initiator_cmd_t **bucket;
230 int collisions;
231 int insertions;
232 int n;
233 iscsi_spin_t lock;
234 } hash_t;
235
236 int hash_init(hash_t * , int );
237 int hash_insert(hash_t * , struct initiator_cmd_t * , uint32_t );
238 struct initiator_cmd_t *hash_remove(hash_t * , uint32_t );
239 int hash_destroy(hash_t * );
240
241 /*
242 * Queuing
243 */
244
245 typedef struct iscsi_queue_t {
246 int head;
247 int tail;
248 int count;
249 void **elem;
250 int depth;
251 iscsi_spin_t lock;
252 } iscsi_queue_t;
253
254 int iscsi_queue_init(iscsi_queue_t * , int );
255 void iscsi_queue_destroy(iscsi_queue_t * );
256 int iscsi_queue_insert(iscsi_queue_t * , void *);
257 void *iscsi_queue_remove(iscsi_queue_t * );
258 int iscsi_queue_depth(iscsi_queue_t * );
259 int iscsi_queue_full(iscsi_queue_t * );
260
261 /*
262 * Socket Abstraction
263 */
264
265 /* Turning off Nagle's Algorithm doesn't always seem to work, */
266 /* so we combine two messages into one when the second's size */
267 /* is less than or equal to ISCSI_SOCK_HACK_CROSSOVER. */
268
269 #define ISCSI_SOCK_HACK_CROSSOVER 1024
270 #define ISCSI_SOCK_CONNECT_NONBLOCK 0
271 #define ISCSI_SOCK_CONNECT_TIMEOUT 1
272 #define ISCSI_SOCK_MSG_BYTE_ALIGN 4
273
274 int iscsi_sock_create(int *);
275 int iscsi_socks_establish(int *, int *, int *, char *, int);
276 int iscsi_waitfor_connection(int *, int, const char *cf, int *);
277 const char *iscsi_address_family(int);
278 int iscsi_sock_setsockopt(int * , int , int , void *, unsigned);
279 int iscsi_sock_getsockopt(int * , int , int , void *, unsigned *);
280 int iscsi_sock_bind(int , int);
281 int iscsi_sock_listen(int);
282 int iscsi_sock_connect(int , char *, int);
283 int iscsi_sock_accept(int , int *);
284 int iscsi_sock_shutdown(int , int);
285 int iscsi_sock_close(int);
286 int iscsi_sock_msg(int , int , unsigned , void *, int);
287 int iscsi_sock_send_header_and_data(int ,
288 void *, unsigned ,
289 const void *, unsigned , int);
290 int iscsi_sock_getsockname(int , struct sockaddr * , unsigned *);
291 int iscsi_sock_getpeername(int , struct sockaddr * , unsigned *);
292 int modify_iov(struct iovec ** , int *, uint32_t , uint32_t);
293
294
295 /*
296 * Mutexes
297 */
298
299 typedef pthread_mutex_t iscsi_mutex_t;
300
301 int iscsi_mutex_init(iscsi_mutex_t *);
302 int iscsi_mutex_lock(iscsi_mutex_t *);
303 int iscsi_mutex_unlock(iscsi_mutex_t *);
304 int iscsi_mutex_destroy(iscsi_mutex_t *);
305
306 #define ISCSI_LOCK(M, ELSE) do { \
307 if (iscsi_mutex_lock(M) != 0) { \
308 iscsi_err(__FILE__, __LINE__, "iscsi_mutex_lock() failed\n"); \
309 ELSE; \
310 } \
311 } while (/* CONSTCOND */ 0)
312
313 #define ISCSI_UNLOCK(M, ELSE) do { \
314 if (iscsi_mutex_unlock(M) != 0) { \
315 iscsi_err(__FILE__, __LINE__, "iscsi_mutex_unlock() failed\n"); \
316 ELSE; \
317 } \
318 } while (/* CONSTCOND */ 0)
319
320 #define ISCSI_MUTEX_INIT(M, ELSE) do { \
321 if (iscsi_mutex_init(M) != 0) { \
322 iscsi_err(__FILE__, __LINE__, "iscsi_mutex_init() failed\n"); \
323 ELSE; \
324 } \
325 } while (/* CONSTCOND */ 0)
326
327 #define ISCSI_MUTEX_DESTROY(M, ELSE) do { \
328 if (iscsi_mutex_destroy(M) != 0) { \
329 iscsi_err(__FILE__, __LINE__, "iscsi_mutex_destroy() failed\n"); \
330 ELSE; \
331 } \
332 } while (/* CONSTCOND */ 0)
333
334 /*
335 * Condition Variable
336 */
337
338 typedef pthread_cond_t iscsi_cond_t;
339
340 int iscsi_cond_init(iscsi_cond_t *);
341 int iscsi_cond_wait(iscsi_cond_t * , iscsi_mutex_t *);
342 int iscsi_cond_signal(iscsi_cond_t *);
343 int iscsi_cond_destroy(iscsi_cond_t *);
344
345 #define ISCSI_COND_INIT(C, ELSE) do { \
346 if (iscsi_cond_init(C) != 0) { \
347 ELSE; \
348 } \
349 } while (/* CONSTCOND */ 0)
350
351 #define ISCSI_WAIT(C, M, ELSE) do { \
352 if (iscsi_cond_wait(C, M) != 0) { \
353 ELSE; \
354 } \
355 } while (/* CONSTCOND */ 0)
356
357 #define ISCSI_SIGNAL(C, ELSE) do { \
358 if (iscsi_cond_signal(C) != 0) { \
359 ELSE; \
360 } \
361 } while (/* CONSTCOND */ 0)
362
363 #define ISCSI_COND_DESTROY(C, ELSE) do { \
364 if (iscsi_cond_destroy(C) != 0) { \
365 ELSE; \
366 } \
367 } while (/* CONSTCOND */ 0)
368
369 /*
370 * Threading Routines
371 */
372
373 typedef struct iscsi_thread_t {
374 pthread_t pthread;
375 } iscsi_thread_t;
376
377 int iscsi_thread_create(iscsi_thread_t * , void *(*proc) (void *), void *);
378
379 #define ISCSI_SET_THREAD(ME) /* for user pthread id set by pthread_create
380 * in iscsi_thread_create */
381 #define ISCSI_THREAD_START(NAME)
382
383 /*
384 * Worker Thread
385 */
386
387 #define ISCSI_WORKER_STATE_STARTED 1
388 #define ISCSI_WORKER_STATE_ERROR 2
389 #define ISCSI_WORKER_STATE_EXITING 4
390
391 typedef struct {
392 iscsi_thread_t thread;
393 iscsi_mutex_t work_mutex;
394 iscsi_cond_t work_cond;
395 iscsi_mutex_t exit_mutex;
396 iscsi_cond_t exit_cond;
397 int id;
398 int pid;
399 volatile uint32_t state;
400 } iscsi_worker_t;
401
402 #define ISCSI_WORKER_EXIT(ME) do { \
403 iscsi_trace(TRACE_ISCSI_DEBUG, "%s:%d: %s", __FILE__, __LINE__, "exiting\n");\
404 (ME)->state |= ISCSI_WORKER_STATE_EXITING; \
405 return 0; \
406 /* NOTREACHED */ \
407 } while (/* CONSTCOND */ 0)
408
409 /*
410 * Spin Lock
411 */
412 #define ISCSI_SPIN
413
414 /*
415 * Pre/Post condition checking
416 */
417
418 #define NO_CLEANUP {}
419
420 #if 0
421 #define RETURN_NOT_EQUAL(NAME, V1, V2, CU, RC) \
422 if ((V1)!=(V2)) { \
423 iscsi_err(__FILE__, __LINE__, "Bad \"%s\": Got %u expected %u.\n", NAME, V1, V2); \
424 CU; \
425 return RC; \
426 }
427 #endif
428
429 #if 0
430 #define ERROR_NOT_EQUAL(NAME, V1, V2, CU) do { \
431 if ((V1)!=(V2)) { \
432 iscsi_err(__FILE__, __LINE__, \
433 "Bad \"%s\": Got %u expected %u.\n", NAME, V1, V2); \
434 CU; \
435 } \
436 } while(/* CONSTCOND */0)
437 #endif
438
439 /*
440 * Misc. Functions
441 */
442
443 uint32_t iscsi_atoi(char *);
444 int HexTextToData(const char *, uint32_t , uint8_t *, uint32_t);
445 int HexDataToText(uint8_t *, uint32_t , char *, uint32_t);
446 void GenRandomData(uint8_t *, uint32_t);
447
448 /* this is the maximum number of iovecs which we can use in
449 * iscsi_sock_send_header_and_data */
450 #ifndef ISCSI_MAX_IOVECS
451 #define ISCSI_MAX_IOVECS 32
452 #endif
453
454 enum {
455 /* used in iscsi_sock_msg() */
456 Receive = 0,
457 Transmit = 1
458 };
459
460 int allow_netmask(const char *, const char *);
461
462 #endif /* _ISCSIUTIL_H_ */
463