File tgt-git-update of Package tgt

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>
 
 #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
+}
+
 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)
 
 	/* 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;
 }
 
-static int sbc_service_action(int host_no, struct scsi_cmd *cmd)
+static int sbc_readcapacity16(int host_no, struct scsi_cmd *cmd)
 {
 	uint32_t *data;
 	unsigned int bshift;
@@ -437,9 +466,6 @@ static int sbc_service_action(int host_no, struct scsi_cmd *cmd)
 		goto sense;
 	}
 
-	if (cmd->scb[1] != SAI_READ_CAPACITY_16)
-		goto sense;
-
 	if (scsi_get_in_length(cmd) < 12)
 		goto overflow;
 
@@ -468,6 +494,106 @@ sense:
 	return SAM_STAT_CHECK_CONDITION;
 }
 
+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,},
 
 		/* 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}
 };
 
-static struct service_action *
+struct service_action *
 find_service_action(struct service_action *service_action, uint32_t action)
 {
 	while (service_action->cmd_perform) {
diff --git a/usr/tgtd.c b/usr/tgtd.c
index 4ec6f23..cba2b66 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);
 	}
 
-	nr_lld = lld_init(argv[optind]);
+	spare_args = optind < argc ? argv[optind] : NULL;
+
+	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 update_lbppbe(struct scsi_lu *lu, int blksize);
 
+struct service_action *
+find_service_action(struct service_action *service_action,
+		    uint32_t action);
+
 #endif
openSUSE Build Service is sponsored by