On Mon, Mar 11, 2019 at 03:35:54PM +0100, Christoph Hellwig wrote:
> >             struct bio_vec *prev = &bio->bi_io_vec[bio->bi_vcnt - 1];
> >  
> > +           /* segment size is always >= PAGE_SIZE */
> 
> I don't think that actually is true.  We have various drivers with 4k
> segment size, for which this would not be true with a 64k page size
> system.

Please look at blk_queue_max_segment_size():

void blk_queue_max_segment_size(struct request_queue *q, unsigned int max_size)
{
        if (max_size < PAGE_SIZE) {
                max_size = PAGE_SIZE;
                printk(KERN_INFO "%s: set to minimum %d\n",
                       __func__, max_size);
        }

        q->limits.max_segment_size = max_size;
}

But your concern is correct wrt. 4k segment size vs. 64k page size,
however, seems not see any such report.

> 
> >             if (page == prev->bv_page &&
> >                 offset == prev->bv_offset + prev->bv_len) {
> >                     if (put_same_page)
> >                             put_page(page);
> > + bvec_merge:
> >                     prev->bv_len += len;
> >                     bio->bi_iter.bi_size += len;
> 
> Please throw in a cleanup patch that removes prev and and always uses
> bvec, then we can just move the done label up by two lines and handle
> the increment of bv_len and bi_size in a common branch.

Seems only one line of 'bio->bi_iter.bi_size += len;' can be shared.

> 
> >   done:
> > +   bio->bi_phys_segments = bio->bi_vcnt;
> > +   if (!bio_flagged(bio, BIO_SEG_VALID))
> > +           bio_set_flag(bio, BIO_SEG_VALID);
> 
> How would BIO_SEG_VALID get set previously?  And even if it did

bio_add_pc_page() is run over each page.

> we wouldn't optimize much here, I'd just do it unconditionally.

OK.

> 
> Btw, there are various comments in this function that either already
> were or have become out of data, like talking about REQ_PC or
> file system I/O - I think they could use some love.

OK.

Thanks,
Ming

Reply via email to