1

Let consider following code. For someone who read Linux Device Driver the context will be clear.

In short, sbull is a driver which acts a disk device and the sbull_transfer function aims to transfer block of data from/to disk/user_space.

And everything is clear expect one thing. I don't understand why we can just simply use memcpy function. After all, we copy from user space so why it is possible? Usually, I noticed, that we should use copy_from_user()/copy_to_user().

I don't understand why we needn't to use them. Please explain.

static void sbull_transfer(struct sbull_dev *dev, unsigned long sector,
        unsigned long nsect, char *buffer, int write)
{
    unsigned long offset = sector*KERNEL_SECTOR_SIZE;
    unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE;

    if ((offset + nbytes) > dev->size) {
        printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);
        return;
    }
    if (write)
        memcpy(dev->data + offset, buffer, nbytes);
    else
        memcpy(buffer, dev->data + offset, nbytes);
}
J. Doe
  • 101
  • 8
  • Are you sure that you can call this function from user space, passing a user space allocated buffer? – LPs Sep 09 '15 at 12:28
  • Have you registered `sbull_transfer()` as the read file operation when registering the device with fops? – Santosh A Sep 09 '15 at 12:29
  • @Jens Gustedt the question you reference is about the rationale behind the copy_to/from_user - this question here is about why copy_to/from_user hasn't been used - it is totally different – 4pie0 Sep 09 '15 at 15:13
  • @tinky_winky I think Jens is correct. This is the same question and I think the accepted answer is the answer to this question at all. – JeremyP Sep 09 '15 at 15:26
  • @JeremyP I can't agree with that. In my opinion it is clear that OP is thinking that copy_from/to_user has been omitted. He doesn't ask why copy_to_user exist as he probably knows this (or thinks that he knows). The reference question is about "Why is that we should use copy_to_user instead of memcpy()". It is totally different. OP knows why we should and he asks why we don't. – 4pie0 Sep 09 '15 at 15:32
  • 1
    @tinky_winky On reflection, I think you are correct. – JeremyP Sep 09 '15 at 15:35

1 Answers1

2

The sbull driver can implement the actual data transfer with a simple memcpy call because data is already in memory, after all.

Function

static void sbull_request(request_queue_t *q)
{
    struct request *req;

    while ((req = elv_next_request(q)) != NULL) {
        struct sbull_dev *dev = req->rq_disk->private_data;
        if (! blk_fs_request(req)) {
            printk (KERN_NOTICE "Skip non-fs request\n");
            end_request(req, 0);
            continue;
        }
        sbull_transfer(dev, req->sector, req->current_nr_sectors,
                req->buffer, rq_data_dir(req));
        end_request(req, 1);
    }
}

calls elv_next_request before data is passed to sbull_transfer. Request function takes care about copying data to/from user space. The buffer contained in returned request struct is described in book as:

char *buffer;

A pointer to the buffer to or from which the data should be transferred. This pointer is a kernel virtual address and can be dereferenced directly by the driver if need be.

Community
  • 1
  • 1
4pie0
  • 29,204
  • 9
  • 82
  • 118