⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iscsi_tcp.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		crypto_free_hash(tcp_conn->rx_hash.tfm);	kfree(tcp_conn);}static voidiscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag){	struct iscsi_conn *conn = cls_conn->dd_data;	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;	iscsi_conn_stop(cls_conn, flag);	iscsi_tcp_release_conn(conn);	tcp_conn->hdr_size = sizeof(struct iscsi_hdr);}static int iscsi_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock,			      char *buf, int *port,			      int (*getname)(struct socket *, struct sockaddr *,					int *addrlen)){	struct sockaddr_storage *addr;	struct sockaddr_in6 *sin6;	struct sockaddr_in *sin;	int rc = 0, len;	addr = kmalloc(sizeof(*addr), GFP_KERNEL);	if (!addr)		return -ENOMEM;	if (getname(sock, (struct sockaddr *) addr, &len)) {		rc = -ENODEV;		goto free_addr;	}	switch (addr->ss_family) {	case AF_INET:		sin = (struct sockaddr_in *)addr;		spin_lock_bh(&conn->session->lock);		sprintf(buf, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr));		*port = be16_to_cpu(sin->sin_port);		spin_unlock_bh(&conn->session->lock);		break;	case AF_INET6:		sin6 = (struct sockaddr_in6 *)addr;		spin_lock_bh(&conn->session->lock);		sprintf(buf, NIP6_FMT, NIP6(sin6->sin6_addr));		*port = be16_to_cpu(sin6->sin6_port);		spin_unlock_bh(&conn->session->lock);		break;	}free_addr:	kfree(addr);	return rc;}static intiscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,		    struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,		    int is_leading){	struct iscsi_conn *conn = cls_conn->dd_data;	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;	struct sock *sk;	struct socket *sock;	int err;	/* lookup for existing socket */	sock = sockfd_lookup((int)transport_eph, &err);	if (!sock) {		printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err);		return -EEXIST;	}	/*	 * copy these values now because if we drop the session	 * userspace may still want to query the values since we will	 * be using them for the reconnect	 */	err = iscsi_tcp_get_addr(conn, sock, conn->portal_address,				 &conn->portal_port, kernel_getpeername);	if (err)		goto free_socket;	err = iscsi_tcp_get_addr(conn, sock, conn->local_address,				&conn->local_port, kernel_getsockname);	if (err)		goto free_socket;	err = iscsi_conn_bind(cls_session, cls_conn, is_leading);	if (err)		goto free_socket;	/* bind iSCSI connection and socket */	tcp_conn->sock = sock;	/* setup Socket parameters */	sk = sock->sk;	sk->sk_reuse = 1;	sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */	sk->sk_allocation = GFP_ATOMIC;	/* FIXME: disable Nagle's algorithm */	/*	 * Intercept TCP callbacks for sendfile like receive	 * processing.	 */	conn->recv_lock = &sk->sk_callback_lock;	iscsi_conn_set_callbacks(conn);	tcp_conn->sendpage = tcp_conn->sock->ops->sendpage;	/*	 * set receive state machine into initial state	 */	tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;	return 0;free_socket:	sockfd_put(sock);	return err;}/* called with host lock */static voidiscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask){	struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;	tcp_mtask->xmstate = 1 << XMSTATE_BIT_IMM_HDR_INIT;}static intiscsi_r2tpool_alloc(struct iscsi_session *session){	int i;	int cmd_i;	/*	 * initialize per-task: R2T pool and xmit queue	 */	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {	        struct iscsi_cmd_task *ctask = session->cmds[cmd_i];		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;		/*		 * pre-allocated x4 as much r2ts to handle race when		 * target acks DataOut faster than we data_xmit() queues		 * could replenish r2tqueue.		 */		/* R2T pool */		if (iscsi_pool_init(&tcp_ctask->r2tpool, session->max_r2t * 4,				    (void***)&tcp_ctask->r2ts,				    sizeof(struct iscsi_r2t_info))) {			goto r2t_alloc_fail;		}		/* R2T xmit queue */		tcp_ctask->r2tqueue = kfifo_alloc(		      session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL);		if (tcp_ctask->r2tqueue == ERR_PTR(-ENOMEM)) {			iscsi_pool_free(&tcp_ctask->r2tpool,					(void**)tcp_ctask->r2ts);			goto r2t_alloc_fail;		}	}	return 0;r2t_alloc_fail:	for (i = 0; i < cmd_i; i++) {		struct iscsi_cmd_task *ctask = session->cmds[i];		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;		kfifo_free(tcp_ctask->r2tqueue);		iscsi_pool_free(&tcp_ctask->r2tpool,				(void**)tcp_ctask->r2ts);	}	return -ENOMEM;}static voidiscsi_r2tpool_free(struct iscsi_session *session){	int i;	for (i = 0; i < session->cmds_max; i++) {		struct iscsi_cmd_task *ctask = session->cmds[i];		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;		kfifo_free(tcp_ctask->r2tqueue);		iscsi_pool_free(&tcp_ctask->r2tpool,				(void**)tcp_ctask->r2ts);	}}static intiscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,		     char *buf, int buflen){	struct iscsi_conn *conn = cls_conn->dd_data;	struct iscsi_session *session = conn->session;	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;	int value;	switch(param) {	case ISCSI_PARAM_HDRDGST_EN:		iscsi_set_param(cls_conn, param, buf, buflen);		tcp_conn->hdr_size = sizeof(struct iscsi_hdr);		if (conn->hdrdgst_en)			tcp_conn->hdr_size += sizeof(__u32);		break;	case ISCSI_PARAM_DATADGST_EN:		iscsi_set_param(cls_conn, param, buf, buflen);		tcp_conn->sendpage = conn->datadgst_en ?			sock_no_sendpage : tcp_conn->sock->ops->sendpage;		break;	case ISCSI_PARAM_MAX_R2T:		sscanf(buf, "%d", &value);		if (session->max_r2t == roundup_pow_of_two(value))			break;		iscsi_r2tpool_free(session);		iscsi_set_param(cls_conn, param, buf, buflen);		if (session->max_r2t & (session->max_r2t - 1))			session->max_r2t = roundup_pow_of_two(session->max_r2t);		if (iscsi_r2tpool_alloc(session))			return -ENOMEM;		break;	default:		return iscsi_set_param(cls_conn, param, buf, buflen);	}	return 0;}static intiscsi_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,			 enum iscsi_param param, char *buf){	struct iscsi_conn *conn = cls_conn->dd_data;	int len;	switch(param) {	case ISCSI_PARAM_CONN_PORT:		spin_lock_bh(&conn->session->lock);		len = sprintf(buf, "%hu\n", conn->portal_port);		spin_unlock_bh(&conn->session->lock);		break;	case ISCSI_PARAM_CONN_ADDRESS:		spin_lock_bh(&conn->session->lock);		len = sprintf(buf, "%s\n", conn->portal_address);		spin_unlock_bh(&conn->session->lock);		break;	default:		return iscsi_conn_get_param(cls_conn, param, buf);	}	return len;}static intiscsi_tcp_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,			 char *buf){        struct iscsi_session *session = iscsi_hostdata(shost->hostdata);	int len;	switch (param) {	case ISCSI_HOST_PARAM_IPADDRESS:		spin_lock_bh(&session->lock);		if (!session->leadconn)			len = -ENODEV;		else			len = sprintf(buf, "%s\n",				     session->leadconn->local_address);		spin_unlock_bh(&session->lock);		break;	default:		return iscsi_host_get_param(shost, param, buf);	}	return len;}static voidiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats){	struct iscsi_conn *conn = cls_conn->dd_data;	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;	stats->txdata_octets = conn->txdata_octets;	stats->rxdata_octets = conn->rxdata_octets;	stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;	stats->dataout_pdus = conn->dataout_pdus_cnt;	stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;	stats->datain_pdus = conn->datain_pdus_cnt;	stats->r2t_pdus = conn->r2t_pdus_cnt;	stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;	stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;	stats->custom_length = 3;	strcpy(stats->custom[0].desc, "tx_sendpage_failures");	stats->custom[0].value = tcp_conn->sendpage_failures_cnt;	strcpy(stats->custom[1].desc, "rx_discontiguous_hdr");	stats->custom[1].value = tcp_conn->discontiguous_hdr_cnt;	strcpy(stats->custom[2].desc, "eh_abort_cnt");	stats->custom[2].value = conn->eh_abort_cnt;}static struct iscsi_cls_session *iscsi_tcp_session_create(struct iscsi_transport *iscsit,			 struct scsi_transport_template *scsit,			 uint16_t cmds_max, uint16_t qdepth,			 uint32_t initial_cmdsn, uint32_t *hostno){	struct iscsi_cls_session *cls_session;	struct iscsi_session *session;	uint32_t hn;	int cmd_i;	cls_session = iscsi_session_setup(iscsit, scsit, cmds_max, qdepth,					 sizeof(struct iscsi_tcp_cmd_task),					 sizeof(struct iscsi_tcp_mgmt_task),					 initial_cmdsn, &hn);	if (!cls_session)		return NULL;	*hostno = hn;	session = class_to_transport_session(cls_session);	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {		struct iscsi_cmd_task *ctask = session->cmds[cmd_i];		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;		ctask->hdr = &tcp_ctask->hdr;	}	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) {		struct iscsi_mgmt_task *mtask = session->mgmt_cmds[cmd_i];		struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;		mtask->hdr = &tcp_mtask->hdr;	}	if (iscsi_r2tpool_alloc(class_to_transport_session(cls_session)))		goto r2tpool_alloc_fail;	return cls_session;r2tpool_alloc_fail:	iscsi_session_teardown(cls_session);	return NULL;}static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session){	iscsi_r2tpool_free(class_to_transport_session(cls_session));	iscsi_session_teardown(cls_session);}static int iscsi_tcp_slave_configure(struct scsi_device *sdev){	blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_ANY);	blk_queue_dma_alignment(sdev->request_queue, 0);	return 0;}static struct scsi_host_template iscsi_sht = {	.module			= THIS_MODULE,	.name			= "iSCSI Initiator over TCP/IP",	.queuecommand           = iscsi_queuecommand,	.change_queue_depth	= iscsi_change_queue_depth,	.can_queue		= ISCSI_DEF_XMIT_CMDS_MAX - 1,	.sg_tablesize		= ISCSI_SG_TABLESIZE,	.max_sectors		= 0xFFFF,	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,	.eh_abort_handler       = iscsi_eh_abort,	.eh_host_reset_handler	= iscsi_eh_host_reset,	.use_clustering         = DISABLE_CLUSTERING,	.slave_configure        = iscsi_tcp_slave_configure,	.proc_name		= "iscsi_tcp",	.this_id		= -1,};static struct iscsi_transport iscsi_tcp_transport = {	.owner			= THIS_MODULE,	.name			= "tcp",	.caps			= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST				  | CAP_DATADGST,	.param_mask		= ISCSI_MAX_RECV_DLENGTH |				  ISCSI_MAX_XMIT_DLENGTH |				  ISCSI_HDRDGST_EN |				  ISCSI_DATADGST_EN |				  ISCSI_INITIAL_R2T_EN |				  ISCSI_MAX_R2T |				  ISCSI_IMM_DATA_EN |				  ISCSI_FIRST_BURST |				  ISCSI_MAX_BURST |				  ISCSI_PDU_INORDER_EN |				  ISCSI_DATASEQ_INORDER_EN |				  ISCSI_ERL |				  ISCSI_CONN_PORT |				  ISCSI_CONN_ADDRESS |				  ISCSI_EXP_STATSN |				  ISCSI_PERSISTENT_PORT |				  ISCSI_PERSISTENT_ADDRESS |				  ISCSI_TARGET_NAME | ISCSI_TPGT |				  ISCSI_USERNAME | ISCSI_PASSWORD |				  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN,	.host_param_mask	= ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS |				  ISCSI_HOST_INITIATOR_NAME |				  ISCSI_HOST_NETDEV_NAME,	.host_template		= &iscsi_sht,	.conndata_size		= sizeof(struct iscsi_conn),	.max_conn		= 1,	.max_cmd_len		= ISCSI_TCP_MAX_CMD_LEN,	/* session management */	.create_session		= iscsi_tcp_session_create,	.destroy_session	= iscsi_tcp_session_destroy,	/* connection management */	.create_conn		= iscsi_tcp_conn_create,	.bind_conn		= iscsi_tcp_conn_bind,	.destroy_conn		= iscsi_tcp_conn_destroy,	.set_param		= iscsi_conn_set_param,	.get_conn_param		= iscsi_tcp_conn_get_param,	.get_session_param	= iscsi_session_get_param,	.start_conn		= iscsi_conn_start,	.stop_conn		= iscsi_tcp_conn_stop,	/* iscsi host params */	.get_host_param		= iscsi_tcp_host_get_param,	.set_host_param		= iscsi_host_set_param,	/* IO */	.send_pdu		= iscsi_conn_send_pdu,	.get_stats		= iscsi_conn_get_stats,	.init_cmd_task		= iscsi_tcp_cmd_init,	.init_mgmt_task		= iscsi_tcp_mgmt_init,	.xmit_cmd_task		= iscsi_tcp_ctask_xmit,	.xmit_mgmt_task		= iscsi_tcp_mtask_xmit,	.cleanup_cmd_task	= iscsi_tcp_cleanup_ctask,	/* recovery */	.session_recovery_timedout = iscsi_session_recovery_timedout,};static int __initiscsi_tcp_init(void){	if (iscsi_max_lun < 1) {		printk(KERN_ERR "iscsi_tcp: Invalid max_lun value of %u\n",		       iscsi_max_lun);		return -EINVAL;	}	iscsi_tcp_transport.max_lun = iscsi_max_lun;	if (!iscsi_register_transport(&iscsi_tcp_transport))		return -ENODEV;	return 0;}static void __exitiscsi_tcp_exit(void){	iscsi_unregister_transport(&iscsi_tcp_transport);}module_init(iscsi_tcp_init);module_exit(iscsi_tcp_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -