514 lines · c
1/* SPDX-License-Identifier: GPL-2.0-or-later */2/*3 * iSCSI lib definitions4 *5 * Copyright (C) 2006 Red Hat, Inc. All rights reserved.6 * Copyright (C) 2004 - 2006 Mike Christie7 * Copyright (C) 2004 - 2005 Dmitry Yusupov8 * Copyright (C) 2004 - 2005 Alex Aizman9 */10#ifndef LIBISCSI_H11#define LIBISCSI_H12 13#include <linux/types.h>14#include <linux/wait.h>15#include <linux/mutex.h>16#include <linux/timer.h>17#include <linux/workqueue.h>18#include <linux/kfifo.h>19#include <linux/refcount.h>20#include <scsi/iscsi_proto.h>21#include <scsi/iscsi_if.h>22#include <scsi/scsi_cmnd.h>23#include <scsi/scsi_transport_iscsi.h>24 25struct scsi_transport_template;26struct scsi_host_template;27struct scsi_device;28struct Scsi_Host;29struct scsi_target;30struct scsi_cmnd;31struct socket;32struct iscsi_transport;33struct iscsi_cls_session;34struct iscsi_cls_conn;35struct iscsi_session;36struct iscsi_nopin;37struct device;38 39#define ISCSI_DEF_XMIT_CMDS_MAX 128 /* must be power of 2 */40#define ISCSI_MGMT_CMDS_MAX 1541 42#define ISCSI_DEF_CMD_PER_LUN 3243 44/* Task Mgmt states */45enum {46 TMF_INITIAL,47 TMF_QUEUED,48 TMF_SUCCESS,49 TMF_FAILED,50 TMF_TIMEDOUT,51 TMF_NOT_FOUND,52};53 54#define ISID_SIZE 655 56/* Connection flags */57#define ISCSI_CONN_FLAG_SUSPEND_TX 058#define ISCSI_CONN_FLAG_SUSPEND_RX 159#define ISCSI_CONN_FLAG_BOUND 260 61#define ISCSI_ITT_MASK 0x1fff62#define ISCSI_TOTAL_CMDS_MAX 409663/* this must be a power of two greater than ISCSI_MGMT_CMDS_MAX */64#define ISCSI_TOTAL_CMDS_MIN 1665#define ISCSI_AGE_SHIFT 2866#define ISCSI_AGE_MASK 0xf67 68#define ISCSI_ADDRESS_BUF_LEN 6469 70enum {71 /* this is the maximum possible storage for AHSs */72 ISCSI_MAX_AHS_SIZE = sizeof(struct iscsi_ecdb_ahdr) +73 sizeof(struct iscsi_rlength_ahdr),74 ISCSI_DIGEST_SIZE = sizeof(__u32),75};76 77 78enum {79 ISCSI_TASK_FREE,80 ISCSI_TASK_COMPLETED,81 ISCSI_TASK_PENDING,82 ISCSI_TASK_RUNNING,83 ISCSI_TASK_ABRT_TMF, /* aborted due to TMF */84 ISCSI_TASK_ABRT_SESS_RECOV, /* aborted due to session recovery */85 ISCSI_TASK_REQUEUE_SCSIQ, /* qcmd requeueing to scsi-ml */86};87 88struct iscsi_r2t_info {89 __be32 ttt; /* copied from R2T */90 __be32 exp_statsn; /* copied from R2T */91 uint32_t data_length; /* copied from R2T */92 uint32_t data_offset; /* copied from R2T */93 int data_count; /* DATA-Out payload progress */94 int datasn;95 /* LLDs should set/update these values */96 int sent; /* R2T sequence progress */97};98 99struct iscsi_task {100 /*101 * Because LLDs allocate their hdr differently, this is a pointer102 * and length to that storage. It must be setup at session103 * creation time.104 */105 struct iscsi_hdr *hdr;106 unsigned short hdr_max;107 unsigned short hdr_len; /* accumulated size of hdr used */108 /* copied values in case we need to send tmfs */109 itt_t hdr_itt;110 __be32 cmdsn;111 struct scsi_lun lun;112 113 int itt; /* this ITT */114 115 unsigned imm_count; /* imm-data (bytes) */116 /* offset in unsolicited stream (bytes); */117 struct iscsi_r2t_info unsol_r2t;118 char *data; /* mgmt payload */119 unsigned data_count;120 struct scsi_cmnd *sc; /* associated SCSI cmd*/121 struct iscsi_conn *conn; /* used connection */122 123 /* data processing tracking */124 unsigned long last_xfer;125 unsigned long last_timeout;126 bool have_checked_conn;127 128 /* T10 protection information */129 bool protected;130 131 /* state set/tested under session->lock */132 int state;133 refcount_t refcount;134 struct list_head running; /* running cmd list */135 void *dd_data; /* driver/transport data */136};137 138static inline int iscsi_task_has_unsol_data(struct iscsi_task *task)139{140 return task->unsol_r2t.data_length > task->unsol_r2t.sent;141}142 143static inline void* iscsi_next_hdr(struct iscsi_task *task)144{145 return (void*)task->hdr + task->hdr_len;146}147 148static inline bool iscsi_task_is_completed(struct iscsi_task *task)149{150 return task->state == ISCSI_TASK_COMPLETED ||151 task->state == ISCSI_TASK_ABRT_TMF ||152 task->state == ISCSI_TASK_ABRT_SESS_RECOV;153}154 155/* Private data associated with struct scsi_cmnd. */156struct iscsi_cmd {157 struct iscsi_task *task;158 int age;159};160 161static inline struct iscsi_cmd *iscsi_cmd(struct scsi_cmnd *cmd)162{163 return scsi_cmd_priv(cmd);164}165 166/* Connection's states */167enum {168 ISCSI_CONN_INITIAL_STAGE,169 ISCSI_CONN_STARTED,170 ISCSI_CONN_STOPPED,171 ISCSI_CONN_CLEANUP_WAIT,172};173 174struct iscsi_conn {175 struct iscsi_cls_conn *cls_conn; /* ptr to class connection */176 void *dd_data; /* iscsi_transport data */177 struct iscsi_session *session; /* parent session */178 /*179 * conn_stop() flag: stop to recover, stop to terminate180 */181 int stop_stage;182 struct timer_list transport_timer;183 unsigned long last_recv;184 unsigned long last_ping;185 int ping_timeout;186 int recv_timeout;187 struct iscsi_task *ping_task;188 189 /* iSCSI connection-wide sequencing */190 uint32_t exp_statsn;191 uint32_t statsn;192 193 /* control data */194 int id; /* CID */195 int c_stage; /* connection state */196 /*197 * Preallocated buffer for pdus that have data but do not198 * originate from scsi-ml. We never have two pdus using the199 * buffer at the same time. It is only allocated to200 * the default max recv size because the pdus we support201 * should always fit in this buffer202 */203 char *data;204 struct iscsi_task *login_task; /* mtask used for login/text */205 struct iscsi_task *task; /* xmit task in progress */206 207 /* xmit */208 /* items must be added/deleted under frwd lock */209 struct list_head mgmtqueue; /* mgmt (control) xmit queue */210 struct list_head cmdqueue; /* data-path cmd queue */211 struct list_head requeue; /* tasks needing another run */212 struct work_struct xmitwork; /* per-conn. xmit workqueue */213 /* recv */214 struct work_struct recvwork;215 unsigned long flags; /* ISCSI_CONN_FLAGs */216 217 /* negotiated params */218 unsigned max_recv_dlength; /* initiator_max_recv_dsl*/219 unsigned max_xmit_dlength; /* target_max_recv_dsl */220 int hdrdgst_en;221 int datadgst_en;222 int ifmarker_en;223 int ofmarker_en;224 /* values userspace uses to id a conn */225 int persistent_port;226 char *persistent_address;227 228 unsigned max_segment_size;229 unsigned tcp_xmit_wsf;230 unsigned tcp_recv_wsf;231 uint16_t keepalive_tmo;232 uint16_t local_port;233 uint8_t tcp_timestamp_stat;234 uint8_t tcp_nagle_disable;235 uint8_t tcp_wsf_disable;236 uint8_t tcp_timer_scale;237 uint8_t tcp_timestamp_en;238 uint8_t fragment_disable;239 uint8_t ipv4_tos;240 uint8_t ipv6_traffic_class;241 uint8_t ipv6_flow_label;242 uint8_t is_fw_assigned_ipv6;243 char *local_ipaddr;244 245 /* MIB-statistics */246 uint64_t txdata_octets;247 uint64_t rxdata_octets;248 uint32_t scsicmd_pdus_cnt;249 uint32_t dataout_pdus_cnt;250 uint32_t scsirsp_pdus_cnt;251 uint32_t datain_pdus_cnt;252 uint32_t r2t_pdus_cnt;253 uint32_t tmfcmd_pdus_cnt;254 int32_t tmfrsp_pdus_cnt;255 256 /* custom statistics */257 uint32_t eh_abort_cnt;258 uint32_t fmr_unalign_cnt;259};260 261struct iscsi_pool {262 struct kfifo queue; /* FIFO Queue */263 void **pool; /* Pool of elements */264 int max; /* Max number of elements */265};266 267/* Session's states */268enum {269 ISCSI_STATE_FREE = 1,270 ISCSI_STATE_LOGGED_IN,271 ISCSI_STATE_FAILED,272 ISCSI_STATE_TERMINATE,273 ISCSI_STATE_IN_RECOVERY,274 ISCSI_STATE_RECOVERY_FAILED,275 ISCSI_STATE_LOGGING_OUT,276};277 278struct iscsi_session {279 struct iscsi_cls_session *cls_session;280 /*281 * Syncs up the scsi eh thread with the iscsi eh thread when sending282 * task management functions. This must be taken before the session283 * and recv lock.284 */285 struct mutex eh_mutex;286 /* abort */287 wait_queue_head_t ehwait; /* used in eh_abort() */288 struct iscsi_tm tmhdr;289 struct timer_list tmf_timer;290 int tmf_state; /* see TMF_INITIAL, etc.*/291 struct iscsi_task *running_aborted_task;292 293 /* iSCSI session-wide sequencing */294 uint32_t cmdsn;295 uint32_t exp_cmdsn;296 uint32_t max_cmdsn;297 298 /* This tracks the reqs queued into the initiator */299 uint32_t queued_cmdsn;300 301 /* configuration */302 int abort_timeout;303 int lu_reset_timeout;304 int tgt_reset_timeout;305 int initial_r2t_en;306 unsigned short max_r2t;307 int imm_data_en;308 unsigned first_burst;309 unsigned max_burst;310 int time2wait;311 int time2retain;312 int pdu_inorder_en;313 int dataseq_inorder_en;314 int erl;315 int fast_abort;316 int tpgt;317 char *username;318 char *username_in;319 char *password;320 char *password_in;321 char *targetname;322 char *targetalias;323 char *ifacename;324 char *initiatorname;325 char *boot_root;326 char *boot_nic;327 char *boot_target;328 char *portal_type;329 char *discovery_parent_type;330 uint16_t discovery_parent_idx;331 uint16_t def_taskmgmt_tmo;332 uint16_t tsid;333 uint8_t auto_snd_tgt_disable;334 uint8_t discovery_sess;335 uint8_t chap_auth_en;336 uint8_t discovery_logout_en;337 uint8_t bidi_chap_en;338 uint8_t discovery_auth_optional;339 uint8_t isid[ISID_SIZE];340 341 /* control data */342 struct iscsi_transport *tt;343 struct Scsi_Host *host;344 struct iscsi_conn *leadconn; /* leading connection */345 /* Between the forward and the backward locks exists a strict locking346 * hierarchy. The mutual exclusion zone protected by the forward lock347 * can enclose the mutual exclusion zone protected by the backward lock348 * but not vice versa.349 */350 spinlock_t frwd_lock; /* protects session state, *351 * cmdsn, queued_cmdsn *352 * session resources: *353 * - cmdpool kfifo_out , *354 * - mgmtpool, queues */355 spinlock_t back_lock; /* protects cmdsn_exp *356 * cmdsn_max, *357 * cmdpool kfifo_in */358 int state; /* session state */359 int age; /* counts session re-opens */360 361 int scsi_cmds_max; /* max scsi commands */362 int cmds_max; /* size of cmds array */363 struct iscsi_task **cmds; /* Original Cmds arr */364 struct iscsi_pool cmdpool; /* PDU's pool */365 void *dd_data; /* LLD private data */366};367 368enum {369 ISCSI_HOST_SETUP,370 ISCSI_HOST_REMOVED,371};372 373struct iscsi_host {374 char *initiatorname;375 /* hw address or netdev iscsi connection is bound to */376 char *hwaddress;377 char *netdev;378 379 wait_queue_head_t session_removal_wq;380 /* protects sessions and state */381 spinlock_t lock;382 int num_sessions;383 int state;384 385 struct workqueue_struct *workq;386};387 388/*389 * scsi host template390 */391extern int iscsi_eh_abort(struct scsi_cmnd *sc);392extern int iscsi_eh_recover_target(struct scsi_cmnd *sc);393extern int iscsi_eh_session_reset(struct scsi_cmnd *sc);394extern int iscsi_eh_device_reset(struct scsi_cmnd *sc);395extern int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc);396extern enum scsi_timeout_action iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc);397 398/*399 * iSCSI host helpers.400 */401#define iscsi_host_priv(_shost) \402 (shost_priv(_shost) + sizeof(struct iscsi_host))403 404extern int iscsi_host_set_param(struct Scsi_Host *shost,405 enum iscsi_host_param param, char *buf,406 int buflen);407extern int iscsi_host_get_param(struct Scsi_Host *shost,408 enum iscsi_host_param param, char *buf);409extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev);410extern struct Scsi_Host *iscsi_host_alloc(const struct scsi_host_template *sht,411 int dd_data_size,412 bool xmit_can_sleep);413extern void iscsi_host_remove(struct Scsi_Host *shost, bool is_shutdown);414extern void iscsi_host_free(struct Scsi_Host *shost);415extern int iscsi_target_alloc(struct scsi_target *starget);416extern int iscsi_host_get_max_scsi_cmds(struct Scsi_Host *shost,417 uint16_t requested_cmds_max);418 419/*420 * session management421 */422extern struct iscsi_cls_session *423iscsi_session_setup(struct iscsi_transport *, struct Scsi_Host *shost,424 uint16_t, int, int, uint32_t, unsigned int);425void iscsi_session_remove(struct iscsi_cls_session *cls_session);426void iscsi_session_free(struct iscsi_cls_session *cls_session);427extern void iscsi_session_teardown(struct iscsi_cls_session *);428extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);429extern int iscsi_set_param(struct iscsi_cls_conn *cls_conn,430 enum iscsi_param param, char *buf, int buflen);431extern int iscsi_session_get_param(struct iscsi_cls_session *cls_session,432 enum iscsi_param param, char *buf);433 434#define iscsi_session_printk(prefix, _sess, fmt, a...) \435 iscsi_cls_session_printk(prefix, _sess->cls_session, fmt, ##a)436 437/*438 * connection management439 */440extern struct iscsi_cls_conn *iscsi_conn_setup(struct iscsi_cls_session *,441 int, uint32_t);442extern void iscsi_conn_teardown(struct iscsi_cls_conn *);443extern int iscsi_conn_start(struct iscsi_cls_conn *);444extern void iscsi_conn_stop(struct iscsi_cls_conn *, int);445extern int iscsi_conn_bind(struct iscsi_cls_session *, struct iscsi_cls_conn *,446 int);447extern void iscsi_conn_unbind(struct iscsi_cls_conn *cls_conn, bool is_active);448extern void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err);449extern void iscsi_session_failure(struct iscsi_session *session,450 enum iscsi_err err);451extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,452 enum iscsi_param param, char *buf);453extern int iscsi_conn_get_addr_param(struct sockaddr_storage *addr,454 enum iscsi_param param, char *buf);455extern void iscsi_suspend_tx(struct iscsi_conn *conn);456extern void iscsi_suspend_rx(struct iscsi_conn *conn);457extern void iscsi_suspend_queue(struct iscsi_conn *conn);458extern void iscsi_conn_queue_xmit(struct iscsi_conn *conn);459extern void iscsi_conn_queue_recv(struct iscsi_conn *conn);460 461#define iscsi_conn_printk(prefix, _c, fmt, a...) \462 iscsi_cls_conn_printk(prefix, ((struct iscsi_conn *)_c)->cls_conn, \463 fmt, ##a)464 465/*466 * pdu and task processing467 */468extern void iscsi_update_cmdsn(struct iscsi_session *, struct iscsi_nopin *);469extern void iscsi_prep_data_out_pdu(struct iscsi_task *task,470 struct iscsi_r2t_info *r2t,471 struct iscsi_data *hdr);472extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *,473 char *, uint32_t);474extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,475 char *, int);476extern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,477 char *, int);478extern int iscsi_verify_itt(struct iscsi_conn *, itt_t);479extern struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *, itt_t);480extern struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *, itt_t);481extern void iscsi_requeue_task(struct iscsi_task *task);482extern void iscsi_put_task(struct iscsi_task *task);483extern void __iscsi_put_task(struct iscsi_task *task);484extern bool iscsi_get_task(struct iscsi_task *task);485extern void iscsi_complete_scsi_task(struct iscsi_task *task,486 uint32_t exp_cmdsn, uint32_t max_cmdsn);487 488/*489 * generic helpers490 */491extern void iscsi_pool_free(struct iscsi_pool *);492extern int iscsi_pool_init(struct iscsi_pool *, int, void ***, int);493extern int iscsi_switch_str_param(char **, char *);494 495/*496 * inline functions to deal with padding.497 */498static inline unsigned int499iscsi_padded(unsigned int len)500{501 return (len + ISCSI_PAD_LEN - 1) & ~(ISCSI_PAD_LEN - 1);502}503 504static inline unsigned int505iscsi_padding(unsigned int len)506{507 len &= (ISCSI_PAD_LEN - 1);508 if (len)509 len = ISCSI_PAD_LEN - len;510 return len;511}512 513#endif514