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

📄 iscsi_iser.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * iSCSI Initiator over iSER Data-Path * * Copyright (C) 2004 Dmitry Yusupov * Copyright (C) 2004 Alex Aizman * Copyright (C) 2005 Mike Christie * Copyright (c) 2005, 2006 Voltaire, Inc. All rights reserved. * maintained by openib-general@openib.org * * This software is available to you under a choice of one of two * licenses.  You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * *     Redistribution and use in source and binary forms, with or *     without modification, are permitted provided that the following *     conditions are met: * *	- Redistributions of source code must retain the above *	  copyright notice, this list of conditions and the following *	  disclaimer. * *	- Redistributions in binary form must reproduce the above *	  copyright notice, this list of conditions and the following *	  disclaimer in the documentation and/or other materials *	  provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Credits: *	Christoph Hellwig *	FUJITA Tomonori *	Arne Redlich *	Zhenyu Wang * Modified by: *      Erez Zilber * * * $Id: iscsi_iser.c 6965 2006-05-07 11:36:20Z ogerlitz $ */#include <linux/types.h>#include <linux/list.h>#include <linux/hardirq.h>#include <linux/kfifo.h>#include <linux/blkdev.h>#include <linux/init.h>#include <linux/ioctl.h>#include <linux/cdev.h>#include <linux/in.h>#include <linux/net.h>#include <linux/scatterlist.h>#include <linux/delay.h>#include <net/sock.h>#include <asm/uaccess.h>#include <scsi/scsi_cmnd.h>#include <scsi/scsi_device.h>#include <scsi/scsi_eh.h>#include <scsi/scsi_tcq.h>#include <scsi/scsi_host.h>#include <scsi/scsi.h>#include <scsi/scsi_transport_iscsi.h>#include "iscsi_iser.h"static unsigned int iscsi_max_lun = 512;module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);int iser_debug_level = 0;MODULE_DESCRIPTION("iSER (iSCSI Extensions for RDMA) Datamover "		   "v" DRV_VER " (" DRV_DATE ")");MODULE_LICENSE("Dual BSD/GPL");MODULE_AUTHOR("Alex Nezhinsky, Dan Bar Dov, Or Gerlitz");module_param_named(debug_level, iser_debug_level, int, 0644);MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0 (default:disabled)");struct iser_global ig;voidiscsi_iser_recv(struct iscsi_conn *conn,		struct iscsi_hdr *hdr, char *rx_data, int rx_data_len){	int rc = 0;	uint32_t ret_itt;	int datalen;	int ahslen;	/* verify PDU length */	datalen = ntoh24(hdr->dlength);	if (datalen != rx_data_len) {		printk(KERN_ERR "iscsi_iser: datalen %d (hdr) != %d (IB) \n",		       datalen, rx_data_len);		rc = ISCSI_ERR_DATALEN;		goto error;	}	/* read AHS */	ahslen = hdr->hlength * 4;	/* verify itt (itt encoding: age+cid+itt) */	rc = iscsi_verify_itt(conn, hdr, &ret_itt);	if (!rc)		rc = iscsi_complete_pdu(conn, hdr, rx_data, rx_data_len);	if (rc && rc != ISCSI_ERR_NO_SCSI_CMD)		goto error;	return;error:	iscsi_conn_failure(conn, rc);}/** * iscsi_iser_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands * **/static voidiscsi_iser_cmd_init(struct iscsi_cmd_task *ctask){	struct iscsi_iser_conn     *iser_conn  = ctask->conn->dd_data;	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;	iser_ctask->command_sent = 0;	iser_ctask->iser_conn    = iser_conn;	iser_ctask_rdma_init(iser_ctask);}/** * iscsi_mtask_xmit - xmit management(immediate) task * @conn: iscsi connection * @mtask: task management task * * Notes: *	The function can return -EAGAIN in which case caller must *	call it again later, or recover. '0' return code means successful *	xmit. * **/static intiscsi_iser_mtask_xmit(struct iscsi_conn *conn,		      struct iscsi_mgmt_task *mtask){	int error = 0;	debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id, mtask->itt);	error = iser_send_control(conn, mtask);	/* since iser xmits control with zero copy, mtasks can not be recycled	 * right after sending them.	 * The recycling scheme is based on whether a response is expected	 * - if yes, the mtask is recycled at iscsi_complete_pdu	 * - if no,  the mtask is recycled at iser_snd_completion	 */	if (error && error != -ENOBUFS)		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);	return error;}static intiscsi_iser_ctask_xmit_unsol_data(struct iscsi_conn *conn,				 struct iscsi_cmd_task *ctask){	struct iscsi_data  hdr;	int error = 0;	/* Send data-out PDUs while there's still unsolicited data to send */	while (ctask->unsol_count > 0) {		iscsi_prep_unsolicit_data_pdu(ctask, &hdr);		debug_scsi("Sending data-out: itt 0x%x, data count %d\n",			   hdr.itt, ctask->data_count);		/* the buffer description has been passed with the command */		/* Send the command */		error = iser_send_data_out(conn, ctask, &hdr);		if (error) {			ctask->unsol_datasn--;			goto iscsi_iser_ctask_xmit_unsol_data_exit;		}		ctask->unsol_count -= ctask->data_count;		debug_scsi("Need to send %d more as data-out PDUs\n",			   ctask->unsol_count);	}iscsi_iser_ctask_xmit_unsol_data_exit:	return error;}static intiscsi_iser_ctask_xmit(struct iscsi_conn *conn,		      struct iscsi_cmd_task *ctask){	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;	int error = 0;	if (ctask->sc->sc_data_direction == DMA_TO_DEVICE) {		BUG_ON(scsi_bufflen(ctask->sc) == 0);		debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n",			   ctask->itt, scsi_bufflen(ctask->sc),			   ctask->imm_count, ctask->unsol_count);	}	debug_scsi("ctask deq [cid %d itt 0x%x]\n",		   conn->id, ctask->itt);	/*	 * serialize with TMF AbortTask	 */	if (ctask->mtask)		return error;	/* Send the cmd PDU */	if (!iser_ctask->command_sent) {		error = iser_send_command(conn, ctask);		if (error)			goto iscsi_iser_ctask_xmit_exit;		iser_ctask->command_sent = 1;	}	/* Send unsolicited data-out PDU(s) if necessary */	if (ctask->unsol_count)		error = iscsi_iser_ctask_xmit_unsol_data(conn, ctask); iscsi_iser_ctask_xmit_exit:	if (error && error != -ENOBUFS)		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);	return error;}static voidiscsi_iser_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask){	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;	if (iser_ctask->status == ISER_TASK_STATUS_STARTED) {		iser_ctask->status = ISER_TASK_STATUS_COMPLETED;		iser_ctask_rdma_finalize(iser_ctask);	}}static struct iser_conn *iscsi_iser_ib_conn_lookup(__u64 ep_handle){	struct iser_conn *ib_conn;	struct iser_conn *uib_conn = (struct iser_conn *)(unsigned long)ep_handle;	mutex_lock(&ig.connlist_mutex);	list_for_each_entry(ib_conn, &ig.connlist, conn_list) {		if (ib_conn == uib_conn) {			mutex_unlock(&ig.connlist_mutex);			return ib_conn;		}	}	mutex_unlock(&ig.connlist_mutex);	iser_err("no conn exists for eph %llx\n",(unsigned long long)ep_handle);	return NULL;}static struct iscsi_cls_conn *iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx){	struct iscsi_conn *conn;	struct iscsi_cls_conn *cls_conn;	struct iscsi_iser_conn *iser_conn;	cls_conn = iscsi_conn_setup(cls_session, conn_idx);	if (!cls_conn)		return NULL;	conn = cls_conn->dd_data;	/*	 * due to issues with the login code re iser sematics	 * this not set in iscsi_conn_setup - FIXME	 */	conn->max_recv_dlength = 128;	iser_conn = kzalloc(sizeof(*iser_conn), GFP_KERNEL);	if (!iser_conn)		goto conn_alloc_fail;	/* currently this is the only field which need to be initiated */	rwlock_init(&iser_conn->lock);	conn->dd_data = iser_conn;	iser_conn->iscsi_conn = conn;	return cls_conn;conn_alloc_fail:	iscsi_conn_teardown(cls_conn);	return NULL;}static voidiscsi_iser_conn_destroy(struct iscsi_cls_conn *cls_conn){	struct iscsi_conn *conn = cls_conn->dd_data;	struct iscsi_iser_conn *iser_conn = conn->dd_data;	iscsi_conn_teardown(cls_conn);	if (iser_conn->ib_conn)		iser_conn->ib_conn->iser_conn = NULL;	kfree(iser_conn);}static intiscsi_iser_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_iser_conn *iser_conn;	struct iser_conn *ib_conn;	int error;	error = iscsi_conn_bind(cls_session, cls_conn, is_leading);	if (error)		return error;	/* the transport ep handle comes from user space so it must be

⌨️ 快捷键说明

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