蛋博士最近的兴趣是UFS,作为蛋读系列的忠实读者,我定了个小目标:读好NVMe,然后像蛋博士一样成为人生赢家。
向偶像靠拢的第一次就从NVMe Reservation这个功能开始。Reservation的意义在于,提供一个机制,避免多个Host访问一个共享的Namespace出现冲突。
下图是一个实际的应用场景,一个典型的高可用(双活)存储系统:
- 上方的两个Storage Controller是两台Host: Host A和Host B (状态可以是Active-Active, Active-Idle, Idle-Active)
- 中间的两个交叉箭头,是两个PCIe Switch芯片:Switch A和Switch B
- 下方是一堆2的双端口SSD,SSD_1~SSD_N
- SSD_1~SSD_N他们通过Switch A和Switch B同时连到Host A和Host B
针对每一个独立的SSD,Host A和Host B都可以对它进行访问,为了避免冲突,就需要使用Reservation功能。需要注意的是,Reservation操作的对象是Namespace,而不是SSD,如果Host对该SSD的某个Namespace发送了一个权限以外的命令,SSD会abort这个命令。
NVMe Reservation是一个可选支持的功能,SSD通过Identify Namespace数据结构里的Reservation Capabilities (RESCAP)位告知Host自己是否支持该功能。
为了更好的理解Reservation的概念,我们结合一个蛋博士例子进行讲解。在200x年,蛋博士刚到上海准备租房,为了省钱买光盘,他决定找人合租,然后他找到了一位美女合租。
他们俩租的这套房子不大但是功能齐全,唯一的不足是只有一间卧室。好在,美女早出晚归,蛋蛋昼伏夜出,只要合理安排,一间卧室也可以满足大家的需求。
这样,蛋博士和美女就是Host A和Host B,租的房子是SSD,卧室则是Namespace。
Registering (注册)
首先,蛋博士和美女需要分别从房东那里获取一卧室把钥匙。在NVMe里,Host通过向SSD发送Reservation Register命令(把Reservation Register Action字段设置为000b)获取一个Reservation Key。
蛋蛋如果泡吧的时候把钥匙弄丢了,可以再向房东领一把。在NVMe里,Host可以发送Reservation Register命令(把Reservation Register Action字段设置为010b)替换掉原来的钥匙,但是前提是必须在Current Reservation Key字段填上之前的Key。
也就是说,蛋蛋如果想找房东配一把美女房间的钥匙,因为不知道美女的Key,是没法配的。
Reservation Type (预约模式)
在租来的房子里,蛋蛋仍然有一股男主人的气势,跟美女合租的第一天就约法三章:
- 不能在我备份小电影的时候动我的电脑;
- 我看电视的时候,你可以在我旁边一起看,但不能随便换台;
- 不准随便带陌生人回来,除非是漂亮妹子;
在NVMe里,有3类角色:
- Reservation Holder – 当前获得namespace使用权Host (蛋蛋)
- Registrant – 所有获得Reservation Key的Host (蛋蛋和美女)
- Non-Registrant – 其他Host (陌生人)
Reservation Holder,有6种Reservation模式
- Write Exclusive — 除了Reservation Holder,其他Host都不能写该Namespace
- Exclusive Access — 除了Reservation Holder,其他Host都不能访问该Namespace
- Write Exclusive – Registrant Only — 除了Reservation Holder和一个Registrant,其他Host都不能写该Namespace
- Exclusive Access – Registrant Only –除了Reservation Holder和一个Registrant,其他Host都不能访问该Namespace
- Write Exclusive – All Registrant Only –除了Reservation Holder和Registrants,其他Host不能访问该Namespace
- Exclusive Access – All Registrant Only –除了Reservation Holder和Registrants,其他Host不能访问该Namespace
看表格会比较直观,不同身份的Host对某个被Reserve的Namespace的访问权限
拓展到具体的NVMe命令
上表中:
A代表Allowed,命令会被正常执行
C代表 Conflict,命令会被SSD Abort掉,并且会告知原因是Reservation Conflict
Unregistering (注销)
蛋蛋有很强的灵活性,随时可以退租换个美女继续合租。
NVMe里Host可以通过发送Reservation Register命令(把Reservation Register Action字段设置为001b)注销对Namespace的Reservation。
注销以后,这个host就不再是该Namespace的Registrant。
当某个Namespace的所有Registrant全部注销以后,这个Namespace就被release了。
Acquiring a Reservation (获得使用权)
获得房间钥匙是第一步,想跟蛋蛋一样获得对Namespace的全部访问权限,Host需要下发Reservation Acquire命令, 把Reservation Acquire Action字段设置为000b, 同时在Current Reservation Key字段设置正确的Key (与前面注册时的Key相同)。
一个Namespace同时只能接收一个Reservation,在Host A已经占用namespace时,如果Host B发送Reservation Acquire命令,该命令会被SSD abort。
Release a Reservation (释放使用权)
Host A在完成相关操作以后,可以下发 Reservation Release命令,把Reservation Release Action字段设置为000b),同时在Current Reservation Key字段设置正确的Key,从而释放该Namespace。
Preempting a Reservation or Registration (抢占使用权)
蛋蛋与各位美女合租,一直耀武扬威,直到遇到了蛋嫂…
在Host A是Reservation Holder的情况下,Host B也有方式把namespace的使用权夺过来,具体方式是下发Reservation Acquire命令, 把Reservation Acquire Action字段设置为001b,同时在Current Reservation Key字段设置正确的Key。
只要当前Host A的reservation type不是”Write Exclusive – All Registrants”或者“Exclusive Access – All Registrants”, SSD就会注销Host A,释放其使用权,并将Host B设置为新的Reservation Holder。
Clear a Reservation (清理)
蛋蛋遇到了蛋嫂不再强势,不是因为不敢,只是不想…
Host A即使被Host B抢走了Namespace的使用权,但是只要保持了Registrant身份,仍然可以下发Reservation Release命令,将Reservation Release Action字段设置为001,同时在Current Reservation Key字段设置正确的Key。就可以召唤神龙,将所有注册为该Namespace registrant的Host全部注销掉。