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
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.
- 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.
- 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.
here in-memory TIMB should be reloaded properly whenever ALFS is mounted again.
- Basic activity of write of garbage collection
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.
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;
}