Signed-off-by: Ronnie Sahlberg <ronniesahlberg at gmail.com> --- usr/bs_passthrough.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++ usr/passthrough.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 399 insertions(+), 0 deletions(-) create mode 100644 usr/bs_passthrough.c create mode 100644 usr/passthrough.c diff --git a/usr/bs_passthrough.c b/usr/bs_passthrough.c new file mode 100644 index 0000000..9b7487a --- /dev/null +++ b/usr/bs_passthrough.c @@ -0,0 +1,200 @@ +/* + * 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 void set_medium_error(int *result, uint8_t *key, uint16_t *asc) +{ + *result = SAM_STAT_CHECK_CONDITION; + *key = MEDIUM_ERROR; + *asc = ASC_READ_ERROR; +} + +static void bs_sync_sync_range(struct scsi_cmd *cmd, uint32_t length, + int *result, uint8_t *key, uint16_t *asc) +{ + int ret; + unsigned int flags = SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE; + + ret = __sync_file_range(cmd->dev->fd, cmd->offset, length, flags); + if (ret) + set_medium_error(result, key, asc); +} + +static void bs_rdwr_request(struct scsi_cmd *cmd) +{ + int ret, fd = cmd->dev->fd; + uint32_t length; + int result = SAM_STAT_GOOD; + uint8_t key; + uint16_t asc; + + ret = 0; + length = 0; + key = 0; + asc = 0; + + switch (cmd->scb[0]) { + case SYNCHRONIZE_CACHE: + case SYNCHRONIZE_CACHE_16: + /* TODO */ + length = (cmd->scb[0] == SYNCHRONIZE_CACHE) ? 0 : 0; + + if (cmd->scb[1] & 0x2) { + result = SAM_STAT_CHECK_CONDITION; + key = ILLEGAL_REQUEST; + asc = ASC_INVALID_FIELD_IN_CDB; + } else + bs_sync_sync_range(cmd, length, &result, &key, &asc); + break; + case WRITE_6: + case WRITE_10: + case WRITE_12: + case WRITE_16: + length = scsi_get_out_length(cmd); + ret = pwrite64(fd, scsi_get_out_buffer(cmd), length, + cmd->offset); + if (ret == length) { + /* + * it would be better not to access to pg + * directy. + */ + struct mode_pg *pg = cmd->dev->mode_pgs[0x8]; + + if (((cmd->scb[0] != WRITE_6) && (cmd->scb[1] & 0x8)) || + !(pg->mode_data[0] & 0x04)) + bs_sync_sync_range(cmd, length, &result, &key, + &asc); + } else + set_medium_error(&result, &key, &asc); + + break; + case READ_6: + case READ_10: + case READ_12: + case READ_16: + length = scsi_get_in_length(cmd); + ret = pread64(fd, scsi_get_in_buffer(cmd), length, + cmd->offset); + + if (ret != length) + set_medium_error(&result, &key, &asc); + break; + default: + break; + } + + dprintf("io done %p %x %d %u\n", cmd, cmd->scb[0], ret, length); + + scsi_set_result(cmd, result); + + if (result != SAM_STAT_GOOD) { + eprintf("io error %p %x %d %d %" PRIu64 ", %m\n", + cmd, cmd->scb[0], ret, length, cmd->offset); + sense_data_build(cmd, key, asc); + } +} + +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) +{ + int ret; + struct bs_thread_info *info = BS_THREAD_I(lu); + + *fd = open_scsi_device(path); + if (*fd < 0) + return *fd; + + ret = bs_thread_open(info, bs_rdwr_request); + if (ret) { + close(*fd); + return -1; + } + if (size) + *size = 0; + + return 0; +} + +static void bs_passthrough_close(struct scsi_lu *lu) +{ + struct bs_thread_info *info = BS_THREAD_I(lu); + + bs_thread_close(info); + + close(lu->fd); +} + +static int bs_passthrough_cmd_done(struct scsi_cmd *cmd) +{ + return 0; +} + +static struct backingstore_template passthrough_bst = { + .bs_name = "passthrough", + .bs_datasize = sizeof(struct bs_thread_info), + .bs_open = bs_passthrough_open, + .bs_close = bs_passthrough_close, + .bs_cmd_submit = bs_thread_cmd_submit, + .bs_cmd_done = bs_passthrough_cmd_done, +}; + +__attribute__((constructor)) static void bs_passthrough_constructor(void) +{ + register_backingstore_template(&passthrough_bst); +} diff --git a/usr/passthrough.c b/usr/passthrough.c new file mode 100644 index 0000000..3f9350f --- /dev/null +++ b/usr/passthrough.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("passthrough"); + if (!bst) { + eprintf("failed to find bstype, passthrough\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); +} -- 1.5.5 ------=_Part_14243_33234650.1217649510936 Content-Type: application/x-gzip; name=0002-Add-the-file-for-the-backend-and-the-file-for-the-de.patch.gz Content-Transfer-Encoding: base64 X-Attachment-Id: f_fjdovylq0 Content-Disposition: attachment; filename=0002-Add-the-file-for-the-backend-and-the-file-for-the-de.patch.gz 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 cvnfo4A6wuQoAAA= ------=_Part_14243_33234650.1217649510936-- |