简体   繁体   中英

What is the purpose of the function "blk_rq_map_user" in the NVME disk driver?

I am trying to understand the nvme linux drivers. I am now tackling the function nvme_user_submit_cmd , which I report partially here:

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 && bufflen) {
        ret = blk_rq_map_user(q, req, NULL, ubuffer, bufflen,
                GFP_KERNEL);
    [...]

The ubuffer is a pointer to some data in the virtual address space (since this comes from an ioctl command from a user application).

Following blk_rq_map_user I was expecting some sort of mmap mechanism to translate the userspace address into a physical address, but I can't wrap my head around what the function is doing. For reference here's the call chain:

blk_rq_map_user -> import_single_range -> blk_rq_map_user_iov

Following those function just created some more confusion for me and I'd like some help.

The reason I think that this function is doing a sort of mmap is (apart from the name) that this address will be part of the struct request in the struct request queue , which will eventually be processed by the NVME disk driver ( https://lwn.net/Articles/738449/ ) and my guess is that the disk wants the physical address when fulfilling the requests.

However I don't understand how is this mapping done.

ubuffer is a user virtual address, which means it can only be used in the context of a user process, which it is when submit is called. To use that buffer after this call ends, it has to be mapped to one or more physical addresses for the bios/bvecs. The unmap call frees the mapping after the I/O completes. If the device can't directly address the user buffer due to hardware constraints then a bounce buffer will be mapped and a copy of the data will be made.

Edit: note that unless a copy is needed, there is no kernel virtual address mapped to the buffer because the kernel never needs to touch the data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM