Какова цель функции «blk_rq_map_user» в драйвере диска NVME?

#linux-kernel #linux-device-driver #block-device #nvme

Вопрос:

Я пытаюсь понять драйверы nvme linux. Сейчас я занимаюсь функцией nvme_user_submit_cmd, о которой я частично сообщаю здесь:

 static int nvme_submit_user_cmd(struct request_queue *q,
        struct nvme_command *cmd, void __user *ubuffer,
        unsigned bufflen, void __user *meta_buffer, unsigned meta_len,
        u32 meta_seed, u32 *result, unsigned timeout)
{
    bool write = nvme_is_write(cmd);
    struct nvme_ns *ns = q->queuedata;
    struct gendisk *disk = ns ? ns->disk : NULL;
    struct request *req;
    struct bio *bio = NULL;
    void *meta = NULL;
    int ret;

    req = nvme_alloc_request(q, cmd, 0, NVME_QID_ANY);
    [...]
    if (ubuffer amp;amp; bufflen) {
        ret = blk_rq_map_user(q, req, NULL, ubuffer, bufflen,
                GFP_KERNEL);
    [...]
 

Это ubuffer указатель на некоторые данные в виртуальном адресном пространстве (поскольку это происходит из ioctl команды пользовательского приложения).

После blk_rq_map_user этого я ожидал какого-то mmap механизма для преобразования адреса пользовательского пространства в физический адрес, но я не могу понять, что делает функция. Для справки вот цепочка вызовов:

blk_rq_map_user -> import_single_range -> blk_rq_map_user_iov

Следование этой функции только что создало для меня еще большую путаницу, и я хотел бы получить некоторую помощь.

Причина, по которой я думаю, что эта функция выполняет своего рода mmap, заключается в том (помимо имени), что этот адрес будет частью struct request in struct request queue , который в конечном итоге будет обработан драйвером диска NVME (https://lwn.net/Articles/738449 /) и я предполагаю, что диску нужен физический адрес при выполнении запросов.

Однако я не понимаю, как выполняется это сопоставление.

Ответ №1:

ubuffer — это виртуальный адрес пользователя, что означает, что его можно использовать только в контексте пользовательского процесса, которым он является при вызове submit. Чтобы использовать этот буфер после завершения этого вызова, он должен быть сопоставлен с одним или несколькими физическими адресами для bios / bvecs. Вызов unmap освобождает сопоставление после завершения ввода-вывода. Если устройство не может напрямую обращаться к пользовательскому буферу из-за аппаратных ограничений, тогда будет отображен буфер отказов и будет сделана копия данных.

Редактировать: обратите внимание, что, если не требуется копирование, виртуальный адрес ядра не отображается в буфер, потому что ядру никогда не нужно прикасаться к данным.