|
|
|
@@ -1,265 +1,555 @@
|
|
|
|
|
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
|
|
|
|
|
diff --git a/doc/README.rbd b/doc/README.rbd
|
|
|
|
|
index 274cc4d..18aeceb 100644
|
|
|
|
|
--- a/doc/README.rbd
|
|
|
|
|
+++ b/doc/README.rbd
|
|
|
|
|
@@ -43,7 +43,13 @@ something like "tgt" so that the name of the ceph client is
|
|
|
|
|
for the tgt client compared to others, and sets the default log path, etc.
|
|
|
|
|
See the Ceph documentation regarding client names.
|
|
|
|
|
|
|
|
|
|
-To specify both options, separate them with ';', and since you are,
|
|
|
|
|
+cluster=<cluster name>
|
|
|
|
|
+
|
|
|
|
|
#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>
|
|
|
|
|
|
|
|
|
|
#include "list.h"
|
|
|
|
|
#include "util.h"
|
|
|
|
|
@@ -45,6 +49,23 @@
|
|
|
|
|
|
|
|
|
|
static unsigned int blk_shift = DEFAULT_BLK_SHIFT;
|
|
|
|
|
|
|
|
|
|
+static off_t find_next_data(struct scsi_lu *dev, off_t offset)
|
|
|
|
|
+{
|
|
|
|
|
+#ifdef SEEK_DATA
|
|
|
|
|
+ return lseek64(dev->fd, offset, SEEK_DATA);
|
|
|
|
|
+#else
|
|
|
|
|
+ return offset;
|
|
|
|
|
+#endif
|
|
|
|
|
+}
|
|
|
|
|
+static off_t find_next_hole(struct scsi_lu *dev, off_t offset)
|
|
|
|
|
+{
|
|
|
|
|
+#ifdef SEEK_HOLE
|
|
|
|
|
+ return lseek64(dev->fd, offset, SEEK_HOLE);
|
|
|
|
|
+#else
|
|
|
|
|
+ return dev->size;
|
|
|
|
|
+#endif
|
|
|
|
|
+}
|
|
|
|
|
+This sets the Ceph cluster name, if you have multiple clusters or
|
|
|
|
|
+if your cluster name is anything other than "ceph".
|
|
|
|
|
+This is in turn used by librados to find the conf file and key files.
|
|
|
|
|
+
|
|
|
|
|
static int sbc_mode_page_update(struct scsi_cmd *cmd, uint8_t *data, int *changed)
|
|
|
|
|
{
|
|
|
|
|
uint8_t pcode = data[0] & 0x3f;
|
|
|
|
|
@@ -281,10 +302,18 @@ static int sbc_rw(int host_no, struct scsi_cmd *cmd)
|
|
|
|
|
+To specify multiple options, separate them with ';', and since you are,
|
|
|
|
|
make sure to quote the option string to protect the semicolon from
|
|
|
|
|
the shell:
|
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
+ }
|
|
|
|
|
diff --git a/usr/bs_rbd.c b/usr/bs_rbd.c
|
|
|
|
|
index 3ea9d36..3a052ed 100644
|
|
|
|
|
--- a/usr/bs_rbd.c
|
|
|
|
|
+++ b/usr/bs_rbd.c
|
|
|
|
|
@@ -480,6 +480,9 @@ static char *slurp_to_semi(char **p)
|
|
|
|
|
strncpy(ret, *p, len);
|
|
|
|
|
ret[len] = '\0';
|
|
|
|
|
*p = end;
|
|
|
|
|
+ /* Jump past the semicolon, if we stopped at one */
|
|
|
|
|
+ if (**p == ';')
|
|
|
|
|
+ *p = end + 1;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -514,17 +517,21 @@ static tgtadm_err bs_rbd_init(struct scsi_lu *lu, char *bsopts)
|
|
|
|
|
struct active_rbd *rbd = RBDP(lu);
|
|
|
|
|
char *confname = NULL;
|
|
|
|
|
char *clientid = NULL;
|
|
|
|
|
+ char *clustername = NULL;
|
|
|
|
|
+ char clientid_full[128];
|
|
|
|
|
char *ignore = NULL;
|
|
|
|
|
|
|
|
|
|
dprintf("bs_rbd_init bsopts: \"%s\"\n", bsopts);
|
|
|
|
|
|
|
|
|
|
- // look for conf= or id=
|
|
|
|
|
+ // look for conf= or id= or cluster=
|
|
|
|
|
|
|
|
|
|
while (bsopts && strlen(bsopts)) {
|
|
|
|
|
if (is_opt("conf", bsopts))
|
|
|
|
|
confname = slurp_value(&bsopts);
|
|
|
|
|
else if (is_opt("id", bsopts))
|
|
|
|
|
clientid = slurp_value(&bsopts);
|
|
|
|
|
+ else if (is_opt("cluster", bsopts))
|
|
|
|
|
+ clustername = slurp_value(&bsopts);
|
|
|
|
|
else {
|
|
|
|
|
ignore = slurp_to_semi(&bsopts);
|
|
|
|
|
eprintf("bs_rbd: ignoring unknown option \"%s\"\n",
|
|
|
|
|
@@ -538,10 +545,27 @@ static tgtadm_err bs_rbd_init(struct scsi_lu *lu, char *bsopts)
|
|
|
|
|
eprintf("bs_rbd_init: clientid %s\n", clientid);
|
|
|
|
|
if (confname)
|
|
|
|
|
eprintf("bs_rbd_init: confname %s\n", confname);
|
|
|
|
|
+ if (clustername)
|
|
|
|
|
+ eprintf("bs_rbd_init: clustername %s\n", clustername);
|
|
|
|
|
|
|
|
|
|
eprintf("bs_rbd_init bsopts=%s\n", bsopts);
|
|
|
|
|
- /* clientid may be set by -i/--id */
|
|
|
|
|
- rados_ret = rados_create(&rbd->cluster, clientid);
|
|
|
|
|
+ /*
|
|
|
|
|
+ * clientid may be set by -i/--id. If clustername is set, then
|
|
|
|
|
+ * we use rados_create2, else rados_create
|
|
|
|
|
+ */
|
|
|
|
|
+ if (clustername) {
|
|
|
|
|
+ /* rados_create2 wants the full client name */
|
|
|
|
|
+ if (clientid)
|
|
|
|
|
+ snprintf(clientid_full, sizeof clientid_full,
|
|
|
|
|
+ "client.%s", clientid);
|
|
|
|
|
+ else /* if not specified, default to client.admin */
|
|
|
|
|
+ snprintf(clientid_full, sizeof clientid_full,
|
|
|
|
|
+ "client.admin");
|
|
|
|
|
+ rados_ret = rados_create2(&rbd->cluster, clustername,
|
|
|
|
|
+ clientid_full, 0);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if (lba >= lu->size) {
|
|
|
|
|
+ key = ILLEGAL_REQUEST;
|
|
|
|
|
+ asc = ASC_LBA_OUT_OF_RANGE;
|
|
|
|
|
+ goto sense;
|
|
|
|
|
+ rados_ret = rados_create(&rbd->cluster, clientid);
|
|
|
|
|
+ }
|
|
|
|
|
}
|
|
|
|
|
if (rados_ret < 0) {
|
|
|
|
|
eprintf("bs_rbd_init: rados_create: %d\n", rados_ret);
|
|
|
|
|
return ret;
|
|
|
|
|
diff --git a/usr/iscsi/conn.c b/usr/iscsi/conn.c
|
|
|
|
|
index bb18ac0..4cef6fd 100644
|
|
|
|
|
--- a/usr/iscsi/conn.c
|
|
|
|
|
+++ b/usr/iscsi/conn.c
|
|
|
|
|
@@ -100,13 +100,13 @@ void conn_close(struct iscsi_connection *conn)
|
|
|
|
|
eprintf("failed to close a connection, %p %u %s\n",
|
|
|
|
|
conn, conn->refcount, strerror(errno));
|
|
|
|
|
else
|
|
|
|
|
- eprintf("connection closed, %p %u\n", conn, conn->refcount);
|
|
|
|
|
+ dprintf("connection closed, %p %u\n", conn, conn->refcount);
|
|
|
|
|
|
|
|
|
|
cmd->offset = lba;
|
|
|
|
|
@@ -421,7 +450,7 @@ sense:
|
|
|
|
|
return SAM_STAT_CHECK_CONDITION;
|
|
|
|
|
}
|
|
|
|
|
/* may not have been in FFP yet */
|
|
|
|
|
if (!conn->session)
|
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
|
|
-static int sbc_service_action(int host_no, struct scsi_cmd *cmd)
|
|
|
|
|
+static int sbc_readcapacity16(int host_no, struct scsi_cmd *cmd)
|
|
|
|
|
- eprintf("session %p %d\n", conn->session, conn->session->refcount);
|
|
|
|
|
+ dprintf("session %p %d\n", conn->session, conn->session->refcount);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We just closed the ep so we are not going to send/recv anything.
|
|
|
|
|
diff --git a/usr/iscsi/iser_text.c b/usr/iscsi/iser_text.c
|
|
|
|
|
index 08cdfe5..16520cb 100644
|
|
|
|
|
--- a/usr/iscsi/iser_text.c
|
|
|
|
|
+++ b/usr/iscsi/iser_text.c
|
|
|
|
|
@@ -832,6 +832,7 @@ static void iser_text_scan(struct iscsi_connection *iscsi_conn,
|
|
|
|
|
struct sockaddr_storage ss;
|
|
|
|
|
socklen_t slen, blen;
|
|
|
|
|
char *p, buf[NI_MAXHOST + 128];
|
|
|
|
|
+ int port;
|
|
|
|
|
|
|
|
|
|
if (value[0] == 0)
|
|
|
|
|
continue;
|
|
|
|
|
@@ -857,7 +858,14 @@ static void iser_text_scan(struct iscsi_connection *iscsi_conn,
|
|
|
|
|
if (ss.ss_family == AF_INET6)
|
|
|
|
|
*p++ = ']';
|
|
|
|
|
|
|
|
|
|
- sprintf(p, ":%d,1", ISCSI_LISTEN_PORT);
|
|
|
|
|
+ if (ss.ss_family == AF_INET6)
|
|
|
|
|
+ port = ntohs(((struct sockaddr_in6 *)
|
|
|
|
|
+ &ss)->sin6_port);
|
|
|
|
|
+ else
|
|
|
|
|
+ port = ntohs(((struct sockaddr_in *)
|
|
|
|
|
+ &ss)->sin_port);
|
|
|
|
|
+
|
|
|
|
|
+ sprintf(p, ":%d,1", port);
|
|
|
|
|
iser_target_list_build(iscsi_conn, tx_pdu, buf,
|
|
|
|
|
strcmp(value, "All") ? value : NULL);
|
|
|
|
|
} else
|
|
|
|
|
diff --git a/usr/iscsi/session.c b/usr/iscsi/session.c
|
|
|
|
|
index 98c0949..22638e7 100644
|
|
|
|
|
--- a/usr/iscsi/session.c
|
|
|
|
|
+++ b/usr/iscsi/session.c
|
|
|
|
|
@@ -106,8 +106,7 @@ int session_create(struct iscsi_connection *conn)
|
|
|
|
|
session->info = zalloc(1024);
|
|
|
|
|
if (!session->info) {
|
|
|
|
|
free(session->initiator);
|
|
|
|
|
- if (session->initiator_alias)
|
|
|
|
|
- free(session->initiator_alias);
|
|
|
|
|
+ free(session->initiator_alias);
|
|
|
|
|
free(session);
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
}
|
|
|
|
|
@@ -124,6 +123,7 @@ int session_create(struct iscsi_connection *conn)
|
|
|
|
|
err = it_nexus_create(target->tid, tsih, 0, session->info);
|
|
|
|
|
if (err) {
|
|
|
|
|
free(session->initiator);
|
|
|
|
|
+ free(session->initiator_alias);
|
|
|
|
|
free(session->info);
|
|
|
|
|
free(session);
|
|
|
|
|
return err;
|
|
|
|
|
@@ -174,6 +174,7 @@ static void session_destroy(struct iscsi_session *session)
|
|
|
|
|
list_del(&session->hlist);
|
|
|
|
|
|
|
|
|
|
free(session->initiator);
|
|
|
|
|
+ free(session->initiator_alias);
|
|
|
|
|
free(session->info);
|
|
|
|
|
free(session);
|
|
|
|
|
}
|
|
|
|
|
diff --git a/usr/scsi.c b/usr/scsi.c
|
|
|
|
|
index d7c0095..4eccf13 100644
|
|
|
|
|
--- a/usr/scsi.c
|
|
|
|
|
+++ b/usr/scsi.c
|
|
|
|
|
@@ -59,164 +59,184 @@ int get_scsi_cdb_size(struct scsi_cmd *cmd)
|
|
|
|
|
const unsigned char *get_scsi_cdb_usage_data(unsigned char op, unsigned char sa)
|
|
|
|
|
{
|
|
|
|
|
uint32_t *data;
|
|
|
|
|
unsigned int bshift;
|
|
|
|
|
@@ -437,9 +466,6 @@ static int sbc_service_action(int host_no, struct scsi_cmd *cmd)
|
|
|
|
|
goto sense;
|
|
|
|
|
}
|
|
|
|
|
static const unsigned char usage[16];
|
|
|
|
|
+ unsigned char *buf = NULL;
|
|
|
|
|
|
|
|
|
|
- if (cmd->scb[1] != SAI_READ_CAPACITY_16)
|
|
|
|
|
- goto sense;
|
|
|
|
|
- static const unsigned char allow_medium_removal[] = {
|
|
|
|
|
+ static unsigned char allow_medium_removal[] = {
|
|
|
|
|
0xff, 0x00, 0x00, 0x00, 0x03, 0x07};
|
|
|
|
|
- static const unsigned char send_diagnostics[] = {
|
|
|
|
|
+ static unsigned char send_diagnostics[] = {
|
|
|
|
|
0xff, 0xff, 0x00, 0xff, 0xff, 0x07};
|
|
|
|
|
- static const unsigned char start_stop[] = {
|
|
|
|
|
+ static unsigned char start_stop[] = {
|
|
|
|
|
0xff, 0x01, 0x00, 0x0f, 0xf7, 0x07};
|
|
|
|
|
- static const unsigned char mode_sense[] = {
|
|
|
|
|
+ static unsigned char mode_sense[] = {
|
|
|
|
|
0xff, 0x08, 0xff, 0xff, 0xff, 0x07};
|
|
|
|
|
- static const unsigned char mode_select[] = {
|
|
|
|
|
+ static unsigned char mode_select[] = {
|
|
|
|
|
0xff, 0x11, 0x00, 0x00, 0xff, 0x07};
|
|
|
|
|
- static const unsigned char reserve_release[] = {
|
|
|
|
|
+ static unsigned char reserve_release[] = {
|
|
|
|
|
0xff, 0x00, 0x00, 0x00, 0x00, 0x07};
|
|
|
|
|
- static const unsigned char inquiry[] = {
|
|
|
|
|
+ static unsigned char inquiry[] = {
|
|
|
|
|
0xff, 0x01, 0xff, 0xff, 0xff, 0x07};
|
|
|
|
|
- static const unsigned char read_write_6[] = {
|
|
|
|
|
+ static unsigned char read_write_6[] = {
|
|
|
|
|
0xff, 0x1f, 0xff, 0xff, 0xff, 0x07};
|
|
|
|
|
- static const unsigned char format_unit[] = {
|
|
|
|
|
+ static unsigned char format_unit[] = {
|
|
|
|
|
0xff, 0xff, 0x00, 0x00, 0x00, 0x07};
|
|
|
|
|
- static const unsigned char request_sense[] = {
|
|
|
|
|
+ static unsigned char request_sense[] = {
|
|
|
|
|
0xff, 0x01, 0x00, 0x00, 0xff, 0x07};
|
|
|
|
|
- static const unsigned char test_unit_ready[] = {
|
|
|
|
|
+ static unsigned char test_unit_ready[] = {
|
|
|
|
|
0xff, 0x00, 0x00, 0x00, 0x00, 0x07};
|
|
|
|
|
-
|
|
|
|
|
if (scsi_get_in_length(cmd) < 12)
|
|
|
|
|
goto overflow;
|
|
|
|
|
- static const unsigned char persistent_reserve_in[] = {
|
|
|
|
|
+ static unsigned char persistent_reserve_in[] = {
|
|
|
|
|
0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
|
|
|
0xff, 0x07};
|
|
|
|
|
- static const unsigned char persistent_reserve_out[] = {
|
|
|
|
|
+ static unsigned char persistent_reserve_out[] = {
|
|
|
|
|
0xff, 0x1f, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff,
|
|
|
|
|
0xff, 0x07};
|
|
|
|
|
- static const unsigned char mode_sense_10[] = {
|
|
|
|
|
+ static unsigned char mode_sense_10[] = {
|
|
|
|
|
0xff, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff,
|
|
|
|
|
0xff, 0x07};
|
|
|
|
|
- static const unsigned char mode_select_10[] = {
|
|
|
|
|
+ static unsigned char mode_select_10[] = {
|
|
|
|
|
0xff, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
|
|
|
0xff, 0x07};
|
|
|
|
|
- static const unsigned char unmap[] = {
|
|
|
|
|
+ static unsigned char unmap[] = {
|
|
|
|
|
0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
|
|
|
0xff, 0x07};
|
|
|
|
|
- static const unsigned char write_same_10[] = {
|
|
|
|
|
+ static unsigned char write_same_10[] = {
|
|
|
|
|
0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff,
|
|
|
|
|
0xff, 0x07};
|
|
|
|
|
- static const unsigned char pre_fetch_10[] = {
|
|
|
|
|
+ static unsigned char pre_fetch_10[] = {
|
|
|
|
|
0xff, 0x02, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff,
|
|
|
|
|
0xff, 0x07};
|
|
|
|
|
- static const unsigned char synchronize_cache_10[] = {
|
|
|
|
|
+ static unsigned char synchronize_cache_10[] = {
|
|
|
|
|
0xff, 0x06, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff,
|
|
|
|
|
0xff, 0x07};
|
|
|
|
|
- static const unsigned char verify_10[] = {
|
|
|
|
|
+ static unsigned char verify_10[] = {
|
|
|
|
|
0xff, 0xf2, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff,
|
|
|
|
|
0xff, 0x07};
|
|
|
|
|
- static const unsigned char write_10[] = {
|
|
|
|
|
+ static unsigned char write_10[] = {
|
|
|
|
|
0xff, 0xfa, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff,
|
|
|
|
|
0xff, 0x07};
|
|
|
|
|
- static const unsigned char read_10[] = {
|
|
|
|
|
+ static unsigned char read_10[] = {
|
|
|
|
|
0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff,
|
|
|
|
|
0xff, 0x07};
|
|
|
|
|
- static const unsigned char read_capacity[] = {
|
|
|
|
|
+ static unsigned char read_capacity[] = {
|
|
|
|
|
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x07};
|
|
|
|
|
-
|
|
|
|
|
- static const unsigned char verify_12[] = {
|
|
|
|
|
+ static unsigned char verify_12[] = {
|
|
|
|
|
0xff, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
0xff, 0xff, 0x00, 0x07};
|
|
|
|
|
- static const unsigned char write_12[] = {
|
|
|
|
|
+ static unsigned char write_12[] = {
|
|
|
|
|
0xff, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
0xff, 0xff, 0x00, 0x07};
|
|
|
|
|
- static const unsigned char read_12[] = {
|
|
|
|
|
+ static unsigned char read_12[] = {
|
|
|
|
|
0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
0xff, 0xff, 0x00, 0x07};
|
|
|
|
|
- static const unsigned char rep_sup_opcodes[] = {
|
|
|
|
|
+ static unsigned char rep_sup_opcodes[] = {
|
|
|
|
|
0xff, 0x1f, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
0xff, 0xff, 0x00, 0x07};
|
|
|
|
|
- static const unsigned char report_luns[] = {
|
|
|
|
|
+ static unsigned char report_luns[] = {
|
|
|
|
|
0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff,
|
|
|
|
|
0xff, 0xff, 0x00, 0x07};
|
|
|
|
|
-
|
|
|
|
|
- static const unsigned char get_lba_status[] = {
|
|
|
|
|
+ static unsigned char get_lba_status[] = {
|
|
|
|
|
0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x07};
|
|
|
|
|
- static const unsigned char read_capacity_16[] = {
|
|
|
|
|
+ static unsigned char read_capacity_16[] = {
|
|
|
|
|
0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x07};
|
|
|
|
|
- static const unsigned char write_same_16[] = {
|
|
|
|
|
+ static unsigned char write_same_16[] = {
|
|
|
|
|
0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x07};
|
|
|
|
|
- static const unsigned char synchronize_cache_16[] = {
|
|
|
|
|
+ static unsigned char synchronize_cache_16[] = {
|
|
|
|
|
0xff, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x07};
|
|
|
|
|
- static const unsigned char pre_fetch_16[] = {
|
|
|
|
|
+ static unsigned char pre_fetch_16[] = {
|
|
|
|
|
0xff, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x07};
|
|
|
|
|
- static const unsigned char verify_16[] = {
|
|
|
|
|
+ static unsigned char verify_16[] = {
|
|
|
|
|
0xff, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x07};
|
|
|
|
|
- static const unsigned char orwrite_16[] = {
|
|
|
|
|
+ static unsigned char orwrite_16[] = {
|
|
|
|
|
0xff, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x07};
|
|
|
|
|
- static const unsigned char compare_and_write[] = {
|
|
|
|
|
+ static unsigned char compare_and_write[] = {
|
|
|
|
|
0xff, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x07};
|
|
|
|
|
- static const unsigned char read_16[] = {
|
|
|
|
|
+ static unsigned char read_16[] = {
|
|
|
|
|
0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x07};
|
|
|
|
|
|
|
|
|
|
@@ -468,6 +494,106 @@ sense:
|
|
|
|
|
return SAM_STAT_CHECK_CONDITION;
|
|
|
|
|
switch (op) {
|
|
|
|
|
case TEST_UNIT_READY:
|
|
|
|
|
- return test_unit_ready;
|
|
|
|
|
+ buf = test_unit_ready;
|
|
|
|
|
+ break;
|
|
|
|
|
case REQUEST_SENSE:
|
|
|
|
|
- return request_sense;
|
|
|
|
|
+ buf = request_sense;
|
|
|
|
|
+ break;
|
|
|
|
|
case FORMAT_UNIT:
|
|
|
|
|
- return format_unit;
|
|
|
|
|
+ buf = format_unit;
|
|
|
|
|
+ break;
|
|
|
|
|
case READ_6:
|
|
|
|
|
case WRITE_6:
|
|
|
|
|
- return read_write_6;
|
|
|
|
|
+ buf = read_write_6;
|
|
|
|
|
+ break;
|
|
|
|
|
case INQUIRY:
|
|
|
|
|
- return inquiry;
|
|
|
|
|
+ buf = inquiry;
|
|
|
|
|
+ break;
|
|
|
|
|
case MODE_SELECT:
|
|
|
|
|
- return mode_select;
|
|
|
|
|
+ buf = mode_select;
|
|
|
|
|
+ break;
|
|
|
|
|
case RELEASE:
|
|
|
|
|
case RESERVE:
|
|
|
|
|
- return reserve_release;
|
|
|
|
|
+ buf = reserve_release;
|
|
|
|
|
+ break;
|
|
|
|
|
case MODE_SENSE:
|
|
|
|
|
- return mode_sense;
|
|
|
|
|
+ buf = mode_sense;
|
|
|
|
|
+ break;
|
|
|
|
|
case START_STOP:
|
|
|
|
|
- return start_stop;
|
|
|
|
|
+ buf = start_stop;
|
|
|
|
|
+ break;
|
|
|
|
|
case SEND_DIAGNOSTIC:
|
|
|
|
|
- return send_diagnostics;
|
|
|
|
|
+ buf = send_diagnostics;
|
|
|
|
|
+ break;
|
|
|
|
|
case ALLOW_MEDIUM_REMOVAL:
|
|
|
|
|
- return allow_medium_removal;
|
|
|
|
|
+ buf = allow_medium_removal;
|
|
|
|
|
+ break;
|
|
|
|
|
case READ_CAPACITY:
|
|
|
|
|
- return read_capacity;
|
|
|
|
|
+ buf = read_capacity;
|
|
|
|
|
+ break;
|
|
|
|
|
case READ_10:
|
|
|
|
|
- return read_10;
|
|
|
|
|
+ buf = read_10;
|
|
|
|
|
+ break;
|
|
|
|
|
case WRITE_10:
|
|
|
|
|
- return write_10;
|
|
|
|
|
+ buf = write_10;
|
|
|
|
|
+ break;
|
|
|
|
|
case WRITE_VERIFY:
|
|
|
|
|
case VERIFY_10:
|
|
|
|
|
- return verify_10;
|
|
|
|
|
+ buf = verify_10;
|
|
|
|
|
+ break;
|
|
|
|
|
case PRE_FETCH_10:
|
|
|
|
|
- return pre_fetch_10;
|
|
|
|
|
+ buf = pre_fetch_10;
|
|
|
|
|
+ break;
|
|
|
|
|
case SYNCHRONIZE_CACHE:
|
|
|
|
|
- return synchronize_cache_10;
|
|
|
|
|
+ buf = synchronize_cache_10;
|
|
|
|
|
+ break;
|
|
|
|
|
case WRITE_SAME:
|
|
|
|
|
- return write_same_10;
|
|
|
|
|
+ buf = write_same_10;
|
|
|
|
|
+ break;
|
|
|
|
|
case UNMAP:
|
|
|
|
|
- return unmap;
|
|
|
|
|
+ buf = unmap;
|
|
|
|
|
+ break;
|
|
|
|
|
case MODE_SELECT_10:
|
|
|
|
|
- return mode_select_10;
|
|
|
|
|
+ buf = mode_select_10;
|
|
|
|
|
+ break;
|
|
|
|
|
case MODE_SENSE_10:
|
|
|
|
|
- return mode_sense_10;
|
|
|
|
|
+ buf = mode_sense_10;
|
|
|
|
|
+ break;
|
|
|
|
|
case PERSISTENT_RESERVE_IN:
|
|
|
|
|
switch (sa) {
|
|
|
|
|
case PR_IN_READ_KEYS:
|
|
|
|
|
case PR_IN_READ_RESERVATION:
|
|
|
|
|
case PR_IN_REPORT_CAPABILITIES:
|
|
|
|
|
case PR_IN_READ_FULL_STATUS:
|
|
|
|
|
- return persistent_reserve_in;
|
|
|
|
|
+ buf = persistent_reserve_in;
|
|
|
|
|
+ break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case PERSISTENT_RESERVE_OUT:
|
|
|
|
|
@@ -229,49 +249,70 @@ const unsigned char *get_scsi_cdb_usage_data(unsigned char op, unsigned char sa)
|
|
|
|
|
case PR_OUT_PREEMPT_AND_ABORT:
|
|
|
|
|
case PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY:
|
|
|
|
|
case PR_OUT_REGISTER_AND_MOVE:
|
|
|
|
|
- return persistent_reserve_out;
|
|
|
|
|
+ buf = persistent_reserve_out;
|
|
|
|
|
+ break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case READ_16:
|
|
|
|
|
- return read_16;
|
|
|
|
|
+ buf = read_16;
|
|
|
|
|
+ break;
|
|
|
|
|
case COMPARE_AND_WRITE:
|
|
|
|
|
- return compare_and_write;
|
|
|
|
|
+ buf = compare_and_write;
|
|
|
|
|
+ break;
|
|
|
|
|
case WRITE_16:
|
|
|
|
|
case ORWRITE_16:
|
|
|
|
|
- return orwrite_16;
|
|
|
|
|
+ buf = orwrite_16;
|
|
|
|
|
+ break;
|
|
|
|
|
case WRITE_VERIFY_16:
|
|
|
|
|
case VERIFY_16:
|
|
|
|
|
- return verify_16;
|
|
|
|
|
+ buf = verify_16;
|
|
|
|
|
+ break;
|
|
|
|
|
case PRE_FETCH_16:
|
|
|
|
|
- return pre_fetch_16;
|
|
|
|
|
+ buf = pre_fetch_16;
|
|
|
|
|
+ break;
|
|
|
|
|
case SYNCHRONIZE_CACHE_16:
|
|
|
|
|
- return synchronize_cache_16;
|
|
|
|
|
+ buf = synchronize_cache_16;
|
|
|
|
|
+ break;
|
|
|
|
|
case WRITE_SAME_16:
|
|
|
|
|
- return write_same_16;
|
|
|
|
|
+ buf = write_same_16;
|
|
|
|
|
+ break;
|
|
|
|
|
case SERVICE_ACTION_IN:
|
|
|
|
|
switch (sa) {
|
|
|
|
|
case SAI_READ_CAPACITY_16:
|
|
|
|
|
- return read_capacity_16;
|
|
|
|
|
+ buf = read_capacity_16;
|
|
|
|
|
+ break;
|
|
|
|
|
case SAI_GET_LBA_STATUS:
|
|
|
|
|
- return get_lba_status;
|
|
|
|
|
+ buf = get_lba_status;
|
|
|
|
|
+ break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case REPORT_LUNS:
|
|
|
|
|
- return report_luns;
|
|
|
|
|
+ buf = report_luns;
|
|
|
|
|
+ break;
|
|
|
|
|
case MAINT_PROTOCOL_IN:
|
|
|
|
|
switch (sa) {
|
|
|
|
|
case MPI_REPORT_SUPPORTED_OPCODES:
|
|
|
|
|
- return rep_sup_opcodes;
|
|
|
|
|
+ buf = rep_sup_opcodes;
|
|
|
|
|
+ break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case READ_12:
|
|
|
|
|
- return read_12;
|
|
|
|
|
+ buf = read_12;
|
|
|
|
|
+ break;
|
|
|
|
|
case VERIFY_12:
|
|
|
|
|
case WRITE_VERIFY_12:
|
|
|
|
|
- return verify_12;
|
|
|
|
|
+ buf = verify_12;
|
|
|
|
|
+ break;
|
|
|
|
|
case WRITE_12:
|
|
|
|
|
- return write_12;
|
|
|
|
|
+ buf = write_12;
|
|
|
|
|
+ break;
|
|
|
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ if (buf) {
|
|
|
|
|
+ buf[0] = op;
|
|
|
|
|
+ return buf;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
return usage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+static int sbc_getlbastatus(int host_no, struct scsi_cmd *cmd)
|
|
|
|
|
+{
|
|
|
|
|
+ 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;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (scsi_get_in_length(cmd) < 24)
|
|
|
|
|
+ goto overflow;
|
|
|
|
|
+
|
|
|
|
|
+ len = scsi_get_in_length(cmd);
|
|
|
|
|
+ buf = scsi_get_in_buffer(cmd);
|
|
|
|
|
+ memset(buf, 0, len);
|
|
|
|
|
+
|
|
|
|
|
+ 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;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pdl = 4;
|
|
|
|
|
+ put_unaligned_be32(pdl, &buf[0]);
|
|
|
|
|
+
|
|
|
|
|
+ type = 0;
|
|
|
|
|
+ while (len >= 4 + pdl + 16) {
|
|
|
|
|
+ off_t next_offset;
|
|
|
|
|
+
|
|
|
|
|
+ put_unaligned_be32(pdl + 16, &buf[0]);
|
|
|
|
|
+
|
|
|
|
|
+ if (offset >= cmd->dev->size)
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ next_offset = (type == 0) ?
|
|
|
|
|
+ find_next_hole(cmd->dev, offset) :
|
|
|
|
|
+ find_next_data(cmd->dev, offset);
|
|
|
|
|
+ if (next_offset == offset) {
|
|
|
|
|
+ type = 1 - type;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ 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;
|
|
|
|
|
+
|
|
|
|
|
+ pdl += 16;
|
|
|
|
|
+ type = 1 - type;
|
|
|
|
|
+ offset = next_offset;
|
|
|
|
|
+ }
|
|
|
|
|
+ len = 4 + pdl;
|
|
|
|
|
+
|
|
|
|
|
+overflow:
|
|
|
|
|
+ scsi_set_in_resid_by_actual(cmd, len);
|
|
|
|
|
+ return SAM_STAT_GOOD;
|
|
|
|
|
+
|
|
|
|
|
+sense:
|
|
|
|
|
+ sense_data_build(cmd, key, asc);
|
|
|
|
|
+ return SAM_STAT_CHECK_CONDITION;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+struct service_action sbc_service_actions[] = {
|
|
|
|
|
+ {SAI_READ_CAPACITY_16, sbc_readcapacity16},
|
|
|
|
|
+ {SAI_GET_LBA_STATUS, sbc_getlbastatus},
|
|
|
|
|
+ {0, NULL}
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+static int sbc_service_action(int host_no, struct scsi_cmd *cmd)
|
|
|
|
|
+{
|
|
|
|
|
+ uint8_t action;
|
|
|
|
|
+ unsigned char op = cmd->scb[0];
|
|
|
|
|
+ struct service_action *service_action, *actions;
|
|
|
|
|
+
|
|
|
|
|
+ action = cmd->scb[1] & 0x1f;
|
|
|
|
|
+ actions = cmd->dev->dev_type_template.ops[op].service_actions;
|
|
|
|
|
+
|
|
|
|
|
+ service_action = find_service_action(actions, action);
|
|
|
|
|
+
|
|
|
|
|
+ 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;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return service_action->cmd_perform(host_no, cmd);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
static int sbc_sync_cache(int host_no, struct scsi_cmd *cmd)
|
|
|
|
|
{
|
|
|
|
|
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,},
|
|
|
|
|
diff --git a/usr/target.c b/usr/target.c
|
|
|
|
|
index f4c5b4e..b6f324c 100644
|
|
|
|
|
--- a/usr/target.c
|
|
|
|
|
+++ b/usr/target.c
|
|
|
|
|
@@ -1581,7 +1581,6 @@ static tgtadm_err __inaccount_bind(struct target *target, int aid)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
|
diff --git a/usr/spc.c b/usr/spc.c
|
|
|
|
|
index a7f9a36..117c9f3 100644
|
|
|
|
|
--- a/usr/spc.c
|
|
|
|
|
+++ b/usr/spc.c
|
|
|
|
|
@@ -794,7 +794,7 @@ struct service_action maint_in_service_actions[] = {
|
|
|
|
|
{0, NULL}
|
|
|
|
|
};
|
|
|
|
|
target->account.in_aids[i] = aid;
|
|
|
|
|
- target->account.nr_inaccount++;
|
|
|
|
|
} else {
|
|
|
|
|
int new_max = target->account.max_inaccount << 1;
|
|
|
|
|
int *buf;
|
|
|
|
|
@@ -1597,6 +1596,7 @@ static tgtadm_err __inaccount_bind(struct target *target, int aid)
|
|
|
|
|
target->account.in_aids[target->account.max_inaccount] = aid;
|
|
|
|
|
target->account.max_inaccount = new_max;
|
|
|
|
|
}
|
|
|
|
|
+ target->account.nr_inaccount++;
|
|
|
|
|
|
|
|
|
|
-static struct service_action *
|
|
|
|
|
+struct service_action *
|
|
|
|
|
find_service_action(struct service_action *service_action, uint32_t action)
|
|
|
|
|
{
|
|
|
|
|
while (service_action->cmd_perform) {
|
|
|
|
|
return TGTADM_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
diff --git a/usr/tgtd.c b/usr/tgtd.c
|
|
|
|
|
index 4ec6f23..cba2b66 100644
|
|
|
|
|
index 50e1c83..9975e03 100644
|
|
|
|
|
--- a/usr/tgtd.c
|
|
|
|
|
+++ b/usr/tgtd.c
|
|
|
|
|
@@ -487,6 +487,7 @@ int main(int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
@@ -212,6 +212,8 @@ static struct event_data *tgt_event_lookup(int fd)
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- nr_lld = lld_init(argv[optind]);
|
|
|
|
|
+ spare_args = optind < argc ? argv[optind] : NULL;
|
|
|
|
|
+static int event_need_refresh;
|
|
|
|
|
+
|
|
|
|
|
+ nr_lld = lld_init(spare_args);
|
|
|
|
|
if (!nr_lld) {
|
|
|
|
|
fprintf(stderr, "No available low level driver!\n");
|
|
|
|
|
exit(1);
|
|
|
|
|
diff --git a/usr/tgtd.h b/usr/tgtd.h
|
|
|
|
|
index b303e21..aa9b9d5 100644
|
|
|
|
|
--- a/usr/tgtd.h
|
|
|
|
|
+++ b/usr/tgtd.h
|
|
|
|
|
@@ -353,4 +353,8 @@ int call_program(const char *cmd,
|
|
|
|
|
void tgt_event_del(int fd)
|
|
|
|
|
{
|
|
|
|
|
struct event_data *tev;
|
|
|
|
|
@@ -229,6 +231,8 @@ void tgt_event_del(int fd)
|
|
|
|
|
|
|
|
|
|
void update_lbppbe(struct scsi_lu *lu, int blksize);
|
|
|
|
|
|
|
|
|
|
+struct service_action *
|
|
|
|
|
+find_service_action(struct service_action *service_action,
|
|
|
|
|
+ uint32_t action);
|
|
|
|
|
list_del(&tev->e_list);
|
|
|
|
|
free(tev);
|
|
|
|
|
+
|
|
|
|
|
#endif
|
|
|
|
|
+ event_need_refresh = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int tgt_event_modify(int fd, int events)
|
|
|
|
|
@@ -426,6 +430,11 @@ retry:
|
|
|
|
|
for (i = 0; i < nevent; i++) {
|
|
|
|
|
tev = (struct event_data *) events[i].data.ptr;
|
|
|
|
|
tev->handler(tev->fd, events[i].events, tev->data);
|
|
|
|
|
+
|
|
|
|
|
+ if (event_need_refresh) {
|
|
|
|
|
+ event_need_refresh = 0;
|
|
|
|
|
+ goto retry;
|
|
|
|
|
+ }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|