Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * iSCSI lib definitions
0004  *
0005  * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
0006  * Copyright (C) 2004 - 2006 Mike Christie
0007  * Copyright (C) 2004 - 2005 Dmitry Yusupov
0008  * Copyright (C) 2004 - 2005 Alex Aizman
0009  */
0010 #ifndef LIBISCSI_H
0011 #define LIBISCSI_H
0012 
0013 #include <linux/types.h>
0014 #include <linux/wait.h>
0015 #include <linux/mutex.h>
0016 #include <linux/timer.h>
0017 #include <linux/workqueue.h>
0018 #include <linux/kfifo.h>
0019 #include <linux/refcount.h>
0020 #include <scsi/iscsi_proto.h>
0021 #include <scsi/iscsi_if.h>
0022 #include <scsi/scsi_cmnd.h>
0023 #include <scsi/scsi_transport_iscsi.h>
0024 
0025 struct scsi_transport_template;
0026 struct scsi_host_template;
0027 struct scsi_device;
0028 struct Scsi_Host;
0029 struct scsi_target;
0030 struct scsi_cmnd;
0031 struct socket;
0032 struct iscsi_transport;
0033 struct iscsi_cls_session;
0034 struct iscsi_cls_conn;
0035 struct iscsi_session;
0036 struct iscsi_nopin;
0037 struct device;
0038 
0039 #define ISCSI_DEF_XMIT_CMDS_MAX 128 /* must be power of 2 */
0040 #define ISCSI_MGMT_CMDS_MAX 15
0041 
0042 #define ISCSI_DEF_CMD_PER_LUN   32
0043 
0044 /* Task Mgmt states */
0045 enum {
0046     TMF_INITIAL,
0047     TMF_QUEUED,
0048     TMF_SUCCESS,
0049     TMF_FAILED,
0050     TMF_TIMEDOUT,
0051     TMF_NOT_FOUND,
0052 };
0053 
0054 #define ISID_SIZE           6
0055 
0056 /* Connection flags */
0057 #define ISCSI_CONN_FLAG_SUSPEND_TX  0
0058 #define ISCSI_CONN_FLAG_SUSPEND_RX  1
0059 #define ISCSI_CONN_FLAG_BOUND       2
0060 
0061 #define ISCSI_ITT_MASK          0x1fff
0062 #define ISCSI_TOTAL_CMDS_MAX        4096
0063 /* this must be a power of two greater than ISCSI_MGMT_CMDS_MAX */
0064 #define ISCSI_TOTAL_CMDS_MIN        16
0065 #define ISCSI_AGE_SHIFT         28
0066 #define ISCSI_AGE_MASK          0xf
0067 
0068 #define ISCSI_ADDRESS_BUF_LEN       64
0069 
0070 enum {
0071     /* this is the maximum possible storage for AHSs */
0072     ISCSI_MAX_AHS_SIZE = sizeof(struct iscsi_ecdb_ahdr) +
0073                 sizeof(struct iscsi_rlength_ahdr),
0074     ISCSI_DIGEST_SIZE = sizeof(__u32),
0075 };
0076 
0077 
0078 enum {
0079     ISCSI_TASK_FREE,
0080     ISCSI_TASK_COMPLETED,
0081     ISCSI_TASK_PENDING,
0082     ISCSI_TASK_RUNNING,
0083     ISCSI_TASK_ABRT_TMF,        /* aborted due to TMF */
0084     ISCSI_TASK_ABRT_SESS_RECOV, /* aborted due to session recovery */
0085     ISCSI_TASK_REQUEUE_SCSIQ,   /* qcmd requeueing to scsi-ml */
0086 };
0087 
0088 struct iscsi_r2t_info {
0089     __be32          ttt;        /* copied from R2T */
0090     __be32          exp_statsn; /* copied from R2T */
0091     uint32_t        data_length;    /* copied from R2T */
0092     uint32_t        data_offset;    /* copied from R2T */
0093     int         data_count; /* DATA-Out payload progress */
0094     int         datasn;
0095     /* LLDs should set/update these values */
0096     int         sent;       /* R2T sequence progress */
0097 };
0098 
0099 struct iscsi_task {
0100     /*
0101      * Because LLDs allocate their hdr differently, this is a pointer
0102      * and length to that storage. It must be setup at session
0103      * creation time.
0104      */
0105     struct iscsi_hdr    *hdr;
0106     unsigned short      hdr_max;
0107     unsigned short      hdr_len;    /* accumulated size of hdr used */
0108     /* copied values in case we need to send tmfs */
0109     itt_t           hdr_itt;
0110     __be32          cmdsn;
0111     struct scsi_lun     lun;
0112 
0113     int         itt;        /* this ITT */
0114 
0115     unsigned        imm_count;  /* imm-data (bytes)   */
0116     /* offset in unsolicited stream (bytes); */
0117     struct iscsi_r2t_info   unsol_r2t;
0118     char            *data;      /* mgmt payload */
0119     unsigned        data_count;
0120     struct scsi_cmnd    *sc;        /* associated SCSI cmd*/
0121     struct iscsi_conn   *conn;      /* used connection    */
0122 
0123     /* data processing tracking */
0124     unsigned long       last_xfer;
0125     unsigned long       last_timeout;
0126     bool            have_checked_conn;
0127 
0128     /* T10 protection information */
0129     bool            protected;
0130 
0131     /* state set/tested under session->lock */
0132     int         state;
0133     refcount_t      refcount;
0134     struct list_head    running;    /* running cmd list */
0135     void            *dd_data;   /* driver/transport data */
0136 };
0137 
0138 static inline int iscsi_task_has_unsol_data(struct iscsi_task *task)
0139 {
0140     return task->unsol_r2t.data_length > task->unsol_r2t.sent;
0141 }
0142 
0143 static inline void* iscsi_next_hdr(struct iscsi_task *task)
0144 {
0145     return (void*)task->hdr + task->hdr_len;
0146 }
0147 
0148 static inline bool iscsi_task_is_completed(struct iscsi_task *task)
0149 {
0150     return task->state == ISCSI_TASK_COMPLETED ||
0151            task->state == ISCSI_TASK_ABRT_TMF ||
0152            task->state == ISCSI_TASK_ABRT_SESS_RECOV;
0153 }
0154 
0155 /* Private data associated with struct scsi_cmnd. */
0156 struct iscsi_cmd {
0157     struct iscsi_task   *task;
0158     int         age;
0159 };
0160 
0161 static inline struct iscsi_cmd *iscsi_cmd(struct scsi_cmnd *cmd)
0162 {
0163     return scsi_cmd_priv(cmd);
0164 }
0165 
0166 /* Connection's states */
0167 enum {
0168     ISCSI_CONN_INITIAL_STAGE,
0169     ISCSI_CONN_STARTED,
0170     ISCSI_CONN_STOPPED,
0171     ISCSI_CONN_CLEANUP_WAIT,
0172 };
0173 
0174 struct iscsi_conn {
0175     struct iscsi_cls_conn   *cls_conn;  /* ptr to class connection */
0176     void            *dd_data;   /* iscsi_transport data */
0177     struct iscsi_session    *session;   /* parent session */
0178     /*
0179      * conn_stop() flag: stop to recover, stop to terminate
0180      */
0181         int         stop_stage;
0182     struct timer_list   transport_timer;
0183     unsigned long       last_recv;
0184     unsigned long       last_ping;
0185     int         ping_timeout;
0186     int         recv_timeout;
0187     struct iscsi_task   *ping_task;
0188 
0189     /* iSCSI connection-wide sequencing */
0190     uint32_t        exp_statsn;
0191     uint32_t        statsn;
0192 
0193     /* control data */
0194     int         id;     /* CID */
0195     int         c_stage;    /* connection state */
0196     /*
0197      * Preallocated buffer for pdus that have data but do not
0198      * originate from scsi-ml. We never have two pdus using the
0199      * buffer at the same time. It is only allocated to
0200      * the default max recv size because the pdus we support
0201      * should always fit in this buffer
0202      */
0203     char            *data;
0204     struct iscsi_task   *login_task;    /* mtask used for login/text */
0205     struct iscsi_task   *task;      /* xmit task in progress */
0206 
0207     /* xmit */
0208     /* items must be added/deleted under frwd lock */
0209     struct list_head    mgmtqueue;  /* mgmt (control) xmit queue */
0210     struct list_head    cmdqueue;   /* data-path cmd queue */
0211     struct list_head    requeue;    /* tasks needing another run */
0212     struct work_struct  xmitwork;   /* per-conn. xmit workqueue */
0213     /* recv */
0214     struct work_struct  recvwork;
0215     unsigned long       flags;      /* ISCSI_CONN_FLAGs */
0216 
0217     /* negotiated params */
0218     unsigned        max_recv_dlength; /* initiator_max_recv_dsl*/
0219     unsigned        max_xmit_dlength; /* target_max_recv_dsl */
0220     int         hdrdgst_en;
0221     int         datadgst_en;
0222     int         ifmarker_en;
0223     int         ofmarker_en;
0224     /* values userspace uses to id a conn */
0225     int         persistent_port;
0226     char            *persistent_address;
0227 
0228     unsigned        max_segment_size;
0229     unsigned        tcp_xmit_wsf;
0230     unsigned        tcp_recv_wsf;
0231     uint16_t        keepalive_tmo;
0232     uint16_t        local_port;
0233     uint8_t         tcp_timestamp_stat;
0234     uint8_t         tcp_nagle_disable;
0235     uint8_t         tcp_wsf_disable;
0236     uint8_t         tcp_timer_scale;
0237     uint8_t         tcp_timestamp_en;
0238     uint8_t         fragment_disable;
0239     uint8_t         ipv4_tos;
0240     uint8_t         ipv6_traffic_class;
0241     uint8_t         ipv6_flow_label;
0242     uint8_t         is_fw_assigned_ipv6;
0243     char            *local_ipaddr;
0244 
0245     /* MIB-statistics */
0246     uint64_t        txdata_octets;
0247     uint64_t        rxdata_octets;
0248     uint32_t        scsicmd_pdus_cnt;
0249     uint32_t        dataout_pdus_cnt;
0250     uint32_t        scsirsp_pdus_cnt;
0251     uint32_t        datain_pdus_cnt;
0252     uint32_t        r2t_pdus_cnt;
0253     uint32_t        tmfcmd_pdus_cnt;
0254     int32_t         tmfrsp_pdus_cnt;
0255 
0256     /* custom statistics */
0257     uint32_t        eh_abort_cnt;
0258     uint32_t        fmr_unalign_cnt;
0259 };
0260 
0261 struct iscsi_pool {
0262     struct kfifo        queue;      /* FIFO Queue */
0263     void            **pool;     /* Pool of elements */
0264     int         max;        /* Max number of elements */
0265 };
0266 
0267 /* Session's states */
0268 enum {
0269     ISCSI_STATE_FREE = 1,
0270     ISCSI_STATE_LOGGED_IN,
0271     ISCSI_STATE_FAILED,
0272     ISCSI_STATE_TERMINATE,
0273     ISCSI_STATE_IN_RECOVERY,
0274     ISCSI_STATE_RECOVERY_FAILED,
0275     ISCSI_STATE_LOGGING_OUT,
0276 };
0277 
0278 struct iscsi_session {
0279     struct iscsi_cls_session *cls_session;
0280     /*
0281      * Syncs up the scsi eh thread with the iscsi eh thread when sending
0282      * task management functions. This must be taken before the session
0283      * and recv lock.
0284      */
0285     struct mutex        eh_mutex;
0286     /* abort */
0287     wait_queue_head_t   ehwait;     /* used in eh_abort() */
0288     struct iscsi_tm     tmhdr;
0289     struct timer_list   tmf_timer;
0290     int         tmf_state;  /* see TMF_INITIAL, etc.*/
0291     struct iscsi_task   *running_aborted_task;
0292 
0293     /* iSCSI session-wide sequencing */
0294     uint32_t        cmdsn;
0295     uint32_t        exp_cmdsn;
0296     uint32_t        max_cmdsn;
0297 
0298     /* This tracks the reqs queued into the initiator */
0299     uint32_t        queued_cmdsn;
0300 
0301     /* configuration */
0302     int         abort_timeout;
0303     int         lu_reset_timeout;
0304     int         tgt_reset_timeout;
0305     int         initial_r2t_en;
0306     unsigned short      max_r2t;
0307     int         imm_data_en;
0308     unsigned        first_burst;
0309     unsigned        max_burst;
0310     int         time2wait;
0311     int         time2retain;
0312     int         pdu_inorder_en;
0313     int         dataseq_inorder_en;
0314     int         erl;
0315     int         fast_abort;
0316     int         tpgt;
0317     char            *username;
0318     char            *username_in;
0319     char            *password;
0320     char            *password_in;
0321     char            *targetname;
0322     char            *targetalias;
0323     char            *ifacename;
0324     char            *initiatorname;
0325     char            *boot_root;
0326     char            *boot_nic;
0327     char            *boot_target;
0328     char            *portal_type;
0329     char            *discovery_parent_type;
0330     uint16_t        discovery_parent_idx;
0331     uint16_t        def_taskmgmt_tmo;
0332     uint16_t        tsid;
0333     uint8_t         auto_snd_tgt_disable;
0334     uint8_t         discovery_sess;
0335     uint8_t         chap_auth_en;
0336     uint8_t         discovery_logout_en;
0337     uint8_t         bidi_chap_en;
0338     uint8_t         discovery_auth_optional;
0339     uint8_t         isid[ISID_SIZE];
0340 
0341     /* control data */
0342     struct iscsi_transport  *tt;
0343     struct Scsi_Host    *host;
0344     struct iscsi_conn   *leadconn;  /* leading connection */
0345     /* Between the forward and the backward locks exists a strict locking
0346      * hierarchy. The mutual exclusion zone protected by the forward lock
0347      * can enclose the mutual exclusion zone protected by the backward lock
0348      * but not vice versa.
0349      */
0350     spinlock_t      frwd_lock;  /* protects session state, *
0351                          * cmdsn, queued_cmdsn     *
0352                          * session resources:      *
0353                          * - cmdpool kfifo_out ,   *
0354                          * - mgmtpool, queues      */
0355     spinlock_t      back_lock;  /* protects cmdsn_exp      *
0356                          * cmdsn_max,              *
0357                          * cmdpool kfifo_in        */
0358     int         state;      /* session state           */
0359     int         age;        /* counts session re-opens */
0360 
0361     int         scsi_cmds_max;  /* max scsi commands */
0362     int         cmds_max;   /* size of cmds array */
0363     struct iscsi_task   **cmds;     /* Original Cmds arr */
0364     struct iscsi_pool   cmdpool;    /* PDU's pool */
0365     void            *dd_data;   /* LLD private data */
0366 };
0367 
0368 enum {
0369     ISCSI_HOST_SETUP,
0370     ISCSI_HOST_REMOVED,
0371 };
0372 
0373 struct iscsi_host {
0374     char            *initiatorname;
0375     /* hw address or netdev iscsi connection is bound to */
0376     char            *hwaddress;
0377     char            *netdev;
0378 
0379     wait_queue_head_t   session_removal_wq;
0380     /* protects sessions and state */
0381     spinlock_t      lock;
0382     int         num_sessions;
0383     int         state;
0384 
0385     struct workqueue_struct *workq;
0386 };
0387 
0388 /*
0389  * scsi host template
0390  */
0391 extern int iscsi_eh_abort(struct scsi_cmnd *sc);
0392 extern int iscsi_eh_recover_target(struct scsi_cmnd *sc);
0393 extern int iscsi_eh_session_reset(struct scsi_cmnd *sc);
0394 extern int iscsi_eh_device_reset(struct scsi_cmnd *sc);
0395 extern int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc);
0396 extern enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc);
0397 
0398 /*
0399  * iSCSI host helpers.
0400  */
0401 #define iscsi_host_priv(_shost) \
0402     (shost_priv(_shost) + sizeof(struct iscsi_host))
0403 
0404 extern int iscsi_host_set_param(struct Scsi_Host *shost,
0405                 enum iscsi_host_param param, char *buf,
0406                 int buflen);
0407 extern int iscsi_host_get_param(struct Scsi_Host *shost,
0408                 enum iscsi_host_param param, char *buf);
0409 extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev);
0410 extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
0411                       int dd_data_size,
0412                       bool xmit_can_sleep);
0413 extern void iscsi_host_remove(struct Scsi_Host *shost, bool is_shutdown);
0414 extern void iscsi_host_free(struct Scsi_Host *shost);
0415 extern int iscsi_target_alloc(struct scsi_target *starget);
0416 extern int iscsi_host_get_max_scsi_cmds(struct Scsi_Host *shost,
0417                     uint16_t requested_cmds_max);
0418 
0419 /*
0420  * session management
0421  */
0422 extern struct iscsi_cls_session *
0423 iscsi_session_setup(struct iscsi_transport *, struct Scsi_Host *shost,
0424             uint16_t, int, int, uint32_t, unsigned int);
0425 extern void iscsi_session_teardown(struct iscsi_cls_session *);
0426 extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
0427 extern int iscsi_set_param(struct iscsi_cls_conn *cls_conn,
0428                enum iscsi_param param, char *buf, int buflen);
0429 extern int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
0430                    enum iscsi_param param, char *buf);
0431 
0432 #define iscsi_session_printk(prefix, _sess, fmt, a...)  \
0433     iscsi_cls_session_printk(prefix, _sess->cls_session, fmt, ##a)
0434 
0435 /*
0436  * connection management
0437  */
0438 extern struct iscsi_cls_conn *iscsi_conn_setup(struct iscsi_cls_session *,
0439                            int, uint32_t);
0440 extern void iscsi_conn_teardown(struct iscsi_cls_conn *);
0441 extern int iscsi_conn_start(struct iscsi_cls_conn *);
0442 extern void iscsi_conn_stop(struct iscsi_cls_conn *, int);
0443 extern int iscsi_conn_bind(struct iscsi_cls_session *, struct iscsi_cls_conn *,
0444                int);
0445 extern void iscsi_conn_unbind(struct iscsi_cls_conn *cls_conn, bool is_active);
0446 extern void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err);
0447 extern void iscsi_session_failure(struct iscsi_session *session,
0448                   enum iscsi_err err);
0449 extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
0450                 enum iscsi_param param, char *buf);
0451 extern int iscsi_conn_get_addr_param(struct sockaddr_storage *addr,
0452                      enum iscsi_param param, char *buf);
0453 extern void iscsi_suspend_tx(struct iscsi_conn *conn);
0454 extern void iscsi_suspend_rx(struct iscsi_conn *conn);
0455 extern void iscsi_suspend_queue(struct iscsi_conn *conn);
0456 extern void iscsi_conn_queue_xmit(struct iscsi_conn *conn);
0457 extern void iscsi_conn_queue_recv(struct iscsi_conn *conn);
0458 
0459 #define iscsi_conn_printk(prefix, _c, fmt, a...) \
0460     iscsi_cls_conn_printk(prefix, ((struct iscsi_conn *)_c)->cls_conn, \
0461                   fmt, ##a)
0462 
0463 /*
0464  * pdu and task processing
0465  */
0466 extern void iscsi_update_cmdsn(struct iscsi_session *, struct iscsi_nopin *);
0467 extern void iscsi_prep_data_out_pdu(struct iscsi_task *task,
0468                     struct iscsi_r2t_info *r2t,
0469                     struct iscsi_data *hdr);
0470 extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *,
0471                 char *, uint32_t);
0472 extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
0473                   char *, int);
0474 extern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
0475                 char *, int);
0476 extern int iscsi_verify_itt(struct iscsi_conn *, itt_t);
0477 extern struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *, itt_t);
0478 extern struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *, itt_t);
0479 extern void iscsi_requeue_task(struct iscsi_task *task);
0480 extern void iscsi_put_task(struct iscsi_task *task);
0481 extern void __iscsi_put_task(struct iscsi_task *task);
0482 extern bool iscsi_get_task(struct iscsi_task *task);
0483 extern void iscsi_complete_scsi_task(struct iscsi_task *task,
0484                      uint32_t exp_cmdsn, uint32_t max_cmdsn);
0485 
0486 /*
0487  * generic helpers
0488  */
0489 extern void iscsi_pool_free(struct iscsi_pool *);
0490 extern int iscsi_pool_init(struct iscsi_pool *, int, void ***, int);
0491 extern int iscsi_switch_str_param(char **, char *);
0492 
0493 /*
0494  * inline functions to deal with padding.
0495  */
0496 static inline unsigned int
0497 iscsi_padded(unsigned int len)
0498 {
0499     return (len + ISCSI_PAD_LEN - 1) & ~(ISCSI_PAD_LEN - 1);
0500 }
0501 
0502 static inline unsigned int
0503 iscsi_padding(unsigned int len)
0504 {
0505     len &= (ISCSI_PAD_LEN - 1);
0506     if (len)
0507         len = ISCSI_PAD_LEN - len;
0508     return len;
0509 }
0510 
0511 #endif