Commit bc756235 authored by Michael S. Tsirkin's avatar Michael S. Tsirkin

Merge branch 'for-next-merge' of...

Merge branch 'for-next-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending into vhost-net-next
parents c39904a0 b8d26b3b
......@@ -59,5 +59,6 @@ source "drivers/infiniband/ulp/srp/Kconfig"
source "drivers/infiniband/ulp/srpt/Kconfig"
source "drivers/infiniband/ulp/iser/Kconfig"
source "drivers/infiniband/ulp/isert/Kconfig"
endif # INFINIBAND
......@@ -13,3 +13,4 @@ obj-$(CONFIG_INFINIBAND_IPOIB) += ulp/ipoib/
obj-$(CONFIG_INFINIBAND_SRP) += ulp/srp/
obj-$(CONFIG_INFINIBAND_SRPT) += ulp/srpt/
obj-$(CONFIG_INFINIBAND_ISER) += ulp/iser/
obj-$(CONFIG_INFINIBAND_ISERT) += ulp/isert/
config INFINIBAND_ISERT
tristate "iSCSI Extentions for RDMA (iSER) target support"
depends on INET && INFINIBAND_ADDR_TRANS && TARGET_CORE && ISCSI_TARGET
---help---
Support for iSCSI Extentions for RDMA (iSER) Target on Infiniband fabrics.
ccflags-y := -Idrivers/target -Idrivers/target/iscsi
obj-$(CONFIG_INFINIBAND_ISERT) += ib_isert.o
This diff is collapsed.
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <rdma/ib_verbs.h>
#include <rdma/rdma_cm.h>
#define ISERT_RDMA_LISTEN_BACKLOG 10
enum isert_desc_type {
ISCSI_TX_CONTROL,
ISCSI_TX_DATAIN
};
enum iser_ib_op_code {
ISER_IB_RECV,
ISER_IB_SEND,
ISER_IB_RDMA_WRITE,
ISER_IB_RDMA_READ,
};
enum iser_conn_state {
ISER_CONN_INIT,
ISER_CONN_UP,
ISER_CONN_TERMINATING,
ISER_CONN_DOWN,
};
struct iser_rx_desc {
struct iser_hdr iser_header;
struct iscsi_hdr iscsi_header;
char data[ISER_RECV_DATA_SEG_LEN];
u64 dma_addr;
struct ib_sge rx_sg;
char pad[ISER_RX_PAD_SIZE];
} __packed;
struct iser_tx_desc {
struct iser_hdr iser_header;
struct iscsi_hdr iscsi_header;
enum isert_desc_type type;
u64 dma_addr;
struct ib_sge tx_sg[2];
int num_sge;
struct isert_cmd *isert_cmd;
struct ib_send_wr send_wr;
} __packed;
struct isert_rdma_wr {
struct list_head wr_list;
struct isert_cmd *isert_cmd;
enum iser_ib_op_code iser_ib_op;
struct ib_sge *ib_sge;
int num_sge;
struct scatterlist *sge;
int send_wr_num;
struct ib_send_wr *send_wr;
};
struct isert_cmd {
uint32_t read_stag;
uint32_t write_stag;
uint64_t read_va;
uint64_t write_va;
u64 sense_buf_dma;
u32 sense_buf_len;
u32 read_va_off;
u32 write_va_off;
u32 rdma_wr_num;
struct isert_conn *conn;
struct iscsi_cmd iscsi_cmd;
struct ib_sge *ib_sge;
struct iser_tx_desc tx_desc;
struct isert_rdma_wr rdma_wr;
struct work_struct comp_work;
};
struct isert_device;
struct isert_conn {
enum iser_conn_state state;
bool logout_posted;
int post_recv_buf_count;
atomic_t post_send_buf_count;
u32 responder_resources;
u32 initiator_depth;
u32 max_sge;
char *login_buf;
char *login_req_buf;
char *login_rsp_buf;
u64 login_req_dma;
u64 login_rsp_dma;
unsigned int conn_rx_desc_head;
struct iser_rx_desc *conn_rx_descs;
struct ib_recv_wr conn_rx_wr[ISERT_MIN_POSTED_RX];
struct iscsi_conn *conn;
struct list_head conn_accept_node;
struct completion conn_login_comp;
struct iser_tx_desc conn_login_tx_desc;
struct rdma_cm_id *conn_cm_id;
struct ib_pd *conn_pd;
struct ib_mr *conn_mr;
struct ib_qp *conn_qp;
struct isert_device *conn_device;
struct work_struct conn_logout_work;
wait_queue_head_t conn_wait;
wait_queue_head_t conn_wait_comp_err;
struct kref conn_kref;
};
#define ISERT_MAX_CQ 64
struct isert_cq_desc {
struct isert_device *device;
int cq_index;
struct work_struct cq_rx_work;
struct work_struct cq_tx_work;
};
struct isert_device {
int cqs_used;
int refcount;
int cq_active_qps[ISERT_MAX_CQ];
struct ib_device *ib_device;
struct ib_pd *dev_pd;
struct ib_mr *dev_mr;
struct ib_cq *dev_rx_cq[ISERT_MAX_CQ];
struct ib_cq *dev_tx_cq[ISERT_MAX_CQ];
struct isert_cq_desc *cq_desc;
struct list_head dev_node;
};
struct isert_np {
wait_queue_head_t np_accept_wq;
struct rdma_cm_id *np_cm_id;
struct mutex np_accept_mutex;
struct list_head np_accept_list;
struct completion np_login_comp;
};
/* From iscsi_iser.h */
struct iser_hdr {
u8 flags;
u8 rsvd[3];
__be32 write_stag; /* write rkey */
__be64 write_va;
__be32 read_stag; /* read rkey */
__be64 read_va;
} __packed;
/*Constant PDU lengths calculations */
#define ISER_HEADERS_LEN (sizeof(struct iser_hdr) + sizeof(struct iscsi_hdr))
#define ISER_RECV_DATA_SEG_LEN 8192
#define ISER_RX_PAYLOAD_SIZE (ISER_HEADERS_LEN + ISER_RECV_DATA_SEG_LEN)
#define ISER_RX_LOGIN_SIZE (ISER_HEADERS_LEN + ISCSI_DEF_MAX_RECV_SEG_LEN)
/* QP settings */
/* Maximal bounds on received asynchronous PDUs */
#define ISERT_MAX_TX_MISC_PDUS 4 /* NOOP_IN(2) , ASYNC_EVENT(2) */
#define ISERT_MAX_RX_MISC_PDUS 6 /* NOOP_OUT(2), TEXT(1), *
* SCSI_TMFUNC(2), LOGOUT(1) */
#define ISCSI_DEF_XMIT_CMDS_MAX 128 /* from libiscsi.h, must be power of 2 */
#define ISERT_QP_MAX_RECV_DTOS (ISCSI_DEF_XMIT_CMDS_MAX)
#define ISERT_MIN_POSTED_RX (ISCSI_DEF_XMIT_CMDS_MAX >> 2)
#define ISERT_INFLIGHT_DATAOUTS 8
#define ISERT_QP_MAX_REQ_DTOS (ISCSI_DEF_XMIT_CMDS_MAX * \
(1 + ISERT_INFLIGHT_DATAOUTS) + \
ISERT_MAX_TX_MISC_PDUS + \
ISERT_MAX_RX_MISC_PDUS)
#define ISER_RX_PAD_SIZE (ISER_RECV_DATA_SEG_LEN + 4096 - \
(ISER_RX_PAYLOAD_SIZE + sizeof(u64) + sizeof(struct ib_sge)))
#define ISER_VER 0x10
#define ISER_WSV 0x08
#define ISER_RSV 0x04
#define ISCSI_CTRL 0x10
#define ISER_HELLO 0x20
#define ISER_HELLORPLY 0x30
......@@ -2585,25 +2585,6 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
ha->tgt.tgt_ops->free_cmd(cmd);
}
/* ha->hardware_lock supposed to be held on entry */
/* called via callback from qla2xxx */
void qlt_ctio_completion(struct scsi_qla_host *vha, uint32_t handle)
{
struct qla_hw_data *ha = vha->hw;
struct qla_tgt *tgt = ha->tgt.qla_tgt;
if (likely(tgt == NULL)) {
ql_dbg(ql_dbg_tgt, vha, 0xe021,
"CTIO, but target mode not enabled"
" (ha %d %p handle %#x)", vha->vp_idx, ha, handle);
return;
}
tgt->irq_cmd_count++;
qlt_do_ctio_completion(vha, handle, CTIO_SUCCESS, NULL);
tgt->irq_cmd_count--;
}
static inline int qlt_get_fcp_task_attr(struct scsi_qla_host *vha,
uint8_t task_codes)
{
......
......@@ -980,7 +980,6 @@ extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t);
extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *);
extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *);
extern void qlt_free_cmd(struct qla_tgt_cmd *cmd);
extern void qlt_ctio_completion(struct scsi_qla_host *, uint32_t);
extern void qlt_async_event(uint16_t, struct scsi_qla_host *, uint16_t *);
extern void qlt_enable_vha(struct scsi_qla_host *);
extern void qlt_vport_create(struct scsi_qla_host *, struct qla_hw_data *);
......
......@@ -15,6 +15,7 @@ iscsi_target_mod-y += iscsi_target_parameters.o \
iscsi_target_util.o \
iscsi_target.o \
iscsi_target_configfs.o \
iscsi_target_stat.o
iscsi_target_stat.o \
iscsi_target_transport.o
obj-$(CONFIG_ISCSI_TARGET) += iscsi_target_mod.o
This diff is collapsed.
......@@ -16,11 +16,12 @@ extern int iscsit_reset_np_thread(struct iscsi_np *, struct iscsi_tpg_np *,
struct iscsi_portal_group *);
extern int iscsit_del_np(struct iscsi_np *);
extern int iscsit_add_reject_from_cmd(u8, int, int, unsigned char *, struct iscsi_cmd *);
extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *);
extern int iscsit_logout_closesession(struct iscsi_cmd *, struct iscsi_conn *);
extern int iscsit_logout_closeconnection(struct iscsi_cmd *, struct iscsi_conn *);
extern int iscsit_logout_removeconnforrecovery(struct iscsi_cmd *, struct iscsi_conn *);
extern int iscsit_send_async_msg(struct iscsi_conn *, u16, u8, u8);
extern int iscsit_build_r2ts_for_cmd(struct iscsi_cmd *, struct iscsi_conn *, bool recovery);
extern int iscsit_build_r2ts_for_cmd(struct iscsi_conn *, struct iscsi_cmd *, bool recovery);
extern void iscsit_thread_get_cpumask(struct iscsi_conn *);
extern int iscsi_target_tx_thread(void *);
extern int iscsi_target_rx_thread(void *);
......
......@@ -49,32 +49,6 @@ static void chap_binaryhex_to_asciihex(char *dst, char *src, int src_len)
}
}
static void chap_set_random(char *data, int length)
{
long r;
unsigned n;
while (length > 0) {
get_random_bytes(&r, sizeof(long));
r = r ^ (r >> 8);
r = r ^ (r >> 4);
n = r & 0x7;
get_random_bytes(&r, sizeof(long));
r = r ^ (r >> 8);
r = r ^ (r >> 5);
n = (n << 3) | (r & 0x7);
get_random_bytes(&r, sizeof(long));
r = r ^ (r >> 8);
r = r ^ (r >> 5);
n = (n << 2) | (r & 0x3);
*data++ = n;
length--;
}
}
static void chap_gen_challenge(
struct iscsi_conn *conn,
int caller,
......@@ -86,7 +60,7 @@ static void chap_gen_challenge(
memset(challenge_asciihex, 0, CHAP_CHALLENGE_LENGTH * 2 + 1);
chap_set_random(chap->challenge, CHAP_CHALLENGE_LENGTH);
get_random_bytes(chap->challenge, CHAP_CHALLENGE_LENGTH);
chap_binaryhex_to_asciihex(challenge_asciihex, chap->challenge,
CHAP_CHALLENGE_LENGTH);
/*
......
......@@ -27,6 +27,7 @@
#include <target/target_core_fabric_configfs.h>
#include <target/target_core_configfs.h>
#include <target/configfs_macros.h>
#include <target/iscsi/iscsi_transport.h>
#include "iscsi_target_core.h"
#include "iscsi_target_parameters.h"
......@@ -124,8 +125,87 @@ static ssize_t lio_target_np_store_sctp(
TF_NP_BASE_ATTR(lio_target, sctp, S_IRUGO | S_IWUSR);
static ssize_t lio_target_np_show_iser(
struct se_tpg_np *se_tpg_np,
char *page)
{
struct iscsi_tpg_np *tpg_np = container_of(se_tpg_np,
struct iscsi_tpg_np, se_tpg_np);
struct iscsi_tpg_np *tpg_np_iser;
ssize_t rb;
tpg_np_iser = iscsit_tpg_locate_child_np(tpg_np, ISCSI_INFINIBAND);
if (tpg_np_iser)
rb = sprintf(page, "1\n");
else
rb = sprintf(page, "0\n");
return rb;
}
static ssize_t lio_target_np_store_iser(
struct se_tpg_np *se_tpg_np,
const char *page,
size_t count)
{
struct iscsi_np *np;
struct iscsi_portal_group *tpg;
struct iscsi_tpg_np *tpg_np = container_of(se_tpg_np,
struct iscsi_tpg_np, se_tpg_np);
struct iscsi_tpg_np *tpg_np_iser = NULL;
char *endptr;
u32 op;
int rc;
op = simple_strtoul(page, &endptr, 0);
if ((op != 1) && (op != 0)) {
pr_err("Illegal value for tpg_enable: %u\n", op);
return -EINVAL;
}
np = tpg_np->tpg_np;
if (!np) {
pr_err("Unable to locate struct iscsi_np from"
" struct iscsi_tpg_np\n");
return -EINVAL;
}
tpg = tpg_np->tpg;
if (iscsit_get_tpg(tpg) < 0)
return -EINVAL;
if (op) {
int rc = request_module("ib_isert");
if (rc != 0)
pr_warn("Unable to request_module for ib_isert\n");
tpg_np_iser = iscsit_tpg_add_network_portal(tpg, &np->np_sockaddr,
np->np_ip, tpg_np, ISCSI_INFINIBAND);
if (!tpg_np_iser || IS_ERR(tpg_np_iser))
goto out;
} else {
tpg_np_iser = iscsit_tpg_locate_child_np(tpg_np, ISCSI_INFINIBAND);
if (!tpg_np_iser)
goto out;
rc = iscsit_tpg_del_network_portal(tpg, tpg_np_iser);
if (rc < 0)
goto out;
}
printk("lio_target_np_store_iser() done, op: %d\n", op);
iscsit_put_tpg(tpg);
return count;
out:
iscsit_put_tpg(tpg);
return -EINVAL;
}
TF_NP_BASE_ATTR(lio_target, iser, S_IRUGO | S_IWUSR);
static struct configfs_attribute *lio_target_portal_attrs[] = {
&lio_target_np_sctp.attr,
&lio_target_np_iser.attr,
NULL,
};
......@@ -1536,16 +1616,18 @@ static int lio_queue_data_in(struct se_cmd *se_cmd)
struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
cmd->i_state = ISTATE_SEND_DATAIN;
iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
cmd->conn->conn_transport->iscsit_queue_data_in(cmd->conn, cmd);
return 0;
}
static int lio_write_pending(struct se_cmd *se_cmd)
{
struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
struct iscsi_conn *conn = cmd->conn;
if (!cmd->immediate_data && !cmd->unsolicited_data)
return iscsit_build_r2ts_for_cmd(cmd, cmd->conn, false);
return conn->conn_transport->iscsit_get_dataout(conn, cmd, false);
return 0;
}
......@@ -1567,7 +1649,8 @@ static int lio_queue_status(struct se_cmd *se_cmd)
struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
cmd->i_state = ISTATE_SEND_STATUS;
iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
cmd->conn->conn_transport->iscsit_queue_status(cmd->conn, cmd);
return 0;
}
......@@ -1696,11 +1779,17 @@ static void lio_set_default_node_attributes(struct se_node_acl *se_acl)
iscsit_set_default_node_attribues(acl);
}
static int lio_check_stop_free(struct se_cmd *se_cmd)
{
return target_put_sess_cmd(se_cmd->se_sess, se_cmd);
}
static void lio_release_cmd(struct se_cmd *se_cmd)
{
struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
iscsit_release_cmd(cmd);
pr_debug("Entering lio_release_cmd for se_cmd: %p\n", se_cmd);
cmd->release_cmd(cmd);
}
/* End functions for target_core_fabric_ops */
......@@ -1740,6 +1829,7 @@ int iscsi_target_register_configfs(void)
fabric->tf_ops.tpg_alloc_fabric_acl = &lio_tpg_alloc_fabric_acl;
fabric->tf_ops.tpg_release_fabric_acl = &lio_tpg_release_fabric_acl;
fabric->tf_ops.tpg_get_inst_index = &lio_tpg_get_inst_index;
fabric->tf_ops.check_stop_free = &lio_check_stop_free,
fabric->tf_ops.release_cmd = &lio_release_cmd;
fabric->tf_ops.shutdown_session = &lio_tpg_shutdown_session;
fabric->tf_ops.close_session = &lio_tpg_close_session;
......
......@@ -60,7 +60,7 @@
#define ISCSI_IOV_DATA_BUFFER 5
enum tpg_np_network_transport_table {
enum iscsit_transport_type {
ISCSI_TCP = 0,
ISCSI_SCTP_TCP = 1,
ISCSI_SCTP_UDP = 2,
......@@ -244,6 +244,11 @@ struct iscsi_conn_ops {
u8 IFMarker; /* [0,1] == [No,Yes] */
u32 OFMarkInt; /* [1..65535] */
u32 IFMarkInt; /* [1..65535] */
/*
* iSER specific connection parameters
*/
u32 InitiatorRecvDataSegmentLength; /* [512..2**24-1] */
u32 TargetRecvDataSegmentLength; /* [512..2**24-1] */
};
struct iscsi_sess_ops {
......@@ -265,6 +270,10 @@ struct iscsi_sess_ops {
u8 DataSequenceInOrder; /* [0,1] == [No,Yes] */
u8 ErrorRecoveryLevel; /* [0..2] */
u8 SessionType; /* [0,1] == [Normal,Discovery]*/
/*
* iSER specific session parameters
*/
u8 RDMAExtensions; /* [0,1] == [No,Yes] */
};
struct iscsi_queue_req {
......@@ -284,6 +293,7 @@ struct iscsi_data_count {
};
struct iscsi_param_list {
bool iser;
struct list_head param_list;
struct list_head extra_response_list;
};
......@@ -475,6 +485,7 @@ struct iscsi_cmd {
u32 first_data_sg_off;
u32 kmapped_nents;
sense_reason_t sense_reason;
void (*release_cmd)(struct iscsi_cmd *);
} ____cacheline_aligned;
struct iscsi_tmr_req {
......@@ -503,6 +514,7 @@ struct iscsi_conn {
u16 login_port;
u16 local_port;
int net_size;
int login_family;
u32 auth_id;
u32 conn_flags;
/* Used for iscsi_tx_login_rsp() */
......@@ -562,9 +574,12 @@ struct iscsi_conn {
struct list_head immed_queue_list;
struct list_head response_queue_list;
struct iscsi_conn_ops *conn_ops;
struct iscsi_login *conn_login;
struct iscsit_transport *conn_transport;
struct iscsi_param_list *param_list;
/* Used for per connection auth state machine */
void *auth_protocol;
void *context;
struct iscsi_login_thread_s *login_thread;
struct iscsi_portal_group *tpg;
/* Pointer to parent session */
......@@ -663,6 +678,8 @@ struct iscsi_login {
u8 first_request;
u8 version_min;
u8 version_max;
u8 login_complete;
u8 login_failed;
char isid[6];
u32 cmd_sn;
itt_t init_task_tag;
......@@ -670,10 +687,11 @@ struct iscsi_login {
u32 rsp_length;
u16 cid;
u16 tsih;
char *req;
char *rsp;
char req[ISCSI_HDR_LEN];
char rsp[ISCSI_HDR_LEN];
char *req_buf;
char *rsp_buf;
struct iscsi_conn *conn;
} ____cacheline_aligned;
struct iscsi_node_attrib {
......@@ -754,6 +772,8 @@ struct iscsi_np {
struct task_struct *np_thread;
struct timer_list np_login_timer;
struct iscsi_portal_group *np_login_tpg;
void *np_context;
struct iscsit_transport *np_transport;
struct list_head np_list;
} ____cacheline_aligned;
......
......@@ -60,8 +60,13 @@ void iscsit_increment_maxcmdsn(struct iscsi_cmd *cmd, struct iscsi_session *sess
cmd->maxcmdsn_inc = 1;
mutex_lock(&sess->cmdsn_mutex);
if (!mutex_trylock(&sess->cmdsn_mutex)) {
sess->max_cmd_sn += 1;
pr_debug("Updated MaxCmdSN to 0x%08x\n", sess->max_cmd_sn);
return;
}
sess->max_cmd_sn += 1;
pr_debug("Updated MaxCmdSN to 0x%08x\n", sess->max_cmd_sn);
mutex_unlock(&sess->cmdsn_mutex);
}
EXPORT_SYMBOL(iscsit_increment_maxcmdsn);
......@@ -22,6 +22,7 @@
#include <scsi/iscsi_proto.h>
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
#include <target/iscsi/iscsi_transport.h>
#include "iscsi_target_core.h"
#include "iscsi_target_seq_pdu_list.h"
......@@ -53,6 +54,9 @@ int iscsit_dump_data_payload(
u32 length, padding, offset = 0, size;
struct kvec iov;
if (conn->sess->sess_ops->RDMAExtensions)
return 0;
length = (buf_len > OFFLOAD_BUF_SIZE) ? OFFLOAD_BUF_SIZE : buf_len;
buf = kzalloc(length, GFP_ATOMIC);
......@@ -919,6 +923,7 @@ int iscsit_execute_ooo_cmdsns(struct iscsi_session *sess)
int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
{
struct se_cmd *se_cmd = &cmd->se_cmd;
struct iscsi_conn *conn = cmd->conn;
int lr = 0;
spin_lock_bh(&cmd->istate_lock);
......@@ -981,7 +986,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
return 0;
iscsit_set_dataout_sequence_values(cmd);
iscsit_build_r2ts_for_cmd(cmd, cmd->conn, false);
conn->conn_transport->iscsit_get_dataout(conn, cmd, false);
}
return 0;
}
......@@ -999,10 +1004,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
if (transport_check_aborted_status(se_cmd, 1) != 0)
return 0;
iscsit_set_dataout_sequence_values(cmd);
spin_lock_bh(&cmd->dataout_timeout_lock);
iscsit_start_dataout_timer(cmd, cmd->conn);
spin_unlock_bh(&cmd->dataout_timeout_lock);
iscsit_set_unsoliticed_dataout(cmd);
}
return transport_handle_cdb_direct(&cmd->se_cmd);
......@@ -1290,3 +1292,4 @@ void iscsit_stop_dataout_timer(struct iscsi_cmd *cmd)
cmd->init_task_tag);
spin_unlock_bh(&cmd->dataout_timeout_lock);
}
EXPORT_SYMBOL(iscsit_stop_dataout_timer);
This diff is collapsed.
......@@ -4,8 +4,14 @@
extern int iscsi_login_setup_crypto(struct iscsi_conn *);
extern int iscsi_check_for_session_reinstatement(struct iscsi_conn *);
extern int iscsi_login_post_auth_non_zero_tsih(struct iscsi_conn *, u16, u32);
extern int iscsit_setup_np(struct iscsi_np *,
struct __kernel_sockaddr_storage *);
extern int iscsi_target_setup_login_socket(struct iscsi_np *,
struct __kernel_sockaddr_storage *);
extern int iscsit_accept_np(struct iscsi_np *, struct iscsi_conn *);
extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *);
extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32);
extern void iscsit_free_conn(struct iscsi_np *, struct iscsi_conn *);
extern int iscsi_target_login_thread(void *);
extern int iscsi_login_disable_FIM_keys(struct iscsi_param_list *, struct iscsi_conn *);
......
......@@ -22,6 +22,7 @@
#include <scsi/iscsi_proto.h>
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
#include <target/iscsi/iscsi_transport.h>
#include "iscsi_target_core.h"
#include "iscsi_target_parameters.h"
......@@ -169,7 +170,7 @@ static void iscsi_remove_failed_auth_entry(struct iscsi_conn *conn)
kfree(conn->auth_protocol);
}
static int iscsi_target_check_login_request(
int iscsi_target_check_login_request(
struct iscsi_conn *conn,
struct iscsi_login *login)
{
......@@ -200,8 +201,8 @@ static int iscsi_target_check_login_request(
return -1;
}
req_csg = (login_req->flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2;
req_nsg = (login_req->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK);
req_csg = ISCSI_LOGIN_CURRENT_STAGE(login_req->flags);
req_nsg = ISCSI_LOGIN_NEXT_STAGE(login_req->flags);
if (req_csg != login->current_stage) {
pr_err("Initiator unexpectedly changed login stage"
......@@ -352,11 +353,8 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log
padding = ((-login->rsp_length) & 3);
if (iscsi_login_tx_data(
conn,
login->rsp,
login->rsp_buf,
login->rsp_length + padding) < 0)
if (conn->conn_transport->iscsit_put_login_tx(conn, login,
login->rsp_length + padding) < 0)
return -1;
login->rsp_length = 0;
......@@ -368,72 +366,12 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log
return 0;
}
static int iscsi_target_do_rx_login_io(struct iscsi_conn *conn, struct iscsi_login *login)
{
u32 padding = 0, payload_length;
struct iscsi_login_req *login_req;
if (iscsi_login_rx_data(conn, login->req, ISCSI_HDR_LEN) < 0)
return -1;
login_req = (struct iscsi_login_req *) login->req;
payload_length = ntoh24(login_req->dlength);
pr_debug("Got Login Command, Flags 0x%02x, ITT: 0x%08x,"
" CmdSN: 0x%08x, ExpStatSN: 0x%08x, CID: %hu, Length: %u\n",
login_req->flags, login_req->itt, login_req->cmdsn,
login_req->exp_statsn, login_req->cid, payload_length);
if (iscsi_target_check_login_request(conn, login) < 0)
return -1;
padding = ((-payload_length) & 3);
memset(login->req_buf, 0, MAX_KEY_VALUE_PAIRS);
if (iscsi_login_rx_data(
conn,
login->req_buf,
payload_length + padding) < 0)
return -1;
return 0;
}
static int iscsi_target_do_login_io(struct iscsi_conn *conn, struct iscsi_login *login)
{
if (iscsi_target_do_tx_login_io(conn, login) < 0)
return -1;
if (iscsi_target_do_rx_login_io(conn, login) < 0)
return -1;
return 0;
}
static int iscsi_target_get_initial_payload(
struct iscsi_conn *conn,
struct iscsi_login *login)
{
u32 padding = 0, payload_length;
struct iscsi_login_req *login_req;
login_req = (struct iscsi_login_req *) login->req;
payload_length = ntoh24(login_req->dlength);
pr_debug("Got Login Command, Flags 0x%02x, ITT: 0x%08x,"
" CmdSN: 0x%08x, ExpStatSN: 0x%08x, Length: %u\n",
login_req->flags, login_req->itt, login_req->cmdsn,
login_req->exp_statsn, payload_length);
if (iscsi_target_check_login_request(conn, login) < 0)
return -1;
padding = ((-payload_length) & 3);
if (iscsi_login_rx_data(
conn,
login->req_buf,
payload_length + padding) < 0)
if (conn->conn_transport->iscsit_get_login_rx(conn, login) < 0)
return -1;
return 0;
......@@ -681,9 +619,9 @@ static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *lo
return -1;
}
switch ((login_req->flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2) {
switch (ISCSI_LOGIN_CURRENT_STAGE(login_req->flags)) {
case 0:
login_rsp->flags |= (0 & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK);
login_rsp->flags &= ~ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK;
if (iscsi_target_handle_csg_zero(conn, login) < 0)
return -1;
break;
......@@ -693,6 +631,7 @@ static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *lo
return -1;
if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) {
login->tsih = conn->sess->tsih;
login->login_complete = 1;
if (iscsi_target_do_tx_login_io(conn,
login) < 0)
return -1;
......@@ -702,8 +641,7 @@ static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *lo
default:
pr_err("Illegal CSG: %d received from"
" Initiator, protocol error.\n",
(login_req->flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK)
>> 2);
ISCSI_LOGIN_CURRENT_STAGE(login_req->flags));
break;
}
......@@ -737,7 +675,7 @@ static void iscsi_initiatorname_tolower(
/*
* Processes the first Login Request..
*/
static int iscsi_target_locate_portal(
int iscsi_target_locate_portal(
struct iscsi_np *np,
struct iscsi_conn *conn,
struct iscsi_login *login)
......@@ -753,22 +691,6 @@ static int iscsi_target_locate_portal(
login_req = (struct iscsi_login_req *) login->req;
payload_length = ntoh24(login_req->dlength);
login->first_request = 1;
login->leading_connection = (!login_req->tsih) ? 1 : 0;
login->current_stage =
(login_req->flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2;
login->version_min = login_req->min_version;
login->version_max = login_req->max_version;
memcpy(login->isid, login_req->isid, 6);
login->cmd_sn = be32_to_cpu(login_req->cmdsn);
login->init_task_tag = login_req->itt;
login->initial_exp_statsn = be32_to_cpu(login_req->exp_statsn);
login->cid = be16_to_cpu(login_req->cid);
login->tsih = be16_to_cpu(login_req->tsih);
if (iscsi_target_get_initial_payload(conn, login) < 0)
return -1;
tmpbuf = kzalloc(payload_length + 1, GFP_KERNEL);
if (!tmpbuf) {
pr_err("Unable to allocate memory for tmpbuf.\n");
......@@ -800,6 +722,8 @@ static int iscsi_target_locate_portal(
start += strlen(key) + strlen(value) + 2;
}
printk("i_buf: %s, s_buf: %s, t_buf: %s\n", i_buf, s_buf, t_buf);
/*
* See 5.3. Login Phase.
*/
......@@ -958,100 +882,30 @@ static int iscsi_target_locate_portal(
return ret;
}
struct iscsi_login *iscsi_target_init_negotiation(
struct iscsi_np *np,
struct iscsi_conn *conn,
char *login_pdu)
{
struct iscsi_login *login;
login = kzalloc(sizeof(struct iscsi_login), GFP_KERNEL);
if (!login) {
pr_err("Unable to allocate memory for struct iscsi_login.\n");
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_NO_RESOURCES);
return NULL;
}
login->req = kmemdup(login_pdu, ISCSI_HDR_LEN, GFP_KERNEL);
if (!login->req) {
pr_err("Unable to allocate memory for Login Request.\n");
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_NO_RESOURCES);
goto out;
}
login->req_buf = kzalloc(MAX_KEY_VALUE_PAIRS, GFP_KERNEL);
if (!login->req_buf) {
pr_err("Unable to allocate memory for response buffer.\n");
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_NO_RESOURCES);
goto out;
}
/*
* SessionType: Discovery
*
* Locates Default Portal
*
* SessionType: Normal
*
* Locates Target Portal from NP -> Target IQN
*/
if (iscsi_target_locate_portal(np, conn, login) < 0) {
goto out;
}
return login;
out:
kfree(login->req);
kfree(login->req_buf);
kfree(login);
return NULL;
}
int iscsi_target_start_negotiation(
struct iscsi_login *login,
struct iscsi_conn *conn)
{
int ret = -1;
login->rsp = kzalloc(ISCSI_HDR_LEN, GFP_KERNEL);
if (!login->rsp) {
pr_err("Unable to allocate memory for"
" Login Response.\n");
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_NO_RESOURCES);
ret = -1;
goto out;
}
login->rsp_buf = kzalloc(MAX_KEY_VALUE_PAIRS, GFP_KERNEL);
if (!login->rsp_buf) {
pr_err("Unable to allocate memory for"
" request buffer.\n");
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
ISCSI_LOGIN_STATUS_NO_RESOURCES);
ret = -1;
goto out;
}
int ret;
ret = iscsi_target_do_login(conn, login);
out:
if (ret != 0)
iscsi_remove_failed_auth_entry(conn);
iscsi_target_nego_release(login, conn);
iscsi_target_nego_release(conn);
return ret;
}
void iscsi_target_nego_release(
struct iscsi_login *login,
struct iscsi_conn *conn)
void iscsi_target_nego_release(struct iscsi_conn *conn)
{
kfree(login->req);
kfree(login->rsp);
struct iscsi_login *login = conn->conn_login;
if (!login)
return;
kfree(login->req_buf);
kfree(login->rsp_buf);
kfree(login);
conn->conn_login = NULL;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -8,6 +8,7 @@ extern struct iscsi_r2t *iscsit_get_r2t_for_eos(struct iscsi_cmd *, u32, u32);
extern struct iscsi_r2t *iscsit_get_r2t_from_list(struct iscsi_cmd *);
extern void iscsit_free_r2t(struct iscsi_r2t *, struct iscsi_cmd *);
extern void iscsit_free_r2ts_from_list(struct iscsi_cmd *);
extern struct iscsi_cmd *iscsit_alloc_cmd(struct iscsi_conn *, gfp_t);
extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t);
extern struct iscsi_seq *iscsit_get_seq_holder_for_datain(struct iscsi_cmd *, u32);
extern struct iscsi_seq *iscsit_get_seq_holder_for_r2t(struct iscsi_cmd *);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment