increase the rw buffer for nfsv3 read/write commands to 1M
[amitay/dbench.git] / iscsi.c
diff --git a/iscsi.c b/iscsi.c
index 752758ba3e7a5e54620b737a79956c3a7515fc54..327317e777e275049ca90a204eb15d20db6548e9 100644 (file)
--- a/iscsi.c
+++ b/iscsi.c
    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)))
 
@@ -36,6 +33,9 @@
 #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;
@@ -407,6 +407,12 @@ need_more_data:
                        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) {
@@ -502,6 +508,63 @@ static void iscsi_read10(struct dbench_op *op)
 }
 
 
+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)
 {
@@ -542,6 +605,61 @@ 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);
@@ -674,6 +792,8 @@ static struct backend_op ops[] = {
        { "TESTUNITREADY",    iscsi_testunitready },
        { "READ10",           iscsi_read10 },
        { "READCAPACITY10",   iscsi_readcapacity10 },
+       { "PROUT",            iscsi_prout },
+       { "WRITE10",          iscsi_write10 },
        { NULL, NULL}
 };