Exemplo n.º 1
0
void
test_read10_beyond_eol(void)
{ 
        int i;

        if (num_blocks >= 0x80000000) {
                CU_PASS("LUN is too big for read-beyond-eol tests with READ10. Skipping test.\n");
                return;
        }

        logging(LOG_VERBOSE, LOG_BLANK_LINE);
        logging(LOG_VERBOSE, "Test READ10 1-256 blocks one block beyond the end");
        for (i = 1; i <= 256; i++) {
                if (maximum_transfer_length && maximum_transfer_length < i) {
                        break;
                }
                READ10(sd, NULL, num_blocks + 1 - i,
                       i * block_size, block_size, 0, 0, 0, 0, 0, NULL,
                       EXPECT_LBA_OOB);
        }

        logging(LOG_VERBOSE, "Test READ10 1-256 blocks at LBA==2^31");
        for (i = 1; i <= 256; i++) {
                if (maximum_transfer_length && maximum_transfer_length < i) {
                        break;
                }
                READ10(sd, NULL, 0x80000000,
                       i * block_size, block_size, 0, 0, 0, 0, 0, NULL,
                       EXPECT_LBA_OOB);
        }

        logging(LOG_VERBOSE, "Test READ10 1-256 blocks at LBA==-1");
        for (i = 1; i <= 256; i++) {
                if (maximum_transfer_length && maximum_transfer_length < i) {
                        break;
                }
                READ10(sd, NULL, -1, i * block_size,
                       block_size, 0, 0, 0, 0, 0, NULL,
                       EXPECT_LBA_OOB);
        }

        logging(LOG_VERBOSE, "Test READ10 2-256 blocks all but one block beyond the end");
        for (i = 2; i <= 256; i++) {
                if (maximum_transfer_length && maximum_transfer_length < i) {
                        break;
                }
                READ10(sd, NULL, num_blocks - 1,
                       i * block_size, block_size, 0, 0, 0, 0, 0, NULL,
                       EXPECT_LBA_OOB);
        }
}
Exemplo n.º 2
0
void
test_verify12_vrprotect(void)
{
        int i;

        logging(LOG_VERBOSE, LOG_BLANK_LINE);
        logging(LOG_VERBOSE, "Test VERIFY12 with non-zero VRPROTECT");

        CHECK_FOR_SBC;

        if (!inq->protect || (rc16 != NULL && !rc16->prot_en)) {
                logging(LOG_VERBOSE, "Device does not support/use protection information. All commands should fail.");
                for (i = 1; i < 8; i++) {
                        READ10(sd, NULL, 0, block_size,
                               block_size, 0, 0, 0, 0, 0, scratch,
                               EXPECT_STATUS_GOOD);
                        VERIFY12(sd, 0, block_size,
                                 block_size, i, 0, 1, scratch,
                                 EXPECT_INVALID_FIELD_IN_CDB);
                }
                return;
        }

        logging(LOG_NORMAL, "No tests for devices that support protection information yet.");
}
Exemplo n.º 3
0
void
test_writesame10_check(void)
{
	int i;
	int ws_max_blocks = 256;
	unsigned char read_buf[ws_max_blocks * block_size];

	CHECK_FOR_DATALOSS;
	CHECK_FOR_SBC;

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test WRITESAME10 of 1-256 blocks at the start of the LUN");

	for (i = 1; i <= ws_max_blocks; i++) {
		/*
		 * fill the full buffer so that memcmp is straightforward,
		 * even though writesame is only using one block of it.
		 */
		memset(scratch, i, block_size * ws_max_blocks);
		WRITESAME10(sd, 0, block_size, i, 0, 0, 0, 0, scratch,
			    EXPECT_STATUS_GOOD);

		memset(read_buf, 0, i * block_size);
		READ10(sd, NULL, 0, i * block_size,
		       block_size, 0, 0, 0, 0, 0, read_buf,
		       EXPECT_STATUS_GOOD);

		CU_ASSERT_EQUAL(0, memcmp(read_buf, scratch, i));
	}

	logging(LOG_VERBOSE, "Test WRITESAME10 of 1-256 blocks at the end of the LUN");
	for (i = 1; i <= ws_max_blocks; i++) {
		memset(scratch, i, block_size * ws_max_blocks);
		WRITESAME10(sd, num_blocks - i,
			    block_size, i, 0, 0, 0, 0, scratch,
			    EXPECT_STATUS_GOOD);

		memset(read_buf, 0, i * block_size);
		READ10(sd, NULL, num_blocks - i, i * block_size,
		       block_size, 0, 0, 0, 0, 0, read_buf,
		       EXPECT_STATUS_GOOD);

		CU_ASSERT_EQUAL(0, memcmp(read_buf, scratch, i));
	}
}
Exemplo n.º 4
0
void
test_verify10_mismatch(void)
{
        int i;

        logging(LOG_VERBOSE, LOG_BLANK_LINE);
        logging(LOG_VERBOSE, "Test VERIFY10 for blocks 1-255");
        for (i = 1; i <= 256; i++) {
                int offset = random() % (i * block_size);

                if (maximum_transfer_length && maximum_transfer_length < i) {
                        break;
                }
                READ10(sd, NULL, 0, i * block_size,
                       block_size, 0, 0, 0, 0, 0, scratch,
                       EXPECT_STATUS_GOOD);

                /* flip a random byte in the data */
                scratch[offset] ^= 'X';
                logging(LOG_VERBOSE, "Flip some bits in the data");

                VERIFY10(sd, 0, i * block_size, block_size, 0, 0, 1, scratch,
                         EXPECT_MISCOMPARE);
        }

        logging(LOG_VERBOSE, "Test VERIFY10 of 1-256 blocks at the end of the LUN");
        for (i = 1; i <= 256; i++) {
                int offset = random() % (i * block_size);

                if (maximum_transfer_length && maximum_transfer_length < i) {
                        break;
                }
                READ10(sd, NULL, num_blocks - i,
                       i * block_size, block_size, 0, 0, 0, 0, 0, scratch,
                       EXPECT_STATUS_GOOD);

                /* flip a random byte in the data */
                scratch[offset] ^= 'X';
                logging(LOG_VERBOSE, "Flip some bits in the data");

                VERIFY10(sd, num_blocks - i,
                         i * block_size, block_size, 0, 0, 1, scratch,
                         EXPECT_MISCOMPARE);
        }
}
Exemplo n.º 5
0
static void
check_wabereq(void)
{
        struct scsi_task *task_ret = NULL;

        logging(LOG_VERBOSE, "Read one block from LBA 0");
        READ10(sd, &task_ret, 0, block_size, block_size, 0, 0, 0, 0, 0, NULL,
               EXPECT_STATUS_GOOD);
        CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
        if (task_ret == NULL) {
                return;
        }
        CU_ASSERT_NOT_EQUAL(task_ret->status, SCSI_STATUS_CANCELLED);

        switch (inq_bdc->wabereq) {
        case 0:
                logging(LOG_NORMAL, "[FAILED] SANITIZE BLOCK ERASE "
                        "opcode is supported but WABEREQ is 0");
                CU_FAIL("[FAILED] SANITIZE BLOCK ERASE "
                        "opcode is supported but WABEREQ is 0");
                break;
        case 1:
                logging(LOG_VERBOSE, "WABEREQ==1. Reads from the "
                        "device should be successful.");
                if (task_ret->status == SCSI_STATUS_GOOD) {
                        logging(LOG_VERBOSE, "[SUCCESS] Read was "
                                "successful after SANITIZE");
                        break;
                }
                logging(LOG_NORMAL, "[FAILED] Read after "
                        "SANITIZE failed but WABEREQ is 1");
                CU_FAIL("[FAILED] Read after SANITIZE failed "
                        "but WABEREQ is 1");
                break;
        case 2:
                logging(LOG_VERBOSE, "WABEREQ==2. Reads from the "
                        "device should fail.");
                if (task_ret->status        == SCSI_STATUS_CHECK_CONDITION
                    && task_ret->sense.key  == SCSI_SENSE_MEDIUM_ERROR
                    && task_ret->sense.ascq != SCSI_SENSE_ASCQ_WRITE_AFTER_SANITIZE_REQUIRED) {
                        logging(LOG_VERBOSE, "[SUCCESS] Read failed "
                                "with CHECK_CONDITION/MEDIUM_ERROR/"
                                "!WRITE_AFTER_SANITIZE_REQUIRED");
                        break;
                }
                logging(LOG_VERBOSE, "[FAILED] Read should have failed "
                        "with CHECK_CONDITION/MEDIUM_ERROR/"
                        "!WRITE_AFTER_SANITIZE_REQUIRED");
                CU_FAIL("[FAILED] Read should have failed "
                        "with CHECK_CONDITION/MEDIUM_ERROR/"
                        "!WRITE_AFTER_SANITIZE_REQUIRED");
                break;
        case 3:
                logging(LOG_VERBOSE, "WABEREQ==3. Reads from the "
                        "device should fail.");
                if (task_ret->status        == SCSI_STATUS_CHECK_CONDITION
                    && task_ret->sense.key  == SCSI_SENSE_MEDIUM_ERROR
                    && task_ret->sense.ascq == SCSI_SENSE_ASCQ_WRITE_AFTER_SANITIZE_REQUIRED) {
                        logging(LOG_VERBOSE, "[SUCCESS] Read failed "
                                "with CHECK_CONDITION/MEDIUM_ERROR/"
                                "WRITE_AFTER_SANITIZE_REQUIRED");
                        break;
                }
                logging(LOG_VERBOSE, "[FAILED] Read should have failed "
                        "with CHECK_CONDITION/MEDIUM_ERROR/"
                        "WRITE_AFTER_SANITIZE_REQUIRED");
                CU_FAIL("[FAILED] Read should have failed "
                        "with CHECK_CONDITION/MEDIUM_ERROR/"
                        "WRITE_AFTER_SANITIZE_REQUIRED");
                break;
        }

        scsi_free_scsi_task(task_ret);
}
Exemplo n.º 6
0
void
test_writesame10_unmap(void)
{
        unsigned int i;

        CHECK_FOR_DATALOSS;
        CHECK_FOR_THIN_PROVISIONING;
        CHECK_FOR_LBPWS10;
        CHECK_FOR_SBC;

        logging(LOG_VERBOSE, LOG_BLANK_LINE);
        logging(LOG_VERBOSE, "Test WRITESAME10 of 1-256 blocks at the start of "
                "the LUN");
        memset(scratch, 0xa6, 256 * block_size);
        for (i = 1; i <= 256; i++) {
                logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i);
                memset(scratch, 0xff, i * block_size);
                WRITE10(sd, 0, i * block_size, block_size,
                        0, 0, 0, 0, 0, scratch,
                        EXPECT_STATUS_GOOD);

                logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME10", i);
                memset(scratch, 0, block_size);
                WRITESAME10(sd, 0, block_size, i, 0, 1, 0, 0, scratch,
                            EXPECT_STATUS_GOOD);

                if (rc16->lbprz) {
                        logging(LOG_VERBOSE, "LBPRZ is set. Read the unmapped "
                                "blocks back and verify they are all zero");

                        logging(LOG_VERBOSE, "Read %d blocks and verify they "
                                "are now zero", i);
                        READ10(sd, NULL, 0, i * block_size, block_size,
                               0, 0, 0, 0, 0, scratch,
                               EXPECT_STATUS_GOOD);
                        ALL_ZERO(scratch, i * block_size);
                } else {
                        logging(LOG_VERBOSE, "LBPRZ is clear. Skip the read "
                                "and verify zero test");
                }
        }


        logging(LOG_VERBOSE, "Test WRITESAME10 of 1-256 blocks at the end of "
                "the LUN");
        for (i = 1; i <= 256; i++) {
                logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i);
                memset(scratch, 0xff, i * block_size);
                WRITE10(sd, num_blocks - i,
                        i * block_size, block_size, 0, 0, 0, 0, 0, scratch,
                        EXPECT_STATUS_GOOD);

                logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME10", i);
                memset(scratch, 0, block_size);
                WRITESAME10(sd, num_blocks - i,
                            block_size, i, 0, 1, 0, 0, scratch,
                            EXPECT_STATUS_GOOD);

                if (rc16->lbprz) {
                        logging(LOG_VERBOSE, "LBPRZ is set. Read the unmapped "
                                "blocks back and verify they are all zero");

                        logging(LOG_VERBOSE, "Read %d blocks and verify they "
                                "are now zero", i);
                        READ10(sd, NULL, num_blocks - i,
                               i * block_size, block_size,
                               0, 0, 0, 0, 0, scratch,
                               EXPECT_STATUS_GOOD);
                        ALL_ZERO(scratch, i * block_size);
                } else {
                        logging(LOG_VERBOSE, "LBPRZ is clear. Skip the read "
                                "and verify zero test");
                }
        }

        logging(LOG_VERBOSE, "Verify that WRITESAME10 ANCHOR==1 + UNMAP==0 is "
                "invalid");
        WRITESAME10(sd, 0, block_size, 1, 1, 0, 0, 0, scratch,
                    EXPECT_INVALID_FIELD_IN_CDB);

        if (inq_lbp->anc_sup) {
                logging(LOG_VERBOSE, "Test WRITESAME10 ANCHOR==1 + UNMAP==0");
                memset(scratch, 0, block_size);
                WRITESAME10(sd, 0, block_size, 1, 1, 1, 0, 0, scratch,
                            EXPECT_STATUS_GOOD);
        } else {
                logging(LOG_VERBOSE, "Test WRITESAME10 ANCHOR==1 + UNMAP==0 no "
                        "ANC_SUP so expecting to fail");
                WRITESAME10(sd, 0, block_size, 1, 1, 1, 0, 0, scratch,
                            EXPECT_INVALID_FIELD_IN_CDB);
        }
        
        if (inq_bl == NULL) {
                logging(LOG_VERBOSE, "[FAILED] WRITESAME10 works but "
                        "BlockLimits VPD is missing.");
                CU_FAIL("[FAILED] WRITESAME10 works but "
                        "BlockLimits VPD is missing.");
                return;
        }

        i = 256;
        if (i <= num_blocks
            && (inq_bl->max_ws_len == 0 || inq_bl->max_ws_len >= i)) {
                logging(LOG_VERBOSE, "Block Limits VPD page reports MAX_WS_LEN "
                        "as either 0 (==no limit) or >= %d. Test Unmapping "
                        "%d blocks to verify that it can handle 2-byte "
                        "lengths", i, i);

                logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i);
                memset(scratch, 0xff, i * block_size);
                WRITE10(sd, 0,
                        i * block_size, block_size, 0, 0, 0, 0, 0, scratch,
                        EXPECT_STATUS_GOOD);

                logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME10", i);
                memset(scratch, 0, block_size);
                WRITESAME10(sd, 0, block_size, i, 0, 1, 0, 0, scratch,
                            EXPECT_STATUS_GOOD);

                if (rc16->lbprz) {
                        logging(LOG_VERBOSE, "LBPRZ is set. Read the unmapped "
                                "blocks back and verify they are all zero");

                        logging(LOG_VERBOSE, "Read %d blocks and verify they "
                                "are now zero", i);
                        READ10(sd, NULL, 0, i * block_size, block_size,
                               0, 0, 0, 0, 0, scratch,
                               EXPECT_STATUS_GOOD);
                        ALL_ZERO(scratch, i * block_size);
                } else {
                        logging(LOG_VERBOSE, "LBPRZ is clear. Skip the read "
                                "and verify zero test");
                }
        } else if (i <= num_blocks) {
                logging(LOG_VERBOSE, "Block Limits VPD page reports MAX_WS_LEN "
                        "as <256. Verify that a 256 block unmap fails with "
                        "INVALID_FIELD_IN_CDB.");

                logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME10", i);
                WRITESAME10(sd, 0, block_size, i, 0, 1, 0, 0, scratch,
                            EXPECT_INVALID_FIELD_IN_CDB);
        }
}
void
test_writeverify10_residuals(void)
{
        struct scsi_task *task_ret;
        unsigned char buf[10000];
        struct iscsi_data data;
        int ok;
        unsigned int i;

        logging(LOG_VERBOSE, LOG_BLANK_LINE);
        logging(LOG_VERBOSE, "Test WRITEVERIFY10 commands with residuals");
        logging(LOG_VERBOSE, "Block size is %zu", block_size);

        CHECK_FOR_DATALOSS;
        CHECK_FOR_SBC;

        if (sd->iscsi_ctx == NULL) {
                const char *err = "[SKIPPED] This WRITEVERIFY10 test is only "
                        "supported for iSCSI backends";
                logging(LOG_NORMAL, "%s", err);
                CU_PASS(err);
                return;
        }

        /* check if writeverify10 is supported */
        WRITEVERIFY10(sd, 0, 0, block_size, 0, 0, 0, 0, NULL,
                      EXPECT_STATUS_GOOD);

        /* Try a writeverify10 of 1 block but xferlength == 0 */
        task = malloc(sizeof(struct scsi_task));
        CU_ASSERT_PTR_NOT_NULL_FATAL(task);

        memset(task, 0, sizeof(struct scsi_task));
        task->cdb[0] = SCSI_OPCODE_WRITE_VERIFY10;
        task->cdb[1] = 2; /* BYTCHK = 1 */
        task->cdb[8] = 1;
        task->cdb_size = 10;
        task->xfer_dir = SCSI_XFER_WRITE;
        task->expxferlen = 0;

        /*
         * we don't want autoreconnect since some targets will drop the session
         * on this condition.
         */
        iscsi_set_noautoreconnect(sd->iscsi_ctx, 1);

        logging(LOG_VERBOSE, "Try writing one block but with iSCSI expected transfer length==0");

        task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, NULL);
        CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);
        CU_ASSERT_NOT_EQUAL(task->status, SCSI_STATUS_CANCELLED); /* XXX redundant? */

        if (task->status        == SCSI_STATUS_CHECK_CONDITION
            && task->sense.key  == SCSI_SENSE_ILLEGAL_REQUEST
            && task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
                logging(LOG_NORMAL, "[SKIPPED] WRITEVERIFY10 is not implemented.");
                CU_PASS("WRITEVERIFY10 is not implemented.");
                return;
        }        
        logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
        if (task->status != SCSI_STATUS_GOOD) {
                logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
                        iscsi_get_error(sd->iscsi_ctx));
        }
        CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);

        logging(LOG_VERBOSE, "Verify residual overflow flag is set");
        if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
                logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
                        "overflow flag");
        }
        CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);

        logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
                block_size);
        if (task->residual != block_size) {
                logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
                        "amount of residual. Expected %zu but got %zu.",
                        block_size, task->residual);
        }
        CU_ASSERT_EQUAL(task->residual, block_size);
        scsi_free_scsi_task(task);
        task = NULL;

        /* in case the previous test failed the session */
        iscsi_set_noautoreconnect(sd->iscsi_ctx, 0);


        logging(LOG_VERBOSE, "Try writing one block but with iSCSI expected transfer length==10000");
        task = malloc(sizeof(struct scsi_task));
        CU_ASSERT_PTR_NOT_NULL_FATAL(task);

        memset(task, 0, sizeof(struct scsi_task));
        task->cdb[0] = SCSI_OPCODE_WRITE_VERIFY10;
        task->cdb[1] = 2; /* BYTCHK = 1 */
        task->cdb[8] = 1;
        task->cdb_size = 10;
        task->xfer_dir = SCSI_XFER_WRITE;
        task->expxferlen = 10000;

        memset(buf, 0xa6, sizeof(buf));
        data.size = task->expxferlen;
        data.data = &buf[0];
        task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data);
        CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);

        logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
        if (task->status != SCSI_STATUS_GOOD) {
                logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
                        iscsi_get_error(sd->iscsi_ctx));
        }
        CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);

        logging(LOG_VERBOSE, "Verify residual underflow flag is set");
        if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) {
                logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
                        "underflow flag");
        }
        CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW);

        logging(LOG_VERBOSE, "Verify we got %zu bytes of residual underflow",
                10000 - block_size);
        if (task->residual != 10000 - block_size) {
                logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
                        "amount of residual. Expected %zu but got %zu.",
                        10000 - block_size, task->residual);
        }
        CU_ASSERT_EQUAL(task->residual, 10000 - block_size);
        scsi_free_scsi_task(task);
        task = NULL;


        logging(LOG_VERBOSE, "Try writing one block but with iSCSI expected transfer length==200");
        task = malloc(sizeof(struct scsi_task));
        CU_ASSERT_PTR_NOT_NULL_FATAL(task);

        memset(task, 0, sizeof(struct scsi_task));
        task->cdb[0] = SCSI_OPCODE_WRITE_VERIFY10;
        task->cdb[1] = 2; /* BYTCHK = 1 */
        task->cdb[8] = 1;
        task->cdb_size = 10;
        task->xfer_dir = SCSI_XFER_WRITE;
        task->expxferlen = 200;

        data.size = task->expxferlen;
        data.data = &buf[0];
        task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data);
        CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);

        logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
        ok = task->status == SCSI_STATUS_GOOD ||
                (task->status == SCSI_STATUS_CHECK_CONDITION &&
                 task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST &&
                 task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_FIELD_IN_INFORMATION_UNIT);
        if (!ok) {
                logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
                        iscsi_get_error(sd->iscsi_ctx));
        }
        CU_ASSERT(ok);

        logging(LOG_VERBOSE, "Verify residual overflow flag is set");
        if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
                logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
                        "overflow flag");
        }
        CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);

        logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow",
                block_size - 200);
        if (task->residual != block_size - 200) {
                logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
                        "amount of residual. Expected %zu but got %zu.",
                        block_size - 200, task->residual);
        }
        CU_ASSERT_EQUAL(task->residual, block_size - 200);

        scsi_free_scsi_task(task);
        task = NULL;



        logging(LOG_VERBOSE, "Try writing two blocks but iSCSI expected "
                "transfer length==%zu (==one block)", block_size);
        task = malloc(sizeof(struct scsi_task));
        CU_ASSERT_PTR_NOT_NULL_FATAL(task);

        memset(task, 0, sizeof(struct scsi_task));
        task->cdb[0] = SCSI_OPCODE_WRITE_VERIFY10;
        task->cdb[1] = 2; /* BYTCHK = 1 */
        task->cdb[8] = 2;
        task->cdb_size = 10;
        task->xfer_dir = SCSI_XFER_WRITE;
        task->expxferlen = block_size;

        data.size = task->expxferlen;
        data.data = &buf[0];
        task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data);
        CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);

        logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
        if (task->status != SCSI_STATUS_GOOD) {
                logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
                        iscsi_get_error(sd->iscsi_ctx));
        }
        CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);

        logging(LOG_VERBOSE, "Verify residual overflow flag is set");
        if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
                logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
                        "overflow flag");
        }
        CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);

        logging(LOG_VERBOSE, "Verify we got one block of residual overflow");
        if (task->residual != block_size) {
                logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
                        "amount of residual. Expected %zu but got %zu.",
                        block_size, task->residual);
        }
        CU_ASSERT_EQUAL(task->residual, block_size);

        scsi_free_scsi_task(task);
        task = NULL;




        logging(LOG_VERBOSE, "Verify that if iSCSI EDTL > SCSI TL then we only write SCSI TL amount of data");

        logging(LOG_VERBOSE, "Write two blocks of 'a'");
        memset(buf, 'a', 10000);
        WRITE10(sd, 0, 2 * block_size, block_size, 0, 0, 0, 0, 0, buf,
                EXPECT_STATUS_GOOD);

        logging(LOG_VERBOSE, "Write one block of 'b' but set iSCSI EDTL to 2 blocks.");
        task = malloc(sizeof(struct scsi_task));
        CU_ASSERT_PTR_NOT_NULL_FATAL(task);

        memset(buf, 'b', 10000);

        memset(task, 0, sizeof(struct scsi_task));
        task->cdb[0] = SCSI_OPCODE_WRITE_VERIFY10;
        task->cdb[1] = 2; /* BYTCHK = 1 */
        task->cdb[8] = 1;
        task->cdb_size = 10;
        task->xfer_dir = SCSI_XFER_WRITE;
        task->expxferlen = 2 * block_size;

        data.size = task->expxferlen;
        data.data = &buf[0];
        task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data);
        CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);

        logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
        if (task->status != SCSI_STATUS_GOOD) {
                logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
                        iscsi_get_error(sd->iscsi_ctx));
        }
        CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);

        logging(LOG_VERBOSE, "Verify residual underflow flag is set");
        if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) {
                logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
                        "underflow flag");
        }
        CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW);

        logging(LOG_VERBOSE, "Verify we got one block of residual underflow");
        if (task->residual != block_size) {
                logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
                        "amount of residual. Expected %zu but got %zu.",
                        block_size, task->residual);
        }
        CU_ASSERT_EQUAL(task->residual, block_size);
        scsi_free_scsi_task(task);
        task = NULL;

        logging(LOG_VERBOSE, "Read the two blocks");
        READ10(sd, NULL, 0, 2* block_size, block_size, 0, 0, 0, 0, 0, buf,
               EXPECT_STATUS_GOOD);

        logging(LOG_VERBOSE, "Verify that the first block was changed to 'b'");
        for (i = 0; i < block_size; i++) {
                if (buf[i] != 'b') {
                        logging(LOG_NORMAL, "First block did not contain expected 'b'");
                        CU_FAIL("Block was not written correctly");
                        break;
                }
        }

        logging(LOG_VERBOSE, "Verify that the second block was NOT overwritten and still contains 'a'");
        for (i = block_size; i < 2 * block_size; i++) {
                if (buf[i] != 'a') {
                        logging(LOG_NORMAL, "Second block was overwritten and no longer contain 'a'");
                        CU_FAIL("Second block was incorrectly overwritten");
                        break;
                }
        }


        logging(LOG_VERBOSE, "Verify that if iSCSI EDTL < SCSI TL then we only write iSCSI EDTL amount of data");

        logging(LOG_VERBOSE, "Write two blocks of 'a'");
        memset(buf, 'a', 10000);
        WRITE10(sd, 0, 2 * block_size, block_size, 0, 0, 0, 0, 0, buf,
                EXPECT_STATUS_GOOD);

        logging(LOG_VERBOSE, "Write two blocks of 'b' but set iSCSI EDTL to 1 blocks.");
        task = malloc(sizeof(struct scsi_task));
        CU_ASSERT_PTR_NOT_NULL_FATAL(task);

        memset(buf, 'b', 10000);

        memset(task, 0, sizeof(struct scsi_task));
        task->cdb[0] = SCSI_OPCODE_WRITE_VERIFY10;
        task->cdb[1] = 2; /* BYTCHK = 1 */
        task->cdb[8] = 2;
        task->cdb_size = 10;
        task->xfer_dir = SCSI_XFER_WRITE;
        task->expxferlen = block_size;

        data.size = task->expxferlen;
        data.data = &buf[0];
        task_ret = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun, task, &data);
        CU_ASSERT_PTR_NOT_NULL_FATAL(task_ret);

        logging(LOG_VERBOSE, "Verify that the target returned SUCCESS");
        if (task->status != SCSI_STATUS_GOOD) {
                logging(LOG_VERBOSE, "[FAILED] Target returned error %s",
                        iscsi_get_error(sd->iscsi_ctx));
        }
        CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD);

        logging(LOG_VERBOSE, "Verify residual overflow flag is set");
        if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) {
                logging(LOG_VERBOSE, "[FAILED] Target did not set residual "
                        "overflow flag");
        }
        CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW);

        logging(LOG_VERBOSE, "Verify we got one block of residual overflow");
        if (task->residual != block_size) {
                logging(LOG_VERBOSE, "[FAILED] Target did not set correct "
                        "amount of residual. Expected %zu but got %zu.",
                        block_size, task->residual);
        }
        CU_ASSERT_EQUAL(task->residual, block_size);
        scsi_free_scsi_task(task);
        task = NULL;

        logging(LOG_VERBOSE, "Read the two blocks");
        READ10(sd, NULL, 0, 2* block_size, block_size, 0, 0, 0, 0, 0, buf,
               EXPECT_STATUS_GOOD);

        logging(LOG_VERBOSE, "Verify that the first block was changed to 'b'");
        for (i = 0; i < block_size; i++) {
                if (buf[i] != 'b') {
                        logging(LOG_NORMAL, "First block did not contain expected 'b'");
                        CU_FAIL("Block was not written correctly");
                        break;
                }
        }

        logging(LOG_VERBOSE, "Verify that the second block was NOT overwritten and still contains 'a'");
        for (i = block_size; i < 2 * block_size; i++) {
                if (buf[i] != 'a') {
                        logging(LOG_NORMAL, "Second block was overwritten and no longer contain 'a'");
                        CU_FAIL("Second block was incorrectly overwritten");
                        break;
                }
        }
}
Exemplo n.º 8
0
void
test_verify16_dpo(void)
{ 
        int dpofua, usage_data_dpo;
        struct scsi_task *ms_task = NULL;
        struct scsi_mode_sense *ms;
        struct scsi_task *rso_task = NULL;
        struct scsi_report_supported_op_codes_one_command *rsoc;

        logging(LOG_VERBOSE, LOG_BLANK_LINE);
        logging(LOG_VERBOSE, "Test VERIFY16 DPO flag");

        CHECK_FOR_SBC;

        READ10(sd, NULL, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
               EXPECT_STATUS_GOOD);

        logging(LOG_VERBOSE, "Read the DPOFUA flag from mode sense data");
        MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT,
                   SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255,
                   EXPECT_STATUS_GOOD);

        logging(LOG_VERBOSE, "[SUCCESS] Mode sense returned status GOOD");
        ms = scsi_datain_unmarshall(ms_task);
        dpofua = ms && (ms->device_specific_parameter & 0x10);
        scsi_free_scsi_task(ms_task);

        if (dpofua) {
                logging(LOG_VERBOSE, "DPOFUA flag is set. Device should allow "
                        "DPO/FUA flags in CDBs");
        } else {
                logging(LOG_VERBOSE, "DPOFUA flag is clear. Device should fail "
                        "CDBs with DPO/FUA set");
        }

        logging(LOG_VERBOSE, "Test VERIFY16 with DPO==1");
        if (dpofua) {
                VERIFY16(sd, 0, block_size, block_size, 0, 1, 0, scratch,
                         EXPECT_STATUS_GOOD);
        } else {
                VERIFY16(sd, 0, block_size, block_size, 0, 1, 0, scratch,
                         EXPECT_INVALID_FIELD_IN_CDB);
        }

        logging(LOG_VERBOSE, "Try fetching REPORT_SUPPORTED_OPCODES "
                "for VERIFY16");
        REPORT_SUPPORTED_OPCODES(sd, &rso_task,
                                 0, SCSI_REPORT_SUPPORTING_OPCODE,
                                 SCSI_OPCODE_VERIFY16,
                                 0,
                                 65535,
                                 EXPECT_STATUS_GOOD);
        logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer");
        rsoc = scsi_datain_unmarshall(rso_task);
        CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc);

        usage_data_dpo = rsoc ? rsoc->cdb_usage_data[1] & 0x10 : -1;
        if (dpofua) {
                logging(LOG_VERBOSE, "DPOFUA is set. Verify the DPO flag "
                        "is set in the CDB_USAGE_DATA");
                CU_ASSERT_EQUAL(usage_data_dpo, 0x10);
        } else {
                logging(LOG_VERBOSE, "DPOFUA is clear. Verify the DPO "
                        "flag is clear in the CDB_USAGE_DATA");
                CU_ASSERT_EQUAL(usage_data_dpo, 0x00);
        }

        scsi_free_scsi_task(rso_task);
}