8.8 Reservations 预订
NVMe的reservation预订功能,用于让两个或多个主机能够协调配合的访问共享namespace。使用这些功能的协议和方式超出了本规格说明书的范围。对这些reservations功能的错误应用可能破坏数据或危害系统操作。
namespace上的reservation限制主机访问namespace。如果namespace在reservation情况下,主机提交命令到namespace缺乏足够的权限,那么命令就会被controller终止掉,返回Reservation Conflict状态。如果主机提交命令,命令中NSID设置了0xFFFFFFFF,这里边有任何一个namespace呈现reservation功能但主机缺乏足够权限的话,命令就会被controller终止掉,返回Reservation Conflict状态【预订冲突状态】。如下这种能力需要被提供的:允许从一个被故障或不配合的主机所持有的namespace上的reservation恢复回来。
Reservation要求主机和namespace之间相互关联。如果图Figure 460所示,多路径I/O中的每个controller和namespace共享环境只与一个主机相关联。而构建一个用两个或者更多的主机共享一个单一的controller的系统也许是可能的,但这种用法超出了本规格说明书的范围。
一个主机可以与多个controller关联,在Figure 460中,主机A与两个controller关联,而主机 B和C都是与单个controller相关联。A主机在每个controller上注册一个主机ID(第5.21.1.26章节定义Host Identify),主机ID是在任何与reservation有关的操作之前使用Set Features命令(第5.21章节定义此命令)来让主机与之对应的标识。主机ID给予NVM subsystem识别controller与这个主机关联的,并跨这些controller维持reservation属性(即:主机下发的命令,不论哪个与此主机关联的controller来处理这个命令,都具有相同的reservation权限)。
对于reservations的支持是通过namespace或是controller这个是可选的。在Identify Namespace数据结构的Reservation Capabilities(RESCAP)域中报告非0值就表示这个namespace支持reservations功能。通过Identify Controller数据结构的Optional NVM Command Support(ONCS)域来表示controller支持reservations功能。如果一个主机提交命令带reservations(即:Reservation Report, Reservation Register, Reservation Acquire, Reservation Release)到controller或namespace,但controller和namespace并没有同时都支持reservations,那么命令就会被controller终止掉,返回Invalid Command Opcode非法命令操作码状态。
构成NVM subsystem的Controller们必须所有controller对reservations具有同样的【一致的】支持。尽管强烈建议但并没有要求所有组成NVM subsystem的namespace对reservations具有相同的支持。例如,单个controller中的某些namespace可能支持reservations而另外一些不支持,或者这些namespace们支持的reservation类型可能不同。如果controller支持reservations那么这个controller必须:
- 通过在Identify Controller数据结构的Optional NVM Command Support(ONCS)域第5位返回‘1’表明对reservations支持;
- 支持Reservation Report 命令(参考第6.13章节),Reservation Register命令(参考第6.11章节),Reservation Acquire命令(参考第6.10章节),Reservation Release命令(参考第6.12章节);
- 支持Reservation Notification log page;
- 支持Reservation Log Page Available异步事件;
- 支持Reservation Notification Mask Feature;
- 支持Host Identify Feature;
- 支持Reservation Persistent Feature。
如果namespace支持reservations,那么namespace必须:
- 在Identify Namespace数据结构的Reservation Capabilities(RESCAP)域中呈现非0值;
- 支持Persist Through Power Loss(PTPL)状态;
- 支持给予主机充足的资源在NVM subsystem中每个controller上去顺利地注册一个reservation key,以便访问共享namespace(即:Reservation Register命令必须永远不会因为缺乏资源而失败)。
注意:为了提高与SCSI基本实现的兼容性,Ignore Existing Key的行为已经被做了变更。在Identify Namespace数据结构的Reservation Capabilities(RESCAP)域中表示的与变更后的行为相符合。对于之前的Ignore Existing Key行为,参考规格说明书的1.2.1版本。
8.8.1 Reservation Notifications
有三种类型的reservation通知:registration preempted,reservation released,reservation preempted。【注册抢占、预订发布、预订抢占】。引起reservation通知的条件将在后边章节中描述。在一个已加载到controller的namespace上,只要发生了未被屏蔽的预订通知,Reservation Notification log page就被会创建(参考第5.14.1.16.1章节)。预订通知可以从每个预订通知类型上产生预订日志页,或者基于每个namespace ID通过Reservation Notification Mask特性,屏蔽掉的(参考第5.21.1.27章节)。主机可以使用Asynchronous Event Request命令(参考第5.2章节),出现了一个或多个可用的Reservation Notification日志页时就会被通知到(参考第5.14.1.16.1章节)。
8.8.2 注册
在namespace上建立预订之前,主机必须通过注册一个reservation key成为这个namespace的登记者。这个reservation key可以被主机作为确认登记者(主机)、验证登记者身份、抢占一个已故障或不合作的登记者的一种手段来使用。reservation key的值如何被主机使用,以及用于选择其值的方法超出了本规格说明书的范围。
用namespace注册一个reservation key将创建一个主机与namespace之间的关联关系。作为一个namespace的登记者主机,可以使用任何一个已经与此主机关联的controller(即:有相同的Host Identifier,参考第5.21.1.26章节)去访问这个namespace。因此,一个主机成为namespace的登记者只需要在NVM subsystem中能够访问这个namespace的且已经与这个主机关联的所有controller中的某一个单个controller上注册即可。
主机注册reservation key是通过在namespace上执行一个Reservation Register 命令(参考第6.11章节),把Reservation Register Action(RREGA)域清零(即:Register Reservation Key),并在New Reservation Key(NRKEY)域中提供一个reservation key。
namespace的登记者主机,可以在与此namespace相关的同一个或不同的controller上用相同的reservation key值注册多次。对于一个Reservation Register命令RREGA域为000b:
a)IEKEY域必须被忽略;
b)如果一个主机已经是namespace的登记者,企图再使用不同的注册key值向这个namespace注册,那么命令必须被终止,返回Reservation Conflict状态。
不同主机ID的主机使用的reservation key值没有限制。例如,多个主机可以都用同一个reservation key值注册。
namespace的登记者主机,可以在namespace上通过执行一个Reservation Register命令替换已经存在的reservation key值,带如下信息:
a)RREGA域设置为010b(即:Replace Reservation Key);
b)在Current Reservation Key(CRKEY)域中填写当前reservation key;
c)在NRKEY域中填写新的reservation key。
替换reservation key时,namespace挂载的具有那个主机ID的所有controller中都必须把当前reservation key值替换成新reservation key值。如果CRKEY域中的内容与当前主机关联的key不匹配,那么命令必须被终止,返回Reservation Conflict状态。主机替换它的reservation key时,可以通过把Reservation Register命令中Ignore Existing Key(IEKEY)位设置为1,从而不用再关心它的登记状态或当前reservation key值。替换一个reservation key对在namespace上已经持有的任何预订都没啥影响。
8.3.3 Reservation Types预订类型
NVMe接口支持六种预订类型:
- Write Exclusive;
- Exclusive Access;
- Write Exclusive - Registrants Only;
- Exclusive Access - Registrants Only;
- Write Exclusive - All Registrants;
- Exclusive Access - All Registrants;
这些预订类型之间的区别是:被排除的访问类型,登记者是否与预订持有者具有相同的访问权限,是否登记者也被视为预订持有者。这些区别被总结在Figure 461中,每个NVMe命令的特定行为展示在Figure 462中。
除了断电重启之外,所有Controller Level Resets和所有NVM subsystem Resets,预订和注册仍然持久存在。由于使用Persist Through Power Loss State(PTPLS)断电而重启的情况,预订的保留是可选性配置。一个Persist Through Power Loss State(PTPLS)是与每个支持预订功能namespace关联的,可以用Reservation Register命令的侧面效果或Set Features命令来修改的。
8.8.4 注销
namespace的登记者主机可以在namespace上通过执行Reservation Register命令注销登记,命令RREGA域设置成001b(即Unregister Reservation Key),并在CRKEY域中提供当前的reservation key。如果CRKEY域中的内容与主机当前关联的key不匹配,那么命令就被终止掉,返回Reservation Conflict状态。如果主机不是一个登记者,那么命令被终止掉,返回Reservation Conflict状态。
一个注销操作的成功完成使得主机不再是namespace的登记者。主机可以通过在Reservation Register命令中把IEKEY位设置为1而不关心它的当前reservation key值进行注销。
主机注销过程可以引起这个主机所持有的预订被释放。如果主机是剩下的最后一个预订持有者(即:预订类型是Write Exclusive - All Registrants 或 Exclusive Access - All Registrants)或者是仅有的预订持有者,那么当主机注销时预订就被释放。
如果预订被释放,并且已释放的预订类型是Write Exclusive - Registrants Only 或 Exclusive Access - Registrants Only,那么在所有与已注册主机关联的controller上产生一个预订释放通知,除了下发了Reservation Register命令的主机。
8.8.5 获得一个预订
为了主机在namespace上得到一个预订,该主机必须是namespace的登记者。登记者通过执行Reservation Acquire命令(参考第6.10章节)获得预订,把Reservation Acquire Action(RACQA)域清除为000b(Acquire),在Current Reservation Key(CRKEY)域中提供与主机关联的当前reservation key。CRKEY值必须与登记者在namespace注册时使用的值相匹配。如果CRKEY值不匹配,那么命令被终止返回Reservation Conflict状态。如果主机不是登记者,命令被终止返回Reservation Conflict状态。
同一时间内一个namespace上只允许一个预订。如果登记者在namespace上已经是预订持有者而尝试去获得预订,那么命令被终止返回Reservation Conflict状态。如果预订持有者在namespace上尝试去获得一个不同类型的预订,那么命令被终止返回Reservation Conflict状态。如果预订持有者在namespace上尝试去获得这个主机已经持有的相同类型的预订这不算是一个错误。预订持有者可以抢占预订来变更预订类型。
8.8.6 释放预订
只有预订持有者才可以有秩序的释放在namespace上持有的预订。主机通过执行Reservation Release命令释放预订,把Reservation Release Action(RRELA)域清零,把Reservation Type(RTYPE)域设置成被释放的预订类型,在Current Reservation Key(CRKEY)域中提供与这个主机关联的当前reservation key。CRKEY值必须与主机在namespace上注册的值相匹配。如果key值不匹配,那么命令被终止返回Reservation Conflict状态。如果RTYPE域与当前预订的类型不匹配,那么命令完成返回命令中Invalid Field状态。
登记者使用Reservation Release命令尝试释放一个预订,但这个预订还没有在namespace上被持有预订,或者这个主机不是这个预订的预订持有者,必须让命令成功完成,但是必须对controller和namespace不产生任何影响。
像在本章节中描述的行为结果,当预订被释放,预订类型不是Write Exclusive或Exclusive Access,在NVM subsystem中所有与登记者主机关联的controller上产生一个预订释放通知,除了下发了Reservation Release命令的那个与主机关联的controller。【也就是说主机下发预订释放命令的那个控制器不用再给自己产生释放通知了】
8.8.7 抢占一个预订或登记
一个登记者主机可以通过执行Reservation Acquire命令抢占一个预订或登记,把Reservation Acquire Action(RACQA)域设置成001b(Preempt),在CRKEY域里提供与主机关联的当前预订key。CRKEY值必须与登记者向namespace注册时使用的值相匹配。如果CRKEY值不匹配,那么命令被终止返回Reservation Conflict状态。抢占行为作用依赖于namespace上持有预订的类型(如果有的话),以及命令中Preempt Reservation Key(PRKEY)域的值。如果主机不是一个登记者,那么命令被终止返回Reservation Conflict状态。本章节接下来的描述假定主机是登记者。
如果存在的预订类型不是Write Exclusive - All Registrants 也不是Exclusive Access - All Registrants,那么命令执行的操作依赖于PRKEY域的值,如下:
a)如果PRKEY域的值匹配当前预订持有者的reservation key,那么如下作为原子操作出现:
-
- 除了下发命令的这个主机是未注册的,所有登记者都匹配registration key;
- 预订被释放;
- 为下发命令的主机创建一个新的预订,预订类型由命令中的Reservation Type(RTYPE)域指定,该下发命令的主机作为reservation key持有者;
或者
b)如果PRKEY域值不匹配当前预订持有者的值,且也不等于0h,那么谁的reservation key能匹配PRKEY域值的这些登记者们就会被注销。如果PRKEY域值不匹配当前预订持有者的值,且等于0h,那么命令被终止返回Invalid Field in Command状态。
如果存在的预订类型是Write Exclusive - All Registrants 或 Exclusive Access - All Registrants,那么命令执行行为依赖于PRKEY域,如下:
a)如果PKEY域值是0h,那么如下作为院子操作出现:
-
- 除了下发命令的这个主机,所有登记者们都被注销;
- 预订被释放
- 为下发命令的这个主机创建一个新的预订,预订类型由命令中的Reservation Type(RTYPE)域指定,这个下发命令的主机成为reservation key持有者;
或者
b)如果PRKEY值是非零,那么谁的reservation key匹配PRKEY域值的登记者们就会被注销。如果PRKEY值是非零且没有登记者的reservation key匹配PRKEY域值,controller应该返回一个Reservation Conflict的错误。
如果namespace上没有预订持有者,命令的执行会引起reservation key匹配PRKEY域值的登记者被注销。
如果存在的预订类型不是Write Exclusive - All Registrants 也不是Exclusive Access - All Registrants,那么预订持有者可以使用上边的机制抢占它自身。当一个主机抢占它自身时如下作为原子操作出现:
- 该主机的登记者身份被保持的;
- 预订被释放;
- 为主机创建一个新预订,预订类型由RTYPE域指定。
作为由执行Reservation Acquire命令抢占一个预订的辅助结果主机可以终止命令,设置RACQA域为010b(Preempt和Abort)。此命令的行为与上边描述的RACQA域设置为001b(Preempt)完全相同,但有如下两个例外:
- 原子操作变更namespace预订和注册状态之后,所有与预订和注册的主机相关联的controller们都被原子操作抢占,要求对正在处理的寻址这个namespace的命令都终止,这个namespace在Namespace Identifier域中指定(即:NSID域在Reservation Acquire命令)(‘“正在处理”的定义参考第4.13章节);
- 不论每个被请求中止的命令是否实际中止,直到所有被请求终止的命令完成,不能Reservation Acquire命令的Completion。
像Abort Admin命令那样(参考第5.1章节),中止作为抢占预订的额外效果是尽力而为;当一个Reservation Acquire或Abort Admin命令被提交,作为被请求中止的命令可能当前正在执行,这种命令不能在被中止,或者已经被完成。尽管提示中止请求执行,减小完成Reservation Acquire命令的延迟,被请求中止的命令在完成Reservation Acquire命令之前必须要么被中止要么被完成。
作为本章节中描述的行为结果,当一个登记者被注销,除了下发Reservation Acquire命令的那个主机,在所有与被注销的主机关联的controller们上产生一个注册登记抢占通知。
作为本章节中描述的行为结果,当namespace上持有的预订类型变更,除了下发Reservation Acquire命令的那个主机,与仍然是namespace的注册者的主机相关联的所有controller们上产生一个预订释放通知。
8.8.8 清除预订
通过执行Reservation Release命令(参考第6.12章节),登记者主机可以清除预订(即:强制namespace上持有的预订释放掉和注销所有登记者),设置Reservation Release Action(RRELA)域为001b(即Clear),在Current Reservation Key(CRKEY)域提供与主机相关的当前预订key。如果CRKEY域中的值与主机在namespace上注册使用的值不匹配,命令必须被中止返回Reservation Conflict状态。如果主机不是一个登记者,命令被中止返回Reservation Conflict状态。当命令清除预订被执行以下作为原子操作出现:如果namespace上有预订,则释放,所有的登记者都被从namespace注销。
除了这些与下发Reservation Release命令主机相关联的controller,那些NVM subsystem中的controller上都产生一个预订抢占通知,那些controller是指作为本章节提及的行为结果,与注册被移除的主机相关联的controller们。
8.8.9 报告预订状态
主机可以通过执行Reservation Report命令确认与namespace相关的当前预订状态(参考第6.13章节)。