ABOUT ME

컴퓨터공학 학사. 할줄 아는게 없다.

Today
Yesterday
Total
  • 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 변수를 이와 같이 끼워주었다.

Designed by Tistory.