On 24/03/2021 08:11, Christoph Hellwig wrote: > On Wed, Mar 24, 2021 at 07:07:27AM +0000, Johannes Thumshirn wrote: >>>> if (iov_iter_is_bvec(iter)) { >>>> - if (WARN_ON_ONCE(bio_op(bio) == REQ_OP_ZONE_APPEND)) >>>> - return -EINVAL; >>>> + if (bio_op(bio) == REQ_OP_ZONE_APPEND) { >>>> + struct request_queue *q = bio->bi_bdev->bd_disk->queue; >>>> + unsigned int max_append = >>>> + queue_max_zone_append_sectors(q) << 9; >>>> + >>>> + if (WARN_ON_ONCE(iter->count > max_append)) >>>> + return -EINVAL; >>>> + } >>> >>> That is not correct. bio_iov_iter_get_pages just fills the bio as far >>> as we can, and then returns 0 for the next call to continue. Basically >>> what you want here is a partial version of bio_iov_bvec_set. >>> >> >> Isn't that what I did? The above is checking if we have REQ_OP_ZONE_APPEND and >> then returns EINVAL if iter->count is bigger than queue_max_zone_append_sectors(). >> If the check doesn't fail, its going to call bio_iov_bvec_set(). > > And that is the problem. It should not fail, the payload is decoupled > from the max_append size. > > Doing the proper thing is not too hard as described above - make sure > the bi_iter points to only the chunk of iter passed in that fits, and > only advance the passed in iter by that amount. > Ah got it now, thanks