Re: [PATCH][RFC] USB: zerocopy support for usbfs

From: Oliver Neukum
Date: Fri Jul 04 2014 - 04:55:30 EST


On Wed, 2014-07-02 at 17:53 +0200, Stefan Klug wrote:

> @@ -1471,6 +1526,57 @@ static int proc_do_submiturb(struct
> usb_dev_state
> *ps, struct usbdevfs_urb *uurb
> }
> totlen -= u;
> }
> + } else if(num_pages) {
> + pages = kmalloc(num_pages*sizeof(struct page*), GFP_KERNEL);
> + if(!pages) {
> + ret = -ENOMEM;
> + goto error;
> + }
> +
> + //create the scatterlist
> + as->urb->sg = kmalloc(num_pages * sizeof(struct
> scatterlist),
> GFP_KERNEL);
> + if (!as->urb->sg) {
> + ret = -ENOMEM;
> + goto error;
> + }
> +
> + ret = get_user_pages_fast((unsigned long)buf_aligned,
> + num_pages,
> + is_in,
> + pages);
> +
> + if(ret < 0) {
> + printk("get_user_pages failed %i\n", ret);
> + goto error;
> + }
> +
> + //did we get all pages?
> + if(ret < num_pages) {
> + printk("get_user_pages didn't deliver all pages %i\n",
> ret);
> + //free the pages and error out
> + for(i=0; i<ret; i++) {
> + page_cache_release(pages[i]);
> + }
> + ret = -ENOMEM;
> + goto error;
> + }
> +
> + as->is_user_mem = 1;
> + as->urb->num_sgs = num_pages;
> + sg_init_table(as->urb->sg, as->urb->num_sgs);
> +
> + totlen = uurb->buffer_length + buf_offset;
> + o = buf_offset;
> + for (i = 0; i < as->urb->num_sgs; i++) {
> + u = (totlen > PAGE_SIZE) ? PAGE_SIZE : totlen;
> + u-= o;
> + sg_set_page(&as->urb->sg[i], pages[i], u, o);
> + totlen -= u + o;
> + o = 0;
> + }
> +
> + kfree(pages);
> + pages = NULL;
> } else if (uurb->buffer_length > 0) {
> as->urb->transfer_buffer = kmalloc(uurb->buffer_length,
> GFP_KERNEL)


One more thing: Where do you check that the memory the user has passed
a pointer to is actually writable? It seems to me that for zerocopy you
must do the check before you submit the URB to the HCD.

Regards
Oliver


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/