>From 1f3a05b2c58c40a60c733174af907dcb266fa217 Mon Sep 17 00:00:00 2001
From: Ronnie Sahlberg <[EMAIL PROTECTED]>
Date: Sat, 2 Aug 2008 13:44:12 +1000
Subject: [PATCH] Add the file for the backend and the file for the device type

Signed-off-by: Ronnie Sahlberg <[EMAIL PROTECTED]>
---
 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 <[EMAIL PROTECTED]>
+ *
+ * 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 <[EMAIL PROTECTED]>
+ *
+ * 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

Attachment: 0002-Add-the-file-for-the-backend-and-the-file-for-the-de.patch.gz
Description: GNU Zip compressed data

_______________________________________________
Stgt-devel mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/stgt-devel

Reply via email to