The translation is temporarily closed for contributions due to maintenance, please come back later.

Translation

That is all for the ABORT request, although there is one more issue. BecauseAs the ABORT message cleans all the ongoing transactions on a LUN we have to mark all the other active transactions on this LUN as aborted. That should be done in the interrupt routine, after the transaction gets aborted.
(itstool) path: listitem/para
English
That is all for the ABORT request, although there is one more issue. As the ABORT message cleans all the ongoing transactions on a LUN we have to mark all the other active transactions on this LUN as aborted. That should be done in the interrupt routine, after the transaction gets aborted.
Context English Chinese (Simplified) (zh_CN) State
Implementing the SCSI bus reset as a function may be a good idea because it would be re-used by the timeout function as a last resort if the things go wrong. 将SCSI总线复位作为函数来实现可能是个好主意,因为如果事情出了差错, 它会被超时函数作为最后的报告来重用。
<emphasis>XPT_ABORT</emphasis> - abort the specified CCB <emphasis>XPT_ABORT</emphasis> - 中止指定的CCB
The arguments are transferred in the instance <quote>struct ccb_abort cab</quote> of the union ccb. The only argument field in it is: 参量在联合ccb的实例<quote>struct ccb_abort cab</quote> 中传输。其中唯一的参量字段为:
<emphasis>abort_ccb</emphasis> - pointer to the CCB to be aborted <emphasis>abort_ccb</emphasis> - 指向被中止的ccb的指针
If the abort is not supported just return the status CAM_UA_ABORT. This is also the easy way to minimally implement this call, return CAM_UA_ABORT in any case. 如果不支持中断就返回CAM_UA_ABORT。这也是最小化实现这个调用的 简易方式,任何情况下都返回CAM_UA_ABORT。
The hard way is to implement this request honestly. First check that abort applies to a SCSI transaction: 困难方式则是真正地实现这个请求。首先检查应用到SCSI事务的中止:
struct ccb *abort_ccb;
abort_ccb = ccb-&gt;cab.abort_ccb;

if(abort_ccb-&gt;ccb_h.func_code != XPT_SCSI_IO) {
ccb-&gt;ccb_h.status = CAM_UA_ABORT;
xpt_done(ccb);
return;
}
struct ccb *abort_ccb;
abort_ccb = ccb-&gt;cab.abort_ccb;

if(abort_ccb-&gt;ccb_h.func_code != XPT_SCSI_IO) {
ccb-&gt;ccb_h.status = CAM_UA_ABORT;
xpt_done(ccb);
return;
}
Then it is necessary to find this CCB in our queue. This can be done by walking the list of all our hardware control blocks in search for one associated with this CCB: 然后需要在我们的队列中找到这个CCB。这可以通过遍历我们所有硬件 控制块列表,查找与这个CCB关联的控制块来完成:
struct xxx_hcb *hcb, *h;

hcb = NULL;

/* We assume that softc-&gt;first_hcb is the head of the list of all
* HCBs associated with this bus, including those enqueued for
* processing, being processed by hardware and disconnected ones.
*/
for(h = softc-&gt;first_hcb; h != NULL; h = h-&gt;next) {
if(h-&gt;ccb == abort_ccb) {
hcb = h;
break;
}
}

if(hcb == NULL) {
/* no such CCB in our queue */
ccb-&gt;ccb_h.status = CAM_PATH_INVALID;
xpt_done(ccb);
return;
}

hcb=found_hcb;
struct xxx_hcb *hcb, *h;

hcb = NULL;

/* We assume that softc-&gt;first_hcb is the head of the list of all
* HCBs associated with this bus, including those enqueued for
* processing, being processed by hardware and disconnected ones.
*/
for(h = softc-&gt;first_hcb; h != NULL; h = h-&gt;next) {
if(h-&gt;ccb == abort_ccb) {
hcb = h;
break;
}
}

if(hcb == NULL) {
/* no such CCB in our queue */
ccb-&gt;ccb_h.status = CAM_PATH_INVALID;
xpt_done(ccb);
return;
}

hcb=found_hcb;
Now we look at the current processing status of the HCB. It may be either sitting in the queue waiting to be sent to the SCSI bus, being transferred right now, or disconnected and waiting for the result of the command, or actually completed by hardware but not yet marked as done by software. To make sure that we do not get in any races with hardware we mark the HCB as being aborted, so that if this HCB is about to be sent to the SCSI bus the SCSI controller will see this flag and skip it. 现在我们来看一下HCB当前的处理状态。它可能或呆在队列中正等待 被发送到SCSI总线,或此时正在传输中,或已断开连接并等待命令结果, 或者实际上已由硬件完成但尚未被软件标记为完成。为了确保我们不会 与硬件产生竞争条件,我们将HCB标记为中止(aborted),这样如果这个 HCB要被发送到SCSI总线的话,SCSI控制器将会看到这个旗标并跳过它。
int hstatus;

/* shown as a function, in case special action is needed to make
* this flag visible to hardware
*/
set_hcb_flags(hcb, HCB_BEING_ABORTED);

abort_again:

hstatus = get_hcb_status(hcb);
switch(hstatus) {
case HCB_SITTING_IN_QUEUE:
remove_hcb_from_hardware_queue(hcb);
/* FALLTHROUGH */
case HCB_COMPLETED:
/* this is an easy case */
free_hcb_and_ccb_done(hcb, abort_ccb, CAM_REQ_ABORTED);
break;
int hstatus;

/* shown as a function, in case special action is needed to make
* this flag visible to hardware
*/
set_hcb_flags(hcb, HCB_BEING_ABORTED);

abort_again:

hstatus = get_hcb_status(hcb);
switch(hstatus) {
case HCB_SITTING_IN_QUEUE:
remove_hcb_from_hardware_queue(hcb);
/* FALLTHROUGH */
case HCB_COMPLETED:
/* this is an easy case */
free_hcb_and_ccb_done(hcb, abort_ccb, CAM_REQ_ABORTED);
break;
If the CCB is being transferred right now we would like to signal to the SCSI controller in some hardware-dependent way that we want to abort the current transfer. The SCSI controller would set the SCSI ATTENTION signal and when the target responds to it send an ABORT message. We also reset the timeout to make sure that the target is not sleeping forever. If the command would not get aborted in some reasonable time like 10 seconds the timeout routine would go ahead and reset the whole SCSI bus. Since the command will be aborted in some reasonable time we can just return the abort request now as successfully completed, and mark the aborted CCB as aborted (but not mark it as done yet). 如果CCB此时正在传输中,我们一般会以某种硬件相关的方式发信号 给SCSI控制器,通知它我们希望中止当前的传输。SCSI控制器会设置 SCSI ATTENTION信号,并当目标对其进行响应后发送ABORT消息。我们也复位 超时,以确保目标不会永远睡眠。如果命令不能在某个合理的时间,如 10秒内中止,超时例程就会运行并复位整个SCSI总线。由于命令会在某个 合理的时间后被中止,因此我们现在可以只将中止请求返回,当作成功完成, 并将被中止的CCB标记为中止(但还没有将它标记为完成)。
case HCB_BEING_TRANSFERRED:
untimeout(xxx_timeout, (caddr_t) hcb, abort_ccb-&gt;ccb_h.timeout_ch);
abort_ccb-&gt;ccb_h.timeout_ch =
timeout(xxx_timeout, (caddr_t) hcb, 10 * hz);
abort_ccb-&gt;ccb_h.status = CAM_REQ_ABORTED;
/* ask the controller to abort that HCB, then generate
* an interrupt and stop
*/
if(signal_hardware_to_abort_hcb_and_stop(hcb) &lt; 0) {
/* oops, we missed the race with hardware, this transaction
* got off the bus before we aborted it, try again */
goto abort_again;
}

break;
case HCB_BEING_TRANSFERRED:
untimeout(xxx_timeout, (caddr_t) hcb, abort_ccb-&gt;ccb_h.timeout_ch);
abort_ccb-&gt;ccb_h.timeout_ch =
timeout(xxx_timeout, (caddr_t) hcb, 10 * hz);
abort_ccb-&gt;ccb_h.status = CAM_REQ_ABORTED;
/* ask the controller to abort that HCB, then generate
* an interrupt and stop
*/
if(signal_hardware_to_abort_hcb_and_stop(hcb) &lt; 0) {
/* oops, we missed the race with hardware, this transaction
* got off the bus before we aborted it, try again */
goto abort_again;
}

break;
If the CCB is in the list of disconnected then set it up as an abort request and re-queue it at the front of hardware queue. Reset the timeout and report the abort request to be completed. 如果CCB位于断开连接的列表中,则将它设置为中止请求,并在硬件 队列的前端将它重新入队。复位超时,并报告中止请求完成。
case HCB_DISCONNECTED:
untimeout(xxx_timeout, (caddr_t) hcb, abort_ccb-&gt;ccb_h.timeout_ch);
abort_ccb-&gt;ccb_h.timeout_ch =
timeout(xxx_timeout, (caddr_t) hcb, 10 * hz);
put_abort_message_into_hcb(hcb);
put_hcb_at_the_front_of_hardware_queue(hcb);
break;
}
ccb-&gt;ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
return;
case HCB_DISCONNECTED:
untimeout(xxx_timeout, (caddr_t) hcb, abort_ccb-&gt;ccb_h.timeout_ch);
abort_ccb-&gt;ccb_h.timeout_ch =
timeout(xxx_timeout, (caddr_t) hcb, 10 * hz);
put_abort_message_into_hcb(hcb);
put_hcb_at_the_front_of_hardware_queue(hcb);
break;
}
ccb-&gt;ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
return;
That is all for the ABORT request, although there is one more issue. As the ABORT message cleans all the ongoing transactions on a LUN we have to mark all the other active transactions on this LUN as aborted. That should be done in the interrupt routine, after the transaction gets aborted. 这就是关于ABORT请求的全部,尽管还有一个问题。由于ABORT消息 清除LUN上所有正在进行中的事务,我们必须将LUN上所有其他活动事务 标记为中止。那应当在中断例程中完成,且在中止事务之后。
Implementing the CCB abort as a function may be quite a good idea, this function can be re-used if an I/O transaction times out. The only difference would be that the timed out transaction would return the status CAM_CMD_TIMEOUT for the timed out request. Then the case XPT_ABORT would be small, like that: 将CCB中止作为函数来实现可能是个很好的主意,因为如果I/O事务超时 这个函数能够被重用。唯一的不同是超时事务将为超时请求返回状态 CAM_CMD_TIMEOUT。于是XPT_ABORT的case语句就会很小,像下面这样:
case XPT_ABORT:
struct ccb *abort_ccb;
abort_ccb = ccb-&gt;cab.abort_ccb;

if(abort_ccb-&gt;ccb_h.func_code != XPT_SCSI_IO) {
ccb-&gt;ccb_h.status = CAM_UA_ABORT;
xpt_done(ccb);
return;
}
if(xxx_abort_ccb(abort_ccb, CAM_REQ_ABORTED) &lt; 0)
/* no such CCB in our queue */
ccb-&gt;ccb_h.status = CAM_PATH_INVALID;
else
ccb-&gt;ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
return;
case XPT_ABORT:
struct ccb *abort_ccb;
abort_ccb = ccb-&gt;cab.abort_ccb;

if(abort_ccb-&gt;ccb_h.func_code != XPT_SCSI_IO) {
ccb-&gt;ccb_h.status = CAM_UA_ABORT;
xpt_done(ccb);
return;
}
if(xxx_abort_ccb(abort_ccb, CAM_REQ_ABORTED) &lt; 0)
/* no such CCB in our queue */
ccb-&gt;ccb_h.status = CAM_PATH_INVALID;
else
ccb-&gt;ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
return;
<emphasis>XPT_SET_TRAN_SETTINGS</emphasis> - explicitly set values of SCSI transfer settings <emphasis>XPT_SET_TRAN_SETTINGS</emphasis> - 显式设置SCSI传输设置的值
The arguments are transferred in the instance <quote>struct ccb_trans_setting cts</quote> of the union ccb: 在联合ccb的实例<quote>struct ccb_trans_setting cts</quote> 中传输的参量:
<emphasis>valid</emphasis> - a bitmask showing which settings should be updated: <emphasis>valid</emphasis> - 位掩码,显示应当更新那些设置:
<emphasis>CCB_TRANS_SYNC_RATE_VALID</emphasis> - synchronous transfer rate <emphasis>CCB_TRANS_SYNC_RATE_VALID</emphasis> - 同步传输速率
<emphasis>CCB_TRANS_SYNC_OFFSET_VALID</emphasis> - synchronous offset <emphasis>CCB_TRANS_SYNC_OFFSET_VALID</emphasis> - 同步位移
<emphasis>CCB_TRANS_BUS_WIDTH_VALID</emphasis> - bus width <emphasis>CCB_TRANS_BUS_WIDTH_VALID</emphasis> - 总线宽度
<emphasis>CCB_TRANS_DISC_VALID</emphasis> - set enable/disable disconnection <emphasis>CCB_TRANS_DISC_VALID</emphasis> - 设置启用/禁用断开连接
<emphasis>CCB_TRANS_TQ_VALID</emphasis> - set enable/disable tagged queuing <emphasis>CCB_TRANS_TQ_VALID</emphasis> - 设置启用/禁用带标签的排队
<emphasis>flags</emphasis> - consists of two parts, binary arguments and identification of sub-operations. The binary arguments are: <emphasis>flags</emphasis> - 由两部分组成,两元参量和子操作标识。两元参量为:
<emphasis>CCB_TRANS_DISC_ENB</emphasis> - enable disconnection <emphasis>CCB_TRANS_DISC_ENB</emphasis> - 启用断开连接
<emphasis>CCB_TRANS_TAG_ENB</emphasis> - enable tagged queuing <emphasis>CCB_TRANS_TAG_ENB</emphasis> - 启用带标签的排队
the sub-operations are: 子操作为:
<emphasis>CCB_TRANS_CURRENT_SETTINGS</emphasis> - change the current negotiations <emphasis>CCB_TRANS_CURRENT_SETTINGS</emphasis> - 改变当前的协商

Loading…

That is all for the ABORT request, although there is one more issue. BecauseAs the ABORT message cleans all the ongoing transactions on a LUN we have to mark all the other active transactions on this LUN as aborted. That should be done in the interrupt routine, after the transaction gets aborted.
a month ago
Browse all component changes

Glossary

English Chinese (Simplified) (zh_CN)
No related strings found in the glossary.

Source information

Source string comment
(itstool) path: listitem/para
Source string location
book.translate.xml:20578
String age
a month ago
Source string age
a month ago
Translation file
books/zh_CN/arch-handbook.po, string 2258