Re: [RFC] weird semantics of SG_DXFER_TO_FROM_DEV in BLK_DEV_SKD (drivers/block/skd*)

From: Al Viro
Date: Mon Apr 04 2016 - 15:51:48 EST


On Mon, Apr 04, 2016 at 07:47:36PM +0100, Al Viro wrote:
> On Mon, Apr 04, 2016 at 06:16:12PM +0100, Al Viro wrote:
>
> > will see NULL map_data; the ->from_user case is sg_start_req() stuff. IOW,
> > SG_IO behaviour for /dev/sg* is different from the generic one...
>
> While we are at it: in bio_map_user_iov() we have
> iov_for_each(iov, i, *iter) {
> unsigned long uaddr = (unsigned long) iov.iov_base;
> unsigned long len = iov.iov_len;
> unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
> unsigned long start = uaddr >> PAGE_SHIFT;
>
> /*
> * Overflow, abort
> */
> if (end < start)
> return ERR_PTR(-EINVAL);
>
> nr_pages += end - start;
> /*
> * buffer must be aligned to at least hardsector size for now
> */
> if (uaddr & queue_dma_alignment(q))
> return ERR_PTR(-EINVAL);
> }
>
> Do we only care about the iov_base alignment? IOW, shouldn't we check for
> iov_len being a multiple of queue_dma_alignment(q) as well?

What happens if somebody issues SG_IO with 256-segment vector, each segment
1 byte long and page-aligned? Will the driver really be happy with the
resulting request, as long as it hasn't claimed non-zero queue_virt_boundary?
Because AFAICS we'll get a request with a pile of bvecs, each with
->bv_offset equal to 0 and ->bv_len equal to 1; can that really work?