🌟 Memory Computing and Computer Architecture Lab
NVMeVirt Weekly Study
- 이전글
[NVMeVirt] implementation of DFTL : init & rm
🌟 Memory Computing and Computer Architecture LabNVMeVirt Weekly Seminar- 논문 리뷰로 알아보는 DFTL(참고) Paper Review : DFTL(Demand-based Flash Translation Layer)⏳ DFTL: A Flash Translation Layer Employing Demand-based Selective Caching of
wifiaircat.tistory.com
쓰라린 실패를 맛보며 모든 코드를 폐기하고 다시 시작했으므로
이번에는 차근차근 한 단계씩 신중하게 넘어가기로...
- conv_read의 분석



다시는 서버를 reboot하게 하지 않겠다는 단 하나의 생각으로
완전 공들여서 전체적으로 분석하고 나니까 이후 절차가 많이 편해짐...
이것을 세미나에서 (그럴 필요 없는데도) 보고했는데
무언의 칭찬을 많이 받은 것 같다는 생각이... ദി ᷇ᵕ ᷆ )♡
- read 흐름 그리기

본격적인 코드 수정에 앞서 read의 전체 흐름도를 그려본다.
논리적으로 빠진 부분이 없는지 확인도 가능하고 생각 정리하는 데에 도움이 된다.
이거 보고하고 세미나에서 칭찬 많이 받았다. ദി ᷇ᵕ ᷆ )♡
- 1차 구현
`get_cmt_ent`에서 miss의 경우 miss control 없이 `get_maptbl_ent`(mapping table에서 가져오기)와
`insert_cmt_ent`(CMT에 새로 넣기)를 바로 붙여서 구현하기로 했다.
static inline struct ppa get_cmt_ent(struct conv_ftl *conv_ftl, uint64_t lpn) {
struct ppa new_ppa = { .g.ch = -1 };
if (!conv_ftl->cmt){
NVMEV_DEBUG("[DFTL] get_cmt_ent : conv_ftl is NULL\n");
dump_stack();
return new_ppa;
}
for (int i = 0; i < CMT_SIZE; i++) {
if (conv_ftl->cmt[i].valid && conv_ftl->cmt[i].lpn == lpn) {
/* case of cache hit */
NVMEV_DEBUG("[DFTL] cache hit: lpn=%llu\n", lpn);
/* victim policy : LRU */
conv_ftl->cmt[i].last_access = get_current_time();
return conv_ftl->cmt[i].ppa;
}
}
/* case of cache miss */
NVMEV_DEBUG("[DFTL] cache miss: lpn=%llu\n", lpn);
new_ppa = get_maptbl_ent(conv_ftl, lpn);
insert_cmt_ent(conv_ftl, lpn, &new_ppa);
//new_ppa = miss_control(conv_ftl, lpn);
return new_ppa;
}
위 기본 함수를 `conv_read`에 삽입할 예정
`conv_read` 내에서 기존 Call sites of `get_maptbl_ent`은 `prev_ppa`와 `cur_ppa` 두 부분이 있다.
해당 부분들을 수정한 `get_cmt_ent` 함수로 대체해본다. make가 잘 되면 test로...
테스트
insert module 시에 나오는 dmesg를 보면 miss - insert - hit의 흐름이 보인다. 굿 ദി ᷇ᵕ ᷆ )♡


- 2차 구현
: miss control 부분을 마저 구현해서 read 흐름을 완성한다.
이번에는 miss control 함수를 따로 만들지 않고 `get_cmt_ent`에 함
static inline struct ppa get_cmt_ent(struct conv_ftl *conv_ftl, uint64_t lpn) {
struct ppa new_ppa = { .g.ch = -1 };
struct cmt_entry *victim = NULL;
int victim_index = -1;
if (!conv_ftl->cmt){
NVMEV_DEBUG("[DFTL] get_cmt_ent : conv_ftl->cmt is NULL\n");
dump_stack();
return new_ppa;
}
/* cache hit path */
for (int i = 0; i < CMT_SIZE; i++) {
if (conv_ftl->cmt[i].valid && conv_ftl->cmt[i].lpn == lpn) {
/* case of cache hit */
NVMEV_DEBUG("[DFTL] cache hit: lpn=%llu\n", lpn);
/* victim policy : LRU */
conv_ftl->cmt[i].last_access = get_current_time();
return conv_ftl->cmt[i].ppa;
}
}
/* cache miss path */
NVMEV_DEBUG("[DFTL] cache miss: lpn=%llu\n", lpn);
/* site of miss control function*/
/* is cmt full? */
if (conv_ftl->cmtsize == CMT_SIZE){
NVMEV_DEBUG("[DFTL] select_victim_cmt_ent\n");
victim_index = select_victim_cmt_ent(conv_ftl);
NVMEV_ASSERT(victim_index >= 0 && victim_index < CMT_SIZE);
victim = &conv_ftl->cmt[victim_index];
/* write-back if dirty */
if (victim->dirty){
NVMEV_DEBUG("[DFTL] write-back victim: lpn=%llu\n", victim->lpn);
set_maptbl_ent(conv_ftl, victim->lpn, &victim->ppa);
}
/* eviction */
victim->ppa.ppa = UNMAPPED_PPA;
victim->dirty = false;
victim->valid = false;
conv_ftl->cmtsize--;
}
new_ppa = get_maptbl_ent(conv_ftl, lpn);
insert_cmt_ent(conv_ftl, lpn, &new_ppa);
return new_ppa;
}
테스트

insert module 시에 나온 dmesg 흐름은 괜찮아 보인다.
rmmod에서 계속 kernel thread가 -1로 남던 문제도 없다!
이후 마운트 없이 진행하는 fio read에서도 괜찮게 나왔다. ၄(cʸ„òᴗóリ၃
`select_victim_cmt_ent`에서 중복되는 커널 로그 부분 삭제하고 끝!
- 기타 체크 포인트
insert module 시 : `conv_write`는 호출되지 않는다. `conv_read`는 호출된다.
mount 시 : `conv_write`가 호출된다. File system meta data 를 쓰기 때문이다.

아직 `conv_write`는 연결하지 않았으므로 DFTL이 안 나오는 게 맞다.
진짜 하나도 순조롭지 않았던 고졸의 DFTL read 경로 구현...



나 정말 신났었군아... *⋆꒰ঌ(⁎ᴗ͈ˬᴗ͈⁎)໒꒱⋆*
(부가설명)
함수 이름이 conv_*인 이유는 파일 이름이 conv_ftl이기 때문.
사실 dftl_ftl로 바꿨기 때문에 dftl_*로 바꾸는 게 좋겠지만 그건...
- 3차 구현 : 추가 수정
evaluation 중 발견한 문제로 추가수정 : eval of DFTL에서 후술
for (i = 0; (i < nr_parts) && (start_lpn <= end_lpn); i++, start_lpn++) {
conv_ftl = &conv_ftls[start_lpn % nr_parts];
xfer_size = 0;
//prev_ppa = get_maptbl_ent(conv_ftl, start_lpn / nr_parts);
/* normal IO read path */
for (lpn = start_lpn; lpn <= end_lpn; lpn += nr_parts) {
uint64_t local_lpn;
struct ppa cur_ppa;
local_lpn = lpn / nr_parts;
if (start_lpn == local_lpn){
prev_ppa = get_cmt_ent(conv_ftl, start_lpn / nr_parts);
cur_ppa = prev_ppa;
} else {
cur_ppa =get_cmt_ent(conv_ftl, local_lpn)
}
//cur_ppa = get_cmt_ent(conv_ftl, local_lpn);
//cur_ppa = get_maptbl_ent(conv_ftl, local_lpn);
'My Laboratory' 카테고리의 다른 글
| [NVMeVirt] Implementation of DFTL #3 : write (0) | 2025.09.24 |
|---|---|
| Doc Review : 소프트웨어(s/w) 에러정정코드(ecc)를 이용한 낸드 플래시에서의 데이터 입출력 방법 및 그 방법을 이용한 임베디드 시스템 (0) | 2025.09.24 |
| [NVMeVirt] implementation of DFTL #1 (0) | 2025.09.04 |
| Paper Review : NVMeVirt: A Versatile Software-defined Virtual NVMe Device (0) | 2025.08.08 |
| Paper Review : DFTL(Demand-based Flash Translation Layer) (3) | 2025.07.28 |