在NVM subsystem中,可能會存在多個controllers,每一個controller可能會去存取某些特定namespace。Namespace由多個logical blocks所組成,而logical blocks是controller存取data的最小單位。而一個logical blocks的size為何,可以為512 bytes, 1 KiB, 4 KiB…等,主要透過Identify command的Identify Namespace data structure(INDS)的內容可以得知,單位為bytes。
如圖1所示,表列了所有NVM command的指令的種類,並且使用Opcode來區分,Flush、Write、Read Command為必須support的(mandatory),其餘則為optional。Host必須在CSTS.RDY = 1的情況下才能提交I/O command。
Figure 1. I/O command Set
而提交I/O command到SQ和回覆CQ的格式和Admin Command一樣,然後CDW10~CDW15還是根據不同的command有不同的欄位定義。
Compare、Read、Verify、Write和Write Zeroes command中,如果Host在提交指令的時候設Limit Retry欄位為1,表示command有error recovery時間的限制,不能retry太多次,而error recovery時間限制主要透過Set Feature – Error Recovery來設定。
Namespace是logical blocks的集合,logical block address編號從0開始,直到namespace的最大的size,每個namespace都會有獨立的ID來表示(NSID)。而要如何得知NSID是否是有效(valid)的呢?主要透過Identify Controller Data Structure裡的Number of
Namespaces(NN)欄位來得知,但是NSID 0是無效的,所以有效的NSID就是1 ~ NN,然後NSID 0xFFFFFFFF主要用來表示broadcast,也就是表示all namespace的意思。
如圖2所示,如果NSID介於1~NN則是valid NSID, 其餘的是invalid,然後valid NSID之中又包含Allocated和Unallocated的NSID。Allocated代表NSID有指定到NVME Subsystem中存在的namespace, Unallocated NSID代表還沒指定到任何namespace。NSID的另外一個狀態就是Active和Inactive,如果此NSID有attach到某個controller,那麼此NSID則為active,反之則為inactive。那NSID彼此之間的關係是什麼呢? 首先可以看到紫色框框的部分,Unallocated NSID一定是Inactive的狀態,綠色框框的部分Allocated NSID可能是Active或Inactive,取決於是否有attach到任何controller。
如host發了一個帶著Inactive NSID的command,則controller會回error completion with status “Invalid Field”。如果host發了一個帶著Invalid NSID的command則controller會回error completion
with status “Invalid Namespace or Format”
Figure 2. NSID Types
■ NSID and Namespace Usage
如果Controller有support Namespace Management, ANA Reporting或NVM Sets的話,NSID必定不能重複,如果全部都沒有support的話,則(1) shared namespace的話NSID必須唯一,(2) 如果是private namespace的話則NSID可以重複。
ICDS.MNAN(Maximum Number of Allowed Namespaces)欄位如果為0的話,那麼NVM Subsystem中最大的allocated NSIDs就由ICDS.NN欄位來決定。
那麼要如何去尋找NVM Subsystem中有哪些active NSID呢? 有兩種方式,(1) 對每個supported NSID(MNAM or NN field)下Identify Namespace Data Structure(INDS),如果回報非全0的4096 bytes則為active namespace,(2) 透過Identify – Active Namespace ID list(CNS 02h)來取得如圖3的List,這個list會列出目前狀態為active的NSID,其餘entry則需清為0,list最多可以回報1024個active NSID。
Figure
3. Namespace List Format
那麼要如何去尋找NVM Subsystem中有哪些allocated NSID呢? 可以透過Identify - Allocated Namespace ID list(CNS 10h)來取得,格式和圖3一樣。
NSID可能在經過系統power off後會改變,所以host可以透過UUID or NGUID or EUI64來辨別是否和pweroff前,是否為同一個namesapce。
■ Namespace Size, Capacity and
Utilization
上述有提到host可以透過INDS來得知有哪些NSID為active的狀態,除了得知狀態以外,structure裡面還包還含了一些資訊如下:
NSZE: Namespace Size,描述這個namespace總大小為何,單位為LBAs,而LBA編號為從0開始,所以此欄位回報值為n的話,就是從LBA 0 ~ LBA n-1。
NCAP: Namespace Capacity,表示NSZE裡面最大可以有多少LBA被分配到namespace裡,正常來說NSZE等於NCAP。
NUSE: Namespace Utilization,此欄位表示當前已經有多少LBA已經被分配到namespace裡。
Figure
4. Namespace Attribute
其中這三個欄位還會被NSFEAT的THINP bit所影響,THINP全名應是為Thin Provisioning,意思就是NSZE的空間並不會一開始就全部都分配,而是只分配目前實際使用的空間的大小,當有寫入資料的時候再索取空間,所以當THINP為1b的時候,NCAP值是會小於(或等於)NSZE的值,且NUSE必須隨時更新目前系統上實際使用了多少空間。如果THINP bit為0b,則固定NSZE = NCAP = NUSE。
■ Namespace Creation &
在介紹I/O command之前,首先先介紹一下Admin command中的Namespace Management和Namespace Attachment。Namespace Management可以create一個新的namespace或delete現存的namespace,Command格式如圖5所示,主要會用到DPTR欄位和Select欄位。
接下來介紹Namespace Attachment command,當上述create動作完成後,必須做attach到controller的動作,才能透過controller去存取namespace,其格式如圖7所示
■ Write Command
Opcode為01h,格式如圖9所示,主要就是host想要將data寫到哪個LBA range,需要使用到欄位為NSID、DPTR、CDW10~CDW15。DPTR指向的是host所準備好的write data的data buffer base address,因此controller就可以知道去哪裡讀資料(controller read),然後在Starting LBA(SLBA)欄位填入欲寫入LBA的起始位置,然後長度由Number of Logical Blocks(NLB)決定,因此LBA range為 SLBA ~ SLBA+(NLB-1)。
■ Read Command
Opcode為02h,格式如圖10所示,主要就是host從哪個LBA range將想要的data讀出來,需要使用到欄位為NSID、DPTR、CDW10~CDW15。DPTR指向的是host所準備好的read data buffer base address,因此controller就可以知道要將資料(controller write)寫到何處,然後在SLBA欄位填入欲讀出LBA的起始位置,然後長度由NLB決定,因此LBA range為 SLBA ~ SLBA+(NLB - 1)。
■ Flush Command
Opcode為00h,主要是目的是要將之前寫在Volatile Write Cache(VWC)裡的data,寫到nand flash裡面。VWC基本上就是會暫存Write command的data,來縮短data寫入nand裡面的時間,來得到較好的performance。VWC可以透過ICDS.VWC[0](圖11)來得知controller是否有support,然後透過Set Feature - Volatile Write Cache的Write Cache Enable bit(WCE)來開啟VWC功能(圖12)。
Flush Command(圖13)並不會用到CDW10之後的欄位,因此為reserved,也因為不用帶任何data buffer,因此DPTR並不會使用到。
Opcode為04h,格式如圖14所示,主要是目的是將指定的LBA range標記為invalid(無效的),需要使用到欄位為NSID、CDW10~CDW12,透過SLBA和NLB欄位指定LBA range。如果host發出任何Read cmd到WriteUNC指定的range,controller必須回報error completion with status "Unrecovered Read Error "。如果要消除LBA的invalid的狀態,則host必須提交Write cmd到想要消除的LBA range。
■ Write Zeroes Command
Opcode為08h,格式如圖15所示,主要是目的是將指定的LBA range寫全0,但是資料並不是透過host給予,所以controller可以自己決定用什麼方式來實現,可能是用標記的方式或自己產生全0的data寫入Nand裡面,需要使用到欄位為NSID、CDW10~CDW12和CDW14、CDW15,透過SLBA和NLB欄位指定LBA range。如果host發出任何Read cmd到Write Zeroes指定的range,controller會回全0的data。
■ Compare Command
Opcode為05h,格式如圖16所示,主要就是host將想要比較的data準備好並與指定的LBA range做比較,需要使用到欄位為NSID、DPTR、CDW10~CDW12、 CDW14和CDW15。DPTR指向的是host所準備好的compare data buffer base address,因此controller就從哪裡讀取資料(controller read),然後由SLBA和NLB指定compare LBA range,並且由controller來執行compare的動作,如果比對結果一致則回覆Successful completion,不一致則回覆error completion with status "Compare Failure"。
■ Verify Command
Opcode為0Ch,格式如圖17所示,主要就是host想要確認資料的完整性,因此controller會需要將data從Nand裡面讀出來做integrity checks,所以verify屬於read的行為,需要使用到欄位為NSID、CDW10~CDW12、 CDW14和CDW15。Verify不需要從host給予data因此不需要DPTR,然後由SLBA和NLB指定verify的LBA range。
Reference: NVM Express Base Specification Revision 1.4c
沒有留言:
張貼留言