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

📄 target_disk.c

📁 iscsi企业级target.很好用
💻 C
字号:
/* * (C) 2004 - 2005 FUJITA Tomonori <tomof@acm.org> * This code is licenced under the GPL. * * heavily based on code from kernel/iscsi.c: *   Copyright (C) 2002-2003 Ardis Technolgies <roman@ardistech.com>, *   licensed under the terms of the GNU GPL v2.0, */#include <scsi/scsi.h>#include "iscsi.h"#include "iscsi_dbg.h"static int insert_disconnect_pg(u8 *ptr){	unsigned char disconnect_pg[] = {0x02, 0x0e, 0x80, 0x80, 0x00, 0x0a, 0x00, 0x00,                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};	memcpy(ptr, disconnect_pg, sizeof(disconnect_pg));	return sizeof(disconnect_pg);}static int insert_caching_pg(u8 *ptr){	unsigned char caching_pg[] = {0x08, 0x12, 0x14, 0x00, 0xff, 0xff, 0x00, 0x00,				      0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0x00, 0x00,				      0x00, 0x00, 0x00, 0x00};	memcpy(ptr, caching_pg, sizeof(caching_pg));	return sizeof(caching_pg);}static int insert_ctrl_m_pg(u8 *ptr){	unsigned char ctrl_m_pg[] = {0x0a, 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,				     0x00, 0x00, 0x02, 0x4b};	memcpy(ptr, ctrl_m_pg, sizeof(ctrl_m_pg));	return sizeof(ctrl_m_pg);}static int insert_iec_m_pg(u8 *ptr){	unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0x00, 0x00, 0x00, 0x00,				    0x00, 0x00, 0x00, 0x00, 0x00};	memcpy(ptr, iec_m_pg, sizeof(iec_m_pg));	return sizeof(iec_m_pg);}static int insert_format_m_pg(u8 *ptr){	unsigned char format_m_pg[] = {0x03, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,				       0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,				       0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00};	memcpy(ptr, format_m_pg, sizeof(format_m_pg));	return sizeof(format_m_pg);}static int insert_geo_m_pg(u8 *ptr, u64 sec){	unsigned char geo_m_pg[] = {0x04, 0x16, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,				    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,				    0x00, 0x00, 0x00, 0x00, 0x3a, 0x98, 0x00, 0x00};	u32 ncyl, *p;	/* assume 0xff heads, 15krpm. */	memcpy(ptr, geo_m_pg, sizeof(geo_m_pg));	ncyl = sec >> 14; /* 256 * 64 */	p = (u32 *)(ptr + 1);	*p = *p | cpu_to_be32(ncyl);	return sizeof(geo_m_pg);}static int build_mode_sense_response(struct iscsi_cmnd *cmnd){	struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd);	struct tio *tio = cmnd->tio;	u8 *data, *scb = req->scb;	int len = 4, err = 0;	u8 pcode;	pcode = req->scb[2] & 0x3f;	assert(!tio);	tio = cmnd->tio = tio_alloc(1);	data = page_address(tio->pvec[0]);	assert(data);	clear_page(data);	if ((scb[1] & 0x8))		data[3] = 0;	else {		data[3] = 8;		len += 8;		*(u32 *)(data + 4) = (cmnd->lun->blk_cnt >> 32) ?			cpu_to_be32(0xffffffff) : cpu_to_be32(cmnd->lun->blk_cnt);		*(u32 *)(data + 8) = cpu_to_be32(1 << cmnd->lun->blk_shift);	}	switch (pcode) {	case 0x0:		break;	case 0x2:		len += insert_disconnect_pg(data + len);		break;	case 0x3:		len += insert_format_m_pg(data + len);		break;	case 0x4:		len += insert_geo_m_pg(data + len, cmnd->lun->blk_cnt);		break;	case 0x8:		len += insert_caching_pg(data + len);		break;	case 0xa:		len += insert_ctrl_m_pg(data + len);		break;	case 0x1c:		len += insert_iec_m_pg(data + len);		break;	case 0x3f:		len += insert_disconnect_pg(data + len);		len += insert_format_m_pg(data + len);		len += insert_geo_m_pg(data + len, cmnd->lun->blk_cnt);		len += insert_caching_pg(data + len);		len += insert_ctrl_m_pg(data + len);		len += insert_iec_m_pg(data + len);		break;	default:		err = -1;	}	data[0] = len - 1;	tio_set(tio, len, 0);	return err;}static int build_inquiry_response(struct iscsi_cmnd *cmnd){	struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd);	struct tio *tio = cmnd->tio;	u8 *data;	u8 *scb = req->scb;	int err = -1;	if (((req->scb[1] & 0x3) == 0x3) || (!(req->scb[1] & 0x3) && req->scb[2]))		return err;	assert(!tio);	tio = cmnd->tio = tio_alloc(1);	data = page_address(tio->pvec[0]);	assert(data);	clear_page(data);	if (!(scb[1] & 0x3)) {		data[2] = 4;		data[3] = 0x42;		data[4] = 59;		data[7] = 0x02;		memset(data + 8, 0x20, 28);		memcpy(data + 8,		       VENDOR_ID, min_t(size_t, strlen(VENDOR_ID), 8));		memcpy(data + 16,		       PRODUCT_ID, min_t(size_t, strlen(PRODUCT_ID), 16));		memcpy(data + 32,		       PRODUCT_REV, min_t(size_t, strlen(PRODUCT_REV), 4));		data[58] = 0x03;		data[59] = 0x20;		data[60] = 0x09;		data[61] = 0x60;		data[62] = 0x03;		data[63] = 0x00;		tio_set(tio, 64, 0);		err = 0;	} else if (scb[1] & 0x2) {		/* CmdDt bit is set */		/* We do not support it now. */		data[1] = 0x1;		data[5] = 0;		tio_set(tio, 6, 0);		err = 0;	} else if (scb[1] & 0x1) {		/* EVPD bit set */		if (scb[2] == 0x0) {			data[1] = 0x0;			data[3] = 3;			data[4] = 0x0;			data[5] = 0x80;			data[6] = 0x83;			tio_set(tio, 7, 0);			err = 0;		} else if (scb[2] == 0x80) {			data[1] = 0x80;			data[3] = 4;			memset(data + 4, 0x20, 4);			tio_set(tio, 8, 0);			err = 0;		} else if (scb[2] == 0x83) {			u32 len = SCSI_ID_LEN * sizeof(u8);			data[1] = 0x83;			data[3] = len + 4;			data[4] = 0x1;			data[5] = 0x1;			data[7] = len;			if (cmnd->lun) /* We need this ? */				memcpy(data + 8, cmnd->lun->scsi_id, len);			tio_set(tio, len + 8, 0);			err = 0;		}	}	tio_set(tio, min_t(u8, tio->size, scb[4]), 0);	if (!cmnd->lun)		data[0] = TYPE_NO_LUN;	return err;}static int build_report_luns_response(struct iscsi_cmnd *cmnd){	struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd);	struct tio *tio = cmnd->tio;	u32 *data, size, len;	struct iet_volume *lun;	int rest, idx = 0;	size = be32_to_cpu(*(u32 *)&req->scb[6]);	if (size < 16)		return -1;	len = atomic_read(&cmnd->conn->session->target->nr_volumes) * 8;	size = min(size & ~(8 - 1), len + 8);	assert(!tio);	tio = cmnd->tio = tio_alloc(get_pgcnt(size, 0));	tio_set(tio, size, 0);	data = page_address(tio->pvec[idx]);	assert(data);	*data++ = cpu_to_be32(len);	*data++ = 0;	size -= 8;	rest = PAGE_CACHE_SIZE - 8;	list_for_each_entry(lun, &cmnd->conn->session->target->volumes, list) {		if (lun->l_state != IDEV_RUNNING)			continue;		*data++ = cpu_to_be32((0x3ff & lun->lun) << 16 |				      ((lun->lun > 0xff) ? (0x1 << 30) : 0));		*data++ = 0;		if ((size -= 8) == 0)			break;		if ((rest -= 8) == 0) {			idx++;			data = page_address(tio->pvec[idx]);			rest = PAGE_CACHE_SIZE;		}	}	return 0;}static int build_read_capacity_response(struct iscsi_cmnd *cmnd){	struct tio *tio = cmnd->tio;	u32 *data;	assert(!tio);	tio = cmnd->tio = tio_alloc(1);	data = page_address(tio->pvec[0]);	assert(data);	clear_page(data);	data[0] = (cmnd->lun->blk_cnt >> 32) ?		cpu_to_be32(0xffffffff) : cpu_to_be32(cmnd->lun->blk_cnt - 1);	data[1] = cpu_to_be32(1U << cmnd->lun->blk_shift);	tio_set(tio, 8, 0);	return 0;}static int build_request_sense_response(struct iscsi_cmnd *cmnd){	struct tio *tio = cmnd->tio;	u8 *data;	assert(!tio);	tio = cmnd->tio = tio_alloc(1);	data = page_address(tio->pvec[0]);	assert(data);	memset(data, 0, 18);	data[0] = 0xf0;	data[1] = 0;	data[2] = NO_SENSE;	data[7] = 10;	tio_set(tio, 18, 0);	return 0;}static int build_sevice_action_response(struct iscsi_cmnd *cmnd){	struct tio *tio = cmnd->tio;	u32 *data;	u64 *data64;/* 	assert((req->scb[1] & 0x1f) == 0x10); */	assert(!tio);	tio = cmnd->tio = tio_alloc(1);	data = page_address(tio->pvec[0]);	assert(data);	clear_page(data);	data64 = (u64*) data;	data64[0] = cpu_to_be64(cmnd->lun->blk_cnt - 1);	data[2] = cpu_to_be32(1UL << cmnd->lun->blk_shift);	tio_set(tio, 32, 0);	return 0;}static int build_read_response(struct iscsi_cmnd *cmnd){	struct tio *tio = cmnd->tio;	assert(tio);	assert(cmnd->lun);	tio_read(cmnd->lun, tio);	return 0;}static int build_write_response(struct iscsi_cmnd *cmnd){	struct tio *tio = cmnd->tio;	assert(cmnd);	assert(tio);	assert(cmnd->lun);	list_del_init(&cmnd->list);	tio_write(cmnd->lun, tio);	tio_sync(cmnd->lun, tio);	return 0;}static int build_generic_response(struct iscsi_cmnd *cmnd){	return 0;}static int disk_execute_cmnd(struct iscsi_cmnd *cmnd){	struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd);	req->opcode &= ISCSI_OPCODE_MASK;	switch (req->scb[0]) {	case INQUIRY:		send_data_rsp(cmnd, build_inquiry_response);		break;	case REPORT_LUNS:		send_data_rsp(cmnd, build_report_luns_response);		break;	case READ_CAPACITY:		send_data_rsp(cmnd, build_read_capacity_response);		break;	case MODE_SENSE:		send_data_rsp(cmnd, build_mode_sense_response);		break;	case REQUEST_SENSE:		send_data_rsp(cmnd, build_request_sense_response);		break;	case SERVICE_ACTION_IN:		send_data_rsp(cmnd, build_sevice_action_response);		break;	case READ_6:	case READ_10:	case READ_16:		send_data_rsp(cmnd, build_read_response);		break;	case WRITE_6:	case WRITE_10:	case WRITE_16:	case WRITE_VERIFY:		send_scsi_rsp(cmnd, build_write_response);		break;	case START_STOP:	case TEST_UNIT_READY:	case SYNCHRONIZE_CACHE:	case VERIFY:	case VERIFY_16:	case RESERVE:	case RELEASE:	case RESERVE_10:	case RELEASE_10:		send_scsi_rsp(cmnd, build_generic_response);		break;	default:		eprintk("%s\n", "we should not come here!");		break;	}	return 0;}struct target_type disk_ops ={	.id = 0,	.execute_cmnd = disk_execute_cmnd,};

⌨️ 快捷键说明

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