void
test_orwrite_simple(void)
{
        int i;

        CHECK_FOR_DATALOSS;
        CHECK_FOR_SBC;

        logging(LOG_VERBOSE, LOG_BLANK_LINE);
        logging(LOG_VERBOSE, "Test ORWRITE of 1-256 blocks at the start of the LUN");
        memset(scratch, 0xa6, 256 * block_size);
        for (i = 1; i <= 256; i++) {
                if (maximum_transfer_length && maximum_transfer_length < i) {
                        break;
                }
                ORWRITE(sd, 0, i * block_size,
                        block_size, 0, 0, 0, 0, 0, scratch,
                        EXPECT_STATUS_GOOD);
        }

        logging(LOG_VERBOSE, "Test ORWRITE of 1-256 blocks at the end of the LUN");
        for (i = 1; i <= 256; i++) {
                if (maximum_transfer_length && maximum_transfer_length < i) {
                        break;
                }
                ORWRITE(sd, num_blocks - i, i * block_size, block_size,
                        0, 0, 0, 0, 0, scratch,
                        EXPECT_STATUS_GOOD);
        }
}
void
test_orwrite_beyond_eol(void)
{ 
        int i;

        CHECK_FOR_DATALOSS;
        CHECK_FOR_SBC;

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


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


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


        logging(LOG_VERBOSE, "Test ORWRITE 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;
                }
                ORWRITE(sd, num_blocks - 1, i * block_size, block_size,
                        0, 0, 0, 0, 0, scratch,
                        EXPECT_LBA_OOB);
        }
}
Exemple #3
0
static void
test_orwrite(void)
{
        logging(LOG_VERBOSE, "Test ORWRITE fails with WRITE_PROTECTED");
        ORWRITE(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch,
                EXPECT_WRITE_PROTECTED);
}
void
test_orwrite_0blocks(void)
{
        CHECK_FOR_DATALOSS;
        CHECK_FOR_SBC;

        logging(LOG_VERBOSE, LOG_BLANK_LINE);
        logging(LOG_VERBOSE, "Test ORWRITE 0-blocks at LBA==0");
        ORWRITE(sd, 0, 0, block_size, 0, 0, 0, 0, 0, NULL,
                EXPECT_STATUS_GOOD);

        logging(LOG_VERBOSE, "Test ORWRITE 0-blocks one block past end-of-LUN");
        ORWRITE(sd, num_blocks + 1, 0, block_size, 0, 0, 0, 0, 0, NULL,
                EXPECT_LBA_OOB);

        logging(LOG_VERBOSE, "Test ORWRITE 0-blocks at LBA==2^63");
        ORWRITE(sd, 0x8000000000000000ULL, 0, block_size, 0, 0, 0, 0, 0, NULL,
                EXPECT_LBA_OOB);

        logging(LOG_VERBOSE, "Test ORWRITE 0-blocks at LBA==-1");
        ORWRITE(sd, -1, 0, block_size, 0, 0, 0, 0, 0, NULL,
                EXPECT_LBA_OOB);
}
void
test_orwrite_dpofua(void)
{ 
        int dpofua, usage_data_dpofua;
        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 ORWRITE DPO/FUA flags");

        CHECK_FOR_SBC;
        CHECK_FOR_DATALOSS;

        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 ORWRITE with DPO==1");
        memset(scratch, 0xa6, block_size);
        if (dpofua) {
                ORWRITE(sd, 0, block_size, block_size, 0, 1, 0, 0, 0, scratch,
                        EXPECT_STATUS_GOOD);
        } else {
                ORWRITE(sd, 0, block_size, block_size, 0, 1, 0, 0, 0, scratch,
                        EXPECT_INVALID_FIELD_IN_CDB);
        }

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

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

        logging(LOG_VERBOSE, "Try fetching REPORT_SUPPORTED_OPCODES "
                "for ORWRITE");
        REPORT_SUPPORTED_OPCODES(sd, &rso_task,
                                 0, SCSI_REPORT_SUPPORTING_OPCODE,
                                 SCSI_OPCODE_ORWRITE,
                                 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_dpofua = rsoc->cdb_usage_data[1] & 0x18;
        if (dpofua) {
                logging(LOG_VERBOSE, "DPOFUA is set. Verify the "
                        "DPO/FUA flags are set in the CDB_USAGE_DATA");
                if (!usage_data_dpofua) {
                        logging(LOG_NORMAL, "[FAILED] DpoFua not set "
                                "in CDB_USAGE_DATE");
                        CU_FAIL("DpoFua not set in CDB_USAGE_DATE");
                }
        } else {
                logging(LOG_VERBOSE, "DPOFUA is clear. Verify the "
                        "DPO/FUA flags are clear in the CDB_USAGE_DATA");
                if (usage_data_dpofua) {
                        logging(LOG_NORMAL, "[FAILED] DpoFua not clear "
                                "in CDB_USAGE_DATE");
                        CU_FAIL("DpoFua not clear in CDB_USAGE_DATE");
                }
        }

        scsi_free_scsi_task(rso_task);
}