c8e73d3034300ee7bb86063724eefd8d1b2db42c
[mirror/scst/.git] / iscsi-scst / kernel / iscsi.h
1 /*
2  *  Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
3  *  Copyright (C) 2007 - 2009 Vladislav Bolkhovitin
4  *  Copyright (C) 2007 - 2009 ID7 Ltd.
5  *
6  *  This program is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU General Public License
8  *  as published by the Free Software Foundation, version 2
9  *  of the License.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  *  GNU General Public License for more details.
15  */
16
17 #ifndef __ISCSI_H__
18 #define __ISCSI_H__
19
20 #include <linux/pagemap.h>
21 #include <linux/mm.h>
22 #include <linux/net.h>
23 #include <net/sock.h>
24
25 #include <scst.h>
26
27 #include "iscsi_hdr.h"
28 #include "iscsi_scst.h"
29
30 #include "iscsi_dbg.h"
31
32 #define iscsi_sense_crc_error                   ABORTED_COMMAND, 0x47, 0x5
33 #define iscsi_sense_unexpected_unsolicited_data ABORTED_COMMAND, 0xC, 0xC
34
35 struct iscsi_sess_param {
36         int initial_r2t;
37         int immediate_data;
38         int max_connections;
39         unsigned int max_recv_data_length;
40         unsigned int max_xmit_data_length;
41         unsigned int max_burst_length;
42         unsigned int first_burst_length;
43         int default_wait_time;
44         int default_retain_time;
45         unsigned int max_outstanding_r2t;
46         int data_pdu_inorder;
47         int data_sequence_inorder;
48         int error_recovery_level;
49         int header_digest;
50         int data_digest;
51         int ofmarker;
52         int ifmarker;
53         int ofmarkint;
54         int ifmarkint;
55 };
56
57 struct iscsi_trgt_param {
58         int queued_cmnds;
59 };
60
61 struct network_thread_info {
62         struct task_struct *task;
63         unsigned int ready;
64 };
65
66 struct iscsi_cmnd;
67
68 struct iscsi_target {
69         struct scst_tgt *scst_tgt;
70
71         struct mutex target_mutex;
72
73         struct list_head session_list; /* protected by target_mutex */
74
75         /* Both protected by target_mgmt_mutex */
76         struct iscsi_trgt_param trgt_param;
77         /*
78          * Put here to have uniform parameters checking and assigning
79          * from various places, including iscsi-scst-adm.
80          */
81         struct iscsi_sess_param trgt_sess_param;
82
83         struct list_head target_list_entry;
84         u32 tid;
85
86         /* All protected by target_sysfs_mutex */
87         unsigned int tgt_enabled:1;
88         unsigned int expected_ioctl;
89         int ioctl_res;
90         struct completion *target_enabling_cmpl;
91
92         struct mutex target_sysfs_mutex;
93
94         char name[ISCSI_NAME_LEN];
95 };
96
97 #define ISCSI_HASH_ORDER        8
98 #define cmnd_hashfn(itt)        hash_long((itt), ISCSI_HASH_ORDER)
99
100 struct iscsi_session {
101         struct iscsi_target *target;
102         struct scst_session *scst_sess;
103
104         struct list_head pending_list; /* protected by sn_lock */
105
106         /* Unprotected, since accessed only from a single read thread */
107         u32 next_ttt;
108
109         u32 max_queued_cmnds; /* unprotected, since read-only */
110         atomic_t active_cmds;
111
112         spinlock_t sn_lock;
113         u32 exp_cmd_sn; /* protected by sn_lock */
114
115         /* All 3 protected by sn_lock */
116         int tm_active;
117         u32 tm_sn;
118         struct iscsi_cmnd *tm_rsp;
119
120         /* Read only, if there are connection(s) */
121         struct iscsi_sess_param sess_param;
122
123         spinlock_t cmnd_hash_lock;
124         struct list_head cmnd_hash[1 << ISCSI_HASH_ORDER];
125
126         struct list_head conn_list; /* protected by target_mutex */
127
128         struct list_head session_list_entry;
129
130         /* All protected by target_mutex, where necessary */
131         struct iscsi_session *sess_reinst_successor;
132         unsigned int sess_reinstating:1;
133         unsigned int sess_shutting_down:1;
134
135         /* All don't need any protection */
136         char *initiator_name;
137         u64 sid;
138 };
139
140 #define ISCSI_CONN_IOV_MAX                      (PAGE_SIZE/sizeof(struct iovec))
141
142 #define ISCSI_CONN_RD_STATE_IDLE                0
143 #define ISCSI_CONN_RD_STATE_IN_LIST             1
144 #define ISCSI_CONN_RD_STATE_PROCESSING          2
145
146 #define ISCSI_CONN_WR_STATE_IDLE                0
147 #define ISCSI_CONN_WR_STATE_IN_LIST             1
148 #define ISCSI_CONN_WR_STATE_SPACE_WAIT          2
149 #define ISCSI_CONN_WR_STATE_PROCESSING          3
150
151 struct iscsi_conn {
152         struct iscsi_session *session; /* owning session */
153
154         /* Both protected by session->sn_lock */
155         u32 stat_sn;
156         u32 exp_stat_sn;
157
158 #define ISCSI_CONN_REINSTATING  1
159 #define ISCSI_CONN_SHUTTINGDOWN 2
160         unsigned long conn_aflags;
161
162         spinlock_t cmd_list_lock; /* BH lock */
163
164         /* Protected by cmd_list_lock */
165         struct list_head cmd_list; /* in/outcoming pdus */
166
167         atomic_t conn_ref_cnt;
168
169         spinlock_t write_list_lock;
170         /* List of data pdus to be sent, protected by write_list_lock */
171         struct list_head write_list;
172         /* List of data pdus being sent, protected by write_list_lock */
173         struct list_head written_list;
174
175         struct timer_list rsp_timer;
176
177         /* All 2 protected by iscsi_wr_lock */
178         unsigned short wr_state;
179         unsigned short wr_space_ready:1;
180
181         struct list_head wr_list_entry;
182
183 #ifdef CONFIG_SCST_EXTRACHECKS
184         struct task_struct *wr_task;
185 #endif
186
187         /*
188          * All are unprotected, since accessed only from a single write
189          * thread.
190          */
191         struct iscsi_cmnd *write_cmnd;
192         struct iovec *write_iop;
193         int write_iop_used;
194         struct iovec write_iov[2];
195         u32 write_size;
196         u32 write_offset;
197         int write_state;
198
199         /* Both don't need any protection */
200         struct file *file;
201         struct socket *sock;
202
203         void (*old_state_change)(struct sock *);
204         void (*old_data_ready)(struct sock *, int);
205         void (*old_write_space)(struct sock *);
206
207         /* Both read only. Stay here for better CPU cache locality. */
208         int hdigest_type;
209         int ddigest_type;
210
211         /* All 5 protected by iscsi_rd_lock */
212         unsigned short rd_state;
213         unsigned short rd_data_ready:1;
214         /* Let's save some cache footprint by putting them here */
215         unsigned short closing:1;
216         unsigned short active_close:1;
217         unsigned short deleting:1;
218
219         struct list_head rd_list_entry;
220
221 #ifdef CONFIG_SCST_EXTRACHECKS
222         struct task_struct *rd_task;
223 #endif
224
225         /*
226          * All are unprotected, since accessed only from a single read
227          * thread.
228          */
229         struct iscsi_cmnd *read_cmnd;
230         struct msghdr read_msg;
231         u32 read_size;
232         int read_state;
233         struct iovec *read_iov;
234         struct task_struct *rx_task;
235         uint32_t rpadding;
236
237         struct iscsi_target *target;
238
239         struct list_head conn_list_entry; /* list entry in session conn_list */
240
241         /* All protected by target_mutex, where necessary */
242         struct iscsi_conn *conn_reinst_successor;
243         struct list_head reinst_pending_cmd_list;
244
245         wait_queue_head_t read_state_waitQ;
246         struct completion ready_to_free;
247
248         /* Doesn't need any protection */
249         u16 cid;
250
251 #ifndef CONFIG_SCST_PROC
252         /* Doesn't need any protection */
253         struct kobject iscsi_conn_kobj;
254 #endif /* CONFIG_SCST_PROC */
255 };
256
257 struct iscsi_pdu {
258         struct iscsi_hdr bhs;
259         void *ahs;
260         unsigned int ahssize;
261         unsigned int datasize;
262 };
263
264 typedef void (iscsi_show_info_t)(struct seq_file *seq,
265                                  struct iscsi_target *target);
266
267 /** Command's states **/
268
269 /* New command and SCST processes it */
270 #define ISCSI_CMD_STATE_NEW               0
271
272 /* SCST processes cmd after scst_rx_cmd() */
273 #define ISCSI_CMD_STATE_RX_CMD            1
274
275 /* The command returned from preprocessing_done() */
276 #define ISCSI_CMD_STATE_AFTER_PREPROC     2
277
278 /* The command is waiting for session or connection reinstatement finished */
279 #define ISCSI_CMD_STATE_REINST_PENDING    3
280
281 /* scst_restart_cmd() called and SCST processing it */
282 #define ISCSI_CMD_STATE_RESTARTED         4
283
284 /* SCST done processing */
285 #define ISCSI_CMD_STATE_PROCESSED         5
286
287 /* AEN processing */
288 #define ISCSI_CMD_STATE_AEN               6
289
290 /** Command's reject reasons **/
291 #define ISCSI_REJECT_SCSI_CMD             1
292 #define ISCSI_REJECT_CMD                  2
293 #define ISCSI_REJECT_DATA                 3
294
295 /*
296  * Most of the fields don't need any protection, since accessed from only a
297  * single thread, except where noted.
298  */
299 struct iscsi_cmnd {
300         struct iscsi_conn *conn;
301
302         /*
303          * Some flags protected by conn->write_list_lock, but all modified only
304          * from single read thread or when there are no references to cmd.
305          */
306         unsigned int hashed:1;
307         unsigned int should_close_conn:1;
308         unsigned int should_close_all_conn:1;
309         unsigned int pending:1;
310         unsigned int own_sg:1;
311         unsigned int on_write_list:1;
312         unsigned int write_processing_started:1;
313         unsigned int data_waiting:1;
314         unsigned int force_cleanup_done:1;
315         unsigned int dec_active_cmnds:1;
316         unsigned int ddigest_checked:1;
317         unsigned int rejected:1;
318         unsigned int reject_reason:2;
319 #ifdef CONFIG_SCST_EXTRACHECKS
320         unsigned int on_rx_digest_list:1;
321         unsigned int release_called:1;
322 #endif
323
324         /* It's async. with the above flags */
325         volatile unsigned int tm_aborted;
326
327         struct list_head hash_list_entry;
328
329         spinlock_t rsp_cmd_lock; /* BH lock */
330
331         /*
332          * Unions are for readability and grepability and to save some
333          * cache footprint.
334          */
335
336         union {
337                 /* Protected by rsp_cmd_lock */
338                 struct list_head rsp_cmd_list;
339                 struct list_head rsp_cmd_list_entry;
340         };
341
342         union {
343                 struct list_head pending_list_entry;
344                 struct list_head reinst_pending_cmd_list_entry;
345         };
346
347         union {
348                 struct list_head write_list_entry;
349                 struct list_head written_list_entry;
350         };
351
352         /* Both modified only from single write thread */
353         unsigned int on_written_list:1;
354         unsigned long write_timeout;
355
356         /*
357          * All unprotected, since could be accessed from only a single
358          * thread at time
359          */
360         struct iscsi_cmnd *parent_req;
361         struct iscsi_cmnd *cmd_req;
362
363         /*
364          * All unprotected, since could be accessed from only a single
365          * thread at time
366          */
367         union {
368                 /* Request only fields */
369                 struct {
370                         struct list_head rx_ddigest_cmd_list;
371                         struct list_head rx_ddigest_cmd_list_entry;
372
373                         int scst_state;
374                         union {
375                                 struct scst_cmd *scst_cmd;
376                                 struct scst_aen *scst_aen;
377                         };
378                         int read_size;
379                 };
380
381                 /* Response only fields */
382                 struct {
383                         struct scatterlist rsp_sg[2];
384                         struct iscsi_sense_data sense_hdr;
385                 };
386         };
387
388         atomic_t ref_cnt;
389 #if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
390         atomic_t net_ref_cnt;
391 #endif
392
393         struct iscsi_pdu pdu;
394
395         struct scatterlist *sg;
396         int sg_cnt;
397         unsigned int bufflen;
398         u32 r2t_sn;
399         u32 r2t_length;
400         u32 is_unsolicited_data;
401         u32 target_task_tag;
402         u32 outstanding_r2t;
403
404         u32 hdigest;
405         u32 ddigest;
406
407         struct list_head cmd_list_entry;
408 };
409
410 /* Flags for req_cmnd_release_force() */
411 #define ISCSI_FORCE_RELEASE_WRITE       1
412
413 #define ISCSI_RSP_TIMEOUT               (30 * HZ)
414
415 extern struct mutex target_mgmt_mutex;
416
417 extern const struct file_operations ctr_fops;
418
419 extern spinlock_t iscsi_rd_lock;
420 extern struct list_head iscsi_rd_list;
421 extern wait_queue_head_t iscsi_rd_waitQ;
422
423 extern spinlock_t iscsi_wr_lock;
424 extern struct list_head iscsi_wr_list;
425 extern wait_queue_head_t iscsi_wr_waitQ;
426
427 /* iscsi.c */
428 extern struct iscsi_cmnd *cmnd_alloc(struct iscsi_conn *,
429         struct iscsi_cmnd *parent);
430 extern int cmnd_rx_start(struct iscsi_cmnd *);
431 extern int cmnd_rx_continue(struct iscsi_cmnd *req);
432 extern void cmnd_rx_end(struct iscsi_cmnd *);
433 extern void cmnd_tx_start(struct iscsi_cmnd *);
434 extern void cmnd_tx_end(struct iscsi_cmnd *);
435 extern void req_cmnd_release_force(struct iscsi_cmnd *req, int flags);
436 extern void rsp_cmnd_release(struct iscsi_cmnd *);
437 extern void cmnd_done(struct iscsi_cmnd *cmnd);
438 extern void conn_abort(struct iscsi_conn *conn);
439 extern void iscsi_restart_cmnd(struct iscsi_cmnd *cmnd);
440
441 /* conn.c */
442 extern struct iscsi_conn *conn_lookup(struct iscsi_session *, u16);
443 extern void conn_reinst_finished(struct iscsi_conn *);
444 extern int conn_add(struct iscsi_session *, struct iscsi_kern_conn_info *);
445 extern int conn_del(struct iscsi_session *, struct iscsi_kern_conn_info *);
446 #ifdef CONFIG_SCST_PROC
447 extern int conn_free(struct iscsi_conn *);
448 #endif
449 extern void iscsi_make_conn_rd_active(struct iscsi_conn *conn);
450
451 #define ISCSI_CONN_ACTIVE_CLOSE         1
452 #define ISCSI_CONN_DELETING             2
453 extern void __mark_conn_closed(struct iscsi_conn *, int);
454
455 extern void mark_conn_closed(struct iscsi_conn *);
456 extern void iscsi_make_conn_wr_active(struct iscsi_conn *);
457
458 #ifdef CONFIG_SCST_PROC
459 extern void conn_info_show(struct seq_file *, struct iscsi_session *);
460 #endif
461
462 /* nthread.c */
463 extern int iscsi_send(struct iscsi_conn *conn);
464 #if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
465 extern void iscsi_get_page_callback(struct page *page);
466 extern void iscsi_put_page_callback(struct page *page);
467 #endif
468 extern int istrd(void *arg);
469 extern int istwr(void *arg);
470 extern void iscsi_task_mgmt_affected_cmds_done(struct scst_mgmt_cmd *scst_mcmd);
471
472 /* target.c */
473 #ifndef CONFIG_SCST_PROC
474 extern const struct attribute *iscsi_tgt_attrs[];
475 extern ssize_t iscsi_enable_target(struct scst_tgt *scst_tgt, const char *buf,
476         size_t size);
477 extern bool iscsi_is_target_enabled(struct scst_tgt *scst_tgt);
478 #endif
479 struct iscsi_target *target_lookup_by_id(u32);
480 extern int target_add(struct iscsi_kern_target_info *);
481 extern int target_enable(struct iscsi_kern_target_info *);
482 extern int target_disable(struct iscsi_kern_target_info *);
483 extern int target_del(u32 id);
484 extern void target_del_session(struct iscsi_target *target,
485         struct iscsi_session *session, int flags);
486 extern void target_del_all_sess(struct iscsi_target *target, int flags);
487 extern void target_del_all(void);
488
489 extern const struct seq_operations iscsi_seq_op;
490
491 /* config.c */
492 #ifdef CONFIG_SCST_PROC
493 extern int iscsi_procfs_init(void);
494 extern void iscsi_procfs_exit(void);
495 #else
496 extern const struct attribute *iscsi_attrs[];
497 #endif
498
499 /* session.c */
500 #ifdef CONFIG_SCST_PROC
501 int print_digest_state(char *p, size_t size, unsigned long flags);
502 #else
503 extern const struct attribute *iscsi_sess_attrs[];
504 #endif
505 extern const struct file_operations session_seq_fops;
506 extern struct iscsi_session *session_lookup(struct iscsi_target *, u64);
507 extern void sess_reinst_finished(struct iscsi_session *);
508 extern int session_add(struct iscsi_target *, struct iscsi_kern_session_info *);
509 extern int session_del(struct iscsi_target *, u64);
510 extern int session_free(struct iscsi_session *session, bool del);
511
512 /* params.c */
513 extern int iscsi_param_set(struct iscsi_target *,
514         struct iscsi_kern_param_info *, int);
515
516 /* event.c */
517 extern int event_send(u32, u64, u32, enum iscsi_kern_event_code);
518 extern int event_init(void);
519 extern void event_exit(void);
520
521 #define get_pgcnt(size, offset) \
522         ((((size) + ((offset) & ~PAGE_MASK)) + PAGE_SIZE - 1) >> PAGE_SHIFT)
523
524 static inline void iscsi_cmnd_get_length(struct iscsi_pdu *pdu)
525 {
526 #if defined(__BIG_ENDIAN)
527         pdu->ahssize = pdu->bhs.length.ahslength * 4;
528         pdu->datasize = pdu->bhs.length.datalength;
529 #elif defined(__LITTLE_ENDIAN)
530         pdu->ahssize = (pdu->bhs.length & 0xff) * 4;
531         pdu->datasize = be32_to_cpu(pdu->bhs.length & ~0xff);
532 #else
533 #error
534 #endif
535 }
536
537 static inline void iscsi_cmnd_set_length(struct iscsi_pdu *pdu)
538 {
539 #if defined(__BIG_ENDIAN)
540         pdu->bhs.length.ahslength = pdu->ahssize / 4;
541         pdu->bhs.length.datalength = pdu->datasize;
542 #elif defined(__LITTLE_ENDIAN)
543         pdu->bhs.length = cpu_to_be32(pdu->datasize) | (pdu->ahssize / 4);
544 #else
545 #error
546 #endif
547 }
548
549 extern struct scst_tgt_template iscsi_template;
550
551 /*
552  * Skip this command if result is not 0. Must be called under
553  * corresponding lock.
554  */
555 static inline bool cmnd_get_check(struct iscsi_cmnd *cmnd)
556 {
557         int r = atomic_inc_return(&cmnd->ref_cnt);
558         int res;
559         if (unlikely(r == 1)) {
560                 TRACE_DBG("cmnd %p is being destroyed", cmnd);
561                 atomic_dec(&cmnd->ref_cnt);
562                 res = 1;
563                 /* Necessary code is serialized by locks in cmnd_done() */
564         } else {
565                 TRACE_DBG("cmnd %p, new ref_cnt %d", cmnd,
566                         atomic_read(&cmnd->ref_cnt));
567                 res = 0;
568         }
569         return res;
570 }
571
572 static inline void cmnd_get(struct iscsi_cmnd *cmnd)
573 {
574         atomic_inc(&cmnd->ref_cnt);
575         TRACE_DBG("cmnd %p, new cmnd->ref_cnt %d", cmnd,
576                 atomic_read(&cmnd->ref_cnt));
577 }
578
579 static inline void cmnd_get_ordered(struct iscsi_cmnd *cmnd)
580 {
581         cmnd_get(cmnd);
582         /* See comments for each cmnd_get_ordered() use */
583         smp_mb__after_atomic_inc();
584 }
585
586 static inline void cmnd_put(struct iscsi_cmnd *cmnd)
587 {
588         TRACE_DBG("cmnd %p, new ref_cnt %d", cmnd,
589                 atomic_read(&cmnd->ref_cnt)-1);
590
591         EXTRACHECKS_BUG_ON(atomic_read(&cmnd->ref_cnt) == 0);
592
593         if (atomic_dec_and_test(&cmnd->ref_cnt))
594                 cmnd_done(cmnd);
595 }
596
597 /* conn->write_list_lock supposed to be locked and BHs off */
598 static inline void cmd_add_on_write_list(struct iscsi_conn *conn,
599         struct iscsi_cmnd *cmnd)
600 {
601         TRACE_DBG("%p", cmnd);
602         list_add_tail(&cmnd->write_list_entry, &conn->write_list);
603         cmnd->on_write_list = 1;
604 }
605
606 /* conn->write_list_lock supposed to be locked and BHs off */
607 static inline void cmd_del_from_write_list(struct iscsi_cmnd *cmnd)
608 {
609         TRACE_DBG("%p", cmnd);
610         list_del(&cmnd->write_list_entry);
611         cmnd->on_write_list = 0;
612 }
613
614 static inline void cmd_add_on_rx_ddigest_list(struct iscsi_cmnd *req,
615         struct iscsi_cmnd *cmnd)
616 {
617         TRACE_DBG("Adding RX ddigest cmd %p to digest list "
618                         "of req %p", cmnd, req);
619         list_add_tail(&cmnd->rx_ddigest_cmd_list_entry,
620                         &req->rx_ddigest_cmd_list);
621 #ifdef CONFIG_SCST_EXTRACHECKS
622         cmnd->on_rx_digest_list = 1;
623 #endif
624 }
625
626 static inline void cmd_del_from_rx_ddigest_list(struct iscsi_cmnd *cmnd)
627 {
628         TRACE_DBG("Deleting RX digest cmd %p from digest list", cmnd);
629         list_del(&cmnd->rx_ddigest_cmd_list_entry);
630 #ifdef CONFIG_SCST_EXTRACHECKS
631         cmnd->on_rx_digest_list = 0;
632 #endif
633 }
634
635 static inline int test_write_ready(struct iscsi_conn *conn)
636 {
637         /*
638          * No need for write_list protection, in the worst case we will be
639          * restarted again.
640          */
641         return !list_empty(&conn->write_list) || conn->write_cmnd;
642 }
643
644 static inline void conn_get(struct iscsi_conn *conn)
645 {
646         atomic_inc(&conn->conn_ref_cnt);
647         TRACE_DBG("conn %p, new conn_ref_cnt %d", conn,
648                 atomic_read(&conn->conn_ref_cnt));
649 }
650
651 static inline void conn_get_ordered(struct iscsi_conn *conn)
652 {
653         conn_get(conn);
654         /* See comments for each conn_get_ordered() use */
655         smp_mb__after_atomic_inc();
656 }
657
658 static inline void conn_put(struct iscsi_conn *conn)
659 {
660         TRACE_DBG("conn %p, new conn_ref_cnt %d", conn,
661                 atomic_read(&conn->conn_ref_cnt)-1);
662         sBUG_ON(atomic_read(&conn->conn_ref_cnt) == 0);
663
664         /*
665          * Make it always ordered to protect from undesired side effects like
666          * accessing just destroyed by close_conn() conn caused by reordering
667          * of this atomic_dec().
668          */
669         smp_mb__before_atomic_dec();
670         atomic_dec(&conn->conn_ref_cnt);
671 }
672
673 #ifdef CONFIG_SCST_EXTRACHECKS
674 extern void iscsi_extracheck_is_rd_thread(struct iscsi_conn *conn);
675 extern void iscsi_extracheck_is_wr_thread(struct iscsi_conn *conn);
676 #else
677 static inline void iscsi_extracheck_is_rd_thread(struct iscsi_conn *conn) {}
678 static inline void iscsi_extracheck_is_wr_thread(struct iscsi_conn *conn) {}
679 #endif
680
681 #endif  /* __ISCSI_H__ */