-
FEMU 사용법 익힌 내용개발 로그 2024. 10. 30. 16:52
ftl.c에는 인풋 정보가 들어오지 않는다. 어디에 쓰고 그게 몇 초 걸릴지 계산하는 코드 위주이다. 인풋 정보는 nvme-io.c 이쪽으로 간다. 일단 ftl.c가 인풋 정보를 알 수 있게 하려면 nvme-io.c를 건들여야 한다.
nvme-io.c를 보면 nvme_rw라는 함수가 있는데, 이게 이름 그대로 인풋을 읽으면서 거치는 함수이다. 이 중에 backend_rw라는 함수가 있는데 여기서 실제 인풋을 읽는 코드가 존재한다. 따라서 인풋 정보를 받으려면 backend_rw를 수정해야한다.
int backend_rw(SsdDramBackend *b, QEMUSGList *qsg, uint64_t *lbal, bool is_write) { int sg_cur_index = 0; dma_addr_t sg_cur_byte = 0; dma_addr_t cur_addr, cur_len; uint64_t mb_oft = lbal[0]; void *mb = b->logical_space; DMADirection dir = DMA_DIRECTION_FROM_DEVICE; if (is_write) { dir = DMA_DIRECTION_TO_DEVICE; } while (sg_cur_index < qsg->nsg) { cur_addr = qsg->sg[sg_cur_index].base + sg_cur_byte; cur_len = qsg->sg[sg_cur_index].len - sg_cur_byte; if (dma_memory_rw(qsg->as, cur_addr, mb + mb_oft, cur_len, dir, MEMTXATTRS_UNSPECIFIED)) { femu_err("dma_memory_rw error\n"); } sg_cur_byte += cur_len; if (sg_cur_byte == qsg->sg[sg_cur_index].len) { sg_cur_byte = 0; ++sg_cur_index; } if (b->femu_mode == FEMU_OCSSD_MODE) { mb_oft = lbal[sg_cur_index]; } else if (b->femu_mode == FEMU_BBSSD_MODE || b->femu_mode == FEMU_NOSSD_MODE || b->femu_mode == FEMU_ZNSSD_MODE) { mb_oft += cur_len; } else { assert(0); } } qemu_sglist_destroy(qsg); return 0; }
dma_memory_rw이 함수에서 읽어서, mb에 저장해준다. 이 mb가 해당 io의 내용이 된다. 이걸 수정해서 원하는 바를 이루면 된다.
여기서 끝이 아닐 것이다. 보통 이걸 여기서 읽고, ftl.c로 내용을 보내고 싶다는 욕망이 생길 것이다. 여러가지 방법이 있겠지만, 나는 qsg를 이용하여 보냈다. 다만 qsg에 새로운 변수 추가하여 할당해서 ftl.c에서 읽으면, 아무리 읽어도 무조건 0이 뜰 것이다.
위 코드의 qemu_sglist_destroy(qsg); 이 부분 때문이다. 함수 들어가서 읽으면 알겠지만, qsg를 전부 다 파괴하는 함수이다. 난 단순히 이 부분을 제거하여 이 문제를 해결했다.
Read일 경우(is_write가 false일 경우)에는 상관이 없으나, Write일 경우(is_write가 true일 경우), qsg를 파괴시키지 않았다. 대신 ftl.c 함수에서 qsg를 파괴시켜서 메모리를 관리했다.
벤치마크는 FIO를 사용하여 진행하는 것이 간편하다.
sudo fio --name=gc_test --size=1G --filename=/dev/nvme0n1 --bs=4k --rw=randwrite --direct=1 --numjobs=4 -group_reporting
이런식이다.
여기서 핵심은, numjobs이 부분인데, numjobs가 1인 경우, 어떻게 해도 ftl.c에서 gc가 불리질 않는다. 중복된 lpn은 생성이 되곤 하는 것 같은데, 어째서 gc가 불리질 않는지는 모르겠다. 당시 gc를 만들겠다고 이것 저것 다 건들었는데, 결론은 그냥 numjobs를 1보다 크게 만들면 되는 문제였기에 살짝 김이 빠졌다.
ftl.c에서 io 인풋을 잘 읽고 있는지 확인하려면 --buffer_pattern=0xAB fio에 이런 식으로 옵션을 주는 것도 방법이다. 모든 버퍼가 0xAB로 입력되어 확인이 편해진다.
새로운 라이브러리 인풋하는 것도 문제인데, 최상단의 meson.build를 수정하면 된다.
나 같은 경우에는, openssl을 사용하고 싶어서 아래와 같이 수정했다.
################ # Dependencies # ################ openssl_dep = dependency('openssl', required: true) # When bumping glib minimum version, please check also whether to increase # the _WIN32_WINNT setting in osdep.h according to the value from glib glib_req_ver = '>=2.56.0' glib_pc = dependency('glib-2.0', version: glib_req_ver, required: true, method: 'pkg-config') glib_cflags = [] if enable_modules ...
openssl_dep 변수를 만들어주고,
libqemuutil = static_library('qemuutil', build_by_default: false, sources: util_ss.sources() + stub_ss.sources() + genh, dependencies: [util_ss.dependencies(), libm, threads, glib, openssl_dep, socket, malloc, pixman])
아래에 만들어둔 openssl_dep 변수를 이와 같이 끼워주었다.