List, This patch adds support for passthrough devices to tgtd. Please review/apply. >From 7b9518e0cd6ad4b2051c0bdbba2f5ea4aca324d0 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg <ronniesahlberg at gmail.com> Date: Mon, 18 Aug 2008 15:59:59 +1000 Subject: [PATCH] add support for passthrough luns Signed-off-by: Ronnie Sahlberg <ronniesahlberg at gmail.com> --- usr/Makefile | 7 +- usr/bs_pt.c | 90 ++++++++++++++++++++++++++ usr/pt.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ usr/target.c | 9 +-- usr/tgtd.h | 2 +- 5 files changed, 298 insertions(+), 9 deletions(-) create mode 100644 usr/bs_pt.c create mode 100644 usr/pt.c diff --git a/usr/Makefile b/usr/Makefile index 4245709..b7c7517 100644 --- a/usr/Makefile +++ b/usr/Makefile @@ -11,7 +11,7 @@ CFLAGS += -DISCSI TGTD_OBJS += $(addprefix iscsi/, conn.o param.o session.o \ iscsid.o target.o chap.o transport.o iscsi_tcp.o \ isns.o libcrc32c.o) -TGTD_OBJS += bs_rdwr.o bs_aio.o +TGTD_OBJS += bs_rdwr.o bs_aio.o bs_pt.o LIBS += -lcrypto ifneq ($(ISCSI_RDMA),) @@ -43,7 +43,7 @@ TGTD_OBJS += $(addprefix fcoe/,\ fcoe_if.o fcoe_dev.o \ sa_event.o sa_timer.o sa_hash_kern.o sa_state.o\ crc32_le.o crc32_le_tab.o) -TGTD_OBJS += bs_rdwr.o +TGTD_OBJS += bs_rdwr.o bs_pt.o endif INCLUDES += -I. -I../include -I$(KERNELSRC)/include @@ -57,7 +57,8 @@ LIBS += -lpthread PROGRAMS += tgtd tgtadm SCRIPTS += ../scripts/tgt-setup-lun TGTD_OBJS += tgtd.o mgmt.o target.o scsi.o log.o driver.o util.o work.o \ - parser.o spc.o sbc.o mmc.o osd.o scc.o smc.o ssc.o bs_ssc.o bs.o + parser.o spc.o sbc.o mmc.o osd.o pt.o scc.o \ + smc.o ssc.o bs_ssc.o bs.o MANPAGES = ../doc/manpages/tgtadm.8 ../doc/manpages/tgt-setup-lun.8 TGTD_DEP = $(TGTD_OBJS:.o=.d) diff --git a/usr/bs_pt.c b/usr/bs_pt.c new file mode 100644 index 0000000..299ba2c --- /dev/null +++ b/usr/bs_pt.c @@ -0,0 +1,90 @@ +/* + * Backing store for passthrough devices + * + * Copyright (C) 2008 Ronnie Sahlberg <ronniesahlberg at gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +#define _XOPEN_SOURCE 500 + +#include <errno.h> +#include <fcntl.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <linux/fs.h> +#include <sys/epoll.h> +#include <sys/ioctl.h> +#include <scsi/sg.h> + +#include "list.h" +#include "util.h" +#include "tgtd.h" +#include "scsi.h" +#include "bs_thread.h" + + + +static int open_scsi_device(const char *dev) +{ + int fd, vers; + + fd = open(dev, O_RDWR); + if (fd < 0) { + dprintf("ERROR could not open device %s\n", dev); + return -1; + } + if ((ioctl(fd, SG_GET_VERSION_NUM, &vers) < 0) || (vers < 30000)) { + dprintf("/dev is not an sg device, or old sg driver\n"); + close(fd); + return -1; + } + + return fd; +} + + +static int bs_passthrough_open(struct scsi_lu *lu, char *path, int *fd, + uint64_t *size) +{ + *fd = open_scsi_device(path); + + return 0; +} + +static void bs_passthrough_close(struct scsi_lu *lu) +{ + close(lu->fd); +} + +static int bs_passthrough_cmd_done(struct scsi_cmd *cmd) +{ + return 0; +} + +static struct backingstore_template passthrough_bst = { + .bs_name = "pt", + .bs_open = bs_passthrough_open, + .bs_close = bs_passthrough_close, +}; + +__attribute__((constructor)) static void bs_passthrough_constructor(void) +{ + register_backingstore_template(&passthrough_bst); +} diff --git a/usr/pt.c b/usr/pt.c new file mode 100644 index 0000000..480b4d7 --- /dev/null +++ b/usr/pt.c @@ -0,0 +1,199 @@ +/* + * SCSI passthrough module + * + * Copyright (C) 2008 Ronnie Sahlberg <ronniesahlberg at gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <unistd.h> +#include <linux/fs.h> +#include <sys/stat.h> + +#include "list.h" +#include "util.h" +#include "tgtd.h" +#include <fcntl.h> +#include "target.h" +#include "tgtadm_error.h" +#include "driver.h" +#include "scsi.h" +#include "spc.h" +#include "tgtadm_error.h" +#include <sys/ioctl.h> +#include <scsi/sg.h> + + +static unsigned char scsi_command_size[8] = {6, 10, 10, 12, 16, 12, 10, 10}; + +#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7] +#define CDB_SIZE(cmd) (((((cmd)->scb[0] >> 5) & 7) < 6) ? \ + COMMAND_SIZE((cmd)->scb[0]) : (cmd)->scb_len) + +#define SCSI_TIMEOUT 5000 /* ms */ + + +int scsi_io(int fd, unsigned char *cdb, unsigned char cdb_size, + int xfer_dir, unsigned char *data, int *data_size, + unsigned char *sense, unsigned int *sense_len) +{ + sg_io_hdr_t io_hdr; + + memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); + io_hdr.interface_id = 'S'; + + /* CDB */ + io_hdr.cmdp = cdb; + io_hdr.cmd_len = cdb_size; + + /* Where to store the sense_data, if there was an error */ + io_hdr.sbp = sense; + io_hdr.mx_sb_len = *sense_len; + *sense_len = 0; + + /* Transfer direction, either in or out. Linux does not yet + support bidirectional SCSI transfers ? + */ + io_hdr.dxfer_direction = xfer_dir; + + /* Where to store the DATA IN/OUT from the device and how big the + buffer is + */ + io_hdr.dxferp = data; + io_hdr.dxfer_len = *data_size; + + /* SCSI timeout in ms */ + io_hdr.timeout = SCSI_TIMEOUT; + + + if (ioctl(fd, SG_IO, &io_hdr) < 0) + return -1; + + /* now for the error processing */ + if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) { + if (io_hdr.sb_len_wr > 0) { + *sense_len = io_hdr.sb_len_wr; + return 0; + } + } + if (io_hdr.masked_status) + return -2; + + if (io_hdr.host_status) + return -3; + + if (io_hdr.driver_status) + return -4; + + return 0; +} + + + + +static int scsi_passthrough(int host_no, struct scsi_cmd *cmd) +{ + unsigned int sense_len = 32; + unsigned char sense[sense_len]; + int alloc_len; + uint8_t *data; + int direction; + + alloc_len = scsi_get_in_length(cmd); + if (alloc_len > 0) { + direction = SG_DXFER_FROM_DEV; + data = scsi_get_in_buffer(cmd); + } else { + alloc_len = scsi_get_out_length(cmd); + if (alloc_len > 0) { + direction = SG_DXFER_TO_DEV; + data = scsi_get_out_buffer(cmd); + } else { + direction = SG_DXFER_NONE; + data = NULL; + } + } + + scsi_io(cmd->dev->fd, + cmd->scb, + COMMAND_SIZE(cmd->scb[0]), + direction, + data, &alloc_len, sense, &sense_len); + if (sense_len) { + scsi_set_in_resid_by_actual(cmd, 0); + sense_data_build(cmd, sense[2], sense[12]<<8); + return SAM_STAT_CHECK_CONDITION; + } + + if (direction == SG_DXFER_FROM_DEV) + scsi_set_in_resid_by_actual(cmd, alloc_len); + + return SAM_STAT_GOOD; +} + +static int passthrough_lu_init(struct scsi_lu *lu) +{ + struct backingstore_template *bst; + + /* passthrough devices always use passthrough backingstore */ + bst = get_backingstore_template("pt"); + if (!bst) { + eprintf("failed to find bstype, pt\n"); + return TGTADM_INVALID_REQUEST; + } + lu->bst = bst; + + lu->attrs.device_type = TYPE_SPT; + + return 0; +} + +static int passthrough_lu_online(struct scsi_lu *lu) +{ + lu->attrs.online = 1; + + return 0; +} + +static int passthrough_lu_offline(struct scsi_lu *lu) +{ + lu->attrs.online = 0; + return 0; +} + +static struct device_type_template passthrough_template = { + .type = TYPE_SPT, + .lu_init = passthrough_lu_init, + .lu_config = spc_lu_config, + .lu_online = passthrough_lu_online, + .lu_offline = passthrough_lu_offline, + .lu_exit = spc_lu_exit, + .ops = { + [0x00 ... 0x9F] = {scsi_passthrough,}, + /* 0xA0 */ + {spc_report_luns,}, + [0xA1 ... 0xFF] = {scsi_passthrough,}, + } +}; + +__attribute__((constructor)) static void passthrough_init(void) +{ + device_type_register(&passthrough_template); +} diff --git a/usr/target.c b/usr/target.c index 70bf72a..e200471 100644 --- a/usr/target.c +++ b/usr/target.c @@ -1524,21 +1524,20 @@ static struct { {TYPE_ENCLOSURE, "enclosure"}, {TYPE_RBC, "rbc"}, {TYPE_OSD, "osd"}, - {TYPE_NO_LUN, "No LUN"} + {TYPE_NO_LUN, "No LUN"}, + {TYPE_SPT, "passthrough"} }; static char *print_type(int type) { int i; - char *name = NULL; for (i = 0; i < ARRAY_SIZE(disk_type_names); i++) { if (disk_type_names[i].value == type) { - name = disk_type_names[i].name; - break; + return disk_type_names[i].name; } } - return name; + return "Unknown type"; } diff --git a/usr/tgtd.h b/usr/tgtd.h index 4febcd3..a649129 100644 --- a/usr/tgtd.h +++ b/usr/tgtd.h @@ -60,7 +60,7 @@ struct lu_phy_attr { uint16_t version_desc[VERSION_DESCRIPTOR_LEN]; - char device_type; /* Peripheral device type */ + unsigned char device_type;/* Peripheral device type */ char qualifier; /* Peripheral Qualifier */ char removable; /* Removable media */ char online; /* Logical Unit online */ -- 1.5.5 -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-add-support-for-passthrough-luns.patch.gz Type: application/x-gzip Size: 3540 bytes Desc: not available URL: <http://lists.wpkg.org/pipermail/stgt/attachments/20080818/dfe964c2/attachment.bin> |