void
test_reserve6_itnexus_loss(void)
{
	int ret;


	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test that RESERVE6 is released on it-nexus loss");


	logging(LOG_NORMAL, "Take out a RESERVE6 from the first initiator");
	ret = reserve6(iscsic, tgt_lun);
	if (ret == -2) {
		logging(LOG_VERBOSE, "[SKIPPED] Target does not support RESERVE6. Skipping test");
		CU_PASS("[SKIPPED] Target does not support RESERVE6. Skipping test");
		return;
	}
	CU_ASSERT_EQUAL(ret, 0);


	logging(LOG_VERBOSE, "Create a second connection to the target");
	iscsic2 = iscsi_context_login(initiatorname1, tgt_url, &tgt_lun);
	if (iscsic2 == NULL) {
		logging(LOG_VERBOSE, "Failed to login to target");
		return;
	}

	logging(LOG_NORMAL, "Try to take out a RESERVE6 from the second initiator");
	ret = reserve6_conflict(iscsic2, tgt_lun);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "Disconnect from the target.");
	iscsi_destroy_context(iscsic);

	logging(LOG_VERBOSE, "Sleep for three seconds incase the target is slow to reset");
	sleep(3);

	logging(LOG_VERBOSE, "Reconnect to target");
	iscsic = iscsi_context_login(initiatorname1, tgt_url, &tgt_lun);
	if (iscsic == NULL) {
		logging(LOG_VERBOSE, "Failed to login to target");
		return;
	}

	logging(LOG_NORMAL, "RESERVE6 from the second initiator should work now");
	ret = reserve6(iscsic2, tgt_lun);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_NORMAL, "RELEASE6 from the second initiator");
	ret = release6(iscsic2, tgt_lun);
	CU_ASSERT_EQUAL(ret, 0);
}
void
test_reserve6_logout(void)
{
	int ret;


	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test that RESERVE6 is released on logout");


	logging(LOG_NORMAL, "Take out a RESERVE6 from the first initiator");
	ret = reserve6(iscsic, tgt_lun);
	if (ret == -2) {
		logging(LOG_VERBOSE, "[SKIPPED] Target does not support RESERVE6. Skipping test");
		CU_PASS("[SKIPPED] Target does not support RESERVE6. Skipping test");
		return;
	}
	CU_ASSERT_EQUAL(ret, 0);


	logging(LOG_VERBOSE, "Create a second connection to the target");
	iscsic2 = iscsi_context_login(initiatorname1, tgt_url, &tgt_lun);
	if (iscsic2 == NULL) {
		logging(LOG_VERBOSE, "Failed to login to target");
		return;
	}

	logging(LOG_NORMAL, "Try to take out a RESERVE6 from the second initiator");
	ret = reserve6_conflict(iscsic2, tgt_lun);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "Logout from target");
	iscsi_logout_sync(iscsic);

	logging(LOG_VERBOSE, "Relogin to target");
	iscsic = iscsi_context_login(initiatorname1, tgt_url, &tgt_lun);
	if (iscsic == NULL) {
		logging(LOG_VERBOSE, "Failed to login to target");
		return;
	}

	logging(LOG_NORMAL, "RESERVE6 from the second initiator should work now");
	ret = reserve6(iscsic2, tgt_lun);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_NORMAL, "RELEASE6 from the second initiator");
	ret = release6(iscsic2, tgt_lun);
	CU_ASSERT_EQUAL(ret, 0);
}
Example #3
0
static int connect_scsi_device(struct scsi_device *sdev, const char *initiatorname)
{
	if (sdev->iscsi_url) {
		sdev->iscsi_ctx = iscsi_context_login(initiatorname, sdev->iscsi_url, &sdev->iscsi_lun);
		if (sdev->iscsi_ctx == NULL) {
			return -1;
		}
		return 0;
	}
#ifdef HAVE_SG_IO
	if (sdev->sgio_dev) {
		int version;

		if ((sdev->sgio_fd = open(sdev->sgio_dev, O_RDWR|O_NONBLOCK)) == -1) {
			fprintf(stderr, "Failed to open SG_IO device %s. Error:%s\n", sdev->sgio_dev,
				strerror(errno));
			return -1;
		}
		if ((ioctl(sdev->sgio_fd, SG_GET_VERSION_NUM, &version) < 0) || (version < 30000)) {
			fprintf(stderr, "%s is not a SCSI device node\n", sdev->sgio_dev);
			close(sdev->sgio_fd);
			return -1;
		}
		if (ioctl(sdev->sgio_fd, BLKSECTGET, &maxsectbytes) < 0) {
			fprintf(stderr, "%s failed to read BLKMAXSECT\n", sdev->sgio_dev);
			close(sdev->sgio_fd);
			return -1;
		}
		return 0;
	}
#endif
	return -1;
}
void
test_reserve6_target_warm_reset(void)
{
	int ret;
	struct scsi_device sd2;

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test that RESERVE6 is released on target warm reset");

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

	logging(LOG_VERBOSE, "Take out a RESERVE6 from the first initiator");
	ret = reserve6(sd);
	if (ret == -2) {
		logging(LOG_VERBOSE, "[SKIPPED] Target does not support RESERVE6. Skipping test");
		CU_PASS("[SKIPPED] Target does not support RESERVE6. Skipping test");
		return;
	}
	CU_ASSERT_EQUAL(ret, 0);


	logging(LOG_VERBOSE, "Send a Warm Reset to the target");
	ret = iscsi_task_mgmt_target_warm_reset_sync(sd->iscsi_ctx);
	if (ret != 0) {
		logging(LOG_NORMAL, "Warm reset failed. %s", iscsi_get_error(sd->iscsi_ctx));
	}
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "Sleep for three seconds incase the target is slow to reset");
	sleep(3);


	logging(LOG_VERBOSE, "Create a second connection to the target");
	memset(&sd2, 0, sizeof(sd2));
	sd2.iscsi_url = sd->iscsi_url;
	sd2.iscsi_lun = sd->iscsi_lun;
	sd2.iscsi_ctx = iscsi_context_login(initiatorname2, sd2.iscsi_url, &sd2.iscsi_lun);
	if (sd2.iscsi_ctx == NULL) {
		logging(LOG_VERBOSE, "Failed to login to target");
		return;
	}


	logging(LOG_VERBOSE, "RESERVE6 from the second initiator should work now");
	ret = reserve6(&sd2);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "RELEASE6 from the second initiator");
	ret = release6(&sd2);
	CU_ASSERT_EQUAL(ret, 0);

	iscsi_logout_sync(sd2.iscsi_ctx);
	iscsi_destroy_context(sd2.iscsi_ctx);
}
Example #5
0
int
suite_init(void)
{
	int i;

	for (i = 0; i < mp_num_sds; i++) {
		if (!mp_sds[i]->iscsi_url) {
			continue;
		}
		if (mp_sds[i]->iscsi_ctx) {
			iscsi_logout_sync(mp_sds[i]->iscsi_ctx);
			iscsi_destroy_context(mp_sds[i]->iscsi_ctx);
		}
		mp_sds[i]->iscsi_ctx = iscsi_context_login(initiatorname1,
							mp_sds[i]->iscsi_url,
							&mp_sds[i]->iscsi_lun);
		if (mp_sds[i]->iscsi_ctx == NULL) {
			fprintf(stderr,
				"error: Failed to login to target for test set-up\n");
			return 1;
		}
	}
#ifndef HAVE_CU_SUITEINFO_PSETUPFUNC
	/* libcunit version 1 */
	test_setup();
#endif
	return 0;
}
void
test_prout_reserve_ownership_ea(void)
{
	struct scsi_device sd2;

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

	memset(&sd2, 0, sizeof(sd2));
	sd2.iscsi_url = sd->iscsi_url;
	sd2.iscsi_lun = sd->iscsi_lun;
	sd2.iscsi_ctx = iscsi_context_login(initiatorname2, sd2.iscsi_url, &sd2.iscsi_lun);
	if (sd2.iscsi_ctx == NULL) {
		logging(LOG_VERBOSE, "Failed to login to target");
		return;
	}
	verify_persistent_reserve_ownership(sd, &sd2,
	    SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS, 0);
	iscsi_destroy_context(sd2.iscsi_ctx);
}
void
test_preventallow_logout(void)
{
        CHECK_FOR_SBC;
        CHECK_FOR_REMOVABLE;

        logging(LOG_VERBOSE, LOG_BLANK_LINE);
        logging(LOG_VERBOSE, "Test that Logout loss clears PREVENT MEDIUM REMOVAL");

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

        logging(LOG_VERBOSE, "Set the PREVENT flag");
        PREVENTALLOW(sd, 1);

        logging(LOG_VERBOSE, "Try to eject the medium");
        STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
                      EXPECT_REMOVAL_PREVENTED);

        logging(LOG_VERBOSE, "Verify we can still access the media.");
        TESTUNITREADY(sd,
                      EXPECT_STATUS_GOOD);

        logging(LOG_VERBOSE, "Logout from target");
        iscsi_logout_sync(sd->iscsi_ctx);
        iscsi_destroy_context(sd->iscsi_ctx);

        logging(LOG_VERBOSE, "Relogin to target");
        sd->iscsi_ctx = iscsi_context_login(initiatorname1, sd->iscsi_url, &sd->iscsi_lun);
        if (sd->iscsi_ctx == NULL) {
                logging(LOG_VERBOSE, "Failed to login to target");
                return;
        }

        logging(LOG_VERBOSE, "Try to eject the medium");
        STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
                      EXPECT_STATUS_GOOD);

        logging(LOG_VERBOSE, "Verify we can not access the media.");
        TESTUNITREADY(sd,
                      EXPECT_NO_MEDIUM);

        logging(LOG_VERBOSE, "Load the medium");
        STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 0,
                      EXPECT_STATUS_GOOD);

        logging(LOG_VERBOSE, "Clear PREVENT and load medium in case target failed");
        logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
        PREVENTALLOW(sd, 0);

        logging(LOG_VERBOSE, "Load the medium");
        STARTSTOPUNIT(sd, 0, 0, 0, 0, 1, 1,
                      EXPECT_STATUS_GOOD);
}
void
test_reserve6_logout(void)
{
	int ret;
	struct scsi_device *sd2;

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test that RESERVE6 is released on logout");

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

	logging(LOG_NORMAL, "Take out a RESERVE6 from the first initiator");
	ret = reserve6(sd);
	if (ret == -2) {
		logging(LOG_VERBOSE, "[SKIPPED] Target does not support RESERVE6. Skipping test");
		CU_PASS("[SKIPPED] Target does not support RESERVE6. Skipping test");
		return;
	}
	CU_ASSERT_EQUAL(ret, 0);


	logging(LOG_VERBOSE, "Create a second connection to the target");
	ret = mpath_sd2_get_or_clone(sd, &sd2);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_NORMAL, "Try to take out a RESERVE6 from the second initiator");
	ret = reserve6_conflict(sd2);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "Logout from target");
	iscsi_logout_sync(sd->iscsi_ctx);
	iscsi_destroy_context(sd->iscsi_ctx);

	logging(LOG_VERBOSE, "Relogin to target");
	sd->iscsi_ctx = iscsi_context_login(initiatorname1, sd->iscsi_url, &sd->iscsi_lun);
	if (sd->iscsi_ctx == NULL) {
		logging(LOG_VERBOSE, "Failed to login to target");
		return;
	}

	logging(LOG_NORMAL, "RESERVE6 from the second initiator should work now");
	ret = reserve6(sd2);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_NORMAL, "RELEASE6 from the second initiator");
	ret = release6(sd2);
	CU_ASSERT_EQUAL(ret, 0);

	mpath_sd2_put(sd2);
}
Example #9
0
int
suite_init_pgr(void)
{
	suite_init();
	iscsic2 = iscsi_context_login(initiatorname2, tgt_url, &tgt_lun2);
	if (iscsic2 == NULL) {
		fprintf(stderr,
		    "error: Failed to login to target for test set-up\n");
		suite_cleanup();
		return 1;
	}
	return 0;
}
Example #10
0
int T0211_read12_rdprotect(const char *initiator, const char *url)
{
    struct iscsi_context *iscsi;
    struct scsi_task *task;
    int ret = 0, i, lun;

    printf("0211_read12_rdprotect:\n");
    printf("======================\n");
    if (show_info) {
        printf("Test how READ12 handles the rdprotect bits\n");
        printf("1, Any non-zero valued for rdprotect should fail.\n");
        printf("\n");
        return 0;
    }

    iscsi = iscsi_context_login(initiator, url, &lun);
    if (iscsi == NULL) {
        printf("Failed to login to target\n");
        return -1;
    }


    printf("Read12 with RDPROTECT ");
    for (i = 1; i <= 7; i++) {
        task = iscsi_read12_sync(iscsi, lun, 0, block_size, block_size, i, 0, 0, 0, 0);
        if (task == NULL) {
            printf("[FAILED]\n");
            printf("Failed to send read12 command: %s\n", iscsi_get_error(iscsi));
            ret = -1;
            goto finished;
        }
        if (task->status        != SCSI_STATUS_CHECK_CONDITION
                || task->sense.key  != SCSI_SENSE_ILLEGAL_REQUEST
                || task->sense.ascq != SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB) {
            printf("[FAILED]\n");
            printf("Read12 with RDPROTECT!=0 should have failed with CHECK_CONDITION/ILLEGAL_REQUEST/INVALID_FIELD_IN_CDB\n");
            ret = -1;
            scsi_free_scsi_task(task);
            goto finished;
        }
        scsi_free_scsi_task(task);
    }
    printf("[OK]\n");


finished:
    iscsi_logout_sync(iscsi);
    iscsi_destroy_context(iscsi);
    return ret;
}
Example #11
0
int
suite_init(void)
{
	iscsic = iscsi_context_login(initiatorname1, tgt_url, &tgt_lun);
	if (iscsic == NULL) {
		fprintf(stderr,
		    "error: Failed to login to target for test set-up\n");
		return 1;
	}
#ifndef HAVE_CU_SUITEINFO_PSETUPFUNC
	/* libcunit version 1 */
	test_setup();
#endif
	return 0;
}
void
test_reserve6_target_cold_reset(void)
{
	int ret;


	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test that RESERVE6 is released on target cold reset");


	logging(LOG_VERBOSE, "Take out a RESERVE6 from the first initiator");
	ret = reserve6(iscsic, tgt_lun);
	if (ret == -2) {
		logging(LOG_VERBOSE, "[SKIPPED] Target does not support RESERVE6. Skipping test");
		CU_PASS("[SKIPPED] Target does not support RESERVE6. Skipping test");
		return;
	}
	CU_ASSERT_EQUAL(ret, 0);


	logging(LOG_VERBOSE, "Send a Cold Reset to the target");
	ret = iscsi_task_mgmt_target_cold_reset_sync(iscsic);
	if (ret != 0) {
		logging(LOG_NORMAL, "Cold reset failed. %s", iscsi_get_error(iscsic));
	}
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "Sleep for three seconds incase the target is slow to reset");
	sleep(3);

	logging(LOG_VERBOSE, "Create a second connection to the target");
	iscsic2 = iscsi_context_login(initiatorname1, tgt_url, &tgt_lun);
	if (iscsic2 == NULL) {
		logging(LOG_VERBOSE, "Failed to login to target");
		return;
	}

	logging(LOG_VERBOSE, "RESERVE6 from the second initiator should work now");
	ret = reserve6(iscsic2, tgt_lun);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "RELEASE6 from the second initiator");
	ret = release6(iscsic2, tgt_lun);
	CU_ASSERT_EQUAL(ret, 0);
}
Example #13
0
/*
 * use an existing multi-path connection, or clone iscsi sd1.
 */
int
mpath_sd2_get_or_clone(struct scsi_device *sd1, struct scsi_device **_sd2)
{
	struct scsi_device *sd2;

	if (mp_num_sds > 1) {
		logging(LOG_VERBOSE, "using multipath dev for second session");
		*_sd2 = mp_sds[1];
		return 0;
	}

	if (sd1->iscsi_ctx == NULL) {
		logging(LOG_NORMAL, "can't clone non-iscsi device");
		return -EINVAL;
	}

	logging(LOG_VERBOSE, "cloning sd1 for second session");
	sd2 = malloc(sizeof(*sd2));
	if (sd2 == NULL) {
		return -ENOMEM;
	}

	memset(sd2, 0, sizeof(*sd2));
	sd2->iscsi_url = sd1->iscsi_url;
	sd2->iscsi_lun = sd1->iscsi_lun;
	sd2->iscsi_ctx = iscsi_context_login(initiatorname2, sd2->iscsi_url,
					     &sd2->iscsi_lun);
	if (sd2->iscsi_ctx == NULL) {
		logging(LOG_VERBOSE, "Failed to login to target");
		free(sd2);
		return -ENOMEM;
	}
	*_sd2 = sd2;

	return 0;
}
void
test_preventallow_2_itnexuses(void)
{
	int ret;
	struct scsi_device sd2;

	CHECK_FOR_SBC;
	CHECK_FOR_REMOVABLE;

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test that PREVENT MEDIUM REMOVAL are seen on other nexuses as well");

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

	logging(LOG_VERBOSE, "Set the PREVENT flag");
	ret = preventallow(sd, 1);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "Try to eject the medium");
	ret = startstopunit(sd, 0, 0, 0, 0, 1, 0,
			    EXPECT_REMOVAL_PREVENTED);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "Verify we can still access the media.");
	ret = testunitready(sd,
			    EXPECT_STATUS_GOOD);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "Create a second connection to the target");
	memset(&sd2, 0, sizeof(sd2));
	sd2.iscsi_ctx = iscsi_context_login(initiatorname2, sd->iscsi_url, &sd->iscsi_lun);
	if (sd2.iscsi_ctx == NULL) {
		logging(LOG_VERBOSE, "Failed to login to target");
		return;
	}

	logging(LOG_VERBOSE, "Try to eject the medium on the second connection");
	ret = startstopunit(&sd2, 0, 0, 0, 0, 1, 0,
			    EXPECT_REMOVAL_PREVENTED);
	CU_ASSERT_EQUAL(ret, 0);


	logging(LOG_VERBOSE, "Logout the second connection from target");
	iscsi_logout_sync(sd2.iscsi_ctx);
	iscsi_destroy_context(sd2.iscsi_ctx);



	logging(LOG_VERBOSE, "Clear PREVENT and load medium in case target failed");
	logging(LOG_VERBOSE, "Test we can clear PREVENT flag");
	ret = preventallow(sd, 0);
	CU_ASSERT_EQUAL(ret, 0);

	logging(LOG_VERBOSE, "Load the medium");
	ret = startstopunit(sd, 0, 0, 0, 0, 1, 1,
			    EXPECT_STATUS_GOOD);
	CU_ASSERT_EQUAL(ret, 0);

}
int T1145_persistent_reserve_access_check_wear(const char *initiator,
    const char *url)
{
	struct iscsi_context *iscsi = NULL, *iscsi2 = NULL;
	int ret;
	int lun, lun2;
	const unsigned long long key = rand_key();
	const unsigned long long key2 = rand_key();
	const enum scsi_persistent_out_type pr_type = 
		SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_ALL_REGISTRANTS;
	const char *pr_type_str = scsi_pr_type_str(pr_type);
	unsigned char *buf = NULL;


	printf("1145_persistent_reserve_access_check_wear:\n");
	printf("=========================================\n");
	if (show_info) {
		int idx = 1;

		printf("Test that access constrols are correct for %s Persistent Reservations\n",
		    pr_type_str);
		printf("%d, %s Reservation Holder Read Access\n",
		    idx++, pr_type_str);
		printf("%d, %s Reservation Holder Write Access\n",
		    idx++, pr_type_str);
		printf("%d, non-%s Reservation Holder does not have read access\n",
		    idx++, pr_type_str);
		printf("%d, non-%s Reservation Holder does not have write access\n",
		    idx++, pr_type_str);
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		ret = -1;
		goto finished;
	}
	iscsi2 = iscsi_context_login(initiatorname2, url, &lun2);
	if (iscsi2 == NULL) {
		printf("Failed to login to target (2nd initiator)\n");
		ret = -1;
		goto finished;
	}

	if (!data_loss) {
		printf("--dataloss flag is not set. Skipping test\n");
		ret = -2;
		goto finished;
	}
	
	/* register our reservation key with the target */
	ret = register_and_ignore(iscsi, lun, key);
	if (ret != 0)
		goto finished;
	ret = register_and_ignore(iscsi2, lun2, key2);
	if (ret != 0)
		goto finished;

	/* reserve the target through initiator 1 */
	ret = reserve(iscsi, lun, key, pr_type);
	if (ret != 0)
		goto finished;

	/* verify target reservation */
	ret = verify_reserved_as(iscsi, lun,
	    pr_type_is_all_registrants(pr_type) ? 0 : key,
	    pr_type);
	if (ret != 0)
		goto finished;

	buf = malloc(512);			/* allocate a buffer */
	if (buf == NULL) {
		printf("failed to allocate 512 byes of memory\n");
		ret = -1;
		goto finished;
	}

	/* make sure init1 can read */
	ret = verify_read_works(iscsi, lun, buf);
	if (ret != 0)
		goto finished;

	/* make sure init1 can write */
	ret = verify_write_works(iscsi, lun, buf);
	if (ret != 0)
		goto finished;

	/* make sure init2 does have read access */
	ret = verify_read_works(iscsi2, lun2, buf);
	if (ret != 0)
		goto finished;

	/* make sure init2 does have write access */
	ret = verify_write_works(iscsi2, lun2, buf);
	if (ret != 0)
		goto finished;

	/* unregister init2 */
	ret = register_key(iscsi2, lun2, 0, key);
	if (ret != 0) {
		goto finished;
	}

	/* make sure init2 does have read access */
	ret = verify_read_works(iscsi2, lun2, buf);
	if (ret != 0)
		goto finished;

	/* make sure init2 does not have write access */
	ret = verify_write_fails(iscsi2, lun2, buf);
	if (ret != 0)
		goto finished;

	/* release our reservation */
	ret = release(iscsi, lun, key, pr_type);
	if (ret != 0)
		goto finished;

	/* remove our key from the target */
	ret = register_key(iscsi, lun, 0, key);
	if (ret != 0)
		goto finished;

finished:
	/* XXX should we clean up key if needed? */
	if (iscsi) {
		iscsi_logout_sync(iscsi);
		iscsi_destroy_context(iscsi);
	}
	if (iscsi2) {
		iscsi_logout_sync(iscsi2);
		iscsi_destroy_context(iscsi2);
	}
	if (buf)
		free(buf);
	return ret;
}
int T0234_write12_beyondeol(const char *initiator, const char *url)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	int ret, i, lun;
	unsigned char data[4096 * 258];

	printf("0234_write12_beyond_eol:\n");
	printf("=======================\n");
	if (show_info) {
		printf("Test that WRITE12 fails if writing beyond end-of-lun.\n");
		printf("This test is skipped for LUNs with more than 2^31 blocks\n");
		printf("1, Writing 1-256 blocks beyond end-of-lun should fail.\n");
		printf("\n");
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	if (!data_loss) {
		printf("--dataloss flag is not set. Skipping test\n");
		ret = -2;
		goto finished;
	}


	ret = 0;

	if (num_blocks >= 0x80000000) {
		printf("[SKIPPED]\n");
		printf("LUN is too big for read-beyond-eol tests with WRITE12. Skipping test.\n");
		ret = -2;
		goto finished;
	}

	/* read 1 - 256 blocks beyond the end of the device */
	printf("Writing 1-256 blocks beyond end-of-device ... ");
	for (i = 2; i <= 257; i++) {
		task = iscsi_write12_sync(iscsi, lun, num_blocks, data, i * block_size, block_size, 0, 0, 0, 0, 0);
		if (task == NULL) {
		        printf("[FAILED]\n");
			printf("Failed to send write12 command: %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto finished;
		}
		if (task->status == SCSI_STATUS_GOOD) {
		        printf("[FAILED]\n");
			printf("Write12 command should fail when writing beyond end of device\n");
			ret = -1;
			scsi_free_scsi_task(task);
			goto finished;
		}
		scsi_free_scsi_task(task);
	}
	printf("[OK]\n");


finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
Example #17
0
int T0105_read10_invalid(const char *initiator, const char *url)
{
    struct iscsi_context *iscsi;
    struct scsi_task *task;
    struct iscsi_data data;
    char buf[512];
    int ret, lun;

    iscsi = iscsi_context_login(initiator, url, &lun);
    if (iscsi == NULL) {
        printf("Failed to login to target\n");
        return -1;
    }


    ret = 0;

    /* Try a read of 1 block but xferlength == 0 */
    printf("Read10 1 block but with iscsi ExpectedDataTransferLength==0 ... ");

    task = malloc(sizeof(struct scsi_task));
    if (task == NULL) {
        printf("Failed to allocate task structure\n");
        ret = -1;
        goto finished;
    }

    memset(task, 0, sizeof(struct scsi_task));
    task->cdb[0] = SCSI_OPCODE_READ10;
    task->cdb[8] = 1;
    task->cdb_size = 10;
    task->xfer_dir = SCSI_XFER_READ;
    task->expxferlen = 0;

    if (iscsi_scsi_command_sync(iscsi, lun, task, NULL) == NULL) {
        printf("[FAILED]\n");
        printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
        ret = -1;

        goto finished;
    }
    if (task->status != SCSI_STATUS_GOOD) {
        printf("[FAILED]\n");
        printf("Read10 of 1 block with iscsi ExpectedDataTransferLength==0 should not fail.\n");
        ret = -1;
        scsi_free_scsi_task(task);
        goto test2;
    }
    if (task->residual_status != SCSI_RESIDUAL_OVERFLOW || task->residual != 512) {
        printf("[FAILED]\n");
        printf("Read10 returned incorrect residual overflow.\n");
        ret = -1;
        scsi_free_scsi_task(task);
        goto test5;
    }
    scsi_free_scsi_task(task);
    printf("[OK]\n");


test2:
    /* Try a read of 1 block but xferlength == 1024 */
    printf("Read10 1 block but with iscsi ExpectedDataTransferLength==1024 ... ");

    task = malloc(sizeof(struct scsi_task));
    if (task == NULL) {
        printf("Failed to allocate task structure\n");
        ret = -1;
        goto finished;
    }

    memset(task, 0, sizeof(struct scsi_task));
    task->cdb[0] = SCSI_OPCODE_READ10;
    task->cdb[8] = 1;
    task->cdb_size = 10;
    task->xfer_dir = SCSI_XFER_READ;
    task->expxferlen = 1024;

    if (iscsi_scsi_command_sync(iscsi, lun, task, NULL) == NULL) {
        printf("[FAILED]\n");
        printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
        ret = -1;

        goto finished;
    }
    if (task->status != SCSI_STATUS_GOOD) {
        printf("[FAILED]\n");
        printf("Read10 of 1 block with iscsi ExpectedDataTransferLength==1024 should not fail.\n");
        ret = -1;
        scsi_free_scsi_task(task);
        goto test3;
    }
    if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW || task->residual != 512) {
        printf("[FAILED]\n");
        printf("Read10 returned incorrect residual underflow.\n");
        ret = -1;
        scsi_free_scsi_task(task);
        goto test5;
    }
    scsi_free_scsi_task(task);
    printf("[OK]\n");


test3:
    /* Try a read of 1 block but xferlength == 200 */
    printf("Read10 1 block but with iscsi ExpectedDataTransferLength==200 ... ");

    task = malloc(sizeof(struct scsi_task));
    if (task == NULL) {
        printf("Failed to allocate task structure\n");
        ret = -1;
        goto finished;
    }

    memset(task, 0, sizeof(struct scsi_task));
    task->cdb[0] = SCSI_OPCODE_READ10;
    task->cdb[8] = 1;
    task->cdb_size = 10;
    task->xfer_dir = SCSI_XFER_READ;
    task->expxferlen = 200;

    if (iscsi_scsi_command_sync(iscsi, lun, task, NULL) == NULL) {
        printf("[FAILED]\n");
        printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
        ret = -1;

        goto finished;
    }
    if (task->status != SCSI_STATUS_GOOD) {
        printf("[FAILED]\n");
        printf("Read10 of 1 block with iscsi ExpectedDataTransferLength==200 should not fail.\n");
        ret = -1;
        scsi_free_scsi_task(task);
        goto test4;
    }
    if (task->residual_status != SCSI_RESIDUAL_OVERFLOW || task->residual != 312) {
        printf("[FAILED]\n");
        printf("Read10 returned incorrect residual overflow.\n");
        ret = -1;
        scsi_free_scsi_task(task);
        goto test5;
    }
    scsi_free_scsi_task(task);
    printf("[OK]\n");

test4:
    /* Try a read of 2 blocks but xferlength == 512 */
    printf("Read10 2 blocks but with iscsi ExpectedDataTransferLength==512 ... ");

    task = malloc(sizeof(struct scsi_task));
    if (task == NULL) {
        printf("Failed to allocate task structure\n");
        ret = -1;
        goto finished;
    }

    memset(task, 0, sizeof(struct scsi_task));
    task->cdb[0] = SCSI_OPCODE_READ10;
    task->cdb[8] = 2;
    task->cdb_size = 10;
    task->xfer_dir = SCSI_XFER_READ;
    task->expxferlen = 512;

    if (iscsi_scsi_command_sync(iscsi, lun, task, NULL) == NULL) {
        printf("[FAILED]\n");
        printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
        ret = -1;

        goto finished;
    }
    if (task->status != SCSI_STATUS_GOOD) {
        printf("[FAILED]\n");
        printf("Read10 of 2 blocks with iscsi ExpectedDataTransferLength==512 should succeed.\n");
        ret = -1;
        scsi_free_scsi_task(task);
        goto test5;
    }
    if (task->residual_status != SCSI_RESIDUAL_OVERFLOW || task->residual != 512) {
        printf("[FAILED]\n");
        printf("Read10 returned incorrect residual overflow.\n");
        ret = -1;
        scsi_free_scsi_task(task);
        goto test5;
    }

    scsi_free_scsi_task(task);
    printf("[OK]\n");


test5:
    /* Try a read of 1 block but make it a data-out write on the iscsi layer */
    printf("Read10 of 1 block but sent as data-out write in iscsi layer ... ");

    task = malloc(sizeof(struct scsi_task));
    if (task == NULL) {
        printf("Failed to allocate task structure\n");
        ret = -1;
        goto finished;
    }

    memset(task, 0, sizeof(struct scsi_task));
    task->cdb[0] = SCSI_OPCODE_READ10;
    task->cdb[8] = 1;
    task->cdb_size = 10;
    task->xfer_dir = SCSI_XFER_WRITE;
    task->expxferlen = sizeof(buf);

    data.size = sizeof(buf);
    data.data = &buf[0];

    if (iscsi_scsi_command_sync(iscsi, lun, task, &data) == NULL) {
        printf("[FAILED]\n");
        printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
        ret = -1;

        goto finished;
    }
    if (task->status == SCSI_STATUS_GOOD) {
        printf("[FAILED]\n");
        printf("Read10 of 1 block but iscsi data-out write should fail.\n");
        ret = -1;
        scsi_free_scsi_task(task);
        goto finished;
    }
    scsi_free_scsi_task(task);
    printf("[OK]\n");

finished:
    iscsi_logout_sync(iscsi);
    iscsi_destroy_context(iscsi);
    return ret;
}
int T0360_startstopunit_simple(const char *initiator, const char *url)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	int ret, lun;

	printf("0360_startstopunit_simple:\n");
	printf("===================\n");
	if (show_info) {
		printf("Test basic STARTSTOPUNIT functionality.\n");
		printf("1, Verify we can eject removable the media with IMMED==1\n");
		printf("2, Verify we can load the media back again with IMMED==1\n");
		printf("3, Verify we can eject removable the media with IMMED==0\n");
		printf("4, Verify we can load the media back again with IMMED==0\n");
		printf("\n");
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	if (!data_loss) {
		printf("--dataloss flag is not set. Skipping test\n");
		ret = -2;
		goto finished;
	}
	

	ret = 0;


	if (inq->rmb) {
		printf("Media is removable. STARTSTOPUNIT should work\n");
	} else {
		printf("Media is not removable. STARTSTOPUNIT should fail\n");
	}


	printf("STARTSTOPUNIT try to eject the media with IMMED==1 ... ");
	task = iscsi_startstopunit_sync(iscsi, lun, 1, 0, 0, 0, 1, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send STARTSTOPUNIT command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("STARTSTOPUNIT command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");

	if (inq->rmb) {
		printf("Medium is removable. Check with TESTUNITREADY that was removed.\n");
		ret = testunitready_nomedium(iscsi, lun);
		if (ret != 0) {
			goto finished;
		}
	} else {
		printf("Medium is not removable. Check with TESTUNITREADY that medium is still present.\n");
		ret = testunitready(iscsi, lun);
		if (ret != 0) {
			goto finished;
		}
	}


	printf("STARTSTOPUNIT try to mount the media again with IMMED==1 ... ");
	task = iscsi_startstopunit_sync(iscsi, lun, 1, 0, 0, 0, 1, 1);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send STARTSTOPUNIT command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("STARTSTOPUNIT command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");

	printf("Check with TESTUNITREADY that the medium is present.\n");
	ret = testunitready(iscsi, lun);
	if (ret != 0) {
		goto finished;
	}


	printf("STARTSTOPUNIT try to eject the media with IMMED==0 ... ");
	task = iscsi_startstopunit_sync(iscsi, lun, 0, 0, 0, 0, 1, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send STARTSTOPUNIT command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("STARTSTOPUNIT command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");

	if (inq->rmb) {
		printf("Medium is removable. Check with TESTUNITREADY that was removed.\n");
		ret = testunitready_nomedium(iscsi, lun);
		if (ret != 0) {
			goto finished;
		}
	} else {
		printf("Medium is not removable. Check with TESTUNITREADY that medium is still present.\n");
		ret = testunitready(iscsi, lun);
		if (ret != 0) {
			goto finished;
		}
	}


	printf("STARTSTOPUNIT try to mount the media again with IMMED==0 ... ");
	task = iscsi_startstopunit_sync(iscsi, lun, 0, 0, 0, 0, 1, 1);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send STARTSTOPUNIT command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("STARTSTOPUNIT command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	printf("Check with TESTUNITREADY that the medium is present.\n");
	ret = testunitready(iscsi, lun);
	if (ret != 0) {
		goto finished;
	}


finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
int T0293_write10_0blocks(const char *initiator, const char *url, int data_loss, int show_info)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_readcapacity16 *rc16;
	int ret = 0, lun;
	uint32_t block_size;
	uint32_t num_blocks;

	printf("0293_write10_0blocks:\n");
	printf("====================\n");
	if (show_info) {
		printf("Test that WRITE10 works correctly when writing 0 number of blocks.\n");
		printf("1, Read at LBA:0 should work.\n");
		printf("2, Read at LBA:end-of-lun should work.\n");
		printf("3, Read at LBA:end-of-lun+1 should fail.\n");
		printf("\n");
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	/* find the size of the LUN */
	task = iscsi_readcapacity16_sync(iscsi, lun);
	if (task == NULL) {
		printf("Failed to send READCAPACITY16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("READCAPACITY16 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	rc16 = scsi_datain_unmarshall(task);
	if (rc16 == NULL) {
		printf("failed to unmarshall READCAPACITY16 data. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}

	block_size = rc16->block_length;
	num_blocks = rc16->returned_lba;
	scsi_free_scsi_task(task);

	if (!data_loss) {
		printf("--dataloss flag is not set. Skipping test\n");
		ret = -1;
		goto finished;
	}


	printf("Write10 0blocks at LBA:0 ");
	task = iscsi_write10_sync(iscsi, lun, 0, NULL, 0, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send write10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("Write10 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

	printf("Write10 0blocks at LBA:<end-of-disk> ");
	task = iscsi_write10_sync(iscsi, lun, num_blocks, NULL, 0, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send write10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("Write10 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

	printf("Write10 0blocks at LBA:<beyond end-of-disk> ");
	task = iscsi_write10_sync(iscsi, lun, num_blocks + 1, NULL, 0, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send write10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("Write10 command: Should fail when writing 0blocks beyond end\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
int T0231_write12_wrprotect(const char *initiator, const char *url, int data_loss, int show_info)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_readcapacity16 *rc16;
	int ret = 0, i, lun;
	uint32_t block_size;
	unsigned char data[4096];

	printf("0231_write12_wrprotect:\n");
	printf("======================\n");
	if (show_info) {
		printf("Test how WRITE12 handles the wrprotect bits\n");
		printf("1, Any non-zero valued for wrprotect should fail.\n");
		printf("\n");
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	/* find the size of the LUN */
	task = iscsi_readcapacity16_sync(iscsi, lun);
	if (task == NULL) {
		printf("Failed to send READCAPACITY16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("READCAPACITY16 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	rc16 = scsi_datain_unmarshall(task);
	if (rc16 == NULL) {
		printf("failed to unmarshall READCAPACITY16 data. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}

	block_size = rc16->block_length;

	if(rc16->prot_en != 0) {
		printf("device is formatted with protection information, skipping test\n");
		scsi_free_scsi_task(task);
		ret = -2;
		goto finished;
	}
	scsi_free_scsi_task(task);

	if (!data_loss) {
		printf("--dataloss flag is not set. Skipping test\n");
		ret = -2;
		goto finished;
	}

	printf("Write12 with RDPROTECT ");
	for (i = 1; i <= 7; i++) {
		task = iscsi_write12_sync(iscsi, lun, 0, data, block_size, block_size, i, 0, 0, 0, 0);
		if (task == NULL) {
		        printf("[FAILED]\n");
			printf("Failed to send write12 command: %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto finished;
		}
		if (task->status        != SCSI_STATUS_CHECK_CONDITION
		    || task->sense.key  != SCSI_SENSE_ILLEGAL_REQUEST
		    || task->sense.ascq != SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB) {
		        printf("[FAILED]\n");
			printf("Write12 with RDPROTECT!=0 should have failed with CHECK_CONDITION/ILLEGAL_REQUEST/INVALID_FIELD_IN_CDB\n");
			ret = -1;
			scsi_free_scsi_task(task);
			goto finished;
		}
		scsi_free_scsi_task(task);
	}
	printf("[OK]\n");

finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
int T0294_write10_beyondeol(const char *initiator, const char *url, int data_loss, int show_info)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_readcapacity16 *rc16;
	int ret, i, lun;
	uint32_t block_size;
	uint32_t num_blocks;
	unsigned char data[258 * 512];

	printf("0294_write10_beyond_eol:\n");
	printf("=======================\n");
	if (show_info) {
		printf("Test that WRITE10 fails if writing beyond end-of-lun.\n");
		printf("1, Writing 1-256 blocks beyond end-of-lun should fail.\n");
		printf("\n");
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	/* find the size of the LUN */
	task = iscsi_readcapacity16_sync(iscsi, lun);
	if (task == NULL) {
		printf("Failed to send READCAPACITY16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("READCAPACITY16 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	rc16 = scsi_datain_unmarshall(task);
	if (rc16 == NULL) {
		printf("failed to unmarshall READCAPACITY10 data. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	block_size = rc16->block_length;
	num_blocks = rc16->returned_lba;
	scsi_free_scsi_task(task);

	if (!data_loss) {
		printf("--dataloss flag is not set. Skipping test\n");
		ret = -1;
		goto finished;
	}


	ret = 0;

	/* read 1 - 256 blocks beyond the end of the device */
	printf("Writing 1-256 blocks beyond end-of-device ... ");
	for (i = 2; i <= 257; i++) {
		task = iscsi_write10_sync(iscsi, lun, num_blocks, data, i * block_size, block_size, 0, 0, 0, 0, 0);
		if (task == NULL) {
		        printf("[FAILED]\n");
			printf("Failed to send write10 command: %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto finished;
		}
		if (task->status == SCSI_STATUS_GOOD) {
		        printf("[FAILED]\n");
			printf("Write10 command should fail when writing beyond end of device\n");
			ret = -1;
			scsi_free_scsi_task(task);
			goto finished;
		}
		scsi_free_scsi_task(task);
	}
	printf("[OK]\n");


finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
Example #22
0
int T0170_unmap_simple(const char *initiator, const char *url, int data_loss, int show_info)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_readcapacity16 *rc16;
	int ret, i, lun;
	uint32_t block_size, num_blocks;

	printf("0170_unmap_simple:\n");
	printf("==================\n");
	if (show_info) {
		printf("Test basic UNMAP functionality.\n");
		printf("1, Test UNMAP the first 1-256 blocks of the LUN.\n");
		printf("2, Test UNMAP the last 1-256 blocks of the LUN.\n");
		printf("\n");
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	/* find the size of the LUN */
	task = iscsi_readcapacity16_sync(iscsi, lun);
	if (task == NULL) {
		printf("Failed to send readcapacity16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("Readcapacity command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	rc16 = scsi_datain_unmarshall(task);
	if (rc16 == NULL) {
		printf("failed to unmarshall readcapacity16 data. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}

	if (rc16->lbpme == 0){
		printf("Logical unit is fully provisioned. Skipping test\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}

	block_size = rc16->block_length;
	num_blocks = rc16->returned_lba;

	scsi_free_scsi_task(task);

	if (!data_loss) {
		printf("data_loss flag is not set. Skipping test\n");
		ret = -1;
		goto finished;
	}
	
	ret = 0;

	/* unmap the first 1 - 256 blocks at the start of the LUN */
	printf("Unmapping first 1-256 blocks ... ");
	for (i=1; i<=256; i++) {
		struct unmap_list list[1];

		list[0].lba = 0;
		list[0].num = i;
		task = iscsi_unmap_sync(iscsi, lun, 0, 0, &list[0], 1);
		if (task == NULL) {
		        printf("[FAILED]\n");
			printf("Failed to send UNMAP command: %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto finished;
		}
		if (task->status != SCSI_STATUS_GOOD) {
		        printf("[FAILED]\n");
			printf("UNMAP command: failed with sense. %s\n", iscsi_get_error(iscsi));
			ret = -1;
			scsi_free_scsi_task(task);
			goto finished;
		}
		scsi_free_scsi_task(task);
	}
	printf("[OK]\n");


	/* unmap the last 1 - 256 blocks at the end of the LUN */
	printf("Unmapping last 1-256 blocks ... ");
	for (i=1; i<=256; i++) {
		struct unmap_list list[1];

		list[0].lba = num_blocks + 1 - i;
		list[0].num = i;
		task = iscsi_unmap_sync(iscsi, lun, 0, 0, &list[0], 1);
		if (task == NULL) {
		        printf("[FAILED]\n");
			printf("Failed to send UNMAP command: %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto finished;
		}
		if (task->status != SCSI_STATUS_GOOD) {
		        printf("[FAILED]\n");
			printf("UNMAP command: failed with sense. %s\n", iscsi_get_error(iscsi));
			ret = -1;
			scsi_free_scsi_task(task);
			goto finished;
		}
		scsi_free_scsi_task(task);
	}
	printf("[OK]\n");


finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
Example #23
0
int T0213_read12_0blocks(const char *initiator, const char *url, int data_loss _U_, int show_info)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_readcapacity16 *rc16;
	int ret = 0, lun;
	uint32_t block_size;
	uint64_t num_blocks;

	printf("0213_read12_0blocks:\n");
	printf("====================\n");
	if (show_info) {
		printf("Test that READ12 works correctly when reading 0 number of blocks.\n");
		printf("1, Read at 0 should work.\n");
		printf("2, Read at end-of-lun should work.\n");
		printf("3, Read beyond end-of-lun should fail.\n");
		printf("4, Read at LBA:-1 should fail. (only test this if the device is < 2TB)\n");
		printf("\n");
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	/* find the size of the LUN */
	task = iscsi_readcapacity16_sync(iscsi, lun);
	if (task == NULL) {
		printf("Failed to send READCAPACITY16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("READCAPACITY16 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	rc16 = scsi_datain_unmarshall(task);
	if (rc16 == NULL) {
		printf("failed to unmarshall READCAPACITY16 data. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}

	block_size = rc16->block_length;
	num_blocks = rc16->returned_lba;
	scsi_free_scsi_task(task);


	printf("Read12 0blocks at LBA:0 ");
	task = iscsi_read12_sync(iscsi, lun, 0, 0, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send read12 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("Read12 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

	printf("Read12 0blocks at LBA:<end-of-disk> ");
	task = iscsi_read12_sync(iscsi, lun, num_blocks, 0, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send read12 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("Read12 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

	printf("Read12 0blocks at LBA:<beyond end-of-disk> ");
	task = iscsi_read12_sync(iscsi, lun, num_blocks + 1, 0, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send read12 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("Read12 command: Should fail when reading 0blocks beyond end\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

	/* read12 0 at lba -1, only do this if the device is < 2TB */
	if (num_blocks == 0xffffffff) {
		goto finished;
	}
	printf("Reading 0 blocks at lba:-1 ... ");
	task = iscsi_read12_sync(iscsi, lun, -1, 0, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send read12 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("Read12 command: Should fail when reading 0blocks at -1\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
int T0270_verify16_simple(const char *initiator, const char *url)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	int ret, i, lun;
	unsigned char *buf = NULL;

	printf("0270_verify16_simple:\n");
	printf("=====================\n");
	if (show_info) {
		printf("Test basic VERIFY16 functionality.\n");
		printf("1, Read and verify the first 1-256 blocks of the LUN using READ16/VERIFY16.\n");
		printf("\n");
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}


	buf = malloc(256 * block_size);
	if (buf == NULL) {
		printf("Failed to allocate buffer.\n");
		ret = -1;
		goto finished;
	}

	printf("Read first 256 blocks.\n");
	task = iscsi_read10_sync(iscsi, lun, 0, 256 * block_size, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send READ10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("READ10 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	memcpy(buf, task->datain.data, task->datain.size);
	scsi_free_scsi_task(task);


	ret = 0;


	/* verify the first 1 - 256 blocks at the start of the LUN */
	printf("Verify first 1-256 blocks.\n");
	for (i = 1; i <= 256; i++) {
		ret = verify16(iscsi, lun, 0, i * block_size, block_size, 0, 1, 1, buf);
		if (ret != 0) {
			goto finished;
		}
	}


finished:
	free(buf);
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
Example #25
0
int T0212_read12_flags(const char *initiator, const char *url)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	int ret = 0, lun;

	printf("0212_read12_flags:\n");
	printf("==================\n");
	if (show_info) {
		printf("Test how READ12 handles the flag bits\n");
		printf("1, Reading with DPO should work\n");
		printf("2, Reading with FUA should work\n");
		printf("3, Reading with FUA_NV should work\n");
		printf("4, Reading with FUA+FUA_NV should work\n");
		printf("\n");
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	/* This test is only valid for SBC devices */
	if (device_type != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {
		printf("LUN is not SBC device. Skipping test\n");
		return -2;
	}


	printf("Read12 with DPO ");
	task = iscsi_read12_sync(iscsi, lun, 0, block_size, block_size, 0, 1, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send read12 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("Read12 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

	printf("Read12 with FUA ");
	task = iscsi_read12_sync(iscsi, lun, 0, block_size, block_size, 0, 0, 1, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send read12 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("Read12 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");


	printf("Read12 with FUA_NV ");
	task = iscsi_read12_sync(iscsi, lun, 0, block_size, block_size, 0, 0, 0, 1, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send read12 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("Read12 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

	printf("Read12 with FUA+FUA_NV ");
	task = iscsi_read12_sync(iscsi, lun, 0, block_size, block_size, 0, 0, 1, 1, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send read12 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("Read12 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	printf("[OK]\n");

finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
int T0252_prefetch16_beyondeol(const char *initiator, const char *url, int data_loss _U_, int show_info)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_readcapacity16 *rc16;
	int ret, i, lun;
	uint64_t num_blocks;

	printf("0252_prefetch16_beyondeol:\n");
	printf("===================\n");
	if (show_info) {
		printf("Test PREFETCH16 for blocks beyond the EOL.\n");
		printf("1, Prefetch 1-256 blocks one block beyond end-of-lun.\n");
		printf("2, Prefetch 1-256 blocks at LBA 2^63 should fail.\n");
		printf("3, Prefetch 1-256 blocks at LBA -1 should fail.\n");
		printf("4, Prefetch 1-256 blocks all but one block beyond eol\n");
		printf("\n");
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	/* find the size of the LUN */
	task = iscsi_readcapacity16_sync(iscsi, lun);
	if (task == NULL) {
		printf("Failed to send READCAPACITY16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("READCAPACITY16 command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	rc16 = scsi_datain_unmarshall(task);
	if (rc16 == NULL) {
		printf("failed to unmarshall READCAPACITY16 data. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	num_blocks = rc16->returned_lba;
	scsi_free_scsi_task(task);

	ret = 0;



	/* prefetch 1-256 blocks, one block beyond the end-of-lun */
	printf("Prefetch last 1-256 blocks one block beyond eol ... ");
	for (i = 1; i <= 256; i++) {
		task = iscsi_prefetch16_sync(iscsi, lun, num_blocks + 2 - i, i, 0, 0);
		if (task == NULL) {
		        printf("[FAILED]\n");
			printf("Failed to send prefetch16 command: %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto test2;
		}
		if (task->status    == SCSI_STATUS_CHECK_CONDITION
		&& task->sense.key  == SCSI_SENSE_ILLEGAL_REQUEST
		&& task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) {
			printf("[SKIPPED]\n");
			printf("Opcode is not implemented on target\n");
			scsi_free_scsi_task(task);
			ret = -2;
			goto finished;
		}
		if (task->status        != SCSI_STATUS_CHECK_CONDITION
			|| task->sense.key  != SCSI_SENSE_ILLEGAL_REQUEST
			|| task->sense.ascq != SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE) {
			printf("[FAILED]\n");
			printf("PREFETCH16 failed but with the wrong sense code. It should have failed with ILLEGAL_REQUEST/LBA_OUT_OF_RANGE. Sense:%s\n", iscsi_get_error(iscsi));
			ret = -1;
			scsi_free_scsi_task(task);
			goto test2;
		}
		scsi_free_scsi_task(task);
	}
	printf("[OK]\n");

test2:
	/* Prefetch 1 - 256 blocks at LBA 2^63 */
	printf("Prefetch 1-256 blocks at LBA 2^63 ... ");
	for (i = 1; i <= 256; i++) {
		task = iscsi_prefetch16_sync(iscsi, lun, 0x8000000000000000, i, 0, 0);
		if (task == NULL) {
		        printf("[FAILED]\n");
			printf("Failed to send PREFETCH16 command: %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto test3;
		}
		if (task->status == SCSI_STATUS_GOOD) {
		        printf("[FAILED]\n");
			printf("PREFETCH16 command should fail for LBA 2^31\n");
			ret = -1;
			scsi_free_scsi_task(task);
			goto test3;
		}
		if (task->status        != SCSI_STATUS_CHECK_CONDITION
			|| task->sense.key  != SCSI_SENSE_ILLEGAL_REQUEST
			|| task->sense.ascq != SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE) {
			printf("[FAILED]\n");
			printf("PREFETCH16 failed but with the wrong sense code. It should have failed with ILLEGAL_REQUEST/LBA_OUT_OF_RANGE. Sense:%s\n", iscsi_get_error(iscsi));
			ret = -1;
			scsi_free_scsi_task(task);
			goto test3;
		}
		scsi_free_scsi_task(task);
	}
	printf("[OK]\n");


test3:
	/* prefetch 1 - 256 blocks at LBA -1 */
	for (i = 1; i <= 256; i++) {
		task = iscsi_prefetch16_sync(iscsi, lun, -1, i, 0, 0);
		if (task == NULL) {
		        printf("[FAILED]\n");
			printf("Failed to send PREFETCH16 command: %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto test4;
		}
		if (task->status == SCSI_STATUS_GOOD) {
		        printf("[FAILED]\n");
			printf("PREFETCH16 command should fail for LBA -1\n");
			ret = -1;
			scsi_free_scsi_task(task);
			goto test4;
		}
		if (task->status        != SCSI_STATUS_CHECK_CONDITION
			|| task->sense.key  != SCSI_SENSE_ILLEGAL_REQUEST
			|| task->sense.ascq != SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE) {
			printf("[FAILED]\n");
			printf("PREFETCH16 failed but with the wrong sense code. It should have failed with ILLEGAL_REQUEST/LBA_OUT_OF_RANGE. Sense:%s\n", iscsi_get_error(iscsi));
			ret = -1;
			scsi_free_scsi_task(task);
			goto test4;
		}
		scsi_free_scsi_task(task);
	}
	printf("[OK]\n");


 test4:
	/* prefetch 2-256 blocks, all but one block beyond the eol */
	printf("Prefetch 1-255 blocks beyond eol starting at last block ... ");
	for (i=2; i<=256; i++) {
		task = iscsi_prefetch16_sync(iscsi, lun, num_blocks, i, 0, 0);
		if (task == NULL) {
			printf("[FAILED]\n");
			printf("Failed to send PREFETCH16 command: %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto test5;
		}
		if (task->status == SCSI_STATUS_GOOD) {
			printf("[FAILED]\n");
			printf("PREFETCH16 beyond end-of-lun did not return sense.\n");
			ret = -1;
			scsi_free_scsi_task(task);
			goto test5;
		}
		if (task->status        != SCSI_STATUS_CHECK_CONDITION
		    || task->sense.key  != SCSI_SENSE_ILLEGAL_REQUEST
		    || task->sense.ascq != SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE) {
		        printf("[FAILED]\n");
			printf("PREFETCH16 failed but ascq was wrong. Should have failed with ILLEGAL_REQUEST/LBA_OUT_OF_RANGE. Sense:%s\n", iscsi_get_error(iscsi));
			ret = -1;
			scsi_free_scsi_task(task);
			goto test5;
		}
		scsi_free_scsi_task(task);
	}
	printf("[OK]\n");


test5:

finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
Example #27
0
int T0300_readonly(const char *initiator, const char *url)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_mode_sense *ms;
	int ret, lun;
	unsigned char data[4096];
	struct unmap_list list[1];
	int full_size;

	ret = -1;

	printf("0300_readonly:\n");
	printf("==============\n");
	if (show_info) {
		printf("Test that all commands that modify the medium fail for readonly devices\n");
		printf("1, WRITE10 at LUN 0 should fail.\n");
		printf("2, WRITE12 at LUN 0 should fail.\n");
		printf("3, WRITE16 at LUN 0 should fail.\n");
		printf("4, WRITESAME10 at LUN 0 should fail.\n");
		printf("5, WRITESAME16 at LUN 0 should fail.\n");
		printf("6, WRITESAME10 with UNMAP at LUN 0 should fail (skipped if not thin-provisioned).\n");
		printf("7, WRITESAME16 with UNMAP at LUN 0 should fail (skipped if not thin-provisioned).\n");
		printf("8, UNMAP at LUN 0 should fail (skipped if not thin-provisioned).\n");
		printf("9, WRITEVERIFY10 at LUN 0 should fail.\n");
		printf("10, WRITEVERIFY12 at LUN 0 should fail.\n");
		printf("11, WRITEVERIFY16 at LUN 0 should fail.\n");
		printf("12, COMPAREANDWRITE at LUN 0 should fail.\n");
		printf("13, ORWRITE at LUN 0 should fail.\n");
		printf("\n");
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	if (!data_loss) {
		printf("--dataloss flag is not set. Skipping test\n");
		ret = -2;
		goto finished;
	}

	/* This test is only valid for SBC devices */
	if (device_type != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {
		printf("LUN is not SBC device. Skipping test\n");
		return -2;
	}

	/* verify the device is readonly */
	task = iscsi_modesense6_sync(iscsi, lun, 0, SCSI_MODESENSE_PC_CURRENT,
				     SCSI_MODESENSE_PAGECODE_RETURN_ALL_PAGES, 0,
				     4);
	if (task == NULL) {
		printf("Failed to send modesense6 command: %s\n", iscsi_get_error(iscsi));
		goto finished;
	}
	full_size = scsi_datain_getfullsize(task);
	if (full_size > task->datain.size) {
		scsi_free_scsi_task(task);
		task = iscsi_modesense6_sync(iscsi, lun, 0, SCSI_MODESENSE_PC_CURRENT,
					     SCSI_MODESENSE_PAGECODE_RETURN_ALL_PAGES, 0,
					     full_size);
		if (task == NULL) {
			printf("Failed to send modesense6 command: %s\n", iscsi_get_error(iscsi));
			goto finished;
		}
	}
	ms = scsi_datain_unmarshall(task);
	if (ms == NULL) {
		printf("failed to unmarshall mode sense datain blob\n");
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (!(ms->device_specific_parameter & 0x80)) {
		printf("Device is not read-only. Skipping test\n");
		ret = -2;
		goto finished;
	}
	scsi_free_scsi_task(task);


	ret = 0;


	/* Write one block at lba 0 */
	printf("WRITE10 to LUN 0 ... ");
	task = iscsi_write10_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITE10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITE10 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITE10 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("WRITE12 to LUN 0 ... ");
	task = iscsi_write12_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITE12 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITE12 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITE12 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("WRITE16 to LUN 0 ... ");
	task = iscsi_write16_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITE16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITE16 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITE16 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("WRITESAME10 to LUN 0 ... ");
	task = iscsi_writesame10_sync(iscsi, lun, data, block_size, 0, 1, 0, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITESAME10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITESAME10 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITESAME10 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("WRITESAME16 to LUN 0 ... ");
	task = iscsi_writesame16_sync(iscsi, lun, data, block_size, 0, 1, 0, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITESAME16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITESAME16 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITESAME16 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* UNMAP one block at lba 0 */
	printf("WRITESAME10 to UNMAP LUN 0 ... ");
	if (lbpme == 0) {
		printf("LUN is not thin-provisioned. [SKIPPED]\n");
		goto finished;
	}
	task = iscsi_writesame10_sync(iscsi, lun, data, block_size, 0, 1, 0, 1, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITESAME10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITESAME10 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITESAME10 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* UNMAP one block at lba 0 */
	printf("WRITESAME16 to UNMAP LUN 0 ... ");
	if (lbpme == 0) {
		printf("LUN is not thin-provisioned. [SKIPPED]\n");
		goto finished;
	}
	task = iscsi_writesame16_sync(iscsi, lun, data, block_size, 0, 1, 0, 1, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITESAME16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITESAME16 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITESAME16 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* UNMAP one block at lba 0 */
	printf("UNMAP LUN 0 ... ");
	if (lbpme == 0) {
		printf("LUN is not thin-provisioned. [SKIPPED]\n");
		goto finished;
	}
	list[0].lba = 0;
	list[0].num = 1;
	task = iscsi_unmap_sync(iscsi, lun, 0, 0, &list[0], 1);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send UNMAP command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("UNMAP command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("UNMAP failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("WRITEVERIFY10 to LUN 0 ... ");
	task = iscsi_writeverify10_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITEVERIFY10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITEVERIFY10 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITEVERIFY10 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("WRITEVERIFY12 to LUN 0 ... ");
	task = iscsi_writeverify12_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITEVERIFY12 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITEVERIFY12 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITEVERIFY12 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("WRITEVERIFY16 to LUN 0 ... ");
	task = iscsi_writeverify16_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send WRITEVERIFY16 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("WRITEVERIFY16 command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("WRITEVERIFY16 failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("COMPAREWRITE to LUN 0 ... ");
	task = iscsi_compareandwrite_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send COMPAREANDWRITE command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("COMPAREANDWRITE command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("COMPAREANDWRITE failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* Write one block at lba 0 */
	printf("ORWRITE to LUN 0 ... ");
	task = iscsi_orwrite_sync(iscsi, lun, 0, data, block_size, block_size, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send ORWRITE command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status == SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("ORWRITE command should fail when writing to readonly devices\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	if (task->status        != SCSI_STATUS_CHECK_CONDITION
	    || task->sense.key  != SCSI_SENSE_DATA_PROTECTION
	    || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) {
		printf("[FAILED]\n");
		printf("ORWRITE failed with the wrong sense code. Should fail with DATA_PROTECTION/WRITE_PROTECTED\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}	
	scsi_free_scsi_task(task);
	printf("[OK]\n");


finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
int T0361_startstopunit_pwrcnd(const char *initiator, const char *url)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	int ret, i, lun;

	printf("0361_startstopunit_pwrcnd:\n");
	printf("===================\n");
	if (show_info) {
		printf("Test STARTSTOPUNIT POWERCONDITION functionality.\n");
		printf("1, If PC != 0 we can not eject the media\n");
		printf("2, Try to remount the media\n");
		printf("\n");
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	if (!data_loss) {
		printf("--dataloss flag is not set. Skipping test\n");
		ret = -2;
		goto finished;
	}
	

	ret = 0;


	if (inq->rmb) {
		printf("Media is removable. STARTSTOPUNIT should work\n");
	} else {
		printf("Media is not removable. STARTSTOPUNIT should fail\n");
	}
	for (i = 1; i < 16; i++) {
		printf("Try to eject media with PC == %d ... ", i);
		task = iscsi_startstopunit_sync(iscsi, lun, 1, 0, i, 0, 1, 0);
		if (task == NULL) {
		        printf("[FAILED]\n");
			printf("Failed to send STARTSTOPUNIT command: %s\n", iscsi_get_error(iscsi));
			ret = -1;
			goto finished;
		}
		if (task->status != SCSI_STATUS_GOOD) {
			printf("[FAILED]\n");
			printf("STARTSTOPUNIT command: failed with sense. %s\n", iscsi_get_error(iscsi));
			ret = -1;
			scsi_free_scsi_task(task);
			goto finished;
		}
		scsi_free_scsi_task(task);
		printf("[OK]\n");

		printf("Check with TESTUNITREADY that the medium is still present.\n");
		ret = testunitready(iscsi, lun);
		if (ret != 0) {
			goto finished;
		}
	}



	printf("Try to mount the media again ... ");
	task = iscsi_startstopunit_sync(iscsi, lun, 1, 0, 0, 0, 1, 1);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send STARTSTOPUNIT command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
	        printf("[FAILED]\n");
		printf("STARTSTOPUNIT command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	printf("Check with TESTUNITREADY that the medium is still present.\n");
	ret = testunitready(iscsi, lun);
	if (ret != 0) {
		goto finished;
	}


finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
Example #29
0
int T0102_read10_0blocks(const char *initiator, const char *url)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	struct scsi_readcapacity10 *rc10;
	int ret, i, lun;
	uint32_t block_size, num_blocks;

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	/* find the size of the LUN */
	task = iscsi_readcapacity10_sync(iscsi, lun, 0, 0);
	if (task == NULL) {
		printf("Failed to send readcapacity10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("Readcapacity command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	rc10 = scsi_datain_unmarshall(task);
	if (rc10 == NULL) {
		printf("failed to unmarshall readcapacity10 data. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	block_size = rc10->block_size;
	num_blocks = rc10->lba;
	scsi_free_scsi_task(task);



	ret = 0;

	/* read10 0 blocks one block at lba 0 */
	printf("Reading 0 blocks at lba:0 ... ");
	task = iscsi_read10_sync(iscsi, lun, 0, 0, block_size);
	if (task == NULL) {
 	        printf("[FAILED]\n");
		printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
 	        printf("[FAILED]\n");
		printf("Read10 of 0 at lba:0 failed with sense.\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");

	/* read10 0 blocks one block beyond the eol */
	printf("Reading 0 blocks at one block beyond end ... ");
	task = iscsi_read10_sync(iscsi, lun, num_blocks + 1, 0, block_size);
	if (task == NULL) {
 	        printf("[FAILED]\n");
		printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
 	        printf("[FAILED]\n");
		printf("Read10 of 0 one block beyond end-of-lun failed with sense.\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* read10 0 blocks two blocks beyond the eol */
	printf("Reading 0 blocks at two blocks beyond end ... ");
	task = iscsi_read10_sync(iscsi, lun, num_blocks + 1, 0, block_size);
	if (task == NULL) {
 	        printf("[FAILED]\n");
		printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
 	        printf("[FAILED]\n");
		printf("Read10 of 0 two blocks beyond end-of-lun failed with sense.\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");


	/* read10 0 at lba -1 */
	printf("Reading 0 blocks at lba:-1 ... ");
	task = iscsi_read10_sync(iscsi, lun, 0xffffff, 0, block_size);
	if (task == NULL) {
 	        printf("[FAILED]\n");
		printf("Failed to send read10 command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
 	        printf("[FAILED]\n");
		printf("Read10 of 0 at lba:-1 failed with sense.\n");
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");


finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}
int T0362_startstopunit_noloej(const char *initiator, const char *url)
{ 
	struct iscsi_context *iscsi;
	struct scsi_task *task;
	int ret, lun;

	printf("0362_startstopunit_noloej:\n");
	printf("===================\n");
	if (show_info) {
		printf("Test STARTSTOPUNIT and LOEJ==0 will never eject/load media.\n");
		printf("1, LOEJ==0  IMMED==0 NO_FLUSH==0 START==0 will not eject the media\n");
		printf("2, LOEJ==0  IMMED==0 NO_FLUSH==0 START==1 will not eject the media\n");
		printf("3, LOEJ==0  IMMED==1 NO_FLUSH==0 START==0 will not eject the media\n");
		printf("4, LOEJ==0  IMMED==1 NO_FLUSH==0 START==1 will not eject the media\n");
		printf("5, LOEJ==0  IMMED==0 NO_FLUSH==1 START==0 will not eject the media\n");
		printf("6, LOEJ==0  IMMED==0 NO_FLUSH==1 START==1 will not eject the media\n");
		printf("7, LOEJ==0  IMMED==1 NO_FLUSH==1 START==0 will not eject the media\n");
		printf("8, LOEJ==0  IMMED==1 NO_FLUSH==1 START==1 will not eject the media\n");
		printf("\n");
		return 0;
	}

	iscsi = iscsi_context_login(initiator, url, &lun);
	if (iscsi == NULL) {
		printf("Failed to login to target\n");
		return -1;
	}

	if (!data_loss) {
		printf("--dataloss flag is not set. Skipping test\n");
		ret = -2;
		goto finished;
	}
	

	ret = 0;


	if (!removable) {
		printf("Media is not removable. SKIPPING tests\n");
		ret = -2;
		goto finished;
	}



	printf("STARTSTOP LOEJ==0 IMMED==0 NO_FLUSH==0 START==0 does not eject media ... ");
	task = iscsi_startstopunit_sync(iscsi, lun, 0, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send STARTSTOPUNIT command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("[FAILED]\n");
		printf("STARTSTOPUNIT command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");

	printf("Check with TESTUNITREADY that the medium is still present.\n");
	ret = testunitready(iscsi, lun);
	if (ret != 0) {
		goto finished;
	}


	/* in case the previous command did eject the media */
	iscsi_startstopunit_sync(iscsi, lun, 1, 0, 0, 0, 1, 1);

	printf("STARTSTOP LOEJ==0 IMMED==0 NO_FLUSH==0 START==1 does not eject media ... ");
	task = iscsi_startstopunit_sync(iscsi, lun, 0, 0, 0, 0, 0, 1);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send STARTSTOPUNIT command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("[FAILED]\n");
		printf("STARTSTOPUNIT command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");

	printf("Check with TESTUNITREADY that the medium is still present.\n");
	ret = testunitready(iscsi, lun);
	if (ret != 0) {
		goto finished;
	}


	/* in case the previous command did eject the media */
	iscsi_startstopunit_sync(iscsi, lun, 1, 0, 0, 0, 1, 1);

	printf("STARTSTOP LOEJ==0 IMMED==1 NO_FLUSH==0 START==0 does not eject media ... ");
	task = iscsi_startstopunit_sync(iscsi, lun, 1, 0, 0, 0, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send STARTSTOPUNIT command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("[FAILED]\n");
		printf("STARTSTOPUNIT command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");

	printf("Check with TESTUNITREADY that the medium is still present.\n");
	ret = testunitready(iscsi, lun);
	if (ret != 0) {
		goto finished;
	}


	/* in case the previous command did eject the media */
	iscsi_startstopunit_sync(iscsi, lun, 1, 0, 0, 0, 1, 1);

	printf("STARTSTOP LOEJ==0 IMMED==1 NO_FLUSH==0 START==1 does not eject media ... ");
	task = iscsi_startstopunit_sync(iscsi, lun, 1, 0, 0, 0, 0, 1);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send STARTSTOPUNIT command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("[FAILED]\n");
		printf("STARTSTOPUNIT command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");

	printf("Check with TESTUNITREADY that the medium is still present.\n");
	ret = testunitready(iscsi, lun);
	if (ret != 0) {
		goto finished;
	}


	/* in case the previous command did eject the media */
	iscsi_startstopunit_sync(iscsi, lun, 1, 0, 0, 0, 1, 1);

	printf("STARTSTOP LOEJ==0 IMMED==0 NO_FLUSH==1 START==0 does not eject media ... ");
	task = iscsi_startstopunit_sync(iscsi, lun, 0, 0, 0, 1, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send STARTSTOPUNIT command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("[FAILED]\n");
		printf("STARTSTOPUNIT command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");

	printf("Check with TESTUNITREADY that the medium is still present.\n");
	ret = testunitready(iscsi, lun);
	if (ret != 0) {
		goto finished;
	}


	/* in case the previous command did eject the media */
	iscsi_startstopunit_sync(iscsi, lun, 1, 0, 0, 0, 1, 1);

	printf("STARTSTOP LOEJ==0 IMMED==0 NO_FLUSH==1 START==1 does not eject media ... ");
	task = iscsi_startstopunit_sync(iscsi, lun, 0, 0, 0, 1, 0, 1);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send STARTSTOPUNIT command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("[FAILED]\n");
		printf("STARTSTOPUNIT command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");

	printf("Check with TESTUNITREADY that the medium is still present.\n");
	ret = testunitready(iscsi, lun);
	if (ret != 0) {
		goto finished;
	}


	/* in case the previous command did eject the media */
	iscsi_startstopunit_sync(iscsi, lun, 1, 0, 0, 0, 1, 1);

	printf("STARTSTOP LOEJ==0 IMMED==1 NO_FLUSH==1 START==0 does not eject media ... ");
	task = iscsi_startstopunit_sync(iscsi, lun, 1, 0, 0, 1, 0, 0);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send STARTSTOPUNIT command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("[FAILED]\n");
		printf("STARTSTOPUNIT command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");

	printf("Check with TESTUNITREADY that the medium is still present.\n");
	ret = testunitready(iscsi, lun);
	if (ret != 0) {
		goto finished;
	}


	/* in case the previous command did eject the media */
	iscsi_startstopunit_sync(iscsi, lun, 1, 0, 0, 0, 1, 1);

	printf("STARTSTOP LOEJ==0 IMMED==1 NO_FLUSH==1 START==1 does not eject media ... ");
	task = iscsi_startstopunit_sync(iscsi, lun, 1, 0, 0, 1, 0, 1);
	if (task == NULL) {
	        printf("[FAILED]\n");
		printf("Failed to send STARTSTOPUNIT command: %s\n", iscsi_get_error(iscsi));
		ret = -1;
		goto finished;
	}
	if (task->status != SCSI_STATUS_GOOD) {
		printf("[FAILED]\n");
		printf("STARTSTOPUNIT command: failed with sense. %s\n", iscsi_get_error(iscsi));
		ret = -1;
		scsi_free_scsi_task(task);
		goto finished;
	}
	scsi_free_scsi_task(task);
	printf("[OK]\n");

	printf("Check with TESTUNITREADY that the medium is still present.\n");
	ret = testunitready(iscsi, lun);
	if (ret != 0) {
		goto finished;
	}


	/* in case the previous command did eject the media */
	iscsi_startstopunit_sync(iscsi, lun, 1, 0, 0, 0, 1, 1);

finished:
	iscsi_logout_sync(iscsi);
	iscsi_destroy_context(iscsi);
	return ret;
}