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

📄 iscsi.c

📁 iscsi企业级target.很好用
💻 C
📖 第 1 页 / 共 3 页
字号:
				if (cmnd == req)					continue;				if (all)					__cmnd_abort(cmnd);				else if (translate_lun(cmnd_hdr(cmnd)->lun) == lun)					__cmnd_abort(cmnd);			}		}	}	return 0;}static void task_set_abort(struct iscsi_cmnd *req){	struct iscsi_session *session = req->conn->session;	struct iscsi_conn *conn;	struct iscsi_cmnd *cmnd, *tmp;	list_for_each_entry(conn, &session->conn_list, list) {		list_for_each_entry_safe(cmnd, tmp, &conn->pdu_list, conn_list) {			if (cmnd != req)				__cmnd_abort(cmnd);		}	}}static void execute_task_management(struct iscsi_cmnd *req){	struct iscsi_conn *conn = req->conn;	struct iscsi_target *target = conn->session->target;	struct iscsi_cmnd *rsp;	struct iscsi_task_mgt_hdr *req_hdr = (struct iscsi_task_mgt_hdr *)&req->pdu.bhs;	struct iscsi_task_rsp_hdr *rsp_hdr;	u32 lun;	int err, function = req_hdr->function & ISCSI_FUNCTION_MASK;	rsp = iscsi_cmnd_create_rsp_cmnd(req, 1);	rsp_hdr = (struct iscsi_task_rsp_hdr *)&rsp->pdu.bhs;	rsp_hdr->opcode = ISCSI_OP_SCSI_TASK_MGT_RSP;	rsp_hdr->flags = ISCSI_FLG_FINAL;	rsp_hdr->itt = req_hdr->itt;	rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_COMPLETE;	eprintk("%x %d %x\n", cmnd_itt(req), function, req_hdr->rtt);	switch (function) {	case ISCSI_FUNCTION_ABORT_TASK:	case ISCSI_FUNCTION_ABORT_TASK_SET:	case ISCSI_FUNCTION_CLEAR_ACA:	case ISCSI_FUNCTION_CLEAR_TASK_SET:	case ISCSI_FUNCTION_LOGICAL_UNIT_RESET:		lun = translate_lun(req_hdr->lun);		if (!volume_lookup(target, lun)) {			rsp_hdr->response = ISCSI_RESPONSE_UNKNOWN_LUN;			goto out;		}	}	switch (function) {	case ISCSI_FUNCTION_ABORT_TASK:		if ((err = cmnd_abort(conn->session, req_hdr->rtt)) < 0)			rsp_hdr->response = -err;		break;	case ISCSI_FUNCTION_ABORT_TASK_SET:		task_set_abort(req);		break;	case ISCSI_FUNCTION_CLEAR_ACA:		rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_UNSUPPORTED;		break;	case ISCSI_FUNCTION_CLEAR_TASK_SET:		rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_UNSUPPORTED;		break;	case ISCSI_FUNCTION_LOGICAL_UNIT_RESET:		target_reset(req, translate_lun(req_hdr->lun), 0);		break;	case ISCSI_FUNCTION_TARGET_WARM_RESET:	case ISCSI_FUNCTION_TARGET_COLD_RESET:		target_reset(req, 0, 1);		if (function == ISCSI_FUNCTION_TARGET_COLD_RESET)			set_cmnd_close(rsp);		break;	case ISCSI_FUNCTION_TASK_REASSIGN:		rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_UNSUPPORTED;		break;	default:		rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_REJECTED;		break;	}out:	iscsi_cmnd_init_write(rsp);}static void noop_out_exec(struct iscsi_cmnd *req){	struct iscsi_cmnd *rsp;	struct iscsi_nop_in_hdr *rsp_hdr;	if (cmnd_itt(req) != cpu_to_be32(ISCSI_RESERVED_TAG)) {		rsp = iscsi_cmnd_create_rsp_cmnd(req, 1);		rsp_hdr = (struct iscsi_nop_in_hdr *)&rsp->pdu.bhs;		rsp_hdr->opcode = ISCSI_OP_NOOP_IN;		rsp_hdr->flags = ISCSI_FLG_FINAL;		rsp_hdr->itt = req->pdu.bhs.itt;		rsp_hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG);		if (req->pdu.datasize)			assert(req->tio);		else			assert(!req->tio);		if (req->tio) {			tio_get(req->tio);			rsp->tio = req->tio;		}		assert(get_pgcnt(req->pdu.datasize, 0) < ISCSI_CONN_IOV_MAX);		rsp->pdu.datasize = req->pdu.datasize;		iscsi_cmnd_init_write(rsp);	} else		iscsi_cmnd_remove(req);}static void logout_exec(struct iscsi_cmnd *req){	struct iscsi_logout_req_hdr *req_hdr;	struct iscsi_cmnd *rsp;	struct iscsi_logout_rsp_hdr *rsp_hdr;	req_hdr = (struct iscsi_logout_req_hdr *)&req->pdu.bhs;	rsp = iscsi_cmnd_create_rsp_cmnd(req, 1);	rsp_hdr = (struct iscsi_logout_rsp_hdr *)&rsp->pdu.bhs;	rsp_hdr->opcode = ISCSI_OP_LOGOUT_RSP;	rsp_hdr->flags = ISCSI_FLG_FINAL;	rsp_hdr->itt = req_hdr->itt;	set_cmnd_close(rsp);	iscsi_cmnd_init_write(rsp);}static void iscsi_cmnd_exec(struct iscsi_cmnd *cmnd){	dprintk(D_GENERIC, "%p,%x,%u\n", cmnd, cmnd_opcode(cmnd), cmnd->pdu.bhs.sn);	switch (cmnd_opcode(cmnd)) {	case ISCSI_OP_NOOP_OUT:		noop_out_exec(cmnd);		break;	case ISCSI_OP_SCSI_CMD:		scsi_cmnd_exec(cmnd);		break;	case ISCSI_OP_SCSI_TASK_MGT_MSG:		execute_task_management(cmnd);		break;	case ISCSI_OP_LOGOUT_CMD:		logout_exec(cmnd);		break;	case ISCSI_OP_SCSI_REJECT:		iscsi_cmnd_init_write(get_rsp_cmnd(cmnd));		break;	case ISCSI_OP_TEXT_CMD:	case ISCSI_OP_SNACK_CMD:		break;	default:		eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd));		break;	}}static void __cmnd_send_pdu(struct iscsi_conn *conn, struct tio *tio, u32 offset, u32 size){	dprintk(D_GENERIC, "%p %u,%u\n", tio, offset, size);	offset += tio->offset;	assert(offset <= tio->offset + tio->size);	assert(offset + size <= tio->offset + tio->size);	conn->write_tcmnd = tio;	conn->write_offset = offset;	conn->write_size += size;}static void cmnd_send_pdu(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd){	u32 size;	struct tio *tio;	if (!cmnd->pdu.datasize)		return;	size = (cmnd->pdu.datasize + 3) & -4;	tio = cmnd->tio;	assert(tio);	assert(tio->size == size);	__cmnd_send_pdu(conn, tio, 0, size);}static void set_cork(struct socket *sock, int on){	int opt = on;	mm_segment_t oldfs;	oldfs = get_fs();	set_fs(get_ds());	sock->ops->setsockopt(sock, SOL_TCP, TCP_CORK, (void *)&opt, sizeof(opt));	set_fs(oldfs);}void cmnd_release(struct iscsi_cmnd *cmnd, int force){	struct iscsi_cmnd *req, *rsp;	int is_last = 0;	if (!cmnd)		return;/* 	eprintk("%x %lx %d\n", cmnd_opcode(cmnd), cmnd->flags, force); */	req = cmnd->req;	is_last = cmnd_final(cmnd);	if (force) {		while (!list_empty(&cmnd->pdu_list)) {			rsp = list_entry(cmnd->pdu_list.next, struct iscsi_cmnd, pdu_list);			list_del_init(&rsp->list);			list_del(&rsp->pdu_list);			iscsi_cmnd_remove(rsp);		}		list_del_init(&cmnd->list);	} else		if (cmnd_queued(cmnd))			iscsi_scsi_dequeuecmnd(cmnd);	if (cmnd_hashed(cmnd))		cmnd_remove_hash(cmnd);	if (cmnd_lunit(cmnd)) {		assert(cmnd->lun);		volume_put(cmnd->lun);	}	list_del_init(&cmnd->pdu_list);	iscsi_cmnd_remove(cmnd);	if (is_last) {		assert(!force);		assert(req);		cmnd_release(req, 0);	}	return;}void cmnd_tx_start(struct iscsi_cmnd *cmnd){	struct iscsi_conn *conn = cmnd->conn;	struct iovec *iop;	dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd));	assert(cmnd);	iscsi_cmnd_set_length(&cmnd->pdu);	set_cork(conn->sock, 1);	conn->write_iop = iop = conn->write_iov;	iop->iov_base = &cmnd->pdu.bhs;	iop->iov_len = sizeof(cmnd->pdu.bhs);	iop++;	conn->write_size = sizeof(cmnd->pdu.bhs);	switch (cmnd_opcode(cmnd)) {	case ISCSI_OP_NOOP_IN:		cmnd_set_sn(cmnd, 1);		cmnd_send_pdu(conn, cmnd);		break;	case ISCSI_OP_SCSI_RSP:		cmnd_set_sn(cmnd, 1);		cmnd_send_pdu(conn, cmnd);		break;	case ISCSI_OP_SCSI_TASK_MGT_RSP:		cmnd_set_sn(cmnd, 1);		break;	case ISCSI_OP_TEXT_RSP:		cmnd_set_sn(cmnd, 1);		break;	case ISCSI_OP_SCSI_DATA_IN:	{		struct iscsi_data_in_hdr *rsp = (struct iscsi_data_in_hdr *)&cmnd->pdu.bhs;		u32 offset;		cmnd_set_sn(cmnd, (rsp->flags & ISCSI_FLG_FINAL) ? 1 : 0);		offset = rsp->buffer_offset;		rsp->buffer_offset = cpu_to_be32(offset);		__cmnd_send_pdu(conn, cmnd->tio, offset, cmnd->pdu.datasize);		break;	}	case ISCSI_OP_LOGOUT_RSP:		cmnd_set_sn(cmnd, 1);		break;	case ISCSI_OP_R2T:		cmnd_set_sn(cmnd, 0);		cmnd->pdu.bhs.sn = cpu_to_be32(conn->stat_sn);		break;	case ISCSI_OP_ASYNC_MSG:		cmnd_set_sn(cmnd, 1);		break;	case ISCSI_OP_REJECT:		cmnd_set_sn(cmnd, 1);		cmnd_send_pdu(conn, cmnd);		break;	default:		eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd));		break;	}	iop->iov_len = 0;	// move this?	conn->write_size = (conn->write_size + 3) & -4;	iscsi_dump_pdu(&cmnd->pdu);}void cmnd_tx_end(struct iscsi_cmnd *cmnd){	struct iscsi_conn *conn = cmnd->conn;	dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd));	switch (cmnd_opcode(cmnd)) {	case ISCSI_OP_NOOP_IN:	case ISCSI_OP_SCSI_RSP:	case ISCSI_OP_SCSI_TASK_MGT_RSP:	case ISCSI_OP_TEXT_RSP:	case ISCSI_OP_R2T:	case ISCSI_OP_ASYNC_MSG:	case ISCSI_OP_REJECT:	case ISCSI_OP_SCSI_DATA_IN:	case ISCSI_OP_LOGOUT_RSP:		break;	default:		eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd));		assert(0);		break;	}	if (cmnd_close(cmnd))		conn_close(conn);	list_del_init(&cmnd->list);	set_cork(cmnd->conn->sock, 0);}/** * Push the command for execution. * This functions reorders the commands. * Called from the read thread. * * iscsi_session_push_cmnd -  * @cmnd: ptr to command */static void iscsi_session_push_cmnd(struct iscsi_cmnd *cmnd){	struct iscsi_session *session = cmnd->conn->session;	struct list_head *entry;	u32 cmd_sn;	dprintk(D_GENERIC, "%p:%x %u,%u\n",		cmnd, cmnd_opcode(cmnd), cmnd->pdu.bhs.sn, session->exp_cmd_sn);	if (cmnd->pdu.bhs.opcode & ISCSI_OP_IMMEDIATE) {		iscsi_cmnd_exec(cmnd);		return;	}	cmd_sn = cmnd->pdu.bhs.sn;	if (cmd_sn == session->exp_cmd_sn) {		while (1) {			session->exp_cmd_sn = ++cmd_sn;			iscsi_cmnd_exec(cmnd);			if (list_empty(&session->pending_list))				break;			cmnd = list_entry(session->pending_list.next, struct iscsi_cmnd, list);			if (cmnd->pdu.bhs.sn != cmd_sn)				break;/* 			eprintk("find out-of-order %x %u %u\n", *//* 				cmnd_itt(cmnd), cmd_sn, cmnd->pdu.bhs.sn); */			list_del_init(&cmnd->list);			clear_cmnd_pending(cmnd);		}	} else {/* 		eprintk("out-of-order %x %u %u\n", *//* 			cmnd_itt(cmnd), cmd_sn, session->exp_cmd_sn); */		set_cmnd_pending(cmnd);		if (before(cmd_sn, session->exp_cmd_sn)) /* close the conn */			eprintk("unexpected cmd_sn (%u,%u)\n", cmd_sn, session->exp_cmd_sn);		if (after(cmd_sn, session->exp_cmd_sn + session->max_queued_cmnds))			eprintk("too large cmd_sn (%u,%u)\n", cmd_sn, session->exp_cmd_sn);		list_for_each(entry, &session->pending_list) {			struct iscsi_cmnd *tmp = list_entry(entry, struct iscsi_cmnd, list);			if (before(cmd_sn, tmp->pdu.bhs.sn))				break;		}		assert(list_empty(&cmnd->list));		list_add_tail(&cmnd->list, entry);	}}static int check_segment_length(struct iscsi_cmnd *cmnd){	struct iscsi_conn *conn = cmnd->conn;	struct iscsi_sess_param *param = &conn->session->param;	if (cmnd->pdu.datasize > param->max_recv_data_length) {		eprintk("too lond data %x %u %u\n", cmnd_itt(cmnd),			cmnd->pdu.datasize, param->max_recv_data_length);		if (get_pgcnt(cmnd->pdu.datasize, 0) > ISCSI_CONN_IOV_MAX) {			conn_close(conn);			return -EINVAL;		}	}	return 0;}void cmnd_rx_start(struct iscsi_cmnd *cmnd){	struct iscsi_conn *conn = cmnd->conn;	int err = 0;	iscsi_dump_pdu(&cmnd->pdu);	if (check_segment_length(cmnd) < 0)		return;	switch (cmnd_opcode(cmnd)) {	case ISCSI_OP_NOOP_OUT:		err = noop_out_start(conn, cmnd);		break;	case ISCSI_OP_SCSI_CMD:		if (!(err = cmnd_insert_hash(cmnd)))			scsi_cmnd_start(conn, cmnd);		break;	case ISCSI_OP_SCSI_TASK_MGT_MSG:		err = cmnd_insert_hash(cmnd);		break;	case ISCSI_OP_SCSI_DATA_OUT:		data_out_start(conn, cmnd);		break;	case ISCSI_OP_LOGOUT_CMD:		err = cmnd_insert_hash(cmnd);		break;	case ISCSI_OP_TEXT_CMD:	case ISCSI_OP_SNACK_CMD:		err = -ISCSI_REASON_UNSUPPORTED_COMMAND;		break;	default:		err = -ISCSI_REASON_UNSUPPORTED_COMMAND;		break;	}	if (err < 0) {		eprintk("%x %x %d\n", cmnd_opcode(cmnd), cmnd_itt(cmnd), err);		iscsi_cmnd_reject(cmnd, -err);	}}void cmnd_rx_end(struct iscsi_cmnd *cmnd){	struct iscsi_conn *conn = cmnd->conn;	dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd));	switch (cmnd_opcode(cmnd)) {	case ISCSI_OP_SCSI_REJECT:	case ISCSI_OP_NOOP_OUT:	case ISCSI_OP_SCSI_CMD:	case ISCSI_OP_SCSI_TASK_MGT_MSG:	case ISCSI_OP_TEXT_CMD:	case ISCSI_OP_LOGOUT_CMD:		iscsi_session_push_cmnd(cmnd);		break;	case ISCSI_OP_SCSI_DATA_OUT:		data_out_end(conn, cmnd);		break;	case ISCSI_OP_SNACK_CMD:		break;	case ISCSI_OP_PDU_REJECT:		iscsi_cmnd_init_write(get_rsp_cmnd(cmnd));		break;	case ISCSI_OP_DATA_REJECT:		cmnd_release(cmnd, 0);		break;	default:		eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd));		BUG();		break;	}}static void iscsi_exit(void){	unregister_chrdev(ctr_major, ctr_name);	iet_procfs_exit();	event_exit();	tio_exit();	iotype_exit();	if (iscsi_cmnd_cache)		kmem_cache_destroy(iscsi_cmnd_cache);}static int iscsi_init(void){	int err = -ENOMEM;	printk("iSCSI Enterprise Target Software - version %s\n", IET_VERSION_STRING);	if ((ctr_major = register_chrdev(0, ctr_name, &ctr_fops)) < 0) {		eprintk("failed to register the control device %d\n", ctr_major);		return ctr_major;	}	if ((err = iet_procfs_init()) < 0)		goto err;	if ((err = event_init()) < 0)		goto err;	iscsi_cmnd_cache = kmem_cache_create("iscsi_cmnd", sizeof(struct iscsi_cmnd),					     0, 0, NULL, NULL);	if (!iscsi_cmnd_cache)		goto err;	if ((err = tio_init()) < 0)		goto err;	if ((err = iotype_init()) < 0)		goto err;	return 0;err:	iscsi_exit();	return err;}module_param(debug_enable_flags, ulong, S_IRUGO);module_init(iscsi_init);module_exit(iscsi_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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