You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "dbench.h"
-#define _GNU_SOURCE
#include <stdio.h>
-#undef _GNU_SOURCE
-
#include <sys/types.h>
#include <sys/socket.h>
#include <stdint.h>
#include <arpa/inet.h>
-#include "dbench.h"
#define discard_const(ptr) ((void *)((intptr_t)(ptr)))
#ifndef SG_DXFER_FROM_DEV
#define SG_DXFER_FROM_DEV -3
#endif
+#define PARAMETERS_SIZE 24
+#define PROUT_CMD 0x5F
+#define PROUT_SCOPE_LU_SCOPE 0x0
struct iscsi_device {
const char *portal;
sd->itt++;
return 0;
}
+ if (ish[3] == 0x18) {
+ /* reservation conflict */
+ *sc = 0x18;
+ sd->itt++;
+ return 0;
+ }
break;
case 0x25: /* SCSI Data-In */
if (ish[1]&0x01) {
}
+static void iscsi_write10(struct dbench_op *op)
+{
+ struct iscsi_device *sd=op->child->private;
+ unsigned char cdb[]={0x2a,0,0,0,0,0,0,0,0,0};
+ int res;
+ uint32_t lba = op->params[0];
+ uint32_t xferlen = op->params[1];
+ int fua = op->params[2];
+ int grp = op->params[3];
+ unsigned int data_size=1024*1024;
+ char data[data_size];
+ unsigned char sc;
+
+ if (!options.allow_scsi_writes) {
+ printf("WRITE10 command in loadfile but --allow-scsi-writes not specified. Aborting.\n");
+ failed(op->child);
+ }
+
+ lba = (lba / xferlen) * xferlen;
+
+ /* make sure we wrap properly instead of failing if the loadfile
+ is bigger than our device
+ */
+ if (sd->blocks <= lba) {
+ lba = lba%sd->blocks;
+ }
+ if (sd->blocks <= lba+xferlen) {
+ xferlen=1;
+ }
+
+ cdb[1] = fua;
+
+ cdb[2] = (lba>>24)&0xff;
+ cdb[3] = (lba>>16)&0xff;
+ cdb[4] = (lba>> 8)&0xff;
+ cdb[5] = (lba )&0xff;
+
+ cdb[6] = grp&0x1f;
+
+ cdb[7] = (xferlen>>8)&0xff;
+ cdb[8] = xferlen&0xff;
+ data_size = xferlen*512;
+
+ res=do_iscsi_io(sd, cdb, sizeof(cdb), SG_DXFER_TO_DEV, &data_size, data, &sc);
+ if(res){
+ printf("SCSI_IO failed\n");
+ failed(op->child);
+ }
+ if (!check_sense(sc, op->status)) {
+ printf("[%d] READ10 \"%s\" failed (0x%02x) - expected %s\n",
+ op->child->line, op->fname, sc, op->status);
+ failed(op->child);
+ }
+
+ op->child->bytes += xferlen*512;
+}
+
static void local_iscsi_readcapacity10(struct dbench_op *op, uint64_t *blocks)
{
}
}
+/* <service action> <type> <key> <sa-key>*/
+static void iscsi_prout(struct dbench_op *op)
+{
+ struct iscsi_device *sd;
+ unsigned char sc;
+ unsigned char cdb[10];
+ char parameters[PARAMETERS_SIZE];
+ int i;
+ unsigned int data_size = PARAMETERS_SIZE;
+ u_int64_t sa, type, key, sakey;
+
+ sa = op->params[0];
+ type = op->params[1];
+ key = op->params[2];
+ sakey = op->params[3];
+
+ bzero(parameters, PARAMETERS_SIZE);
+ bzero(cdb, 10);
+
+ /* Persistent Reserve OUT */
+ cdb[0] = PROUT_CMD;
+ /* Registering a key */
+ cdb[1] |= sa & 0x1f;
+
+ cdb[2] |= (PROUT_SCOPE_LU_SCOPE<<4) & 0xf0;
+ cdb[2] |= type & 0x0f;
+
+ /* Parameters size */
+ cdb[8] = PARAMETERS_SIZE;
+
+ /* splitting 64 bits in 8 blocks of 8 */
+ for (i = 0; i <= 7; i++) {
+ parameters[i] = (char) ((key >> 56) & 0xff);
+ key <<= 8;
+
+ parameters[i+8] = (char) ((sakey >> 56) & 0xff);
+ sakey <<= 8;
+ }
+
+ sd = op->child->private;
+
+ i = do_iscsi_io(sd, cdb, sizeof(cdb), SG_DXFER_TO_DEV, &data_size,
+ parameters, &sc);
+ if (i) {
+ printf("SCSI_IO failed\n");
+ failed(op->child);
+ }
+
+ if (!check_sense(sc, op->status)) {
+ printf("[%d] PROUT \"%s\" failed (0x%02x) - expected %s\n",
+ op->child->line, op->fname, sc, op->status);
+ failed(op->child);
+ }
+}
+
static void iscsi_readcapacity10(struct dbench_op *op)
{
return local_iscsi_readcapacity10(op, NULL);
{ "TESTUNITREADY", iscsi_testunitready },
{ "READ10", iscsi_read10 },
{ "READCAPACITY10", iscsi_readcapacity10 },
+ { "PROUT", iscsi_prout },
+ { "WRITE10", iscsi_write10 },
{ NULL, NULL}
};