2012-06-04 14:42:41 +02:00
|
|
|
diff --git a/usr/sbc.c b/usr/sbc.c
|
|
|
|
index cf2b609..248a547 100644
|
|
|
|
--- a/usr/sbc.c
|
|
|
|
+++ b/usr/sbc.c
|
|
|
|
@@ -23,6 +23,9 @@
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
|
|
* 02110-1301 USA
|
|
|
|
*/
|
|
|
|
+#define _FILE_OFFSET_BITS 64
|
|
|
|
+#define __USE_GNU
|
|
|
|
+
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
@@ -30,6 +33,7 @@
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <linux/fs.h>
|
|
|
|
+#include <sys/types.h>
|
2008-09-15 12:24:44 +02:00
|
|
|
|
2012-06-04 14:42:41 +02:00
|
|
|
#include "list.h"
|
|
|
|
#include "util.h"
|
|
|
|
@@ -45,6 +49,23 @@
|
2008-10-09 19:03:54 +02:00
|
|
|
|
2012-06-04 14:42:41 +02:00
|
|
|
static unsigned int blk_shift = DEFAULT_BLK_SHIFT;
|
2008-10-09 19:03:54 +02:00
|
|
|
|
2012-06-04 14:42:41 +02:00
|
|
|
+static off_t find_next_data(struct scsi_lu *dev, off_t offset)
|
2008-10-09 19:03:54 +02:00
|
|
|
+{
|
2012-06-04 14:42:41 +02:00
|
|
|
+#ifdef SEEK_DATA
|
|
|
|
+ return lseek64(dev->fd, offset, SEEK_DATA);
|
|
|
|
+#else
|
|
|
|
+ return offset;
|
|
|
|
+#endif
|
2008-09-15 12:24:44 +02:00
|
|
|
+}
|
2012-06-04 14:42:41 +02:00
|
|
|
+static off_t find_next_hole(struct scsi_lu *dev, off_t offset)
|
2008-10-09 19:03:54 +02:00
|
|
|
+{
|
2012-06-04 14:42:41 +02:00
|
|
|
+#ifdef SEEK_HOLE
|
|
|
|
+ return lseek64(dev->fd, offset, SEEK_HOLE);
|
|
|
|
+#else
|
|
|
|
+ return dev->size;
|
|
|
|
+#endif
|
2008-09-15 12:24:44 +02:00
|
|
|
+}
|
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
static int sbc_mode_page_update(struct scsi_cmd *cmd, uint8_t *data, int *changed)
|
2008-10-09 19:03:54 +02:00
|
|
|
{
|
2012-06-04 14:42:41 +02:00
|
|
|
uint8_t pcode = data[0] & 0x3f;
|
|
|
|
@@ -281,10 +302,18 @@ static int sbc_rw(int host_no, struct scsi_cmd *cmd)
|
|
|
|
|
|
|
|
/* Verify that we are not doing i/o beyond
|
|
|
|
the end-of-lun */
|
|
|
|
- if (tl && (lba + tl > lu->size)) {
|
|
|
|
- key = ILLEGAL_REQUEST;
|
|
|
|
- asc = ASC_LBA_OUT_OF_RANGE;
|
|
|
|
- goto sense;
|
|
|
|
+ if (tl) {
|
|
|
|
+ if (lba + tl > lu->size) {
|
|
|
|
+ key = ILLEGAL_REQUEST;
|
|
|
|
+ asc = ASC_LBA_OUT_OF_RANGE;
|
|
|
|
+ goto sense;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ if (lba >= lu->size) {
|
|
|
|
+ key = ILLEGAL_REQUEST;
|
|
|
|
+ asc = ASC_LBA_OUT_OF_RANGE;
|
|
|
|
+ goto sense;
|
|
|
|
+ }
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd->offset = lba;
|
|
|
|
@@ -421,7 +450,7 @@ sense:
|
|
|
|
return SAM_STAT_CHECK_CONDITION;
|
2008-09-15 12:24:44 +02:00
|
|
|
}
|
|
|
|
|
2012-06-04 14:42:41 +02:00
|
|
|
-static int sbc_service_action(int host_no, struct scsi_cmd *cmd)
|
|
|
|
+static int sbc_readcapacity16(int host_no, struct scsi_cmd *cmd)
|
2008-10-09 19:03:54 +02:00
|
|
|
{
|
2012-06-04 14:42:41 +02:00
|
|
|
uint32_t *data;
|
|
|
|
unsigned int bshift;
|
|
|
|
@@ -437,9 +466,6 @@ static int sbc_service_action(int host_no, struct scsi_cmd *cmd)
|
|
|
|
goto sense;
|
2008-10-09 19:03:54 +02:00
|
|
|
}
|
2008-09-15 12:24:44 +02:00
|
|
|
|
2012-06-04 14:42:41 +02:00
|
|
|
- if (cmd->scb[1] != SAI_READ_CAPACITY_16)
|
|
|
|
- goto sense;
|
|
|
|
-
|
|
|
|
if (scsi_get_in_length(cmd) < 12)
|
|
|
|
goto overflow;
|
2008-09-15 12:24:44 +02:00
|
|
|
|
2012-06-04 14:42:41 +02:00
|
|
|
@@ -468,6 +494,106 @@ sense:
|
|
|
|
return SAM_STAT_CHECK_CONDITION;
|
2008-10-09 19:03:54 +02:00
|
|
|
}
|
2008-09-15 12:24:44 +02:00
|
|
|
|
2012-06-04 14:42:41 +02:00
|
|
|
+static int sbc_getlbastatus(int host_no, struct scsi_cmd *cmd)
|
2008-09-15 12:24:44 +02:00
|
|
|
+{
|
2012-06-04 14:42:41 +02:00
|
|
|
+ int len = 32;
|
|
|
|
+ uint64_t offset;
|
|
|
|
+ uint32_t pdl;
|
|
|
|
+ int type;
|
|
|
|
+ unsigned char *buf;
|
|
|
|
+ unsigned char key = ILLEGAL_REQUEST;
|
|
|
|
+ uint16_t asc = ASC_INVALID_OP_CODE;
|
|
|
|
+
|
|
|
|
+ if (cmd->dev->attrs.removable && !cmd->dev->attrs.online) {
|
|
|
|
+ key = NOT_READY;
|
|
|
|
+ asc = ASC_MEDIUM_NOT_PRESENT;
|
|
|
|
+ goto sense;
|
|
|
|
+ }
|
2008-09-15 12:24:44 +02:00
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+ if (scsi_get_in_length(cmd) < 24)
|
|
|
|
+ goto overflow;
|
2008-09-15 12:24:44 +02:00
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+ len = scsi_get_in_length(cmd);
|
|
|
|
+ buf = scsi_get_in_buffer(cmd);
|
|
|
|
+ memset(buf, 0, len);
|
2008-09-15 12:24:44 +02:00
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+ offset = get_unaligned_be64(&cmd->scb[2]) << cmd->dev->blk_shift;
|
|
|
|
+ if (offset >= cmd->dev->size) {
|
|
|
|
+ key = ILLEGAL_REQUEST;
|
|
|
|
+ asc = ASC_LBA_OUT_OF_RANGE;
|
|
|
|
+ goto sense;
|
|
|
|
+ }
|
2008-09-15 12:24:44 +02:00
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+ pdl = 4;
|
|
|
|
+ put_unaligned_be32(pdl, &buf[0]);
|
2008-10-09 19:03:54 +02:00
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+ type = 0;
|
|
|
|
+ while (len >= 4 + pdl + 16) {
|
|
|
|
+ off_t next_offset;
|
2008-09-15 12:24:44 +02:00
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+ put_unaligned_be32(pdl + 16, &buf[0]);
|
2008-10-09 19:03:54 +02:00
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+ if (offset >= cmd->dev->size)
|
|
|
|
+ break;
|
2008-10-09 19:03:54 +02:00
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+ next_offset = (type == 0) ?
|
|
|
|
+ find_next_hole(cmd->dev, offset) :
|
|
|
|
+ find_next_data(cmd->dev, offset);
|
|
|
|
+ if (next_offset == offset) {
|
|
|
|
+ type = 1 - type;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
2008-10-09 19:03:54 +02:00
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+ put_unaligned_be64(offset >> cmd->dev->blk_shift,
|
|
|
|
+ &buf[4 + pdl + 0]);
|
|
|
|
+ put_unaligned_be32((next_offset - offset)
|
|
|
|
+ >> cmd->dev->blk_shift,
|
|
|
|
+ &buf[4 + pdl + 8]);
|
|
|
|
+ buf[4 + pdl + 12] = type;
|
2008-10-09 19:03:54 +02:00
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+ pdl += 16;
|
|
|
|
+ type = 1 - type;
|
|
|
|
+ offset = next_offset;
|
|
|
|
+ }
|
|
|
|
+ len = 4 + pdl;
|
2008-10-09 19:03:54 +02:00
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+overflow:
|
|
|
|
+ scsi_set_in_resid_by_actual(cmd, len);
|
|
|
|
+ return SAM_STAT_GOOD;
|
2008-10-09 19:03:54 +02:00
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+sense:
|
|
|
|
+ sense_data_build(cmd, key, asc);
|
|
|
|
+ return SAM_STAT_CHECK_CONDITION;
|
2008-09-15 12:24:44 +02:00
|
|
|
+}
|
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+struct service_action sbc_service_actions[] = {
|
|
|
|
+ {SAI_READ_CAPACITY_16, sbc_readcapacity16},
|
|
|
|
+ {SAI_GET_LBA_STATUS, sbc_getlbastatus},
|
|
|
|
+ {0, NULL}
|
|
|
|
+};
|
2008-09-15 12:24:44 +02:00
|
|
|
+
|
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+static int sbc_service_action(int host_no, struct scsi_cmd *cmd)
|
2008-09-15 12:24:44 +02:00
|
|
|
+{
|
2012-06-04 14:42:41 +02:00
|
|
|
+ uint8_t action;
|
|
|
|
+ unsigned char op = cmd->scb[0];
|
|
|
|
+ struct service_action *service_action, *actions;
|
2008-10-09 19:03:54 +02:00
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+ action = cmd->scb[1] & 0x1f;
|
|
|
|
+ actions = cmd->dev->dev_type_template.ops[op].service_actions;
|
2008-09-15 12:24:44 +02:00
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+ service_action = find_service_action(actions, action);
|
2008-09-15 12:24:44 +02:00
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+ if (!service_action) {
|
|
|
|
+ scsi_set_in_resid_by_actual(cmd, 0);
|
|
|
|
+ sense_data_build(cmd, ILLEGAL_REQUEST,
|
|
|
|
+ ASC_INVALID_FIELD_IN_CDB);
|
|
|
|
+ return SAM_STAT_CHECK_CONDITION;
|
2008-10-09 19:03:54 +02:00
|
|
|
+ }
|
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+ return service_action->cmd_perform(host_no, cmd);
|
|
|
|
+}
|
2008-10-09 19:03:54 +02:00
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
static int sbc_sync_cache(int host_no, struct scsi_cmd *cmd)
|
2008-10-09 19:03:54 +02:00
|
|
|
{
|
2012-06-04 14:42:41 +02:00
|
|
|
int ret;
|
|
|
|
@@ -711,7 +837,7 @@ static struct device_type_template sbc_template = {
|
|
|
|
{spc_illegal_op,},
|
|
|
|
{spc_illegal_op,},
|
|
|
|
{spc_illegal_op,},
|
|
|
|
- {sbc_service_action,},
|
|
|
|
+ {sbc_service_action, sbc_service_actions,},
|
|
|
|
{spc_illegal_op,},
|
|
|
|
|
|
|
|
/* 0xA0 */
|
|
|
|
diff --git a/usr/scsi.h b/usr/scsi.h
|
|
|
|
index 0a02c36..2b994f9 100644
|
|
|
|
--- a/usr/scsi.h
|
|
|
|
+++ b/usr/scsi.h
|
|
|
|
@@ -80,6 +80,7 @@
|
|
|
|
#define WRITE_SAME_16 0x93
|
|
|
|
#define SERVICE_ACTION_IN 0x9e
|
|
|
|
#define SAI_READ_CAPACITY_16 0x10
|
|
|
|
+#define SAI_GET_LBA_STATUS 0x12
|
|
|
|
#define REPORT_LUNS 0xa0
|
|
|
|
#define MOVE_MEDIUM 0xa5
|
|
|
|
#define EXCHANGE_MEDIUM 0xa6
|
2008-10-09 19:03:54 +02:00
|
|
|
diff --git a/usr/spc.c b/usr/spc.c
|
2012-06-04 14:42:41 +02:00
|
|
|
index a7f9a36..117c9f3 100644
|
2008-10-09 19:03:54 +02:00
|
|
|
--- a/usr/spc.c
|
|
|
|
+++ b/usr/spc.c
|
2012-06-04 14:42:41 +02:00
|
|
|
@@ -794,7 +794,7 @@ struct service_action maint_in_service_actions[] = {
|
|
|
|
{0, NULL}
|
|
|
|
};
|
2008-09-15 12:24:44 +02:00
|
|
|
|
2012-06-04 14:42:41 +02:00
|
|
|
-static struct service_action *
|
|
|
|
+struct service_action *
|
|
|
|
find_service_action(struct service_action *service_action, uint32_t action)
|
|
|
|
{
|
|
|
|
while (service_action->cmd_perform) {
|
2008-10-09 19:03:54 +02:00
|
|
|
diff --git a/usr/tgtd.c b/usr/tgtd.c
|
2012-06-04 14:42:41 +02:00
|
|
|
index 4ec6f23..cba2b66 100644
|
2008-10-09 19:03:54 +02:00
|
|
|
--- a/usr/tgtd.c
|
|
|
|
+++ b/usr/tgtd.c
|
2012-06-04 14:42:41 +02:00
|
|
|
@@ -487,6 +487,7 @@ int main(int argc, char **argv)
|
2008-09-15 12:24:44 +02:00
|
|
|
{
|
2012-06-04 14:42:41 +02:00
|
|
|
struct sigaction sa_old;
|
|
|
|
struct sigaction sa_new;
|
|
|
|
+ char *spare_args;
|
|
|
|
int err, ch, longindex, nr_lld = 0;
|
|
|
|
int is_daemon = 1, is_debug = 0;
|
|
|
|
int ret;
|
|
|
|
@@ -549,7 +550,9 @@ int main(int argc, char **argv)
|
|
|
|
exit(1);
|
|
|
|
}
|
2008-09-15 12:24:44 +02:00
|
|
|
|
2012-06-04 14:42:41 +02:00
|
|
|
- nr_lld = lld_init(argv[optind]);
|
|
|
|
+ spare_args = optind < argc ? argv[optind] : NULL;
|
2008-09-15 12:24:44 +02:00
|
|
|
+
|
2012-06-04 14:42:41 +02:00
|
|
|
+ nr_lld = lld_init(spare_args);
|
|
|
|
if (!nr_lld) {
|
|
|
|
fprintf(stderr, "No available low level driver!\n");
|
|
|
|
exit(1);
|
2008-10-09 19:03:54 +02:00
|
|
|
diff --git a/usr/tgtd.h b/usr/tgtd.h
|
2012-06-04 14:42:41 +02:00
|
|
|
index b303e21..aa9b9d5 100644
|
2008-10-09 19:03:54 +02:00
|
|
|
--- a/usr/tgtd.h
|
|
|
|
+++ b/usr/tgtd.h
|
2012-06-04 14:42:41 +02:00
|
|
|
@@ -353,4 +353,8 @@ int call_program(const char *cmd,
|
2008-10-09 19:03:54 +02:00
|
|
|
|
2012-06-04 14:42:41 +02:00
|
|
|
void update_lbppbe(struct scsi_lu *lu, int blksize);
|
2008-10-09 19:03:54 +02:00
|
|
|
|
2012-06-04 14:42:41 +02:00
|
|
|
+struct service_action *
|
|
|
|
+find_service_action(struct service_action *service_action,
|
|
|
|
+ uint32_t action);
|
2008-10-09 19:03:54 +02:00
|
|
|
+
|
|
|
|
#endif
|