Basically, If you want to know about SSD, You have to this site

this article refers to and cite this paper(fast16-papers-lee)

Application-Managed Flash

the main concept is in section 2, 3, 4. maybe you want to read this paper and just see section 2, 3, 4.

As name of AMF implies, AMF moves the intelligence from device to applications, which can be file systems, databases, and user applications, leaving only essential management parts of on the device side.

this people define a new block I/O interface

AMF

segment consists of setor and segment have two type, logical segment and physical segment.

in other words, a physical segment is composed of a group of blocks spread among different channels and ways, and sectors within a logical segments are statically mapped to flash pages within a physical segment.

AMF Log-structured File system

ALFS always performs out-of-place updates even for the check-point and inode-map because of the requirements of the AMF block I/O interface.

ALFS

  • Check-point Segment

ALFS has two checkpoints. When ALFS is remounted, it reads all the check-point segments from AFTL, It finds the latest check-point by comparing version numbers. the way to comparing is brute force search, this way is efficient because ALFS has only two segments for check-pointing, regardless fo storage capacity.

ALFS check point

  • Inode-Map Segment

ALFS divides the inode map into 4KB blocks, which is called inode-map blocks.

  • Inode-Map Block Management ALFS maintain a table for inode-map blocks(TIMB) in main memory. TIMB consists of 4 B entries that point to inode-map blocks in inode-map segments.

ALFS table of inode map table

here in-memory TIMB should be reloaded properly whenever ALFS is mounted again.

  • Basic activity of write of garbage collection

ALFS

differnce above is whether LFS and FTL know each other’s work or not.

AML Flash Translation Layer(AFTL)

AFTL works in device driver, this system is statically mapped from logical segment to physical segment STAT is divided into three type which Free, Used or Invalid. ALFS informs AFTL via TRIM commands that the physical segments have only obsolete data.

AFTL after TRIM command

key point is that FTL GC is never invoked in AFTL

git address(driver) - ATFL code

  • : https://github.com/chamdoo/bdbm_drv.git

blueDBM Driver(AFTL) code’s Analaysis.

  • analyzing source code

main data structure in /dbbm_drv/front_end/nvme/main.c file

bdbm_drv_info_t * bdi = NULL;

if you looking in /bdbm_drv/include/bdbm_drv.h file.

typedef struct _bdbm_drv_info_t bdbm_drv_info_t;

so if you search for struct _bdbm_drv_info_t

The following is

/* the main data-structure for bdbm_drv */  
struct _bdbm_drv_info_t {  
        void* private_data;  
        bdbm_ftl_params parm_ftl;  
        bdbm_device_params_t parm_dev;  
        bdbm_host_inf_t* ptr_host_inf;  
        bdbm_dm_inf_t* ptr_dm_inf;  
        bdbm_hlm_inf_t* ptr_hlm_inf;  
        bdbm_llm_inf_t* ptr_llm_inf;  
        bdbm_ftl_inf_t* ptr_ftl_inf;  
        bdbm_perf_monitor_t pm;  
};  

again, if you look in /dbbm_drv/front_end/nvme/main.c file

in main fucntion

int main (int argc, char** argv)
{
        int loop_thread;

        pthread_t thread[NUM_THREADS];
        int thread_args[NUM_THREADS];

        bdbm_msg ("[main] run ftlib... (%d)", sizeof (bdbm_llm_req_t));

        bdbm_msg ("[nvme-main] initialize bdbm_drv");
        if ((_bdi = bdbm_drv_create ()) == NULL) {
                bdbm_error ("[main] bdbm_drv_create () failed");
                return -1;
        }

        if (bdbm_dm_init (_bdi) != 0) {
                bdbm_error ("[main] bdbm_dm_init () failed");
                return -1;
        }

        if (bdbm_drv_setup (_bdi, &_userio_inf, bdbm_dm_get_inf (_bdi)) != 0) {
                bdbm_error ("[main] bdbm_drv_setup () failed");
                return -1;
        }

        if (bdbm_drv_run (_bdi) != 0) {
                bdbm_error ("[main] bdbm_drv_rin () failed");
                return -1;
        }

        do {
                bdbm_msg ("[main] start writes");
                for (loop_thread = 0; loop_thread < NUM_THREADS; loop_thread++) {
                        thread_args[loop_thread] = loop_thread;
                        pthread_create (&thread[loop_thread], NULL,
                                (void*)&host_thread_fn_write,
                                (void*)&thread_args[loop_thread]);
                }

                bdbm_msg ("[main] wait for threads to end...");
                for (loop_thread = 0; loop_thread < NUM_THREADS; loop_thread++) {
                        pthread_join (thread[loop_thread], NULL);

                bdbm_msg ("[main] start reads");
                for (loop_thread = 0; loop_thread < NUM_THREADS; loop_thread++) {
                        thread_args[loop_thread] = loop_thread;
                        pthread_create (&thread[loop_thread], NULL,
                                (void*)&host_thread_fn_read,
                                (void*)&thread_args[loop_thread]);
                }

                bdbm_msg ("[main] wait for threads to end...");
                for (loop_thread = 0; loop_thread < NUM_THREADS; loop_thread++) {
                        pthread_join (thread[loop_thread], NULL);
                }

        } while (0);

        sleep (1);
        bdbm_msg ("[main] destroy bdbm_drv");
        bdbm_drv_close (_bdi);
        bdbm_dm_exit (_bdi);
        bdbm_drv_destroy (_bdi);

        bdbm_msg ("[main] done");

        return 0;
} 

for bdbm_drv_create function, I searched using -grep -rin bdbm_drv_create *_.

so the result :

[hyunyoung.lee@localhost bdbm_drv]$ grep -rin  bdbm_drv_create *
common/bdbm_main.c:69:bdbm_drv_info_t* bdbm_drv_create (void)
frontend/hybrid/kmain.c:39:	if ((_bdi = bdbm_drv_create ()) == NULL) {
frontend/hybrid/kmain.c:40:		bdbm_error ("[kmain] bdbm_drv_create () failed");
frontend/hybrid/umain.c:62:	if ((_bdi = bdbm_drv_create ()) == NULL) {
frontend/hybrid/umain.c:63:		bdbm_error ("[kmain] bdbm_drv_create () failed");
frontend/kernel/kmain.c:38:	if ((_bdi = bdbm_drv_create ()) == NULL) {
frontend/kernel/kmain.c:39:		bdbm_error ("[kmain] bdbm_drv_create () failed");
Binary file frontend/nvme/libftl matches
frontend/nvme/main.c:172:	if ((_bdi = bdbm_drv_create ()) == NULL) {
frontend/nvme/main.c:173:		bdbm_error ("[main] bdbm_drv_create () failed");
Binary file frontend/nvme/.main.c.swp matches
frontend/user/main.c:148:	if ((_bdi = bdbm_drv_create ()) == NULL) {
frontend/user/main.c:149:		bdbm_error ("[kmain] bdbm_drv_create () failed");
include/bdbm_drv.h:386:bdbm_drv_info_t* bdbm_drv_create (void);
Binary file include/.bdbm_drv.h.swp matches

the result above show you common/bdbm_main.c:69:bdbm_drv_info_t* bdbm_drv_create(void) line

so I looked in it

the function is

 69 bdbm_drv_info_t* bdbm_drv_create (void)
 70 {
 71         bdbm_drv_info_t* bdi = NULL;
 72 
 73         /* allocate the memory for bdbm_drv_info_t */
 74         if ((bdi = (bdbm_drv_info_t*)bdbm_malloc (sizeof (bdbm_drv_info_t))) == NULL) {
 75                 bdbm_error ("[bdbm_drv_main] bdbm_malloc () failed");
 76                 return NULL;
 77         }
 78 
 79         /* get default driver paramters */
 80         bdi->parm_ftl = get_default_ftl_params ();
 81         bdi->parm_dev = get_default_device_params ();
 82 
 83         return bdi;
 84 }

because of bdbm_dm_init of main function in /dbbm_drv/front_end/nvme/main.c file

[hyunyoung.lee@localhost bdbm_drv]$ grep -rin bdbm_dm_init *
devices/common/dev_main.c:59:int bdbm_dm_init (bdbm_drv_info_t* bdi)
devices/common/dev_main.c:97:EXPORT_SYMBOL (bdbm_dm_init);
examples/raw-flash/raw-flash.c:185:	if (bdbm_dm_init (bdi) != 0)  {
examples/raw-flash/raw-flash.c:186:		bdbm_error ("bdbm_dm_init () failed");
frontend/hybrid/umain.c:68:	if (bdbm_dm_init (_bdi) != 0) {
frontend/hybrid/umain.c:69:		bdbm_error ("[kmain] bdbm_dm_init () failed");
frontend/kernel/kmain.c:44:	if (bdbm_dm_init (_bdi) != 0) {
frontend/kernel/kmain.c:45:		bdbm_error ("[kmain] bdbm_dm_init () failed");
frontend/nvme/dev_proxy.c:146:int bdbm_dm_init (bdbm_drv_info_t* bdi)
Binary file frontend/nvme/libftl matches
frontend/nvme/main.c:177:	if (bdbm_dm_init (_bdi) != 0) {
frontend/nvme/main.c:178:		bdbm_error ("[main] bdbm_dm_init () failed");
Binary file frontend/nvme/.main.c.swp matches
frontend/user/dev_proxy.c:338:int bdbm_dm_init (bdbm_drv_info_t* bdi)
frontend/user/main.c:153:	if (bdbm_dm_init (_bdi) != 0) {
frontend/user/main.c:154:		bdbm_error ("[kmain] bdbm_dm_init () failed");
include/devices.h:34:int bdbm_dm_init (bdbm_drv_info_t* bdi);

So I enter devices/common/dev_main.c file.

the result is

 59 int bdbm_dm_init (bdbm_drv_info_t* bdi)
 60 {
 61         /* see if bdi is valid or not */
 62         if (bdi == NULL) {
 63                 bdbm_warning ("bid is NULL");
 64                 return 1;
 65         }
 66 
 67         if (_bdi_dm != NULL) {
 68                 bdbm_warning ("dm_stub is already used by other clients");
 69                 return 1;
 70         }
 71 
 72         /* initialize global variables */ // global variable in /bdbm_drv/devices/common/dev_main.c file.
 73         _bdi_dm = bdi;
 74 
 75         return 0;
 76 }

and

because of bdbm_drv_setup of main function in /dbbm_drv/front_end/nvme/main.c file

if you search for the function, bdbm_drv_setup.

the result is

[hyunyoung.lee@localhost bdbm_drv]$ grep -rin bdbm_drv_setup *
common/bdbm_main.c:86:int bdbm_drv_setup (
frontend/hybrid/kmain.c:51:	bdbm_drv_setup (_bdi, &_blkio_proxy_inf, NULL);
frontend/hybrid/umain.c:74:	if (bdbm_drv_setup (_bdi, &_blkio_stub_inf, bdbm_dm_get_inf (_bdi)) != 0) {
frontend/hybrid/umain.c:75:		bdbm_error ("[kmain] bdbm_drv_setup () failed");
frontend/kernel/kmain.c:50:	if (bdbm_drv_setup (_bdi, &_blkio_inf, bdbm_dm_get_inf (_bdi)) != 0) {
frontend/kernel/kmain.c:51:		bdbm_error ("[kmain] bdbm_drv_setup () failed");
Binary file frontend/nvme/libftl matches
frontend/nvme/main.c:182:	if (bdbm_drv_setup (_bdi, &_userio_inf, bdbm_dm_get_inf (_bdi)) != 0) {
frontend/nvme/main.c:183:		bdbm_error ("[main] bdbm_drv_setup () failed");
Binary file frontend/nvme/.main.c.swp matches
frontend/user/main.c:158:	bdbm_drv_setup (_bdi, &_userio_inf, bdbm_dm_get_inf (_bdi));
include/bdbm_drv.h:387:int bdbm_drv_setup (bdbm_drv_info_t* bdi, bdbm_host_inf_t* host_inf, bdbm_dm_inf_t* dm_inf);

if you see the result above, you shoud search for common/dbbm_drv_setup function.

the result is

int bdbm_drv_setup (
        bdbm_drv_info_t* bdi,
        bdbm_host_inf_t* host_inf,
        bdbm_dm_inf_t* dm_inf)
{
        if (bdi == NULL) {
                bdbm_warning ("oops! bdi is NULL");
                return 1;
        }

        /* setup host */
        bdi->ptr_host_inf = host_inf;

        /* setup device */
        bdi->ptr_dm_inf = dm_inf;

        /* setup ftl */
        switch (bdi->parm_ftl.hlm_type) {
        case HLM_NOT_SPECIFIED:
                bdi->ptr_hlm_inf = NULL;
                break;
        case HLM_NO_BUFFER:
                bdi->ptr_hlm_inf = &_hlm_nobuf_inf;
                break;
        case HLM_BUFFER:
                bdi->ptr_hlm_inf = &_hlm_buf_inf;
                break;
        case HLM_DFTL:
                bdi->ptr_hlm_inf = &_hlm_dftl_inf;
                break;
        default:
                bdbm_error ("invalid hlm type");
                bdbm_bug_on (1);
                break;
        }

        switch (bdi->parm_ftl.llm_type) {
        case LLM_NOT_SPECIFIED:
                bdi->ptr_llm_inf = NULL;
                break;
        case LLM_NO_QUEUE:
                bdi->ptr_llm_inf = &_llm_noq_inf;
                break;
        case LLM_MULTI_QUEUE:
                bdi->ptr_llm_inf = &_llm_mq_inf;
        default:
                bdbm_error ("invalid llm type");
                bdbm_bug_on (1);
                break;
        }

        switch (bdi->parm_ftl.mapping_type) {
        case MAPPING_POLICY_NOT_SPECIFIED:
                bdi->ptr_ftl_inf = NULL;
                break;
        case MAPPING_POLICY_NO_FTL:
                bdi->ptr_ftl_inf = &_ftl_no_ftl;
                break;
        case MAPPING_POLICY_BLOCK:
                bdi->ptr_ftl_inf = &_ftl_block_ftl;
                break;
        case MAPPING_POLICY_RSD:
                bdi->ptr_ftl_inf = &_ftl_block_ftl;
                break;
        case MAPPING_POLICY_PAGE:
                bdi->ptr_ftl_inf = &_ftl_page_ftl;
                break;
        case MAPPING_POLICY_DFTL:
                bdi->ptr_ftl_inf = &_ftl_dftl;
                break;
        default:
                bdbm_error ("invalid ftl type");
                bdbm_bug_on (1);
                break;
        }

        return 0;
}

so finally, we search for bdbm_drv_run

/* run all the layers related to bdbm_drv */
int bdbm_drv_run (bdbm_drv_info_t* bdi)
{
        bdbm_host_inf_t* host = NULL;
        bdbm_hlm_inf_t* hlm = NULL;
        bdbm_llm_inf_t* llm = NULL;
        bdbm_ftl_inf_t* ftl = NULL;
        bdbm_dm_inf_t* dm = NULL;
        uint32_t load = 0;

        /* run setup functions */
        if (bdi->ptr_dm_inf) {
                dm = bdi->ptr_dm_inf;

                /* get the device information */
                if (dm->probe == NULL || dm->probe (bdi, &bdi->parm_dev) != 0) {
                        bdbm_error ("[bdbm_drv_main] failed to probe a flash device");
                        goto fail;
                }
                /* open a flash device */
                if (dm->open == NULL || dm->open (bdi) != 0) {
                        bdbm_error ("[bdbm_drv_main] failed to open a flash device");
                        goto fail;
                }
                /* do we need to read a snapshot? */
                if (bdi->parm_ftl.snapshot == SNAPSHOT_ENABLE &&
                        dm->load != NULL) {
                        if (dm->load (bdi, "/usr/share/bdbm_drv/dm.dat") != 0) {
                                bdbm_msg ("[bdbm_drv_main] loading 'dm.dat' failed");
                                load = 0;
                        } else
                                load = 1;
                }
        }
        /* create a low-level memory manager */
        if (bdi->ptr_llm_inf) {
                llm = bdi->ptr_llm_inf;
                if (llm->create == NULL || llm->create (bdi) != 0) {
                        bdbm_error ("[bdbm_drv_main] failed to create llm");
                        goto fail;
                }
        }

        /* create a logical-to-physical mapping manager */
        if (bdi->ptr_ftl_inf) {
                ftl = bdi->ptr_ftl_inf;
                if (ftl->create == NULL || ftl->create (bdi) != 0) {
                        bdbm_error ("[bdbm_drv_main] failed to create ftl");
                        goto fail;
                }
                if (bdi->parm_ftl.snapshot == SNAPSHOT_ENABLE &&
                        load == 1 && ftl->load != NULL) {
                        if (ftl->load (bdi, "/usr/share/bdbm_drv/ftl.dat") != 0) {
                                bdbm_msg ("[bdbm_drv_main] loading 'ftl.dat' failed");
                        }
                }
        }

        /* create a high-level memory manager */
        if (bdi->ptr_hlm_inf) {
                hlm = bdi->ptr_hlm_inf;
                if (hlm->create == NULL || hlm->create (bdi) != 0) {
                        bdbm_error ("[bdbm_drv_main] failed to create hlm");
                        goto fail;
                }
        }

        /* create a host interface */
        if (bdi->ptr_host_inf) {
                host = bdi->ptr_host_inf;
                if (host->open == NULL || host->open (bdi) != 0) {
                        bdbm_error ("[bdbm_drv_main] failed to open a host interface");
                        goto fail;
                }
        }
        /* display default parameters */
        display_device_params (&bdi->parm_dev);
        display_ftl_params (&bdi->parm_ftl);

        /* init performance monitor */
        pmu_create (bdi);

        bdbm_msg ("[bdbm_drv_main] bdbm_drv is registered!");

        return 0;

fail:
        if (host && host->close)
                host->close (bdi);
        if (hlm && hlm->destroy)
                hlm->destroy (bdi);
        if (ftl && ftl->destroy)
                ftl->destroy (bdi);
        if (llm && llm->destroy)
                llm->destroy (bdi);
        if (dm && dm->close)
                dm->close (bdi);
        if (bdi)
                bdbm_free (bdi);

        bdbm_error ("[bdbm_drv_main] bdbm_drv failed!");

        return 1;
}