用于 SCSI、SATA、SAS、iSCSI 硬盘驱动器、磁带驱动器和库外围设备的专业工程、筛选和测试软件,通过现成的 HBA 提供
作为第一个示例,假设您想发出大量写入和读取,但时不时发出不同的命令(例如 Log Sense 命令)。 并且假设您有进一步的要求,即大约每 1000 个 I/O 发出此 Log Sense 命令。 命令概率序列器非常适合实现上述测试场景。 虽然下面的编码示例一开始看起来很吓人,但现在主要关注以下几项:我们正在设置三个用户定义的命令“Write”、“Read”和“Log Sense”,我们需要指定诸如是否 数据进出驱动器(“nDataDir”字段),以及需要传输多少数据(“nTransferLen”字段)。 这是我们第一个示例的代码 – 关注 RED 中具有“nDataDir”和“nTransferLength”参数的代码行,以及命令的实际定义。
const int c_nLenOfArray = 3;
DMM_UserDefinedCDB arrOfCDB[c_nLenOfArray];
double arrOfProb[c_nLenOfArray];
int nIndex;
const long c_lNumberOfIOToIssue = 10000;
//Set up the “Write” command (Write is opcode 0x2A)
BYTE cCDB0[] = {0x2A,0,0,0,0,0,0,0,1,0};
nIndex = 0;
memcpy(arrOfCDB[nIndex].cCDBBytes,cCDB0,10);
arrOfCDB[nIndex].nCDBLength = 10;
arrOfCDB[nIndex].nDataDir = 0;
arrOfCDB[nIndex].nTransferLength = 512;
//Set up the “Read” command (Read opcode is 0x28)
BYTE cCDB1[] = {0x28,0,0,0,0,0,0,0,1,0};
nIndex = 1;
memcpy(arrOfCDB[nIndex].cCDBBytes,cCDB1,10);
arrOfCDB[nIndex].nCDBLength = 10;
arrOfCDB[nIndex].nDataDir = 1;
arrOfCDB[nIndex].nTransferLength = 512;
//Set up the “Log Sense” command (Log Sense opcode is 0x4D)
BYTE cCDB2[] = {0x4D,0,0×40,0,0,0,0,0,0,0x80,0};
nIndex = 2;
memcpy(arrOfCDB[nIndex].cCDBBytes,cCDB2,10);
arrOfCDB[nIndex].nCDBLength = 10;
arrOfCDB[nIndex].nDataDir = 1;
arrOfCDB[nIndex].nTransferLength = 128;
//Now define the probabilities for each of the three commands
//“Write”, “Read”, “Log Sense”
arrOfProb[0] = 0.4995; //this is the probability for the “Write” command
arrOfProb[1] = 0.4995; //this is the probability for the “Read” command
arrOfProb[2] = 0.001; //.001 probability means the Log Sense command will be issued
//with probability .001 (i.e. every 1000th I/O)
VCSCSIAddDiskComProbSeqTest(arrOfCDB,
arrOfProb,
c_nLenOfArray,
c_lNumberOfIOToIssue);
在上面的示例中,我们要发出的命令集是 3(因此我们将 c_nLenOfArry 设置为 3),要发出的命令数是 10000(因此我们将 c_lNumberOfIOToIssue 设置为 10000)。 还要注意在对 API VCSCSIAddDiskComProbSeqTest 的调用中,我们传入了两个数组:第一个是命令序列,第二个是包含这些命令概率的序列。
注意:您的概率之和必须恰好是 1.0(或 100%)。 请注意,在我们的示例中,概率 .4995、.4995 和 .001 的总和正好是 1.0这是上述测试的 BAM(总线分析器模块)输出:
正如您在跟踪中看到的那样,有 Write、Log Sense 和 Read 命令。 在跟踪的下部,在 I/O 统计页面上,它显示了发出的命令的数量和类型。 有 5019 个读取命令、4966 个写入命令和 15 个 Log Sense 命令(请注意,5019 + 4966 + 15 = 10000,这是我们指定给 CPS 发出的命令数)。 从这个特定的运行中,我们看到读取命令形成了 5019/10000 = 50.19% 的命令,写入命令形成了 4966/10000 = 49.66% 的命令,而 Log Sense 命令形成了 15/10000 = 0.15%。 这些百分比几乎正是我们为 CPS 指定的概率。
在这个例子中,我们将介绍 CPS 的另外两个特性——即如何设置数据模式,以及如何自动调整您的写入和读取(以及其他命令)。 要了解您为什么要调整写入命令,假设您暂时没有调整命令。 然后,每次我们发出命令时,我们都将写入驱动器上完全相同的位置(在示例 1 中,我们将每次写入 LBA 0)。 为了允许调整命令写入的位置,我们引入了“nGap”参数。 nGap 参数告诉 CPS 调整写入命令的位置多少。 例如,如果 nGap 为 7,则连续写入将转到 LBA 0、7、14、21 等。
为了写出每个偶数 LBA(即 LBA 0、2、4、6、8、10……),我们需要 nGap 正好为 2。
所以这里是如何查看上述类型的测试 - 关注 RED 中具有“eTestPattern”和“nGap”参数的代码行。
const int c_nLenOfArray = 2;
DMM_UserDefinedCDB arrOfCDB[c_nLenOfArray];
double arrOfProb[c_nLenOfArray];
int nIndex;
const long c_lNumberOfIOToIssue = 10000;
//Set up the “Write” command that writes to even LBA, with Incrementing pattern
BYTE cCDB0[] = {0x2A,0,0,0,0,0,0,0,1,0};
nIndex = 0;
memcpy(arrOfCDB[nIndex].cCDBBytes,cCDB0,10);
arrOfCDB[nIndex].nCDBLength = 10;
arrOfCDB[nIndex].nDataDir = 0;
arrOfCDB[nIndex].nTransferLength = 512;
arrOfCDB[nIndex].eTestPattern = eIncrementing;
arrOfCDB[nIndex].nGap = 2;
//Set up the “Write” command that writes to odd LBA, with Decrementing pattern
BYTE cCDB1[] = {0x2A,0,0,0,0,1,0,0,1,0};
nIndex = 1;
memcpy(arrOfCDB[nIndex].cCDBBytes,cCDB1,10);
arrOfCDB[nIndex].nCDBLength = 10;
arrOfCDB[nIndex].nDataDir = 0;
arrOfCDB[nIndex].nTransferLength = 512;
arrOfCDB[nIndex].eTestPattern = eDecrementing;
arrOfCDB[nIndex].nGap = 2;
//Now define the probabilities for these two commands. There’s no reason you have
//to make the probabilities the same.
arrOfProb[0] = 0.71; //71% of the time we’ll be writing to the even LBA
arrOfProb[1] = 0.29; //29% of the time we’ll be writing to the odd LBA
VCSCSIAddDiskComProbSeqTest(arrOfCDB,
arrOfProb,
c_nLenOfArray,
c_lNumberOfIOToIssue);
这是上述测试的 BAM(总线分析器模块)输出:
请注意,在 BAM 跟踪中,第一个写入命令写入一个递减模式(到 LBA 1),而接下来的三个写入命令写入一个递增模式(到 LBA 0、2、4)。 注意具有递增模式的写入命令之间的“间距”——它们恰好相隔两个块,这正是我们为 CPS 指定的 nGap 值。
在第三个示例中,我们将向您展示如何通过“模式选择”命令将唯一数据发送到驱动器。 我们将设置 AWRE(“错误恢复”模式页面上的“自动写入重新分配启用”位为 0)。 此模式选择仅以百分之一的概率(即概率 0.001)完成。
const int c_nLenOfArray = 3;
DMM_UserDefinedCDB arrOfCDB[c_nLenOfArray];
double arrOfProb[c_nLenOfArray];
int nIndex;
const long c_lNumberOfIOToIssue = 10000;
//执行模式选择(模式选择的操作码为 0x15)
BYTE cCDB0[] = {0x15,0x11,0,0,0×18,0};
BYTE cModeSelectBuffer[24] = {0,0,0,0×08,0,0,0,0,0,0,2,0,1,0x0a,4,1,0,0,0,0,1,0,0,0};
nIndex = 0;
memcpy(arrOfCDB[nIndex].cCDBBytes,cCDB0,6);
arrOfCDB[nIndex].nCDBLength = 6;
arrOfCDB[nIndex].nDataDir = 0;
arrOfCDB[nIndex].nTransferLength = 24;
arrOfCDB[nIndex].pPayloadDataToDrive = &cModeSelectBuffer[0];
//设置“Write”命令(Write is opcode 0x2A)
BYTE cCDB1[] = {0x2A,0,0,0,0,0,0,0,1,0};
nIndex = 1;
memcpy(arrOfCDB[nIndex].cCDBBytes,cCDB1,10);
arrOfCDB[nIndex].nCDBLength = 10;
arrOfCDB[nIndex].nDataDir = 0;
arrOfCDB[nIndex].nTransferLength = 512;
//设置“Read”命令(读取操作码为 0x28)
BYTE cCDB2[] = {0x28,0,0,0,0,0,0,0,1,0};
nIndex = 2;
memcpy(arrOfCDB[nIndex].cCDBBytes,cCDB2,10);
arrOfCDB[nIndex].nCDBLength = 10;
arrOfCDB[nIndex].nDataDir = 1;
arrOfCDB[nIndex].nTransferLength = 512;
//现在定义这两个命令的概率。 你没有理由
//使概率相同。
arrOfProb[0] = 0.001; // .1% of the time we issue mode-select
arrOfProb[1] = 0.4995;
arrOfProb[2] = 0.4995;
VCSCSIAddDiskComProbSeqTest(arrOfCDB,
arrOfProb,
c_nLenOfArray,
c_lNumberOfIOToIssue);
这是上述测试的 BAM(总线分析器模块)输出:
struct _DMM_UserDefinedCDB
{
BOOL bValid;
eUSER_DEFINED_TYPES eUserDefinedType;
char cCDBBytes[16];
int nCDBLength;
int nDataDir;
int nTimeout;
int nTransferLength;
BYTE * pPayloadDataToDrive;
int nAmtDataToLogfile;
char cDataOutFile[MAX_PATH];
ePATTERN_TYPE eTestPattern;
BOOL bCompare;
int nGap;
int nSeed;
}
bValid: | 将其设置为 TRUE |
eUserDefinedType: | 将其设置为 eScsiCDB |
cCDBBytes: | 将特定命令复制到该字段(必须为 16 字节或更少) |
nCDBLength: | 将此设置为命令的长度 |
nDataDir: | 如果数据将发送到驱动器,则将此设置为 0,如果数据从驱动器返回,则将其设置为 1。 注意:如果没有数据正在传输,请将其设置为 0。0 是默认值 |
nTimeout: | 将此设置为命令所需的超时时间(默认值为 30) |
nTransferLength: | 将此设置为要传输的数据量。 如果没有数据正在传输,则将此字段设置为 0 |
pPayloadDataToDrive: | 将此指针设置为包含要传送到驱动器的数据的缓冲区的起始地址。 如果没有数据要传送到驱动器,则将此字段设置为 NULL(这是默认值)。 |
cDataOutFile: | 将字节 0 设置为“?”——这是默认设置 |
eTestPattern: | 将此字段设置为所需的模式。 有关可用模式的列表,请参阅 VCPSSLImports.h 和枚举 ePATTERN_TYPE。 |
bCompare: | 如果命令正在从驱动器接收数据(例如“读取”命令),则将此字段设置为 TRUE。 否则将其设置为 FALSE(这是默认设置)。 从驱动器返回的数据将与 eTestPattern 字段中的数据进行比较 |
nGap: | 对于写入和读取命令,将此字段设置为每个连续命令之间所需的块数 |
此 API 返回 TRUE 表示已将测试添加到您的序列;
如果发生任何问题,它将返回 FALSE。
从 API VCSCSIAddDiskComProbSeq 获得 FALSE 返回码的原因: