linux mtd nftl 算法剖析 整理

NFTL

From ESSLabWiki

Jump to: navigationsearch

Independent Stuedy: NFTL

摘要

目前的隨身電子產品,如手機、隨身聽所用的儲存裝置大都是flash memory,但因為flash的特性,是無法重複寫同一塊記憶體位置做寫入的動作,必須事先erase該塊記憶體位置(將其充電)才能再做寫入的動作,因此一般我們所使用的檔案系統,如FAT16FAT32NTFSext2,將無法直接用在flash memory上。若我們想要沿用這些檔案系統,則必須透過一層Translation Layer來將Logical Block Address對應到實體的flash memory的位置,並透過一些機制能讓系統能把flash memory當作一般的硬碟一樣處理,我們稱這層為FTLFlash Translation Layer

 

動機

因為FTL是用在NOR Flash上的機制,而NOR Flash在大容量的應用上並不如NAND flash划算,因此有NFTLNAND Flash Translation Layer的產生,NFTL主要想法與FTL相似,主要差別在於是用在NAND Flash上,以支援目前隨身電子產品對於容量上的需求。

目前對於NFTL的文件、系統架構並沒有相當足夠的資訊,因此我們藉此機會來trace NFTL的原始碼來了解,NFTL詳細的運作細節及系統架構,本文件將介紹NFTLFlash上的Data structureRAM上的Data structureNFTLREAD / WRITE動作、Garbage CollectionBlock management。(圖一)為NFTL在整個檔案系統中所扮演角色。

(圖一)

 

NAND flash的特性

在介紹NFTL之前,必須先對NAND有一些基本的了解,會幫助我們了解NFTL以及知道為什麼一般的file system無法用在flash上。以下是一個NAND flash memory的架構圖(圖二)

(圖二)NAND flash memory的架構圖

 

NAND flash由很多層的block組成,而blockerase的最小單位。一個Block通常包含了32page,而pageread / write的單位,一個page的大小為512bytes(user space) + 16bytes(spare area)。其中user space是用來存放一般的dataspare area是用來儲存一些meta data作為管理file system用。

 

Major RAM-resident data structures and on-flash data structures employed by NFTL

NFTL主要的功能是將Logical Block Address對應到實體的flash memory address(物理块地址),藉此來達到能讓flash使用FAT等用在block device一類的file system。因為NAND flash的一些特性,必須在RAM上建構一些data structurealgorithm,並且在flash上儲存metadata作為NFTL初始時建構RAM中的data structure所用,才能達到此目的。因此在此我們要介紹NFTLRAM上及flash上的data structure

 

1TerminologiesNFTL之基本架構

    因為NFTLcode中,用了許多term,在此必須先定義一些Terminologies,來幫助之後的說明。(可參考圖三)

· Erase Uniterase的基本單位,即flash中的block (物理块)

· Virtual UnitRAM中對應flashblock的單位。實際上只儲存對應的blockflash上的physical address(逻辑块)

· Block ChainNFTL將資料存在由block所組的chain中,該chain則稱作block chain。透過存放在erase unit上的metadata資訊來達成。

· Replace Unit:在block chain中,接在第一個block後的block都稱作Replace Unit (块链第一物理块之后块)

· Virtual Unit Chain:在RAM中,透過EUNtalbleReplUnitTable可以找到每個virtual unit屬於哪個block chain及他的replace unitphysical address  块链

 

说明:一个 逻辑块上 对应 一个 块链  ,具体的逻辑块上的各个扇区 分别对应块链中 最后物理块的 相应扇区

 

2RAM-resident data structures (内存描述)

RAM上主要的data structure有下列幾項:

struct NFTLrecord {

            __u16 lastEUN;

 

__u16 numfreeEUNs;

 

__u16 LastFreeEUN;

 

__u16 *EUNtable;

 

__u16 *ReplUnitTable;

              unsigned int nb_blocks;

              struct nand_oobinfo oobinfo;

};

其中:

· LastEUN代表flash中最後一個blockphysical adderss(物理块号)

· numfreeEUNs代表目前共有幾個free blocks

· LastFreeEUN代表最後一個被找到的free block (物理块号)

· *EUNtable是一個logical to physicaltable紀錄每個block所屬的chain的起始physical address。其index item代表logical addressdata item代表physical address。而透過EUNtable我們可以找到該virtual unit對應的block所屬block chain的起始physical address。此table是存在RAM中。參考下圖。

· *ReplUnitTable是一個physical to physicaltable紀錄每個在chain中的block,其之後的blockphysical adderss,以維持Virtual Unit Chain的結構。其index item代表目前的blockphysical addressdata item代表串在他後面的blockphysical address。此table存在RAM

· nb_blocks代表Flash中共有幾個block。參考下圖。

· oobinfo則是用來儲存自flash中讀出的oobinformation

 

3on-flash data structures (介质存贮格式)

Flash上的data structure主要則是存在Spare AreaoobinfoOOB則是由bci (block control information)uci(uni control information)組成,bci記錄每個pagestatusuci則記錄每個blockinformation,詳細內容如下圖(圖四):

(圖四)oob中所有的資料

 

其中:

· nftl_bci內包含ECC(error correct code)StatusStatus1,而bci(block control information),是每個page一個,主要用來記錄每個pagestatus

    ECC是用來預防資料存取發生錯誤時所需的錯誤更正碼。

    StatusStatus1則是記錄每個sector的狀態。當寫入資料到user area時,同時將此資訊寫入spare areaoob.b中。而StatusStatus1所存的資料是一樣的,其目的是避免在資料寫入時發生非預期的bit1變成0。在uci方面也是相同的道理,之後不再贅述。

    其狀態有下列四種:

      SECTOR_FREE 0xff

      SECTOR_USED 0x55

      SECTOR_IGNORE 0x11  ?

      SECTOR_DELETED 0x00 ?

· nftl_uci內包含nftl_uci0nftl_uci1nftl_uci2,而uci(unit control information)是記錄整個block的資訊,是每個block一個,他們在flash上的儲存方式如(圖五)

 

   nftl_uci0包含VirtUnitNumReplUnitNum

      VirtUnitNum存每個blockVirtual address以便在初始時建立EUNtable

      ReplUnitNum存接在此block之後的Replace Unitphysical address

寫入flash的時機有下列幾種可能:1.在新增blockblock chain中時寫入oob.u中。2.folding完成後,重新設定其 VirtUnitNumReplUnitNum

 

   nftl_uci1包含WearInfoEraseMark

      WearInfo記錄該blockerase過的次數。

      EraseMark則是用來確定該Block是否被erase過。在成功erase block後會將其內容寫為ERASE_MARK 0x3c69

 

   nftl_uci2包含FoldMarkunused

       FoldMark我們在做Fold Chain(从一个最长块链,各扇区合成一个块,擦除回收可用块),若要做inplace不需另找中间空闲块,outplace需另找中间空闲块時會先將其目標erase unitFoldMark設為FOLD_MARK_IN_PROGRESS

       Unused決定做inplace fold chain後將此欄位全設為1

 

(圖五)oobblock中存放的方式

 

其中,oob.u.aoob.u.boob.u.c需要放在不同的page主要原因是,我們不一定會同時存取這三樣資訊,如果我們把他放在同一個page中,若我們先寫入oob.u.a,之後又想寫oob.u.c,此時我們就無法將oob.u.c寫入,除非我們將該block rease (1个扇区擦完后只能写一次)

 

4初始构建 (从介质存贮格式构建内存描述)

 

   接著介紹NFTL的基本架構,在NFTL初始時,會讀取每個block中的metadataoobinfo,然後在RAM中建構出一個EUNtalbleReplUnitTable(稍後我們會詳細介紹)來模擬成一個Virtual Unit ChainVirtual Unit Chain則是由一個以上的Virtual Unit所組成,virtual unit則是在RAM中用來對應flash中的erase unit,實際上virtual unit並不儲存資料,他只儲存所對應的erase unitphysical address,即ReplUnitTableentry,而Virtual unit chain則是一個logical address指著virtual unit chain的第一個virtual unit的位置。如下圖(圖三)所示:

(圖三)Virtual Unit ChainBlock Chain的關係

 

Blocks management of NFTL

因為NAND flasherase單位是block,所以對大多數的flash file system而言,管理block是主要的課題之一,以下介紹NFTL管理block的方式、如何找到free block以及如何選擇blockerase

 

1How blocks are managed by NFTL?

主要透過RAM中的兩個tableEUNtableReplUnitTable來完成EUNtableReplUnitTable的介紹可參考圖三及section4.1其用法如圖七。

ReplUnitTable另外記錄了每個Block的狀態,當我們想要知道某個block的狀態是FREE或是RESERVED時都是透過ReplUnitTable。而該資訊是在系統起始時所建立的。以下為ReplUnitTable所能記錄的狀態。

· BLOCK_NIL             (=0xffff   表示該block後面沒有串連別的block

· BLOCK_FREE           (=0xfffe 表示該為free block

· BLOCK_NOTEXPLORED (=0xfffd只有在mounting NFTL時才用到。

· BLOCK_RESERVED      (=0xfffc表示該block壞掉或是為bios block

· 非以上 为下一块的物理块号

 

ReplUnitTable最主要的功能是當run time時,我們可以透過在RAM中的ReplUnitTable知道哪些block是屬於同一個chain中的,也可以用來計算每個chain的長度等….

(圖七)Virtual Add.指的是Virtual unitRAM中所在的位置。透過EUNtable找到Chain的實體起始位置,再透過ReplUnitTable找到Repl unit。在RAM中,整個chain的架構都是靠ReplUnitTable維持的。

 

2How to select free block in NFTL?

選擇free block對於wear-leveling是相當重要的一個動作,若我們一直選擇到相同的block來做讀寫其相對被抹除的次數也會大大提升,造成erase次數不平均的現象。

MOUNT NFTL時,我們會將最後讀到的free blockphysical address存到 LastFreeEUN,而我們在找Free Block時,會先看LastFreeEUN是否真的可用,若可用則使用該block;否則循序找其他free block。程式碼NFTL_findfreeblock())簡述如下:

 

3How blocks are chosen to be erased?

如何選擇blockerase是個重要的問題,他不僅影響整個系統的效率,也可能造成erase次數不平均的現象,在此我們介紹NFTL的選擇blockerase的方法。

NFTL認為,最長的chain能夠free最多的block,並不理會blockerase次數。而找最長的chain也是以greedy的方式將整個flash找一次(在RAM中透過ReplUnitTable找),程式碼簡述如下:

 

6 NFTL initializes, handles reads, and handles writes

這邊介紹NFTL在系統初始時,如何將存在spare area的資訊鍵構成run timeRAM使用的資訊。

1. NFTL initializes

· Ini the EUNtableReplUnitTable

· 一個chain一個chain的循序讀取每個blockoob (oob.u.a/oob.u.b)

· 建構 ReplUnitTable

· block status存到ReplUnitTable中。

· Erase unreferenced block(不在Chain中的Block)、計算free block個數

· 如果unreferenced block無法erase

     ReplUnitTable[block] = BLOCK_RESERVED;

· 否則

    ReplUnitTable[block] = BLOCK_FREE;

· numfreeEUNs++;

· LastFreeEUN= block

2. handles reads

直接找latest versionpageread,如何找latest version請參考section.9

3. handles writes

· Findwriteunit()

      若在所屬的Chain中後面的Block對應的page狀態為free則回傳該blockphysical address

     若無法在所屬的Chain寫入則  Find free block,參考section.5.2 ,链入chain

      若沒有free block則做fold chain,參考section.8

· 找到可寫入的block則將對應的pageoob.b.status設為SECTOR_USED

· 最後將DataECCinfo寫入

(圖九)當我們要更新block 11的第4page時,我們會先看看他之後的block 22的第4page是否為free。是則寫入;不是則找free block串在block 22,然後把資料寫到新的block的第4page(最后一版最新)

 

7 About wear-leveling algorithm of NFTL

因為flash的每個blockerase次數的限制,當某個block erase次數過多,可能會造成該block存取速度變慢,嚴重時甚至會造成該block毀損。因此我們希望能夠平均每個block erase的的次數,此機制稱為wear-leveling

此版本的NFTL並沒有實作Wear-Leveling,只有預留一些資訊,如WearInfo,我想Wear-Leveling能夠在find free block時作free block的選擇來達到平均抹除次數的目的。

 

8 Garbage-collection algorithm of NFTL(垃圾回收)

由於flash在更新資料時,無法將資料重新寫回相同的位置,除非先將該位置erase才能再寫入,所以必須採用outplace的方式寫回資料,因此會產生許多不同版本的資料,存放在不同的block中,而舊版本的資料則是無用的,所以必須要有garbage-collection的機制,以下是garbage-collectionNFTL中的作法。NFTL_makefreeblock()函数)

  Find longest chain  

   NFTL中,GCgarbage-collection主要目的是要回收最多的invalid block,而NFTL greedy的認為最長的chain中,能回收最多的block。而找最長的chain是透過ReplUnitTable找出最長的Chain並將該起始位置傳給NFTL_foldchain()做回收的動作。

   NFTL_foldchain()

    判斷是否可做inplace fold chain?

有時我們是在write時發現chain中所對應的page皆已使用,所以必須先判斷是否可以做inplace fold其步驟如下。

   讀取ChainBlock的每個pageoob.b,以每個pagesector status判斷可否inplace

   若可做inplacetargetEUN設為Chain最後一個blockphysical位置(物理块号);反之找一個free block當作targetEUN

  last versionpage對應其位置複製到targetEUN中,如(圖六)。

     NFTL_formatblock()

     Erase 沒用的Blocks

        先讀出將被eraseblockoob information

           Eraseblock

               oob.u.c.WearInfo+1,寫回該blockspare area

              將此blockReplUnitTable中的欄位設成BLOCK_NIL,並將numfreeEUNs+1

         完成fold動作後,更新oob.u.a.VirtUnitNumoob.u.a.ReplUnitTable

              oob.u.a.VirtUnitNum = thisVUC(該Chain原本的virtual address)。

              oob.u.a.ReplUnitNum = 0xffff (BLOCK_NIL)

  

     更新EUNtableReplUnitTable

              ReplUnitTable[targetEUN]=block_NIL

              EUNtable[thisVUC] = targetEUN

(圖六) fold chain示意圖,targetEUNpage一開始全為free

 

 

9 How do NFTL tell the latest version of a piece of data from the old versions of the data (i.e., dead data)?

前面我們提到,flash上更新data大都是使用outplace的方法,所以在我們讀取資料時可能會有許多不同版本的資料,而讀取最新版本的data對於大多數的flash file system都是很重要的問題。在此我們介紹NFTL讀取最新版本資料的方法。

當我們在要更新DATA(sector中的資料)時,會將block中第npage寫到他的replace unit的第npage,所以我們只需要找chain中最後一個狀態是SECTOR_USEDpage就能夠保證他是latest version。如下圖(圖八)所示:

(圖八)圖中紅色粗體的page的資料為latest version

 

 

10 Partial page programming

Partial page programming是指flash上的page在還沒被erase前,又將其中某些bit1改為0,如下圖(圖十)。這在flash上容易造成partial page programming後的資料不正確,而且對於flash的製造上會提高其成本,所以在新一代的flash是不支援partial page programming的。 因此一個flashfile system是否有使用partial page programming是一項值得拿來評估file system的指標。

(圖十) partial page programming

NFTL上,由4.3時提到NFTL on-flash data structuresNFTL將每個flash上的block的前三個pagespare area分為oob.boob.u使用。其中第一個pageoob.uVUN / RUN、第二個pageoob.uerasemark、第三個pageoob.ufoldmark。而當NFTL完成garbage collection時,會將eraseblockerasemark寫為0x3c69,而當NFTL要將資料寫入第二個page時,會一起將該pageoob.b.status狀態改為SECTOR_USED,此時NFTL便做了partial page programming了。另外NFTL在產生一個新的chain或是將block加到chain後面時,會先將資料寫入page並在該pageoob.b中寫入statusECC,最後才將VUN / RUN寫入oob.u..a中,因此若第二的page有使用到話,也會發生partial page programming。如下(圖十一)

(圖十一)oob.boob.ublock中所擺放方式及partial page programming所發生情況。

你可能感兴趣的:(linux)